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