Pol  Revision:cb584c9
object.cpp
Go to the documentation of this file.
1 
11 #include <assert.h>
12 #include <istream>
13 #include <stddef.h>
14 #include <string>
15 
16 #include "../clib/clib.h"
17 #include "../clib/fixalloc.h"
18 #include "../clib/logfacility.h"
19 #include "../clib/random.h"
20 #include "../clib/rawtypes.h"
21 #include "../clib/refptr.h"
22 #include "../clib/stlutil.h"
23 #include "berror.h"
24 #include "bobject.h"
25 #include "bstruct.h"
26 #include "dict.h"
27 #include "executor.h"
28 #include "impstr.h"
29 #include "object.h"
30 #include "objmembers.h"
31 #include "objmethods.h"
32 
33 #if BOBJECTIMP_DEBUG
34 #include "escriptv.h"
35 #include <unordered_map>
36 #endif
37 
38 namespace Pol
39 {
40 namespace Bscript
41 {
46 
48 {
49  if ( get() )
50  return sizeof( BObjectRef ) + get()->sizeEstimate();
51  else
52  return sizeof( BObjectRef );
53 }
54 size_t BObject::sizeEstimate() const
55 {
56  if ( objimp.get() )
57  return sizeof( BObject ) + objimp.get()->sizeEstimate();
58  else
59  return sizeof( BObject );
60 }
61 
62 
80 BObjectImp* BObjectImp::unpack( std::istream& is )
81 {
82  char typech;
83  if ( is >> typech )
84  {
85  switch ( typech )
86  {
87  case 's':
88  return String::unpack( is );
89  case 'S':
90  return String::unpackWithLen( is );
91  case 'i':
92  return BLong::unpack( is );
93  case 'r':
94  return Double::unpack( is );
95  case 'u':
96  return UninitObject::create();
97  case 'a':
98  return ObjArray::unpack( is );
99  case 'd':
100  return BDictionary::unpack( is );
101  case 't':
102  return BStruct::unpack( is );
103  case 'e':
104  return BError::unpack( is );
105  case 'x':
106  return UninitObject::create();
107  case 'b':
108  return BBoolean::unpack( is );
109 
110  default:
111  return new BError( "Unknown object type '" + std::string( 1, typech ) + "'" );
112  }
113  }
114  else
115  {
116  return new BError( "Unable to extract type character" );
117  }
118 }
119 
120 BObjectImp* BObjectImp::unpack( const char* pstr )
121 {
122  ISTRINGSTREAM is( pstr );
123  return unpack( is );
124 }
125 
126 BObject::~BObject() = default;
127 
128 
130 {
131  return new BObject( objimp->copy() );
132 }
133 
134 bool BObject::operator!=( const BObject& obj ) const
135 {
136  return *objimp != *( obj.objimp );
137 }
138 bool BObject::operator==( const BObject& obj ) const
139 {
140  return *objimp == *( obj.objimp );
141 }
142 bool BObject::operator<( const BObject& obj ) const
143 {
144  return *objimp < *( obj.objimp );
145 }
146 bool BObject::operator<=( const BObject& obj ) const
147 {
148  return *objimp <= *( obj.objimp );
149 }
150 bool BObject::operator>( const BObject& obj ) const
151 {
152  return *objimp > *( obj.objimp );
153 }
154 bool BObject::operator>=( const BObject& obj ) const
155 {
156  return *objimp >= *( obj.objimp );
157 }
158 
160 #if BOBJECTIMP_DEBUG
161 typedef std::unordered_map<unsigned int, BObjectImp*> bobjectimps;
162 
163 
166 {
167  INFO_PRINT << imp->instance() << ": " << imp->getStringRep() << "\n";
168  return 0;
169 }
171 {
172  INFO_PRINT << "bobjectimp instances: " << bobjectimp_instances.size() << "\n";
173  for ( bobjectimps::iterator itr = bobjectimp_instances.begin(); itr != bobjectimp_instances.end();
174  ++itr )
175  {
176  display_bobjectimp_instance( ( *itr ).second );
177  }
178 }
179 #endif
180 
181 #if !INLINE_BOBJECTIMP_CTOR
182 unsigned int BObjectImp::instances_ = 0;
184 BObjectImp::BObjectImp( BObjectType type ) : type_( type ), instance_( 0 )
185 {
187  instance_ = instances_++;
190  bobjectimp_instances[instance_] = this;
191 }
192 
194 {
196  bobjectimp_instances.erase( instance_ );
198 }
199 #endif
200 
201 std::string BObjectImp::pack() const
202 {
203  OSTRINGSTREAM os;
204  packonto( os );
205  return OSTRINGSTREAM_STR( os );
206 }
207 
208 void BObjectImp::packonto( std::ostream& os ) const
209 {
210  os << "u";
211 }
212 
214 {
215  return getStringRep();
216 }
217 
219 {
220  switch ( typ )
221  {
222  case OTUnknown:
223  return "Unknown";
224  case OTUninit:
225  return "Uninit";
226  case OTString:
227  return "String";
228  case OTLong:
229  return "Integer";
230  case OTDouble:
231  return "Double";
232  case OTArray:
233  return "Array";
234  case OTApplicPtr:
235  return "ApplicPtr";
236  case OTApplicObj:
237  return "ApplicObj";
238  case OTError:
239  return "Error";
240  case OTDictionary:
241  return "Dictionary";
242  case OTStruct:
243  return "Struct";
244  case OTPacket:
245  return "Packet";
246  case OTBinaryFile:
247  return "BinaryFile";
248  case OTBoolean:
249  return "Boolean";
250  case OTFuncRef:
251  return "FunctionReference";
252  default:
253  return "Undefined";
254  }
255 }
256 
257 const char* BObjectImp::typeOf() const
258 {
259  return typestr( type_ );
260 }
261 
262 
264 {
265  return type_;
266 }
267 
272 bool BObjectImp::operator==( const BObjectImp& objimp ) const
273 {
274  return ( this == &objimp );
275 }
283 bool BObjectImp::operator<( const BObjectImp& objimp ) const
284 {
285  // Error an uninit are always lesser than any other type
286  if ( ( objimp.type_ == OTError || objimp.type_ == OTUninit ) && type_ != OTError &&
287  type_ != OTUninit )
288  return false;
289 
290  if ( type_ == objimp.type_ )
291  {
292  // This is "undefined behavior" and should be avoided by implementing
293  // comparison in child class
294  return ( this < &objimp );
295  }
296 
297  return type_ < objimp.type_;
298 }
302 bool BObjectImp::operator<=( const BObjectImp& objimp ) const
303 {
304  return *this == objimp || *this < objimp;
305 }
309 bool BObjectImp::operator>( const BObjectImp& objimp ) const
310 {
311  return !( *this == objimp || *this < objimp );
312 }
316 bool BObjectImp::operator>=( const BObjectImp& objimp ) const
317 {
318  return !( *this < objimp );
319 }
323 bool BObjectImp::operator!=( const BObjectImp& objimp ) const
324 {
325  return !( *this == objimp );
326 }
327 
328 BObjectImp* BObjectImp::array_assign( BObjectImp* /*idx*/, BObjectImp* /*target*/, bool /*copy*/ )
329 {
330  return this;
331 }
332 
333 BObjectRef BObjectImp::OperMultiSubscript( std::stack<BObjectRef>& indices )
334 {
335  BObjectRef index = indices.top();
336  indices.pop();
337  BObjectRef ref = OperSubscript( *index );
338  if ( indices.empty() )
339  return ref;
340  else
341  return ( *ref ).impptr()->OperMultiSubscript( indices );
342 }
343 
344 BObjectRef BObjectImp::OperMultiSubscriptAssign( std::stack<BObjectRef>& indices,
345  BObjectImp* target )
346 {
347  BObjectRef index = indices.top();
348  indices.pop();
349  if ( indices.empty() )
350  {
351  BObjectImp* imp = array_assign( ( *index ).impptr(), target, false );
352  return BObjectRef( imp );
353  }
354  else
355  {
356  BObjectRef ref = OperSubscript( *index );
357  return ( *ref ).impptr()->OperMultiSubscript( indices );
358  }
359 }
360 
362 {
363  return objimp.selfPlusObj( *this );
364 }
365 BObjectImp* BObjectImp::selfPlusObj( const BObjectImp& /*objimp*/ ) const
366 {
367  return copy();
368 }
369 BObjectImp* BObjectImp::selfPlusObj( const BLong& /*objimp*/ ) const
370 {
371  return copy();
372 }
373 BObjectImp* BObjectImp::selfPlusObj( const Double& /*objimp*/ ) const
374 {
375  return copy();
376 }
377 BObjectImp* BObjectImp::selfPlusObj( const String& /*objimp*/ ) const
378 {
379  return copy();
380 }
381 BObjectImp* BObjectImp::selfPlusObj( const ObjArray& /*objimp*/ ) const
382 {
383  return copy();
384 }
386 {
387  objimp.selfPlusObj( *this, obj );
388 }
389 void BObjectImp::selfPlusObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
390 {
391  //
392 }
393 void BObjectImp::selfPlusObj( BLong& /*objimp*/, BObject& /*obj*/ )
394 {
395  //
396 }
397 void BObjectImp::selfPlusObj( Double& /*objimp*/, BObject& /*obj*/ )
398 {
399  // obj.setimp( selfPlusObj(objimp) );
400 }
401 void BObjectImp::selfPlusObj( String& /*objimp*/, BObject& /*obj*/ )
402 {
403  // obj.setimp( selfPlusObj(objimp) );
404 }
405 void BObjectImp::selfPlusObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
406 {
407  // obj.setimp( selfPlusObj(objimp) );
408 }
409 
411 {
412  return objimp.selfMinusObj( *this );
413 }
414 BObjectImp* BObjectImp::selfMinusObj( const BObjectImp& /*objimp*/ ) const
415 {
416  return copy();
417 }
418 BObjectImp* BObjectImp::selfMinusObj( const BLong& /*objimp*/ ) const
419 {
420  return copy();
421 }
422 BObjectImp* BObjectImp::selfMinusObj( const Double& /*objimp*/ ) const
423 {
424  return copy();
425 }
426 BObjectImp* BObjectImp::selfMinusObj( const String& /*objimp*/ ) const
427 {
428  return copy();
429 }
430 BObjectImp* BObjectImp::selfMinusObj( const ObjArray& /*objimp*/ ) const
431 {
432  return copy();
433 }
435 {
436  objimp.selfMinusObj( *this, obj );
437 }
438 void BObjectImp::selfMinusObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
439 {
440  //
441 }
442 void BObjectImp::selfMinusObj( BLong& /*objimp*/, BObject& /*obj*/ )
443 {
444  //
445 }
446 void BObjectImp::selfMinusObj( Double& /*objimp*/, BObject& /*obj*/ )
447 {
448  //
449 }
450 void BObjectImp::selfMinusObj( String& /*objimp*/, BObject& /*obj*/ )
451 {
452  //
453 }
454 void BObjectImp::selfMinusObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
455 {
456  //
457 }
458 
460 {
461  return objimp.selfTimesObj( *this );
462 }
463 BObjectImp* BObjectImp::selfTimesObj( const BObjectImp& /*objimp*/ ) const
464 {
465  return copy();
466 }
467 BObjectImp* BObjectImp::selfTimesObj( const BLong& /*objimp*/ ) const
468 {
469  return copy();
470 }
471 BObjectImp* BObjectImp::selfTimesObj( const Double& /*objimp*/ ) const
472 {
473  return copy();
474 }
475 BObjectImp* BObjectImp::selfTimesObj( const String& /*objimp*/ ) const
476 {
477  return copy();
478 }
479 BObjectImp* BObjectImp::selfTimesObj( const ObjArray& /*objimp*/ ) const
480 {
481  return copy();
482 }
484 {
485  objimp.selfTimesObj( *this, obj );
486 }
487 void BObjectImp::selfTimesObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
488 {
489  //
490 }
491 void BObjectImp::selfTimesObj( BLong& /*objimp*/, BObject& /*obj*/ )
492 {
493  //
494 }
495 void BObjectImp::selfTimesObj( Double& /*objimp*/, BObject& /*obj*/ )
496 {
497  //
498 }
499 void BObjectImp::selfTimesObj( String& /*objimp*/, BObject& /*obj*/ )
500 {
501  //
502 }
503 void BObjectImp::selfTimesObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
504 {
505  //
506 }
507 
509 {
510  return objimp.selfDividedByObj( *this );
511 }
513 {
514  return copy();
515 }
516 BObjectImp* BObjectImp::selfDividedByObj( const BLong& /*objimp*/ ) const
517 {
518  return copy();
519 }
520 BObjectImp* BObjectImp::selfDividedByObj( const Double& /*objimp*/ ) const
521 {
522  return copy();
523 }
524 BObjectImp* BObjectImp::selfDividedByObj( const String& /*objimp*/ ) const
525 {
526  return copy();
527 }
529 {
530  return copy();
531 }
533 {
534  objimp.selfDividedByObj( *this, obj );
535 }
536 void BObjectImp::selfDividedByObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
537 {
538  //
539 }
540 void BObjectImp::selfDividedByObj( BLong& /*objimp*/, BObject& /*obj*/ )
541 {
542  //
543 }
544 void BObjectImp::selfDividedByObj( Double& /*objimp*/, BObject& /*obj*/ )
545 {
546  //
547 }
548 void BObjectImp::selfDividedByObj( String& /*objimp*/, BObject& /*obj*/ )
549 {
550  //
551 }
552 void BObjectImp::selfDividedByObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
553 {
554  //
555 }
556 
558 {
559  return objimp.selfModulusObj( *this );
560 }
562 {
563  return copy();
564 }
565 BObjectImp* BObjectImp::selfModulusObj( const BLong& /*objimp*/ ) const
566 {
567  return copy();
568 }
569 BObjectImp* BObjectImp::selfModulusObj( const Double& /*objimp*/ ) const
570 {
571  return copy();
572 }
573 BObjectImp* BObjectImp::selfModulusObj( const String& /*objimp*/ ) const
574 {
575  return copy();
576 }
577 BObjectImp* BObjectImp::selfModulusObj( const ObjArray& /*objimp*/ ) const
578 {
579  return copy();
580 }
582 {
583  objimp.selfModulusObj( *this, obj );
584 }
585 void BObjectImp::selfModulusObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
586 {
587  //
588 }
589 void BObjectImp::selfModulusObj( BLong& /*objimp*/, BObject& /*obj*/ )
590 {
591  //
592 }
593 void BObjectImp::selfModulusObj( Double& /*objimp*/, BObject& /*obj*/ )
594 {
595  //
596 }
597 void BObjectImp::selfModulusObj( String& /*objimp*/, BObject& /*obj*/ )
598 {
599  //
600 }
601 void BObjectImp::selfModulusObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
602 {
603  //
604 }
605 
607 {
608  return objimp.selfBitShiftRightObj( *this );
609 }
611 {
612  return copy();
613 }
615 {
616  return copy();
617 }
619 {
620  return copy();
621 }
623 {
624  return copy();
625 }
627 {
628  return copy();
629 }
631 {
632  objimp.selfBitShiftRightObj( *this, obj );
633 }
635 {
636  //
637 }
638 void BObjectImp::selfBitShiftRightObj( BLong& /*objimp*/, BObject& /*obj*/ )
639 {
640  //
641 }
642 void BObjectImp::selfBitShiftRightObj( Double& /*objimp*/, BObject& /*obj*/ )
643 {
644  //
645 }
646 void BObjectImp::selfBitShiftRightObj( String& /*objimp*/, BObject& /*obj*/ )
647 {
648  //
649 }
650 void BObjectImp::selfBitShiftRightObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
651 {
652  //
653 }
654 
656 {
657  return objimp.selfBitShiftLeftObj( *this );
658 }
660 {
661  return copy();
662 }
664 {
665  return copy();
666 }
668 {
669  return copy();
670 }
672 {
673  return copy();
674 }
676 {
677  return copy();
678 }
680 {
681  objimp.selfBitShiftLeftObj( *this, obj );
682 }
684 {
685  //
686 }
687 void BObjectImp::selfBitShiftLeftObj( BLong& /*objimp*/, BObject& /*obj*/ )
688 {
689  //
690 }
691 void BObjectImp::selfBitShiftLeftObj( Double& /*objimp*/, BObject& /*obj*/ )
692 {
693  //
694 }
695 void BObjectImp::selfBitShiftLeftObj( String& /*objimp*/, BObject& /*obj*/ )
696 {
697  //
698 }
699 void BObjectImp::selfBitShiftLeftObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
700 {
701  //
702 }
703 
705 {
706  return objimp.selfBitAndObj( *this );
707 }
709 {
710  return copy();
711 }
712 BObjectImp* BObjectImp::selfBitAndObj( const BLong& /*objimp*/ ) const
713 {
714  return copy();
715 }
716 BObjectImp* BObjectImp::selfBitAndObj( const Double& /*objimp*/ ) const
717 {
718  return copy();
719 }
720 BObjectImp* BObjectImp::selfBitAndObj( const String& /*objimp*/ ) const
721 {
722  return copy();
723 }
724 BObjectImp* BObjectImp::selfBitAndObj( const ObjArray& /*objimp*/ ) const
725 {
726  return copy();
727 }
729 {
730  objimp.selfBitAndObj( *this, obj );
731 }
732 void BObjectImp::selfBitAndObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
733 {
734  //
735 }
736 void BObjectImp::selfBitAndObj( BLong& /*objimp*/, BObject& /*obj*/ )
737 {
738  //
739 }
740 void BObjectImp::selfBitAndObj( Double& /*objimp*/, BObject& /*obj*/ )
741 {
742  //
743 }
744 void BObjectImp::selfBitAndObj( String& /*objimp*/, BObject& /*obj*/ )
745 {
746  //
747 }
748 void BObjectImp::selfBitAndObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
749 {
750  //
751 }
752 
754 {
755  return objimp.selfBitOrObj( *this );
756 }
757 BObjectImp* BObjectImp::selfBitOrObj( const BObjectImp& /*objimp*/ ) const
758 {
759  return copy();
760 }
761 BObjectImp* BObjectImp::selfBitOrObj( const BLong& /*objimp*/ ) const
762 {
763  return copy();
764 }
765 BObjectImp* BObjectImp::selfBitOrObj( const Double& /*objimp*/ ) const
766 {
767  return copy();
768 }
769 BObjectImp* BObjectImp::selfBitOrObj( const String& /*objimp*/ ) const
770 {
771  return copy();
772 }
773 BObjectImp* BObjectImp::selfBitOrObj( const ObjArray& /*objimp*/ ) const
774 {
775  return copy();
776 }
778 {
779  objimp.selfBitOrObj( *this, obj );
780 }
781 void BObjectImp::selfBitOrObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
782 {
783  //
784 }
785 void BObjectImp::selfBitOrObj( BLong& /*objimp*/, BObject& /*obj*/ )
786 {
787  //
788 }
789 void BObjectImp::selfBitOrObj( Double& /*objimp*/, BObject& /*obj*/ )
790 {
791  //
792 }
793 void BObjectImp::selfBitOrObj( String& /*objimp*/, BObject& /*obj*/ )
794 {
795  //
796 }
797 void BObjectImp::selfBitOrObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
798 {
799  //
800 }
801 
803 {
804  return objimp.selfBitXorObj( *this );
805 }
807 {
808  return copy();
809 }
810 BObjectImp* BObjectImp::selfBitXorObj( const BLong& /*objimp*/ ) const
811 {
812  return copy();
813 }
814 BObjectImp* BObjectImp::selfBitXorObj( const Double& /*objimp*/ ) const
815 {
816  return copy();
817 }
818 BObjectImp* BObjectImp::selfBitXorObj( const String& /*objimp*/ ) const
819 {
820  return copy();
821 }
822 BObjectImp* BObjectImp::selfBitXorObj( const ObjArray& /*objimp*/ ) const
823 {
824  return copy();
825 }
827 {
828  objimp.selfBitXorObj( *this, obj );
829 }
830 void BObjectImp::selfBitXorObj( BObjectImp& /*objimp*/, BObject& /*obj*/ )
831 {
832  //
833 }
834 void BObjectImp::selfBitXorObj( BLong& /*objimp*/, BObject& /*obj*/ )
835 {
836  //
837 }
838 void BObjectImp::selfBitXorObj( Double& /*objimp*/, BObject& /*obj*/ )
839 {
840  //
841 }
842 void BObjectImp::selfBitXorObj( String& /*objimp*/, BObject& /*obj*/ )
843 {
844  //
845 }
846 void BObjectImp::selfBitXorObj( ObjArray& /*objimp*/, BObject& /*obj*/ )
847 {
848  //
849 }
850 
852 {
853  return copy();
854 }
855 
856 void BObjectImp::operInsertInto( BObject& obj, const BObjectImp& /*objimp*/ )
857 {
858  obj.setimp( new BError( "Object is not a 'container'" ) );
859 }
860 
861 
863 {
864  objimp.selfPlusObjImp( *this, obj );
865  // obj.setimp( objimp.selfPlusObjImp( *this ) );
866 }
867 
869 {
870  objimp.selfMinusObjImp( *this, obj );
871  // obj.setimp( selfMinusObjImp( objimp ) );
872 }
873 
875 {
876  objimp.selfTimesObjImp( *this, obj );
877  // obj.setimp( selfTimesObjImp( objimp ) );
878 }
879 
881 {
882  objimp.selfDividedByObjImp( *this, obj );
883  // obj.setimp( selfDividedByObjImp( objimp ) );
884 }
885 
887 {
888  objimp.selfModulusObjImp( *this, obj );
889  // obj.setimp( selfModulusObjImp( objimp ) );
890 }
891 
893 {
894  BObjectImp* newobj = inverse();
895  return BObject( newobj );
896 }
897 
899 {
900  return UninitObject::create();
901 }
902 
904 {
905  return BObjectRef( copy() );
906 }
907 
908 /*
909  "All Objects are inherently good."
910  */
911 bool BObjectImp::isTrue( void ) const
912 {
913  return true;
914 }
915 
916 BObjectImp* BObjectImp::call_method( const char* methodname, Executor& /*ex*/ )
917 {
918  return new BError( std::string( "Method '" ) + methodname + "' not found" );
919 }
920 BObjectImp* BObjectImp::call_method_id( const int id, Executor& /*ex*/, bool /*forcebuiltin*/ )
921 {
922  OSTRINGSTREAM os;
923  os << "Method id '" << id << "' (" << getObjMethod( id )->code << ") not found";
924  return new BError( std::string( OSTRINGSTREAM_STR( os ) ) );
925 }
926 BObjectRef BObjectImp::set_member( const char* membername, BObjectImp* /*valueimp*/, bool /*copy*/ )
927 {
928  return BObjectRef( new BError( std::string( "Member '" ) + membername + "' not found" ) );
929 }
930 BObjectRef BObjectImp::get_member( const char* /*membername*/ )
931 {
932  return BObjectRef( new BError( "Object does not support members" ) );
933 }
935 {
936  ObjMember* memb = getObjMember( id );
937 
938  return get_member( memb->code );
939 }
940 BObjectRef BObjectImp::set_member_id( const int id, BObjectImp* valueimp, bool copy )
941 {
942  ObjMember* memb = getObjMember( id );
943 
944  return set_member( memb->code, valueimp, copy );
945 }
946 long BObjectImp::contains( const BObjectImp& /*imp*/ ) const
947 {
948  return 0;
949 }
950 
951 BObjectRef BObjectImp::operDotPlus( const char* /*name*/ )
952 {
953  return BObjectRef( new BError( "Operator .+ undefined" ) );
954 }
955 
956 BObjectRef BObjectImp::operDotMinus( const char* /*name*/ )
957 {
958  return BObjectRef( new BError( "Operator .- undefined" ) );
959 }
960 
961 BObjectRef BObjectImp::operDotQMark( const char* /*name*/ )
962 {
963  return BObjectRef( new BError( "Operator .? undefined" ) );
964 }
965 
968 
970 
972 {
973  return create();
974 }
975 
977 {
978  return sizeof( UninitObject );
979 }
980 
982 {
983  return false;
984 }
985 
989 bool UninitObject::operator==( const BObjectImp& imp ) const
990 {
991  return ( imp.isa( OTError ) || imp.isa( OTUninit ) );
992 }
993 
994 bool UninitObject::operator<( const BObjectImp& imp ) const
995 {
996  if ( imp.isa( OTError ) || imp.isa( OTUninit ) )
997  return false; // Because it's equal can't be lesser
998 
999  return true;
1000 }
1001 
1002 
1003 ObjArray::ObjArray() : BObjectImp( OTArray ), name_arr(), ref_arr() {}
1004 
1006 
1007 ObjArray::ObjArray( const ObjArray& copyfrom )
1008  : BObjectImp( copyfrom.type() ), name_arr( copyfrom.name_arr ), ref_arr( copyfrom.ref_arr )
1009 {
1010  deepcopy();
1011 }
1012 
1014 {
1015  for ( auto& elem : ref_arr )
1016  {
1017  if ( elem.get() )
1018  {
1019  /*
1020  NOTE: all BObjectRefs in an ObjArray reference BNamedObjects not BObjects
1021  HMMM, can this BNamedObject get destructed before we're done with it?
1022  No, we're making a copy, leaving the original be.
1023  (SO, bno's refcount should be >1 here)
1024  */
1025 
1026  BObject* bo = elem.get();
1027  elem.set( new BObject( bo->impptr()->copy() ) );
1028  }
1029  }
1030 }
1031 
1033 {
1034  auto nobj = new ObjArray( *this );
1035  return nobj;
1036 }
1037 
1039 {
1040  size_t size = sizeof( ObjArray );
1041  size += 3 * sizeof( BObjectRef* ) + ref_arr.capacity() * sizeof( BObjectRef );
1042  for ( const auto& elem : ref_arr )
1043  {
1044  size += elem.sizeEstimate();
1045  }
1046  size += 3 * sizeof( std::string* ) + name_arr.capacity() * sizeof( std::string );
1047  for ( const auto& elem : name_arr )
1048  {
1049  size += elem.capacity();
1050  }
1051  return size;
1052 }
1053 
1062 bool ObjArray::operator==( const BObjectImp& imp ) const
1063 {
1064  if ( !imp.isa( OTArray ) )
1065  return false;
1066 
1067  const ObjArray& thatarr = static_cast<const ObjArray&>( imp );
1068  if ( thatarr.ref_arr.size() != ref_arr.size() )
1069  return false;
1070 
1071  for ( unsigned i = 0; i < ref_arr.size(); ++i )
1072  {
1073  const BObjectRef& thisref = ref_arr[i];
1074  const BObjectRef& thatref = thatarr.ref_arr[i];
1075 
1076  const BObject* thisobj = thisref.get();
1077  const BObject* thatobj = thatref.get();
1078  if ( thisobj != NULL && thatobj != NULL )
1079  {
1080  const BObjectImp& thisimp = thisobj->impref();
1081  const BObjectImp& thatimp = thatobj->impref();
1082 
1083  if ( thisimp == thatimp )
1084  continue;
1085  else
1086  return false;
1087  }
1088  else if ( thisobj == NULL && thatobj == NULL )
1089  {
1090  continue;
1091  }
1092  else
1093  {
1094  return false;
1095  }
1096  }
1097  return true;
1098 }
1099 
1100 const BObjectImp* ObjArray::imp_at( unsigned index /* 1-based */ ) const
1101 {
1102  assert( index > 0 );
1103  if ( index > ref_arr.size() )
1104  return NULL;
1105  const BObjectRef& ref = ref_arr[index - 1];
1106  if ( ref.get() == NULL )
1107  return NULL;
1108  return ref.get()->impptr();
1109 }
1110 
1112 {
1113  if ( idx->isa( OTLong ) )
1114  {
1115  BLong& lng = (BLong&)*idx;
1116 
1117  unsigned index = (unsigned)lng.value();
1118  if ( index > ref_arr.size() )
1119  ref_arr.resize( index );
1120  else if ( index <= 0 )
1121  return new BError( "Array index out of bounds" );
1122 
1123  BObjectRef& ref = ref_arr[index - 1];
1124  BObject* refobj = ref.get();
1125 
1126  BObjectImp* new_target = copy ? target->copy() : target;
1127 
1128  if ( refobj != NULL )
1129  {
1130  refobj->setimp( new_target );
1131  }
1132  else
1133  {
1134  ref.set( new BObject( new_target ) );
1135  }
1136  return ref->impptr();
1137  }
1138  else
1139  {
1140  return UninitObject::create();
1141  }
1142 }
1143 
1144 void ObjArray::operInsertInto( BObject& /*obj*/, const BObjectImp& objimp )
1145 {
1146  ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1147 }
1148 
1150 {
1151  std::unique_ptr<ObjArray> result( new ObjArray( *this ) );
1152  result->ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1153  return result.release();
1154 }
1155 BObjectImp* ObjArray::selfPlusObj( const BLong& objimp ) const
1156 {
1157  std::unique_ptr<ObjArray> result( new ObjArray( *this ) );
1158  result->ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1159  return result.release();
1160 }
1161 BObjectImp* ObjArray::selfPlusObj( const Double& objimp ) const
1162 {
1163  std::unique_ptr<ObjArray> result( new ObjArray( *this ) );
1164  result->ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1165  return result.release();
1166 }
1167 BObjectImp* ObjArray::selfPlusObj( const String& objimp ) const
1168 {
1169  std::unique_ptr<ObjArray> result( new ObjArray( *this ) );
1170  result->ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1171  return result.release();
1172 }
1173 
1175 {
1176  std::unique_ptr<ObjArray> result( new ObjArray( *this ) );
1177 
1178  for ( const auto& elem : objimp.ref_arr )
1179  {
1180  if ( elem.get() )
1181  {
1182  /*
1183  NOTE: all BObjectRefs in an ObjArray reference BNamedObjects not BObjects
1184  HMMM, can this BNamedObject get destructed before we're done with it?
1185  No, we're making a copy, leaving the original be.
1186  (SO, bno's refcount should be >1 here)
1187  */
1188  BObject* bo = elem.get();
1189 
1190  result->ref_arr.push_back( BObjectRef( new BObject( ( *bo )->copy() ) ) );
1191  }
1192  else
1193  {
1194  result->ref_arr.push_back( BObjectRef() );
1195  }
1196  }
1197  return result.release();
1198 }
1199 
1201 {
1202  return other.selfPlusObj( *this );
1203 }
1205 {
1206  objimp.selfPlusObj( *this, obj );
1207 }
1208 void ObjArray::selfPlusObj( BObjectImp& objimp, BObject& /*obj*/ )
1209 {
1210  ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1211 }
1212 void ObjArray::selfPlusObj( BLong& objimp, BObject& /*obj*/ )
1213 {
1214  ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1215 }
1216 void ObjArray::selfPlusObj( Double& objimp, BObject& /*obj*/ )
1217 {
1218  ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1219 }
1220 void ObjArray::selfPlusObj( String& objimp, BObject& /*obj*/ )
1221 {
1222  ref_arr.push_back( BObjectRef( new BObject( objimp.copy() ) ) );
1223 }
1224 void ObjArray::selfPlusObj( ObjArray& objimp, BObject& /*obj*/ )
1225 {
1226  for ( const_iterator itr = objimp.ref_arr.begin(), itrend = objimp.ref_arr.end(); itr != itrend;
1227  ++itr )
1228  {
1229  if ( itr->get() )
1230  {
1231  /*
1232  NOTE: all BObjectRefs in an ObjArray reference BNamedObjects not BObjects
1233  HMMM, can this BNamedObject get destructed before we're done with it?
1234  No, we're making a copy, leaving the original be.
1235  (SO, bno's refcount should be >1 here)
1236  */
1237  BObject* bo = itr->get();
1238 
1239  ref_arr.push_back( BObjectRef( new BObject( ( *bo )->copy() ) ) );
1240  }
1241  else
1242  {
1243  ref_arr.push_back( BObjectRef() );
1244  }
1245  }
1246 }
1247 
1248 BObjectRef ObjArray::OperMultiSubscript( std::stack<BObjectRef>& indices )
1249 {
1250  BObjectRef start_ref = indices.top();
1251  indices.pop();
1252  BObjectRef length_ref = indices.top();
1253  indices.pop();
1254 
1255  BObject& length_obj = *length_ref;
1256  BObject& start_obj = *start_ref;
1257 
1258  BObjectImp& length = length_obj.impref();
1259  BObjectImp& start = start_obj.impref();
1260 
1261  // first deal with the start position.
1262  // return BObjectRef(new BError( "Subscript out of range" ));
1263 
1264  unsigned index;
1265  if ( start.isa( OTLong ) )
1266  {
1267  BLong& lng = (BLong&)start;
1268  index = (unsigned)lng.value();
1269  if ( index == 0 || index > ref_arr.size() )
1270  return BObjectRef( new BError( "Array start index out of bounds" ) );
1271  }
1272  else
1273  return BObjectRef( copy() );
1274 
1275  // now the end index
1276 
1277  unsigned end;
1278  if ( length.isa( OTLong ) )
1279  {
1280  BLong& lng = (BLong&)length;
1281  end = (unsigned)lng.value();
1282  if ( end == 0 || end > ref_arr.size() )
1283  return BObjectRef( new BError( "Array end index out of bounds" ) );
1284  }
1285  else
1286  return BObjectRef( copy() );
1287 
1288  auto str = new ObjArray();
1289 
1290 
1291  // std::unique_ptr<ObjArray> result (new ObjArray());
1292  unsigned i = 0;
1293  for ( const_iterator itr = ref_arr.begin(), itrend = ref_arr.end(); itr != itrend; ++itr )
1294  {
1295  if ( ++i < index )
1296  continue;
1297  if ( i > end )
1298  break;
1299  if ( itr->get() )
1300  {
1301  BObject* bo = itr->get();
1302  str->ref_arr.push_back( BObjectRef( new BObject( ( *bo )->copy() ) ) );
1303  }
1304  else
1305  {
1306  str->ref_arr.push_back( BObjectRef() );
1307  }
1308  }
1309  /*
1310  for (unsigned i = index; i < end; i++) {
1311  BObject *bo = ref_arr[i];
1312  if (bo != 0)
1313  str->ref_arr.push_back( BObjectRef( new BObject( (*bo)->copy() ) ) );
1314  else
1315  result->ref_arr.push_back( BObjectRef() );
1316  } */
1317  // return result.release();
1318  return BObjectRef( str );
1319 }
1320 
1322 {
1323  const BObjectImp& right = rightobj.impref();
1324  if ( right.isa( OTLong ) ) // vector
1325  {
1326  BLong& lng = (BLong&)right;
1327 
1328  unsigned index = (unsigned)lng.value();
1329  if ( index > ref_arr.size() )
1330  {
1331  return BObjectRef( new BError( "Array index out of bounds" ) );
1332  }
1333  else if ( index <= 0 )
1334  return BObjectRef( new BError( "Array index out of bounds" ) );
1335 
1336  BObjectRef& ref = ref_arr[index - 1];
1337  if ( ref.get() == NULL )
1338  ref.set( new BObject( UninitObject::create() ) );
1339  return ref;
1340  }
1341  else if ( right.isa( OTString ) )
1342  {
1343  // TODO: search for named variables (structure members)
1344  return BObjectRef( copy() );
1345  }
1346  else
1347  {
1348  // TODO: crap out
1349  return BObjectRef( copy() );
1350  }
1351 }
1352 
1353 BObjectRef ObjArray::get_member( const char* membername )
1354 {
1355  int i = 0;
1356  for ( const_name_iterator itr = name_arr.begin(), end = name_arr.end(); itr != end; ++itr, ++i )
1357  {
1358  const std::string& name = ( *itr );
1359  if ( stricmp( name.c_str(), membername ) == 0 )
1360  {
1361  return ref_arr[i];
1362  }
1363  }
1364 
1365  return BObjectRef( UninitObject::create() );
1366 }
1367 
1368 BObjectRef ObjArray::set_member( const char* membername, BObjectImp* valueimp, bool copy )
1369 {
1370  int i = 0;
1371  for ( const_name_iterator itr = name_arr.begin(), end = name_arr.end(); itr != end; ++itr, ++i )
1372  {
1373  const std::string& name = ( *itr );
1374  if ( stricmp( name.c_str(), membername ) == 0 )
1375  {
1376  BObjectImp* target = copy ? valueimp->copy() : valueimp;
1377  ref_arr[i].get()->setimp( target );
1378  return ref_arr[i];
1379  }
1380  }
1381  return BObjectRef( UninitObject::create() );
1382 }
1383 
1385 {
1386  for ( auto& elem : name_arr )
1387  {
1388  if ( stricmp( name, elem.c_str() ) == 0 )
1389  {
1390  return BObjectRef( new BError( "Member already exists" ) );
1391  }
1392  }
1393  name_arr.push_back( name );
1394  auto pnewobj = new BObject( UninitObject::create() );
1395  ref_arr.push_back( BObjectRef( pnewobj ) );
1396  return BObjectRef( pnewobj );
1397 }
1398 
1400 {
1401  ref_arr.push_back( BObjectRef( new BObject( imp ) ) );
1402 }
1403 
1404 std::string ObjArray::getStringRep() const
1405 {
1406  OSTRINGSTREAM os;
1407  os << "{ ";
1408  bool any = false;
1409  for ( const auto& elem : ref_arr )
1410  {
1411  if ( any )
1412  os << ", ";
1413  else
1414  any = true;
1415 
1416  BObject* bo = elem.get();
1417 
1418  if ( bo != NULL )
1419  {
1420  std::string tmp = bo->impptr()->getStringRep();
1421  os << tmp;
1422  }
1423  }
1424  os << " }";
1425 
1426  return OSTRINGSTREAM_STR( os );
1427 }
1428 
1429 long ObjArray::contains( const BObjectImp& imp ) const
1430 {
1431  for ( auto itr = ref_arr.begin(), end = ref_arr.end(); itr != end; ++itr )
1432  {
1433  if ( itr->get() )
1434  {
1435  BObject* bo = ( itr->get() );
1436  if ( bo == NULL )
1437  {
1438  INFO_PRINT << Clib::scripts_thread_script << " - '" << imp
1439  << " in array{}' check. Invalid data at index " << ( itr - ref_arr.begin() ) + 1
1440  << "\n";
1441  continue;
1442  }
1443  else if ( *( bo->impptr() ) == imp )
1444  {
1445  return ( static_cast<long>( ( itr - ref_arr.begin() ) + 1 ) );
1446  }
1447  }
1448  }
1449  return 0;
1450 }
1451 
1453 {
1454 public:
1455  bool operator()( const BObjectRef& x1, const BObjectRef& x2 ) const
1456  {
1457  const BObject* b1 = x1.get();
1458  const BObject* b2 = x2.get();
1459  if ( b1 == NULL || b2 == NULL )
1460  return ( &x1 < &x2 );
1461 
1462  const BObject& r1 = *b1;
1463  const BObject& r2 = *b2;
1464  return ( r1 < r2 );
1465  }
1466 };
1467 
1468 BObjectImp* ObjArray::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
1469 {
1470  switch ( id )
1471  {
1472  case MTH_SIZE:
1473  if ( ex.numParams() == 0 )
1474  return new BLong( static_cast<int>( ref_arr.size() ) );
1475  else
1476  return new BError( "array.size() doesn't take parameters." );
1477 
1478  case MTH_ERASE:
1479  if ( name_arr.empty() )
1480  {
1481  if ( ex.numParams() == 1 )
1482  {
1483  int idx;
1484  if ( ex.getParam( 0, idx, 1, static_cast<int>( ref_arr.size() ) ) ) // 1-based index
1485  {
1486  ref_arr.erase( ref_arr.begin() + idx - 1 );
1487  return new BLong( 1 );
1488  }
1489  else
1490  {
1491  return NULL;
1492  }
1493  }
1494  else
1495  return new BError( "array.erase(index) requires a parameter." );
1496  }
1497  break;
1498  case MTH_EXISTS:
1499  if ( name_arr.empty() )
1500  {
1501  if ( ex.numParams() == 1 )
1502  {
1503  int idx;
1504  if ( ex.getParam( 0, idx ) && idx >= 0 )
1505  {
1506  bool exists = ( idx <= (int)ref_arr.size() );
1507  return new BLong( exists ? 1 : 0 );
1508  }
1509  else
1510  {
1511  return new BError( "Invalid parameter type" );
1512  }
1513  }
1514  else
1515  return new BError( "array.exists(index) requires a parameter." );
1516  }
1517  break;
1518  case MTH_INSERT:
1519  if ( name_arr.empty() )
1520  {
1521  if ( ex.numParams() == 2 )
1522  {
1523  int idx;
1524  BObjectImp* imp = ex.getParamImp( 1 );
1525  if ( ex.getParam( 0, idx, 1, static_cast<int>( ref_arr.size() + 1 ) ) &&
1526  imp != NULL ) // 1-based index
1527  {
1528  --idx;
1529  BObjectRef tmp;
1530  ref_arr.insert( ref_arr.begin() + idx, tmp );
1531  BObjectRef& ref = ref_arr[idx];
1532  ref.set( new BObject( imp->copy() ) );
1533  }
1534  else
1535  {
1536  return new BError( "Invalid parameter type" );
1537  }
1538  }
1539  else
1540  return new BError( "array.insert(index,value) requires two parameters." );
1541  }
1542  break;
1543  case MTH_SHRINK:
1544  if ( name_arr.empty() )
1545  {
1546  if ( ex.numParams() == 1 )
1547  {
1548  int idx;
1549  if ( ex.getParam( 0, idx, 0, static_cast<int>( ref_arr.size() ) ) ) // 1-based index
1550  {
1551  ref_arr.erase( ref_arr.begin() + idx, ref_arr.end() );
1552  return new BLong( 1 );
1553  }
1554  else
1555  {
1556  return new BError( "Invalid parameter type" );
1557  }
1558  }
1559  else
1560  return new BError( "array.shrink(nelems) requires a parameter." );
1561  }
1562  break;
1563  case MTH_APPEND:
1564  if ( name_arr.empty() )
1565  {
1566  if ( ex.numParams() == 1 )
1567  {
1568  BObjectImp* imp = ex.getParamImp( 0 );
1569  if ( imp )
1570  {
1571  ref_arr.push_back( BObjectRef( new BObject( imp->copy() ) ) );
1572 
1573  return new BLong( 1 );
1574  }
1575  else
1576  {
1577  return new BError( "Invalid parameter type" );
1578  }
1579  }
1580  else
1581  return new BError( "array.append(value) requires a parameter." );
1582  }
1583  break;
1584  case MTH_REVERSE:
1585  if ( name_arr.empty() )
1586  {
1587  if ( ex.numParams() == 0 )
1588  {
1589  reverse( ref_arr.begin(), ref_arr.end() );
1590  return new BLong( 1 );
1591  }
1592  else
1593  return new BError( "array.reverse() doesn't take parameters." );
1594  }
1595  break;
1596  case MTH_SORT:
1597  if ( name_arr.empty() )
1598  {
1599  if ( ex.numParams() == 0 )
1600  {
1601  sort( ref_arr.begin(), ref_arr.end(), objref_cmp() );
1602  return new BLong( 1 );
1603  }
1604  else if ( ex.numParams() == 1 )
1605  {
1606  int sub_index;
1607  if ( !ex.getParam( 0, sub_index ) )
1608  return new BError( "Invalid parameter type" );
1609  if ( sub_index < 1 )
1610  return new BError( "Invalid sub_index value" );
1611  for ( const auto& ref : ref_arr )
1612  {
1613  if ( ref.get() == nullptr || !ref.get()->isa( OTArray ) )
1614  return new BError( "Invalid array" );
1615  auto sub_arr = static_cast<ObjArray*>( ref.get()->impptr() );
1616  if ( sub_arr->ref_arr.size() < static_cast<size_t>( sub_index ) )
1617  return new BError( "Subindex to large" );
1618  }
1619  sort( ref_arr.begin(), ref_arr.end(),
1620  [=]( const BObjectRef& x1, const BObjectRef& x2 ) -> bool {
1621  auto sub_arr1 = static_cast<ObjArray*>( x1.get()->impptr() );
1622  auto sub_arr2 = static_cast<ObjArray*>( x2.get()->impptr() );
1623  auto sub1 = sub_arr1->ref_arr[sub_index - 1];
1624  auto sub2 = sub_arr2->ref_arr[sub_index - 1];
1625  const BObject* b1 = sub1.get();
1626  const BObject* b2 = sub2.get();
1627  if ( b1 == nullptr || b2 == nullptr )
1628  return ( &x1 < &x2 );
1629  return ( *b1 < *b2 );
1630  } );
1631  return new BLong( 1 );
1632  }
1633  else
1634  return new BError( "array.sort(sub_index=0) takes at most one parameter." );
1635  }
1636  break;
1637  case MTH_RANDOMENTRY:
1638  if ( name_arr.empty() )
1639  {
1640  if ( ex.numParams() == 0 )
1641  {
1642  if ( !ref_arr.empty() )
1643  {
1644  const BObjectRef& ref =
1645  ref_arr[Clib::random_int( static_cast<int>( ref_arr.size() ) - 1 )];
1646  if ( ref.get() == NULL )
1647  return NULL;
1648  return ref.get()->impptr();
1649  }
1650  }
1651  else
1652  return new BError( "array.randomentry() doesn't take parameters." );
1653  }
1654  break;
1655  case MTH_CYCLE:
1656  if ( name_arr.empty() )
1657  {
1658  int shift_by;
1659 
1660  if ( ex.numParams() > 0 )
1661  {
1662  if ( !ex.getParam( 0, shift_by ) )
1663  return new BError( "Invalid parameter type" );
1664  if ( shift_by == 0 )
1665  return new BLong( 0 );
1666  }
1667  else
1668  shift_by = 1;
1669 
1670  if ( ref_arr.empty() || std::abs( shift_by ) > (int)ref_arr.size() )
1671  return new BLong( 0 );
1672 
1673  if ( shift_by > 0 )
1674  std::rotate( ref_arr.begin(), ref_arr.end() - shift_by, ref_arr.end() );
1675  else
1676  std::rotate( ref_arr.begin(), ref_arr.begin() - shift_by, ref_arr.end() );
1677 
1678  return new BLong( 1 );
1679  }
1680  break;
1681 
1682  case MTH_SORTEDINSERT:
1683  {
1684  if ( !name_arr.empty() )
1685  break;
1686  if ( ex.numParams() == 0 )
1687  return new BError(
1688  "array.sorted_insert(obj, sub_index:=0, reverse:=0) takes at least one parameter." );
1689  BObjectImp* imp = ex.getParamImp( 0 );
1690  if ( !imp )
1691  return new BError( "Invalid parameter type" );
1692  bool reverse = false;
1693  int sub_index = 0;
1694  if ( ex.numParams() >= 2 )
1695  {
1696  if ( !ex.getParam( 1, sub_index ) )
1697  return new BError( "Invalid parameter type" );
1698  if ( sub_index < 0 )
1699  return new BError( "Invalid sub_index value" );
1700  }
1701  if ( ex.numParams() >= 3 )
1702  {
1703  int reverseparam;
1704  if ( !ex.getParam( 2, reverseparam ) )
1705  return new BError( "Invalid parameter type" );
1706  reverse = reverseparam != 0;
1707  }
1708  BObjectRef item( new BObject( imp->copy() ) );
1709  if ( !sub_index )
1710  {
1711  if ( reverse )
1712  {
1713  ref_arr.insert( std::lower_bound( ref_arr.begin(), ref_arr.end(), item,
1714  []( const BObjectRef& x1, const BObjectRef& x2 ) -> bool {
1715  const BObject* b1 = x1.get();
1716  const BObject* b2 = x2.get();
1717  if ( b1 == nullptr || b2 == nullptr )
1718  return ( &x1 > &x2 );
1719  const BObject& r1 = *b1;
1720  const BObject& r2 = *b2;
1721  return ( r1 > r2 );
1722  } ),
1723  item );
1724  }
1725  else
1726  {
1727  ref_arr.insert( std::upper_bound( ref_arr.begin(), ref_arr.end(), item, objref_cmp() ),
1728  item );
1729  }
1730  }
1731  else
1732  {
1733  auto cmp_func = [=]( const BObjectRef& x1, const BObjectRef& x2 ) -> bool {
1734  if ( x1.get() == nullptr || !x1.get()->isa( OTArray ) )
1735  return false;
1736  if ( x2.get() == nullptr || !x2.get()->isa( OTArray ) )
1737  return false;
1738  auto sub_arr1 = static_cast<ObjArray*>( x1.get()->impptr() );
1739  auto sub_arr2 = static_cast<ObjArray*>( x2.get()->impptr() );
1740  if ( sub_arr1->ref_arr.size() < static_cast<size_t>( sub_index ) )
1741  return false;
1742  if ( sub_arr2->ref_arr.size() < static_cast<size_t>( sub_index ) )
1743  return false;
1744  auto sub1 = sub_arr1->ref_arr[sub_index - 1];
1745  auto sub2 = sub_arr2->ref_arr[sub_index - 1];
1746  const BObject* b1 = sub1.get();
1747  const BObject* b2 = sub2.get();
1748  if ( !reverse )
1749  {
1750  if ( b1 == nullptr || b2 == nullptr )
1751  return ( &x1 < &x2 );
1752  return ( *b1 < *b2 );
1753  }
1754  else
1755  {
1756  if ( b1 == nullptr || b2 == nullptr )
1757  return ( &x1 > &x2 );
1758  return ( *b1 > *b2 );
1759  }
1760  };
1761  if ( reverse )
1762  {
1763  ref_arr.insert( std::lower_bound( ref_arr.begin(), ref_arr.end(), item, cmp_func ), item );
1764  }
1765  else
1766  {
1767  ref_arr.insert( std::upper_bound( ref_arr.begin(), ref_arr.end(), item, cmp_func ), item );
1768  }
1769  }
1770  return new BLong( 1 );
1771  break;
1772  }
1773  default:
1774  return NULL;
1775  }
1776  return NULL;
1777 }
1778 
1779 BObjectImp* ObjArray::call_method( const char* methodname, Executor& ex )
1780 {
1781  ObjMethod* objmethod = getKnownObjMethod( methodname );
1782  if ( objmethod != NULL )
1783  return this->call_method_id( objmethod->id, ex );
1784  else
1785  return NULL;
1786 }
1787 
1788 void ObjArray::packonto( std::ostream& os ) const
1789 {
1790  os << "a" << ref_arr.size() << ":";
1791  for ( const auto& elem : ref_arr )
1792  {
1793  if ( elem.get() )
1794  {
1795  BObject* bo = elem.get();
1796  bo->impptr()->packonto( os );
1797  }
1798  else
1799  {
1800  os << "x";
1801  }
1802  }
1803 }
1804 
1805 BObjectImp* ObjArray::unpack( std::istream& is )
1806 {
1807  unsigned arrsize;
1808  char colon;
1809  if ( !( is >> arrsize >> colon ) )
1810  {
1811  return new BError( "Unable to unpack array elemcount" );
1812  }
1813  if ( (int)arrsize < 0 )
1814  {
1815  return new BError( "Unable to unpack array elemcount. Invalid length!" );
1816  }
1817  if ( colon != ':' )
1818  {
1819  return new BError( "Unable to unpack array elemcount. Bad format. Colon not found!" );
1820  }
1821  std::unique_ptr<ObjArray> arr( new ObjArray );
1822  arr->ref_arr.resize( arrsize );
1823  for ( unsigned i = 0; i < arrsize; ++i )
1824  {
1825  BObjectImp* imp = BObjectImp::unpack( is );
1826  if ( imp != NULL && !imp->isa( OTUninit ) )
1827  {
1828  arr->ref_arr[i].set( new BObject( imp ) );
1829  }
1830  }
1831  return arr.release();
1832 }
1833 
1834 BApplicPtr::BApplicPtr( const BApplicObjType* pointer_type, void* ptr )
1835  : BObjectImp( OTApplicPtr ), ptr_( ptr ), pointer_type_( pointer_type )
1836 {
1837 }
1838 
1840 {
1841  return new BApplicPtr( pointer_type_, ptr_ );
1842 }
1843 
1845 {
1846  return sizeof( BApplicPtr );
1847 }
1848 
1850 {
1851  return pointer_type_;
1852 }
1853 
1854 void* BApplicPtr::ptr() const
1855 {
1856  return ptr_;
1857 }
1858 
1859 std::string BApplicPtr::getStringRep() const
1860 {
1861  return "<appptr>";
1862 }
1863 
1864 
1865 void BApplicPtr::printOn( std::ostream& os ) const
1866 {
1867  os << "<appptr>";
1868 }
1869 
1870 std::string BApplicObjBase::getStringRep() const
1871 {
1872  return std::string( "<appobj:" ) + typeOf() + ">";
1873 }
1874 
1875 void BApplicObjBase::printOn( std::ostream& os ) const
1876 {
1877  os << getStringRep();
1878 }
1879 
1880 #if BOBJECTIMP_DEBUG
1881 BBoolean::BBoolean( bool bval ) : BObjectImp( OTBoolean ), bval_( bval ) {}
1883 #endif
1884 
1885 BObjectImp* BBoolean::unpack( std::istream& is )
1886 {
1887  int lv;
1888  if ( is >> lv )
1889  {
1890  return new BBoolean( lv != 0 );
1891  }
1892  else
1893  {
1894  return new BError( "Error extracting Boolean value" );
1895  }
1896 }
1897 
1898 void BBoolean::packonto( std::ostream& os ) const
1899 {
1900  os << "b" << ( bval_ ? 1 : 0 );
1901 }
1902 
1903 std::string BBoolean::pack() const
1904 {
1905  OSTRINGSTREAM os;
1906  os << "b" << ( bval_ ? 1 : 0 );
1907  return OSTRINGSTREAM_STR( os );
1908 }
1909 
1911 {
1912  return new BBoolean( *this );
1913 }
1914 
1916 {
1917  return sizeof( BBoolean );
1918 }
1919 
1920 bool BBoolean::isTrue() const
1921 {
1922  return bval_;
1923 }
1924 
1925 bool BBoolean::operator==( const BObjectImp& objimp ) const
1926 {
1927  return bval_ == objimp.isTrue();
1928 }
1929 
1930 std::string BBoolean::getStringRep() const
1931 {
1932  return bval_ ? "true" : "false";
1933 }
1934 
1935 
1936 BFunctionRef::BFunctionRef( int progcounter, int param_count, const std::string& scriptname )
1937  : BObjectImp( OTFuncRef ),
1938  pc_( progcounter ),
1939  num_params_( param_count ),
1940  script_name_( scriptname )
1941 {
1942 }
1943 
1946 {
1947 }
1948 
1950 {
1951  return new BFunctionRef( *this );
1952 }
1953 
1955 {
1956  return sizeof( BFunctionRef );
1957 }
1958 
1960 {
1961  return false;
1962 }
1963 
1964 bool BFunctionRef::operator==( const BObjectImp& /*objimp*/ ) const
1965 {
1966  return false;
1967 }
1968 
1969 std::string BFunctionRef::getStringRep() const
1970 {
1971  return "FunctionObject";
1972 }
1973 
1974 BObjectImp* BFunctionRef::call_method( const char* methodname, Executor& ex )
1975 {
1976  ObjMethod* objmethod = getKnownObjMethod( methodname );
1977  if ( objmethod != nullptr )
1978  return call_method_id( objmethod->id, ex );
1979  return nullptr;
1980 }
1981 
1982 bool BFunctionRef::validCall( const int id, Executor& ex, Instruction* inst ) const
1983 {
1984  if ( id != MTH_CALL )
1985  return false;
1986  if ( ex.numParams() != static_cast<size_t>( num_params_ ) )
1987  return false;
1988  if ( ex.scriptname() != script_name_ )
1989  return false;
1990  inst->func = &Executor::ins_nop;
1991  inst->token.lval = pc_;
1992  return true;
1993 }
1994 
1995 bool BFunctionRef::validCall( const char* methodname, Executor& ex, Instruction* inst ) const
1996 {
1997  ObjMethod* objmethod = getKnownObjMethod( methodname );
1998  if ( objmethod == nullptr )
1999  return false;
2000  return validCall( objmethod->id, ex, inst );
2001 }
2002 
2003 BObjectImp* BFunctionRef::call_method_id( const int id, Executor& /*ex*/, bool /*forcebuiltin*/ )
2004 {
2005  switch ( id )
2006  {
2007  case MTH_CALL:
2008  return nullptr; // handled directly
2009  default:
2010  return nullptr;
2011  }
2012 }
2013 }
2014 }
virtual BObjectImp * selfBitShiftRightObjImp(const BObjectImp &objimp) const
Definition: object.cpp:606
virtual BObjectImp * selfBitOrObj(const BObjectImp &objimp) const
Definition: object.cpp:757
unsigned char u8
Definition: rawtypes.h:25
virtual BObjectRef get_member(const char *membername)
Definition: object.cpp:930
std::atomic< int > eobject_imp_count
static BObjectImp * unpack(std::istream &is)
Definition: object.cpp:1805
Clib::fixed_allocator< sizeof(Double), 256 > double_alloc
Definition: object.cpp:45
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1930
virtual std::string getStringRep() const =0
BObject * clone() const
Definition: object.cpp:129
BObjectType type() const
Definition: bobject.h:358
int value() const
Definition: bobject.h:592
virtual BObjectImp * bitnot() const
Definition: object.cpp:851
void set(BObject *obj)
Definition: bobject.h:456
virtual BObjectImp * selfBitAndObjImp(const BObjectImp &objimp) const
Definition: object.cpp:704
virtual BObjectImp * selfTimesObj(const BObjectImp &objimp) const
Definition: object.cpp:463
virtual bool operator==(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:1925
std::string scripts_thread_script
Definition: passert.cpp:36
bool isa(BObjectType type) const
Definition: bobject.h:353
virtual BObjectImp * selfBitOrObjImp(const BObjectImp &objimp) const
Definition: object.cpp:753
void ins_nop(const Instruction &ins)
Definition: executor.cpp:2574
BApplicPtr(const BApplicObjType *pointer_type, void *ptr)
Definition: object.cpp:1834
virtual BObjectImp * selfBitXorObj(const BObjectImp &objimp) const
Definition: object.cpp:806
virtual BObjectImp * selfBitShiftRightObj(const BObjectImp &objimp) const
Definition: object.cpp:610
virtual long contains(const BObjectImp &objimp) const
Definition: object.cpp:946
const BApplicObjType * pointer_type_
Definition: bobject.h:870
std::atomic< int > eobject_imp_constructions
virtual BObjectRef operDotPlus(const char *name) POL_OVERRIDE
Definition: object.cpp:1384
size_t sizeEstimate() const
Definition: object.cpp:47
T * get() const
Definition: refptr.h:176
virtual long contains(const BObjectImp &imp) const POL_OVERRIDE
Definition: object.cpp:1429
virtual BObjectImp * inverse() const
Definition: object.cpp:898
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: object.cpp:1038
static BObjectImp * unpack(const char *pstr)
Definition: blong.cpp:46
virtual bool isTrue() const POL_OVERRIDE
Definition: object.cpp:1959
virtual BObjectImp * copy() const =0
virtual BObjectImp * array_assign(BObjectImp *idx, BObjectImp *target, bool copy) POL_OVERRIDE
Definition: object.cpp:1111
#define OSTRINGSTREAM_STR(x)
Definition: stlutil.h:76
bool operator>=(const BObject &obj) const
Definition: object.cpp:154
virtual bool operator!=(const BObjectImp &objimp) const
Definition: object.cpp:323
virtual BObjectImp * selfBitShiftLeftObj(const BObjectImp &objimp) const
Definition: object.cpp:659
virtual u8 typeOfInt() const
Definition: object.cpp:263
virtual void operInsertInto(BObject &obj, const BObjectImp &objimp)
Definition: object.cpp:856
unsigned int instance() const
Definition: bobject.h:137
virtual BObjectImp * call_method_id(const int id, Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: object.cpp:1468
virtual BObjectImp * call_method(const char *methodname, Executor &ex) POL_OVERRIDE
Definition: object.cpp:1974
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:666
virtual void operModulusEqual(BObject &obj, BObjectImp &objimp)
Definition: object.cpp:886
Clib::fixed_allocator< sizeof(BLong), 256 > blong_alloc
Definition: object.cpp:44
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:1032
virtual BObjectImp * selfBitAndObj(const BObjectImp &objimp) const
Definition: object.cpp:708
virtual void packonto(std::ostream &os) const POL_OVERRIDE
Definition: object.cpp:1788
static BObjectImp * unpack(std::istream &is)
Definition: bstruct.cpp:93
virtual std::string pack() const
Definition: object.cpp:201
virtual BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: object.cpp:1353
virtual BObjectRef operDotPlus(const char *name)
Definition: object.cpp:951
BObjectRef(BObject *pobj=NULL)
Definition: bobject.h:454
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: bobject.h:719
int display_bobjectimp_instance(BObjectImp *imp)
Definition: object.cpp:165
Cont::const_iterator const_iterator
Definition: bobject.h:509
virtual void operDivideEqual(BObject &obj, BObjectImp &objimp)
Definition: object.cpp:880
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1859
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1404
virtual BObjectImp * selfBitShiftLeftObjImp(const BObjectImp &objimp) const
Definition: object.cpp:655
bool operator<=(const BObject &obj) const
Definition: object.cpp:146
void * ptr() const
Definition: object.cpp:1854
virtual std::string pack() const POL_OVERRIDE
Definition: object.cpp:1903
virtual bool operator==(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:1062
virtual BObjectRef OperSubscript(const BObject &obj) POL_OVERRIDE
Definition: object.cpp:1321
void setimp(BObjectImp *imp)
Definition: bobject.h:446
virtual bool operator==(const BObjectImp &objimp) const
Definition: object.cpp:272
virtual bool isTrue() const
Definition: object.cpp:911
virtual bool operator==(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:989
virtual BObjectRef get_member_id(const int id)
Definition: object.cpp:934
const BObjectImp * imp_at(unsigned index) const
Definition: object.cpp:1100
virtual BObjectRef set_member(const char *membername, BObjectImp *valueimp, bool copy)
Definition: object.cpp:926
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: impstr.h:53
virtual BObjectImp * selfDividedByObj(const BObjectImp &objimp) const
Definition: object.cpp:512
Clib::fixed_allocator< sizeof(UninitObject), 256 > uninit_alloc
Definition: object.cpp:43
virtual bool operator<(const BObjectImp &objimp) const
Definition: object.cpp:283
virtual BObjectImp * call_method_id(const int id, Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: object.cpp:2003
bool validCall(const int id, Executor &ex, Instruction *inst) const
Definition: object.cpp:1982
Definition: refptr.h:65
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:1839
virtual bool isTrue() const POL_OVERRIDE
Definition: object.cpp:1920
const BApplicObjType * pointer_type() const
Definition: object.cpp:1849
unsigned int instance_
Definition: bobject.h:337
virtual void operPlusEqual(BObject &obj, BObjectImp &objimp)
Definition: object.cpp:862
BFunctionRef(int progcounter, int param_count, const std::string &scriptname)
Definition: object.cpp:1936
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: object.cpp:1954
static Clib::SpinLock bobjectimp_lock
Definition: bobject.h:339
virtual bool operator<=(const BObjectImp &objimp) const
Definition: object.cpp:302
int random_int(int i)
Definition: random.cpp:34
virtual BObjectRef OperSubscript(const BObject &obj)
Definition: object.cpp:903
size_t sizeEstimate() const
Definition: object.cpp:54
static BObjectImp * unpack(std::istream &is)
Definition: dict.cpp:368
bool operator>(const BObject &obj) const
Definition: object.cpp:150
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1969
bool operator!=(const BObject &obj) const
Definition: object.cpp:134
BBoolean(bool bval=false)
Definition: object.cpp:1881
#define OSTRINGSTREAM
Definition: stlutil.h:75
void display_bobjectimp_instances()
Definition: object.cpp:170
virtual bool operator<(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:994
static UninitObject * create()
Definition: bobject.h:482
virtual std::string getFormattedStringRep() const
Definition: object.cpp:213
virtual void packonto(std::ostream &os) const POL_OVERRIDE
Definition: object.cpp:1898
virtual void operMinusEqual(BObject &obj, BObjectImp &objimp)
Definition: object.cpp:868
size_t numParams() const
Definition: executor.h:145
ObjMember * getObjMember(int id)
Definition: parser.cpp:501
virtual bool operator==(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:1964
ObjMethod * getObjMethod(int id)
Definition: parser.cpp:685
static BObjectImp * unpack(const char *pstr)
Definition: object.cpp:120
virtual BObjectRef set_member_id(const int id, BObjectImp *valueimp, bool copy)
Definition: object.cpp:940
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: object.cpp:1844
virtual BObjectImp * call_method(const char *methodname, Executor &ex)
Definition: object.cpp:916
static BObjectImp * unpack(std::istream &is)
Definition: object.cpp:1885
static BObjectImp * unpack(const char *pstr)
Definition: str.cpp:113
bool operator==(const BObject &obj) const
Definition: object.cpp:138
virtual BObjectImp * call_method_id(const int id, Executor &ex, bool forcebuiltin=false)
Definition: object.cpp:920
bool operator()(const BObjectRef &x1, const BObjectRef &x2) const
Definition: object.cpp:1455
virtual bool isTrue() const POL_OVERRIDE
Definition: object.cpp:981
ref_ptr< BObjectImp > objimp
Definition: bobject.h:404
virtual bool operator>(const BObjectImp &objimp) const
Definition: object.cpp:309
virtual void printOn(std::ostream &) const POL_OVERRIDE
Definition: object.cpp:1865
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: object.cpp:976
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: blong.cpp:73
virtual BObjectImp * selfMinusObjImp(const BObjectImp &objimp) const
Definition: object.cpp:410
virtual BObjectRef operDotQMark(const char *name)
Definition: object.cpp:961
virtual BObjectRef OperMultiSubscript(std::stack< BObjectRef > &indices)
Definition: object.cpp:333
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: object.cpp:1915
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:1910
BObjectImp & impref()
Definition: bobject.h:438
virtual void packonto(std::ostream &os) const
Definition: object.cpp:208
void addElement(BObjectImp *imp)
Definition: object.cpp:1399
static BObjectImp * unpackWithLen(std::istream &is)
Definition: str.cpp:126
const std::string & scriptname() const
Definition: executor.h:413
#define ISTRINGSTREAM
Definition: stlutil.h:73
virtual BObjectImp * selfTimesObjImp(const BObjectImp &objimp) const
Definition: object.cpp:459
virtual BObjectImp * call_method(const char *methodname, Executor &ex) POL_OVERRIDE
Definition: object.cpp:1779
virtual void printOn(std::ostream &) const POL_OVERRIDE
Definition: object.cpp:1875
virtual BObjectRef OperMultiSubscriptAssign(std::stack< BObjectRef > &indices, BObjectImp *target)
Definition: object.cpp:344
virtual BObjectImp * selfPlusObj(const BObjectImp &objimp) const POL_OVERRIDE
Definition: object.cpp:1149
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:1949
virtual BObjectImp * selfMinusObj(const BObjectImp &objimp) const
Definition: object.cpp:414
std::string name
Definition: osmod.cpp:943
static ref_ptr< BObjectImp > SharedInstanceOwner
Definition: bobject.h:468
bool operator<(const BObject &obj) const
Definition: object.cpp:142
NameCont::const_iterator const_name_iterator
Definition: bobject.h:505
virtual BObjectImp * selfModulusObjImp(const BObjectImp &objimp) const
Definition: object.cpp:557
virtual BObjectImp * selfPlusObjImp(const BObjectImp &other) const POL_OVERRIDE
Definition: object.cpp:1200
BObjectImp(BObjectType type)
Definition: object.cpp:184
bobjectimps bobjectimp_instances
Definition: object.cpp:164
virtual BObjectRef OperMultiSubscript(std::stack< BObjectRef > &indices) POL_OVERRIDE
Definition: object.cpp:1248
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1870
virtual BObjectImp * selfBitXorObjImp(const BObjectImp &objimp) const
Definition: object.cpp:802
virtual BObjectRef set_member(const char *membername, BObjectImp *value, bool copy) POL_OVERRIDE
Definition: object.cpp:1368
#define INFO_PRINT
Definition: logfacility.h:223
virtual BObjectImp * selfModulusObj(const BObjectImp &objimp) const
Definition: object.cpp:561
std::lock_guard< SpinLock > SpinLockGuard
Definition: spinlock.h:33
virtual BObjectRef operDotMinus(const char *name)
Definition: object.cpp:956
Clib::fixed_allocator< sizeof(BObject), 256 > bobject_alloc
Definition: object.cpp:42
virtual BObjectImp * array_assign(BObjectImp *idx, BObjectImp *target, bool copy)
Definition: object.cpp:328
std::string script_name_
Definition: bobject.h:840
static BObjectImp * unpack(const char *pstr)
Definition: dbl.cpp:32
virtual void operInsertInto(BObject &obj, const BObjectImp &objimp) POL_OVERRIDE
Definition: object.cpp:1144
virtual BObjectImp * selfDividedByObjImp(const BObjectImp &objimp) const
Definition: object.cpp:508
Definition: berror.cpp:12
virtual const char * typeOf() const
Definition: object.cpp:257
virtual bool operator>=(const BObjectImp &objimp) const
Definition: object.cpp:316
std::unordered_map< unsigned int, BObjectImp * > bobjectimps
Definition: object.cpp:161
static const char * typestr(BObjectType typ)
Definition: object.cpp:218
static UninitObject * SharedInstance
Definition: bobject.h:467
virtual BObjectImp * selfPlusObj(const BObjectImp &objimp) const
Definition: object.cpp:365
virtual void operTimesEqual(BObject &obj, BObjectImp &objimp)
Definition: object.cpp:874
BObjectImp * getParamImp(unsigned param)
Definition: executor.cpp:266
virtual BObjectImp * selfPlusObjImp(const BObjectImp &objimp) const
Definition: object.cpp:361
static BObjectImp * unpack(std::istream &is)
Definition: berror.cpp:75
ExecInstrFunc func
Definition: eprog.h:40
static unsigned int instances_
Definition: bobject.h:338
bool getParam(unsigned param, int &value)
Definition: executor.cpp:363
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: object.cpp:971
virtual BObject operator-() const
Definition: object.cpp:892