Pol  Revision:cb584c9
bstruct.cpp
Go to the documentation of this file.
1 
11 #include "bstruct.h"
12 
13 #include <stddef.h>
14 
15 #include "../clib/passert.h"
16 #include "../clib/stlutil.h"
17 #include "berror.h"
18 #include "bobject.h"
19 #include "contiter.h"
20 #include "executor.h"
21 #include "impstr.h"
22 #include "objmethods.h"
23 
24 namespace Pol
25 {
26 namespace Bscript
27 {
28 BStruct::BStruct() : BObjectImp( OTStruct ), contents_() {}
29 
31 
33 {
34  for ( const auto& elem : other.contents_ )
35  {
36  const std::string& key = elem.first;
37  const BObjectRef& bvalref = elem.second;
38 
39  contents_[key] = BObjectRef( new BObject( bvalref->impref().copy() ) );
40  }
41 }
42 
43 BStruct::BStruct( std::istream& is, unsigned size, BObjectType type )
44  : BObjectImp( type ), contents_()
45 {
46  for ( unsigned i = 0; i < size; ++i )
47  {
48  BObjectImp* keyimp = BObjectImp::unpack( is );
49  BObjectImp* valimp = BObjectImp::unpack( is );
50  if ( keyimp != NULL && valimp != NULL && keyimp->isa( OTString ) )
51  {
52  String* str = static_cast<String*>( keyimp );
53 
54  contents_[str->value()].set( new BObject( valimp ) );
55 
56  BObject cleaner( str );
57  }
58  else
59  {
60  if ( keyimp )
61  BObject objk( keyimp );
62  if ( valimp )
63  BObject objv( valimp );
64  }
65  }
66 }
67 
69 {
70  passert( isa( OTStruct ) );
71  return new BStruct( *this, OTStruct );
72 }
73 char BStruct::packtype() const
74 {
75  return 't';
76 }
77 
78 const char* BStruct::typetag() const
79 {
80  return "struct";
81 }
82 
83 const char* BStruct::typeOf() const
84 {
85  return "Struct";
86 }
88 {
89  return OTStruct;
90 }
91 
92 
93 BObjectImp* BStruct::unpack( std::istream& is )
94 {
95  unsigned size;
96  char colon;
97  if ( !( is >> size >> colon ) )
98  {
99  return new BError( "Unable to unpack struct elemcount" );
100  }
101  if ( (int)size < 0 )
102  {
103  return new BError(
104  "Unable to unpack struct elemcount. Length given must be positive integer!" );
105  }
106  if ( colon != ':' )
107  {
108  return new BError( "Unable to unpack struct elemcount. Bad format. Colon not found!" );
109  }
110  return new BStruct( is, size, OTStruct );
111 }
112 
113 void BStruct::FormatForStringRep( std::ostream& os, const std::string& key,
114  const BObjectRef& bvalref ) const
115 {
116  os << key << " = " << bvalref->impref().getFormattedStringRep();
117 }
118 
120 {
121 public:
122  BStructIterator( BStruct* pDict, BObject* pIterVal );
123  virtual BObject* step() POL_OVERRIDE;
124 
125 private:
129  std::string key;
130  bool m_First;
131 };
133  : m_StructObj( pStruct ),
134  m_pStruct( pStruct ),
135  m_IterVal( pIterVal ),
136  key( "" ),
137  m_First( true )
138 {
139 }
140 
142 {
143  if ( m_First )
144  {
145  auto itr = m_pStruct->contents_.begin();
146  if ( itr == m_pStruct->contents_.end() )
147  return NULL;
148 
149  m_First = false;
150  key = ( *itr ).first;
151  m_IterVal->setimp( new String( key ) );
152 
153  BObjectRef& oref = ( *itr ).second;
154  return oref.get();
155  }
156  else
157  {
158  auto itr = m_pStruct->contents_.find( key );
159  if ( itr == m_pStruct->contents_.end() )
160  return NULL;
161  ++itr;
162  if ( itr == m_pStruct->contents_.end() )
163  return NULL;
164 
165  key = ( *itr ).first;
166  m_IterVal->setimp( new String( key ) );
167 
168  BObjectRef& oref = ( *itr ).second;
169  return oref.get();
170  }
171 }
172 
174 {
175  return new BStructIterator( this, pIterVal );
176 }
177 
178 size_t BStruct::sizeEstimate() const
179 {
180  size_t size = sizeof( BStruct );
181  for ( const auto& elem : contents_ )
182  {
183  const std::string& bkey = elem.first;
184  const BObjectRef& bvalref = elem.second;
185  size += bkey.capacity() + bvalref.sizeEstimate() + ( sizeof( void* ) * 3 + 1 ) / 2;
186  }
187  return size;
188 }
189 
190 size_t BStruct::mapcount() const
191 {
192  return contents_.size();
193 }
194 
195 
196 BObjectRef BStruct::set_member( const char* membername, BObjectImp* value, bool copy )
197 {
198  std::string key( membername );
199  BObjectImp* target = copy ? value->copy() : value;
200  auto itr = contents_.find( key );
201  if ( itr != contents_.end() )
202  {
203  BObjectRef& oref = ( *itr ).second;
204  oref->setimp( target );
205  return oref;
206  }
207  else
208  {
209  BObjectRef ref( new BObject( target ) );
210  contents_[key] = ref;
211  return ref;
212  }
213 }
214 
215 // used programmatically
216 const BObjectImp* BStruct::FindMember( const char* name )
217 {
218  std::string key( name );
219 
220  auto itr = contents_.find( key );
221  if ( itr != contents_.end() )
222  {
223  return ( *itr ).second->impptr();
224  }
225  else
226  {
227  return NULL;
228  }
229 }
230 
231 BObjectRef BStruct::get_member( const char* membername )
232 {
233  std::string key( membername );
234 
235  auto itr = contents_.find( key );
236  if ( itr != contents_.end() )
237  {
238  return ( *itr ).second;
239  }
240  else
241  {
242  return BObjectRef( UninitObject::create() );
243  }
244 }
245 
247 {
248  if ( obj->isa( OTString ) )
249  {
250  const String* keystr = static_cast<const String*>( obj.impptr() );
251 
252  auto itr = contents_.find( keystr->value() );
253  if ( itr != contents_.end() )
254  {
255  BObjectRef& oref = ( *itr ).second;
256  return oref;
257  }
258  else
259  {
260  return BObjectRef( UninitObject::create() );
261  }
262  }
263  else if ( obj->isa( OTLong ) )
264  {
265  throw std::runtime_error( "some fool used operator[] on a struct, with an Integer index" );
266  }
267  else
268  {
269  return BObjectRef( new BError( "Struct members can only be accessed by name" ) );
270  }
271 }
272 
274 {
275  if ( idx->isa( OTString ) )
276  {
277  BObjectImp* new_target = copy ? target->copy() : target;
278 
279  String* keystr = static_cast<String*>( idx );
280 
281  auto itr = contents_.find( keystr->value() );
282  if ( itr != contents_.end() )
283  {
284  BObjectRef& oref = ( *itr ).second;
285  oref->setimp( new_target );
286  return new_target;
287  }
288  else
289  {
290  contents_[keystr->value()].set( new BObject( new_target ) );
291  return new_target;
292  }
293  }
294  else if ( idx->isa( OTLong ) )
295  {
296  throw std::runtime_error(
297  "some fool tried to use operator[] := on a struct, with an Integer index" );
298  }
299  else
300  {
301  return new BError( "Struct members can only be accessed by name" );
302  }
303 }
304 
305 void BStruct::addMember( const char* name, BObjectRef val )
306 {
307  std::string key( name );
308  contents_[key] = val;
309 }
310 
311 void BStruct::addMember( const char* name, BObjectImp* imp )
312 {
313  std::string key( name );
314  contents_[key] = BObjectRef( imp );
315 }
316 
317 BObjectImp* BStruct::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
318 {
319  BObject* keyobj;
320  BObject* valobj;
321  switch ( id )
322  {
323  case MTH_SIZE:
324  if ( ex.numParams() == 0 )
325  return new BLong( static_cast<int>( contents_.size() ) );
326  else
327  return new BError( "struct.size() doesn't take parameters." );
328 
329  case MTH_ERASE:
330  if ( ex.numParams() == 1 && ( keyobj = ex.getParamObj( 0 ) ) != NULL )
331  {
332  if ( !keyobj->isa( OTString ) )
333  return new BError( "Struct keys must be strings" );
334  String* strkey = static_cast<String*>( keyobj->impptr() );
335  int nremove = static_cast<int>( contents_.erase( strkey->value() ) );
336  return new BLong( nremove );
337  }
338  else
339  {
340  return new BError( "struct.erase(key) requires a parameter." );
341  }
342  break;
343  case MTH_INSERT:
344  if ( ex.numParams() == 2 && ( keyobj = ex.getParamObj( 0 ) ) != NULL &&
345  ( valobj = ex.getParamObj( 1 ) ) != NULL )
346  {
347  if ( !keyobj->isa( OTString ) )
348  return new BError( "Struct keys must be strings" );
349  String* strkey = static_cast<String*>( keyobj->impptr() );
350  contents_[strkey->value()] = BObjectRef( new BObject( valobj->impptr()->copy() ) );
351  return new BLong( static_cast<int>( contents_.size() ) );
352  }
353  else
354  {
355  return new BError( "struct.insert(key,value) requires two parameters." );
356  }
357  break;
358  case MTH_EXISTS:
359  if ( ex.numParams() == 1 && ( keyobj = ex.getParamObj( 0 ) ) != NULL )
360  {
361  if ( !keyobj->isa( OTString ) )
362  return new BError( "Struct keys must be strings" );
363  String* strkey = static_cast<String*>( keyobj->impptr() );
364  int count = static_cast<int>( contents_.count( strkey->value() ) );
365  return new BLong( count );
366  }
367  else
368  {
369  return new BError( "struct.exists(key) requires a parameter." );
370  }
371 
372  case MTH_KEYS:
373  if ( ex.numParams() == 0 )
374  {
375  std::unique_ptr<ObjArray> arr( new ObjArray );
376  for ( const auto& content : contents_ )
377  {
378  arr->addElement( new String( content.first ) );
379  }
380  return arr.release();
381  }
382  else
383  return new BError( "struct.keys() doesn't take parameters." );
384  break;
385  default:
386  return NULL;
387  }
388 }
389 
390 BObjectImp* BStruct::call_method( const char* methodname, Executor& ex )
391 {
392  ObjMethod* objmethod = getKnownObjMethod( methodname );
393  if ( objmethod != NULL )
394  return this->call_method_id( objmethod->id, ex );
395  else
396  return NULL;
397 }
398 
399 void BStruct::packonto( std::ostream& os ) const
400 {
401  os << packtype() << contents_.size() << ":";
402  for ( const auto& content : contents_ )
403  {
404  const std::string& key = content.first;
405  const BObjectRef& bvalref = content.second;
406 
407  String::packonto( os, key );
408  bvalref->impref().packonto( os );
409  }
410 }
411 
412 std::string BStruct::getStringRep() const
413 {
414  OSTRINGSTREAM os;
415  os << typetag() << "{ ";
416  bool any = false;
417 
418  for ( const auto& content : contents_ )
419  {
420  const std::string& key = content.first;
421  const BObjectRef& bvalref = content.second;
422 
423  if ( any )
424  os << ", ";
425  else
426  any = true;
427 
428  FormatForStringRep( os, key, bvalref );
429  }
430 
431  os << " }";
432 
433  return OSTRINGSTREAM_STR( os );
434 }
435 
436 
438 {
439  std::string key( name );
440  if ( contents_.count( key ) == 0 )
441  {
442  auto pnewobj = new BObject( new UninitObject );
443  contents_[key] = BObjectRef( pnewobj );
444  return BObjectRef( pnewobj );
445  }
446  else
447  {
448  return BObjectRef( new BError( "Member already exists" ) );
449  }
450 }
451 
453 {
454  std::string key( name );
455  contents_.erase( key );
456  return BObjectRef( new BLong( 1 ) );
457 }
458 
460 {
461  std::string key( name );
462  int count = static_cast<int>( contents_.count( key ) );
463  return BObjectRef( new BLong( count ) );
464 }
465 
467 {
468  return contents_;
469 }
470 }
471 }
virtual void FormatForStringRep(std::ostream &os, const std::string &key, const BObjectRef &bvalref) const
Definition: bstruct.cpp:113
virtual BObjectRef set_member(const char *membername, BObjectImp *value, bool copy) POL_OVERRIDE
Definition: bstruct.cpp:196
unsigned char u8
Definition: rawtypes.h:25
virtual BObjectRef operDotMinus(const char *name) POL_OVERRIDE
Definition: bstruct.cpp:452
#define POL_OVERRIDE
size_t mapcount() const
Definition: bstruct.cpp:190
const std::string & value() const
Definition: impstr.h:67
virtual BObjectRef operDotQMark(const char *name) POL_OVERRIDE
Definition: bstruct.cpp:459
BObjectType type() const
Definition: bobject.h:358
BObjectImp * copy(void) const
Definition: executor.cpp:951
int find(int begin, const char *target)
Definition: str.cpp:170
bool isa(BObjectType type) const
Definition: bobject.h:353
virtual char packtype() const
Definition: bstruct.cpp:73
std::map< std::string, BObjectRef, Clib::ci_cmp_pred > Contents
Definition: bstruct.h:51
size_t sizeEstimate() const
Definition: object.cpp:47
T * get() const
Definition: refptr.h:176
virtual void packonto(std::ostream &os) const POL_OVERRIDE
Definition: str.cpp:104
const Contents & contents() const
Definition: bstruct.cpp:466
virtual BObjectImp * call_method_id(const int id, Executor &ex, bool forcebuiltin=false) POL_OVERRIDE
Definition: bstruct.cpp:317
virtual BObject * step() POL_OVERRIDE
Definition: bstruct.cpp:141
virtual BObjectImp * copy() const =0
#define OSTRINGSTREAM_STR(x)
Definition: stlutil.h:76
void addMember(const char *name, BObjectRef val)
Definition: bstruct.cpp:305
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:666
static BObjectImp * unpack(std::istream &is)
Definition: bstruct.cpp:93
virtual BObjectRef get_member(const char *membername) POL_OVERRIDE
Definition: bstruct.cpp:231
virtual BObjectRef operDotPlus(const char *name) POL_OVERRIDE
Definition: bstruct.cpp:437
virtual void packonto(std::ostream &os) const POL_OVERRIDE
Definition: bstruct.cpp:399
virtual std::string getStringRep() const POL_OVERRIDE
Definition: bstruct.cpp:412
BObject * getParamObj(unsigned param)
Definition: executor.cpp:276
virtual const char * typetag() const
Definition: bstruct.cpp:78
Contents contents_
Definition: bstruct.h:88
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: bstruct.cpp:68
#define OSTRINGSTREAM
Definition: stlutil.h:75
static UninitObject * create()
Definition: bobject.h:482
#define passert(exp)
Definition: passert.h:62
size_t numParams() const
Definition: executor.h:145
static BObjectImp * unpack(const char *pstr)
Definition: object.cpp:120
virtual BObjectImp * call_method(const char *methodname, Executor &ex) POL_OVERRIDE
Definition: bstruct.cpp:390
BObjectImp * impptr()
Definition: bobject.h:428
virtual BObjectImp * call_method_id(const int id, Executor &ex, bool forcebuiltin=false)
Definition: object.cpp:920
unsigned int count() const
Definition: refptr.h:130
virtual u8 typeOfInt() const POL_OVERRIDE
Definition: bstruct.cpp:87
virtual const char * typeOf() const POL_OVERRIDE
Definition: bstruct.cpp:83
virtual BObjectImp * array_assign(BObjectImp *idx, BObjectImp *target, bool copy) POL_OVERRIDE
Definition: bstruct.cpp:273
friend class BStructIterator
Definition: bstruct.h:85
std::string name
Definition: osmod.cpp:943
BStructIterator(BStruct *pDict, BObject *pIterVal)
Definition: bstruct.cpp:132
virtual BObjectRef OperSubscript(const BObject &obj) POL_OVERRIDE
Definition: bstruct.cpp:246
Definition: berror.cpp:12
const BObjectImp * FindMember(const char *name)
Definition: bstruct.cpp:216
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: bstruct.cpp:178
virtual ContIterator * createIterator(BObject *pIterVal) POL_OVERRIDE
Definition: bstruct.cpp:173