Pol  Revision:4b29d2b
str.cpp
Go to the documentation of this file.
1 
11 #include <cstdlib>
12 #include <ctype.h>
13 #include <string>
14 
15 #include "../clib/stlutil.h"
16 #include "berror.h"
17 #include "bobject.h"
18 #include "executor.h"
19 #include "impstr.h"
20 #include "objmethods.h"
21 
22 #ifdef __GNUG__
23 #include <streambuf>
24 #endif
25 
26 #ifdef _MSC_VER
27 #pragma warning( disable : 4244 )
28 #endif
29 namespace Pol
30 {
31 namespace Bscript
32 {
33 String::String( BObjectImp& objimp ) : BObjectImp( OTString ), value_( objimp.getStringRep() ) {}
34 
35 String::String( const char* s, int len ) : BObjectImp( OTString ), value_( s, len ) {}
36 
37 String* String::StrStr( int begin, int len )
38 {
39  return new String( value_.substr( begin - 1, len ) );
40 }
41 
42 String* String::ETrim( const char* CRSet, int type )
43 {
44  std::string tmp = value_;
45 
46  if ( type == 1 ) // This is for Leading Only.
47  {
48  // Find the first character position after excluding leading blank spaces
49  size_t startpos = tmp.find_first_not_of( CRSet );
50  if ( std::string::npos != startpos )
51  tmp = tmp.substr( startpos );
52  else
53  tmp = "";
54  return new String( tmp );
55  }
56  else if ( type == 2 ) // This is for Trailing Only.
57  {
58  // Find the first character position from reverse
59  size_t endpos = tmp.find_last_not_of( CRSet );
60  if ( std::string::npos != endpos )
61  tmp = tmp.substr( 0, endpos + 1 );
62  else
63  tmp = "";
64  return new String( tmp );
65  }
66  else if ( type == 3 )
67  {
68  // Find the first character position after excluding leading blank spaces
69  size_t startpos = tmp.find_first_not_of( CRSet );
70  // Find the first character position from reverse af
71  size_t endpos = tmp.find_last_not_of( CRSet );
72 
73  // if all spaces or empty return on empty string
74  if ( ( std::string::npos == startpos ) || ( std::string::npos == endpos ) )
75  tmp = "";
76  else
77  tmp = tmp.substr( startpos, endpos - startpos + 1 );
78  return new String( tmp );
79  }
80  else
81  return new String( tmp );
82 }
83 
84 void String::EStrReplace( String* str1, String* str2 )
85 {
86  std::string::size_type valpos = 0;
87  while ( std::string::npos != ( valpos = value_.find( str1->value_, valpos ) ) )
88  {
89  value_.replace( valpos, str1->length(), str2->value_ );
90  valpos += str2->length();
91  }
92 }
93 
94 void String::ESubStrReplace( String* replace_with, unsigned int index, unsigned int len )
95 {
96  value_.replace( index - 1, len, replace_with->value_ );
97 }
98 
99 std::string String::pack() const
100 {
101  return "s" + value_;
102 }
103 
104 void String::packonto( std::ostream& os ) const
105 {
106  os << "S" << value_.size() << ":" << value_;
107 }
108 void String::packonto( std::ostream& os, const std::string& value )
109 {
110  os << "S" << value.size() << ":" << value;
111 }
112 
113 BObjectImp* String::unpack( const char* pstr )
114 {
115  return new String( pstr );
116 }
117 
118 BObjectImp* String::unpack( std::istream& is )
119 {
120  std::string tmp;
121  getline( is, tmp );
122 
123  return new String( tmp );
124 }
125 
126 BObjectImp* String::unpackWithLen( std::istream& is )
127 {
128  unsigned len;
129  char colon;
130  if ( !( is >> len >> colon ) )
131  {
132  return new BError( "Unable to unpack string length." );
133  }
134  if ( (int)len < 0 )
135  {
136  return new BError( "Unable to unpack string length. Invalid length!" );
137  }
138  if ( colon != ':' )
139  {
140  return new BError( "Unable to unpack string length. Bad format. Colon not found!" );
141  }
142 
143  is.unsetf( std::ios::skipws );
144  std::string tmp;
145  tmp.reserve( len );
146  while ( len-- )
147  {
148  char ch = '\0';
149  if ( !( is >> ch ) || ch == '\0' )
150  {
151  return new BError( "Unable to unpack string length. String length excessive." );
152  }
153  tmp += ch;
154  }
155 
156  is.setf( std::ios::skipws );
157  return new String( tmp );
158 }
159 
160 size_t String::sizeEstimate() const
161 {
162  return sizeof( String ) + value_.capacity();
163 }
164 
165 /*
166  0-based string find
167  find( "str srch", 2, "srch"):
168  01^-- start
169  */
170 int String::find( int begin, const char* target )
171 {
172  // TODO: check what happens in string if begin position is out of range
173  std::string::size_type pos;
174  pos = value_.find( target, begin );
175  if ( pos == std::string::npos )
176  return -1;
177  else
178  return static_cast<int>( pos );
179 }
180 
181 // Returns the amount of alpha-numeric characters in string.
182 unsigned int String::alnumlen( void ) const
183 {
184  unsigned int c = 0;
185  while ( isalnum( value_[c] ) )
186  {
187  c++;
188  }
189  return c;
190 }
191 
192 unsigned int String::SafeCharAmt() const
193 {
194  int strlen = static_cast<int>( this->length() );
195  for ( int i = 0; i < strlen; i++ )
196  {
197  unsigned char tmp = value_[i];
198  if ( isalnum( tmp ) ) // a-z A-Z 0-9
199  continue;
200  else if ( ispunct( tmp ) ) // !"#$%&'()*+,-./:;<=>?@{|}~
201  {
202  if ( tmp == '{' || tmp == '}' )
203  return i;
204  else
205  continue;
206  }
207  else
208  {
209  return i;
210  }
211  }
212  return strlen;
213 }
214 
215 void String::reverse( void )
216 {
217  std::reverse( value_.begin(), value_.end() );
218 }
219 
220 void String::set( char* newstr )
221 {
222  value_ = newstr;
223  delete newstr;
224 }
225 
226 
228 {
229  return objimp.selfPlusObj( *this );
230 }
232 {
233  return new String( value_ + objimp.getStringRep() );
234 }
235 BObjectImp* String::selfPlusObj( const BLong& objimp ) const
236 {
237  return new String( value_ + objimp.getStringRep() );
238 }
239 BObjectImp* String::selfPlusObj( const Double& objimp ) const
240 {
241  return new String( value_ + objimp.getStringRep() );
242 }
243 BObjectImp* String::selfPlusObj( const String& objimp ) const
244 {
245  return new String( value_ + objimp.getStringRep() );
246 }
247 BObjectImp* String::selfPlusObj( const ObjArray& objimp ) const
248 {
249  return new String( value_ + objimp.getStringRep() );
250 }
252 {
253  objimp.selfPlusObj( *this, obj );
254 }
255 void String::selfPlusObj( BObjectImp& objimp, BObject& /*obj*/ )
256 {
257  value_ += objimp.getStringRep();
258 }
259 void String::selfPlusObj( BLong& objimp, BObject& /*obj*/ )
260 {
261  value_ += objimp.getStringRep();
262 }
263 void String::selfPlusObj( Double& objimp, BObject& /*obj*/ )
264 {
265  value_ += objimp.getStringRep();
266 }
267 void String::selfPlusObj( String& objimp, BObject& /*obj*/ )
268 {
269  value_ += objimp.getStringRep();
270 }
271 void String::selfPlusObj( ObjArray& objimp, BObject& /*obj*/ )
272 {
273  value_ += objimp.getStringRep();
274 }
275 
276 
277 void String::remove( const char* rm )
278 {
279  size_t len = strlen( rm );
280 
281  auto pos = value_.find( rm );
282  if ( pos != std::string::npos )
283  value_.erase( pos, len );
284 }
285 
287 {
288  return objimp.selfMinusObj( *this );
289 }
291 {
292  String* tmp = (String*)copy();
293  tmp->remove( objimp.getStringRep().data() );
294  return tmp;
295 }
296 BObjectImp* String::selfMinusObj( const BLong& objimp ) const
297 {
298  String* tmp = (String*)copy();
299  tmp->remove( objimp.getStringRep().data() );
300  return tmp;
301 }
302 BObjectImp* String::selfMinusObj( const Double& objimp ) const
303 {
304  String* tmp = (String*)copy();
305  tmp->remove( objimp.getStringRep().data() );
306  return tmp;
307 }
308 BObjectImp* String::selfMinusObj( const String& objimp ) const
309 {
310  String* tmp = (String*)copy();
311  tmp->remove( objimp.value_.data() );
312  return tmp;
313 }
314 BObjectImp* String::selfMinusObj( const ObjArray& objimp ) const
315 {
316  String* tmp = (String*)copy();
317  tmp->remove( objimp.getStringRep().data() );
318  return tmp;
319 }
321 {
322  objimp.selfMinusObj( *this, obj );
323 }
324 void String::selfMinusObj( BObjectImp& objimp, BObject& /*obj*/ )
325 {
326  remove( objimp.getStringRep().data() );
327 }
328 void String::selfMinusObj( BLong& objimp, BObject& /*obj*/ )
329 {
330  remove( objimp.getStringRep().data() );
331 }
332 void String::selfMinusObj( Double& objimp, BObject& /*obj*/ )
333 {
334  remove( objimp.getStringRep().data() );
335 }
336 void String::selfMinusObj( String& objimp, BObject& /*obj*/ )
337 {
338  remove( objimp.value_.data() );
339 }
340 void String::selfMinusObj( ObjArray& objimp, BObject& /*obj*/ )
341 {
342  remove( objimp.getStringRep().data() );
343 }
344 
345 bool String::operator==( const BObjectImp& objimp ) const
346 {
347  if ( objimp.isa( OTString ) )
348  return ( value_ == static_cast<const String&>( objimp ).value_ );
349 
350  if ( objimp.isa( OTBoolean ) )
351  return isTrue() == static_cast<const BBoolean&>( objimp ).isTrue();
352  return base::operator==( objimp );
353 }
354 
355 bool String::operator<( const BObjectImp& objimp ) const
356 {
357  if ( objimp.isa( OTString ) )
358  return ( value_ < static_cast<const String&>( objimp ).value_ );
359 
360  return base::operator<( objimp );
361 }
362 
363 String* String::midstring( int begin, int len ) const
364 {
365  return new String( value_.substr( begin - 1, len ) );
366 }
367 
368 void String::toUpper( void )
369 {
370  for ( char& c : value_ )
371  {
372  c = toupper( c );
373  }
374 }
375 
376 void String::toLower( void )
377 {
378  for ( char& c : value_ )
379  {
380  c = tolower( c );
381  }
382 }
383 
384 BObjectImp* String::array_assign( BObjectImp* idx, BObjectImp* target, bool /*copy*/ )
385 {
386  std::string::size_type pos, len;
387 
388  // first, determine position and length.
389  if ( idx->isa( OTString ) )
390  {
391  String& rtstr = (String&)*idx;
392  pos = value_.find( rtstr.value_ );
393  len = rtstr.length();
394  }
395  else if ( idx->isa( OTLong ) )
396  {
397  BLong& lng = (BLong&)*idx;
398  pos = lng.value() - 1;
399  len = 1;
400  }
401  else if ( idx->isa( OTDouble ) )
402  {
403  Double& dbl = (Double&)*idx;
404  pos = static_cast<std::string::size_type>( dbl.value() );
405  len = 1;
406  }
407  else
408  {
409  return UninitObject::create();
410  }
411 
412  if ( pos != std::string::npos )
413  {
414  if ( target->isa( OTString ) )
415  {
416  String* target_str = (String*)target;
417  value_.replace( pos, len, target_str->value_ );
418  }
419  return this;
420  }
421  else
422  {
423  return UninitObject::create();
424  }
425 }
426 
427 BObjectRef String::OperMultiSubscriptAssign( std::stack<BObjectRef>& indices, BObjectImp* target )
428 {
429  BObjectRef start_ref = indices.top();
430  indices.pop();
431  BObjectRef length_ref = indices.top();
432  indices.pop();
433 
434  BObject& length_obj = *length_ref;
435  BObject& start_obj = *start_ref;
436 
437  BObjectImp& length = length_obj.impref();
438  BObjectImp& start = start_obj.impref();
439 
440  // first deal with the start position.
441  unsigned index;
442  if ( start.isa( OTLong ) )
443  {
444  BLong& lng = (BLong&)start;
445  index = (unsigned)lng.value();
446  if ( index == 0 || index > value_.size() )
447  return BObjectRef( new BError( "Subscript out of range" ) );
448  }
449  else if ( start.isa( OTString ) )
450  {
451  String& rtstr = (String&)start;
452  std::string::size_type pos = value_.find( rtstr.value_ );
453  if ( pos != std::string::npos )
454  index = static_cast<unsigned int>( pos + 1 );
455  else
456  return BObjectRef( new UninitObject );
457  }
458  else
459  {
460  return BObjectRef( copy() );
461  }
462 
463  // now deal with the length.
464  int len;
465  if ( length.isa( OTLong ) )
466  {
467  BLong& lng = (BLong&)length;
468 
469  len = (int)lng.value();
470  }
471  else if ( length.isa( OTDouble ) )
472  {
473  Double& dbl = (Double&)length;
474 
475  len = (int)dbl.value();
476  }
477  else
478  {
479  return BObjectRef( copy() );
480  }
481 
482  if ( target->isa( OTString ) )
483  {
484  String* target_str = (String*)target;
485  value_.replace( index - 1, len, target_str->value_ );
486  }
487  else
488  {
489  return BObjectRef( UninitObject::create() );
490  }
491 
492  return BObjectRef( this );
493 }
494 
495 
496 BObjectRef String::OperMultiSubscript( std::stack<BObjectRef>& indices )
497 {
498  BObjectRef start_ref = indices.top();
499  indices.pop();
500  BObjectRef length_ref = indices.top();
501  indices.pop();
502 
503  BObject& length_obj = *length_ref;
504  BObject& start_obj = *start_ref;
505 
506  BObjectImp& length = length_obj.impref();
507  BObjectImp& start = start_obj.impref();
508 
509  // first deal with the start position.
510  unsigned index;
511  if ( start.isa( OTLong ) )
512  {
513  BLong& lng = (BLong&)start;
514  index = (unsigned)lng.value();
515  if ( index == 0 || index > value_.size() )
516  return BObjectRef( new BError( "Subscript out of range" ) );
517  }
518  else if ( start.isa( OTString ) )
519  {
520  String& rtstr = (String&)start;
521  std::string::size_type pos = value_.find( rtstr.value_ );
522  if ( pos != std::string::npos )
523  index = static_cast<unsigned int>( pos + 1 );
524  else
525  return BObjectRef( new UninitObject );
526  }
527  else
528  {
529  return BObjectRef( copy() );
530  }
531 
532  // now deal with the length.
533  int len;
534  if ( length.isa( OTLong ) )
535  {
536  BLong& lng = (BLong&)length;
537 
538  len = (int)lng.value();
539  }
540  else if ( length.isa( OTDouble ) )
541  {
542  Double& dbl = (Double&)length;
543 
544  len = (int)dbl.value();
545  }
546  else
547  {
548  return BObjectRef( copy() );
549  }
550 
551  auto str = new String( value_, index - 1, len );
552  return BObjectRef( str );
553 }
554 
556 {
557  const BObjectImp& right = rightobj.impref();
558  if ( right.isa( OTLong ) )
559  {
560  BLong& lng = (BLong&)right;
561 
562  if ( lng.value() < 0 )
563  return BObjectRef( new BError( "Subscript out of range" ) );
564 
565  unsigned index = (unsigned)lng.value();
566 
567  if ( index == 0 || index > value_.size() )
568  return BObjectRef( new BError( "Subscript out of range" ) );
569 
570  return BObjectRef( new BObject( new String( value_.c_str() + index - 1, 1 ) ) );
571  }
572  else if ( right.isa( OTDouble ) )
573  {
574  Double& dbl = (Double&)right;
575 
576  if ( dbl.value() < 0 )
577  return BObjectRef( new BError( "Subscript out of range" ) );
578  unsigned index = (unsigned)dbl.value();
579 
580  if ( index == 0 || index > value_.size() )
581  return BObjectRef( new BError( "Subscript out of range" ) );
582 
583  return BObjectRef( new BObject( new String( value_.c_str() + index - 1, 1 ) ) );
584  }
585  else if ( right.isa( OTString ) )
586  {
587  String& rtstr = (String&)right;
588  auto pos = value_.find( rtstr.value_ );
589  if ( pos != std::string::npos )
590  return BObjectRef( new BObject( new String( value_, pos, 1 ) ) );
591  else
592  return BObjectRef( new UninitObject );
593  }
594  else
595  {
596  return BObjectRef( new UninitObject );
597  }
598 }
599 
600 // -- format related stuff --
601 
602 bool s_parse_int( int& i, std::string const& s )
603 {
604  if ( s.empty() )
605  return false;
606 
607  char* end;
608  i = strtol( s.c_str(), &end, 10 );
609 
610  if ( !*end )
611  {
612  return true;
613  }
614  else
615  {
616  return false;
617  }
618 }
619 
620 // remove leading/trailing spaces
621 void s_trim( std::string& s )
622 {
623  std::stringstream trimmer;
624  trimmer << s;
625  s.clear();
626  trimmer >> s;
627 }
628 
629 void int_to_binstr( int& value, std::stringstream& s )
630 {
631  int i;
632  for ( i = 31; i > 0; i-- )
633  {
634  if ( value & ( 1 << i ) )
635  break;
636  }
637  for ( ; i >= 0; i-- )
638  {
639  if ( value & ( 1 << i ) )
640  s << "1";
641  else
642  s << "0";
643  }
644 }
645 
646 // suplementory function to format
647 bool try_to_format( std::stringstream& to_stream, BObjectImp* what, std::string& frmt )
648 {
649  if ( frmt.empty() )
650  {
651  to_stream << what->getStringRep();
652  return false;
653  }
654 
655  if ( frmt.find( 'b' ) != std::string::npos )
656  {
657  if ( !what->isa( BObjectImp::OTLong ) )
658  {
659  to_stream << "<needs Int>";
660  return false;
661  }
662  BLong* plong = static_cast<BLong*>( what );
663  int n = plong->value();
664  if ( frmt.find( '#' ) != std::string::npos )
665  to_stream << ( ( n < 0 ) ? "-" : "" ) << "0b";
666  int_to_binstr( n, to_stream );
667  }
668  else if ( frmt.find( 'x' ) != std::string::npos )
669  {
670  if ( !what->isa( BObjectImp::OTLong ) )
671  {
672  to_stream << "<needs Int>";
673  return false;
674  }
675  BLong* plong = static_cast<BLong*>( what );
676  int n = plong->value();
677  if ( frmt.find( '#' ) != std::string::npos )
678  to_stream << "0x";
679  to_stream << std::hex << n << std::dec;
680  }
681  else if ( frmt.find( 'o' ) != std::string::npos )
682  {
683  if ( !what->isa( BObjectImp::OTLong ) )
684  {
685  to_stream << "<needs Int>";
686  return false;
687  }
688  BLong* plong = static_cast<BLong*>( what );
689  int n = plong->value();
690  if ( frmt.find( '#' ) != std::string::npos )
691  to_stream << "0o";
692  to_stream << std::oct << n << std::dec;
693  }
694  else if ( frmt.find( 'd' ) != std::string::npos )
695  {
696  int n;
697  if ( what->isa( BObjectImp::OTLong ) )
698  {
699  BLong* plong = static_cast<BLong*>( what );
700  n = plong->value();
701  }
702  else if ( what->isa( BObjectImp::OTDouble ) )
703  {
704  Double* pdbl = static_cast<Double*>( what );
705  n = (int)pdbl->value();
706  }
707  else
708  {
709  to_stream << "<needs Int, Double>";
710  return false;
711  }
712  to_stream << std::dec << n;
713  }
714  else
715  {
716  to_stream << "<bad format: " << frmt << ">";
717  return false;
718  }
719  return true;
720 }
721 // --
722 
723 BObjectImp* String::call_method( const char* methodname, Executor& ex )
724 {
725  ObjMethod* objmethod = getKnownObjMethod( methodname );
726  if ( objmethod != NULL )
727  return this->call_method_id( objmethod->id, ex );
728  else
729  return NULL;
730 }
731 BObjectImp* String::call_method_id( const int id, Executor& ex, bool /*forcebuiltin*/ )
732 {
733  switch ( id )
734  {
735  case MTH_LENGTH:
736  if ( ex.numParams() == 0 )
737  return new BLong( static_cast<int>( value_.length() ) );
738  else
739  return new BError( "string.length() doesn't take parameters." );
740  break;
741  case MTH_FIND:
742  {
743  if ( ex.numParams() > 2 )
744  return new BError( "string.find(Search, [Start]) takes only two parameters" );
745  if ( ex.numParams() < 1 )
746  return new BError( "string.find(Search, [Start]) takes at least one parameter" );
747  const char* s = ex.paramAsString( 0 );
748  int d = 0;
749  if ( ex.numParams() == 2 )
750  d = ex.paramAsLong( 1 );
751  int posn = find( d ? ( d - 1 ) : 0, s ) + 1;
752  return new BLong( posn );
753  }
754  case MTH_UPPER:
755  {
756  if ( ex.numParams() == 0 )
757  {
758  toUpper();
759  return this;
760  }
761  else
762  return new BError( "string.upper() doesn't take parameters." );
763  }
764 
765  case MTH_LOWER:
766  {
767  if ( ex.numParams() == 0 )
768  {
769  toLower();
770  return this;
771  }
772  else
773  return new BError( "string.lower() doesn't take parameters." );
774  }
775  case MTH_FORMAT:
776  {
777  if ( ex.numParams() > 0 )
778  {
779  // string s = this->getStringRep(); // string itself
780  std::stringstream result;
781 
782  size_t tag_start_pos; // the position of tag's start "{"
783  size_t tag_stop_pos; // the position of tag's end "}"
784  size_t tag_dot_pos;
785 
786  int tag_param_idx;
787 
788  size_t str_pos = 0; // current string position
789  unsigned int next_param_idx = 0; // next index of .format() parameter
790 
791  char w_spaces[] = "\t ";
792 
793  // Tells whether last found tag was an integer
794  bool last_tag_was_int = true;
795 
796  while ( ( tag_start_pos = value_.find( '{', str_pos ) ) != std::string::npos )
797  {
798  if ( ( tag_stop_pos = value_.find( '}', tag_start_pos ) ) != std::string::npos )
799  {
800  result << value_.substr( str_pos, tag_start_pos - str_pos );
801  str_pos = tag_stop_pos + 1;
802 
803  std::string tag_body =
804  value_.substr( tag_start_pos + 1, ( tag_stop_pos - tag_start_pos ) - 1 );
805 
806  tag_start_pos = tag_body.find_first_not_of( w_spaces );
807  tag_stop_pos = tag_body.find_last_not_of( w_spaces );
808 
809  // cout << "' tag_body1: '" << tag_body << "'";
810 
811  // trim the tag of whitespaces (slightly faster code ~25%)
812  if ( tag_start_pos != std::string::npos && tag_stop_pos != std::string::npos )
813  tag_body = tag_body.substr( tag_start_pos, ( tag_stop_pos - tag_start_pos ) + 1 );
814  else if ( tag_start_pos != std::string::npos )
815  tag_body = tag_body.substr( tag_start_pos );
816  else if ( tag_stop_pos != std::string::npos )
817  tag_body = tag_body.substr( 0, tag_stop_pos + 1 );
818 
819  // s_trim( tag_body ); // trim the tag of whitespaces
820 
821  // cout << "' tag_body2: '" << tag_body << "'";
822 
823  std::string frmt;
824  size_t formatter_pos = tag_body.find( ':' );
825 
826  if ( formatter_pos != std::string::npos )
827  {
828  frmt = tag_body.substr( formatter_pos + 1, std::string::npos ); //
829  tag_body = tag_body.substr( 0, formatter_pos ); // remove property from the tag
830  }
831 
832  std::string prop_name;
833  // parsing {1.this_part}
834  tag_dot_pos = tag_body.find( '.', 0 );
835 
836  // '.' is found within the tag, there is a property name
837  if ( tag_dot_pos != std::string::npos )
838  {
839  last_tag_was_int = true;
840  prop_name = tag_body.substr( tag_dot_pos + 1, std::string::npos ); //
841  tag_body = tag_body.substr( 0, tag_dot_pos ); // remove property from the tag
842 
843  // if s_tag_body is numeric then use it as an index
844  if ( s_parse_int( tag_param_idx, tag_body ) )
845  {
846  tag_param_idx -= 1; // sinse POL indexes are 1-based
847  }
848  else
849  {
850  result << "<idx required before: '" << prop_name << "'>";
851  continue;
852  }
853  }
854  else
855  {
856  if ( tag_body == "" )
857  {
858  // empty body just takes next integer idx
859  last_tag_was_int = true;
860  tag_param_idx = next_param_idx++;
861  }
862  else if ( s_parse_int( tag_param_idx, tag_body ) )
863  {
864  last_tag_was_int = true;
865  tag_param_idx -= 1; // sinse POL indexes are 1-based
866  }
867  else
868  {
869  // string body takes next idx in line if this is
870  // the first string body occurrence,
871  // will reuse last idx if this is 2nd or more in a row
872  last_tag_was_int = false;
873  prop_name = tag_body;
874  tag_param_idx = last_tag_was_int ? next_param_idx++ : next_param_idx;
875  }
876  }
877 
878  // -- end of property parsing
879 
880  // cout << "prop_name: '" << prop_name << "' tag_body: '" << tag_body << "'";
881 
882  if ( (int)ex.numParams() <= tag_param_idx )
883  {
884  result << "<invalid index: #" << ( tag_param_idx + 1 ) << ">";
885  continue;
886  }
887 
888  BObjectImp* imp = ex.getParamImp( tag_param_idx );
889 
890  if ( !prop_name.empty() )
891  { // accesing object
892  BObjectRef obj_member = imp->get_member( prop_name.c_str() );
893  BObjectImp* member_imp = obj_member->impptr();
894  try_to_format( result, member_imp, frmt );
895  }
896  else
897  {
898  try_to_format( result, imp, frmt );
899  }
900  }
901  else
902  {
903  break;
904  }
905  }
906 
907  if ( str_pos < value_.length() )
908  {
909  result << value_.substr( str_pos, std::string::npos );
910  }
911 
912  return new String( result.str() );
913  }
914  else
915  {
916  return new BError( "string.format() requires a parameter." );
917  }
918  }
919  case MTH_JOIN:
920  {
921  BObject* cont;
922  if ( ex.numParams() == 1 && ( cont = ex.getParamObj( 0 ) ) != NULL )
923  {
924  if ( !( cont->isa( OTArray ) ) )
925  return new BError( "string.join expects an array" );
926  ObjArray* container = static_cast<ObjArray*>( cont->impptr() );
927  // no empty check here on purpose
928  OSTRINGSTREAM joined;
929  bool first = true;
930  for ( const BObjectRef& ref : container->ref_arr )
931  {
932  if ( ref.get() )
933  {
934  BObject* bo = ref.get();
935 
936  if ( bo == NULL )
937  continue;
938  if ( !first )
939  joined << value_;
940  else
941  first = false;
942  joined << bo->impptr()->getStringRep();
943  }
944  }
945  return new String( OSTRINGSTREAM_STR( joined ) );
946  }
947  else
948  return new BError( "string.join(array) requires a parameter." );
949  }
950  default:
951  return NULL;
952  }
953 }
954 }
955 }
virtual BObjectRef get_member(const char *membername)
Definition: object.cpp:930
virtual std::string getStringRep() const =0
virtual size_t sizeEstimate() const POL_OVERRIDE
Definition: str.cpp:160
const std::string & value() const
Definition: impstr.h:67
BObjectType type() const
Definition: bobject.h:358
int value() const
Definition: bobject.h:592
int find(int begin, const char *target)
Definition: str.cpp:170
void EStrReplace(String *str1, String *str2)
Definition: str.cpp:84
bool isa(BObjectType type) const
Definition: bobject.h:353
T * get() const
Definition: refptr.h:176
virtual void packonto(std::ostream &os) const POL_OVERRIDE
Definition: str.cpp:104
virtual std::string getStringRep() const POL_OVERRIDE
Definition: impstr.h:129
#define OSTRINGSTREAM_STR(x)
Definition: stlutil.h:76
virtual bool operator<(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:355
virtual BObjectRef OperMultiSubscriptAssign(std::stack< BObjectRef > &indices, BObjectImp *target) POL_OVERRIDE
Definition: str.cpp:427
ObjMethod * getKnownObjMethod(const char *token)
Definition: parser.cpp:665
int paramAsLong(unsigned param)
Definition: executor.cpp:240
void ESubStrReplace(String *replace_with, unsigned int index, unsigned int len)
Definition: str.cpp:94
const char * paramAsString(unsigned param)
Definition: executor.cpp:209
void toUpper(void)
Definition: str.cpp:368
virtual BObjectImp * selfPlusObj(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:231
String * midstring(int begin, int len) const
Definition: str.cpp:363
virtual std::string getStringRep() const POL_OVERRIDE
Definition: object.cpp:1404
BObject * getParamObj(unsigned param)
Definition: executor.cpp:276
virtual BObjectImp * selfMinusObj(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:290
void remove(const char *s)
Definition: str.cpp:277
virtual bool operator==(const BObjectImp &objimp) const
Definition: object.cpp:272
virtual bool operator==(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:345
void int_to_binstr(int &value, std::stringstream &s)
Definition: str.cpp:629
virtual BObjectRef OperSubscript(const BObject &obj) POL_OVERRIDE
Definition: str.cpp:555
virtual BObjectImp * copy() const POL_OVERRIDE
Definition: impstr.h:53
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: str.cpp:731
String * ETrim(const char *CRSet, int type)
Definition: str.cpp:42
virtual BObjectImp * selfPlusObjImp(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:227
#define OSTRINGSTREAM
Definition: stlutil.h:75
virtual BObjectRef OperMultiSubscript(std::stack< BObjectRef > &indices) POL_OVERRIDE
Definition: str.cpp:496
static UninitObject * create()
Definition: bobject.h:482
size_t numParams() const
Definition: executor.h:145
unsigned int alnumlen() const
Definition: str.cpp:182
unsigned int SafeCharAmt() const
Definition: str.cpp:192
static BObjectImp * unpack(const char *pstr)
Definition: str.cpp:113
void set(char *newstr)
Definition: str.cpp:220
String * StrStr(int begin, int len)
Definition: str.cpp:37
BObjectImp & impref()
Definition: bobject.h:438
virtual bool isTrue() const POL_OVERRIDE
Definition: impstr.h:86
virtual BObjectImp * call_method(const char *methodname, Executor &ex) POL_OVERRIDE
Definition: str.cpp:723
static BObjectImp * unpackWithLen(std::istream &is)
Definition: str.cpp:126
virtual BObjectImp * selfMinusObjImp(const BObjectImp &objimp) const POL_OVERRIDE
Definition: str.cpp:286
virtual std::string getStringRep() const POL_OVERRIDE
Definition: blong.cpp:122
virtual BObjectImp * selfMinusObj(const BObjectImp &objimp) const
Definition: object.cpp:414
std::string value_
Definition: impstr.h:142
virtual std::string pack() const POL_OVERRIDE
Definition: str.cpp:99
void s_trim(std::string &s)
Definition: str.cpp:621
void toLower(void)
Definition: str.cpp:376
double value() const
Definition: bobject.h:713
bool try_to_format(std::stringstream &to_stream, BObjectImp *what, std::string &frmt)
Definition: str.cpp:647
virtual BObjectImp * array_assign(BObjectImp *idx, BObjectImp *target, bool copy) POL_OVERRIDE
Definition: str.cpp:384
bool s_parse_int(int &i, std::string const &s)
Definition: str.cpp:602
virtual std::string getStringRep() const POL_OVERRIDE
Definition: dbl.cpp:101
Definition: berror.cpp:12
size_t length() const
Definition: impstr.h:68
virtual BObjectImp * selfPlusObj(const BObjectImp &objimp) const
Definition: object.cpp:365
BObjectImp * getParamImp(unsigned param)
Definition: executor.cpp:266