Logo Search packages:      
Sourcecode: falconpl version File versions  Download package

VMachine::returnCode Falcon::VMachine::expandString ( const String src,
String target 
)

Performs a string expansion.

Returns:
a returnCode enumeration explaining possible errors in string expansion

Definition at line 2639 of file vm.cpp.

References Falcon::String::append(), Falcon::Item::dereference(), Falcon::String::find(), findLocalVariable(), Falcon::String::getCharAt(), hadError(), itemToString(), Falcon::String::length(), and Falcon::String::subString().

{
   uint32 pos0 = 0;
   uint32 pos1 = src.find( "$" );
   uint32 len = src.length();
   while( pos1 != String::npos )
   {
      target.append( src.subString( pos0, pos1 ) );
      pos1++;
      if( pos1 == len )
      {
         return return_error_string;
      }

      typedef enum {
         none,
         token,
         open,
         singleQuote,
         doubleQuote,
         escapeSingle,
         escapeDouble,
         complete,
         complete1,
         noAction,
         fail
      }
      t_state;

      t_state state = none;

      pos0 = pos1;
      uint32 chr = 0;
      while( pos1 < len && state != fail && state != complete && state != complete1 && state != noAction )
      {
         chr = src.getCharAt( pos1 );
         switch( state )
         {
            case none:
               if( chr == '$' )
               {
                  target.append( '$' );
                  state = noAction;
                  break;
               }
               else if ( chr == '(' )
               {
                  // scan for balanced ')'
                  pos0 = pos1+1;
                  state = open;
               }
               else if ( chr < '@' )
               {
                  state = fail;
               }
               else {
                  state = token;
               }
            break;

            case token:
               // allow also ':' and '|'
               if( (( chr < '0' && chr != '.' && chr != '%' ) || ( chr > ':' && chr <= '@' ))
                  && chr != '|' && chr != '[' && chr != ']' )
               {
                  state = complete;
                  pos1--;
                  // else we do this below.
               }
            break;

            case open:
               if( chr == ')' )
                  state = complete1;
               else if ( chr == '\'' )
                  state = singleQuote;
               else if ( chr == '\"' )
                  state = doubleQuote;
               // else just continue
            break;

            case singleQuote:
               if( chr == '\'' )
                  state = open;
               else if ( chr == '\\' )
                  state = escapeSingle;
               // else just continue
            break;

            case doubleQuote:
               if( chr == '\"' )
                  state = open;
               else if ( chr == '\\' )
                  state = escapeDouble;
               // else just continue
            break;

            case escapeSingle:
               state = singleQuote;
            break;

            case escapeDouble:
               state = escapeDouble;
            break;
         }

         ++pos1;
      }

      // parse the result in to the target.
      switch( state )
      {
         case token:
         case complete:
         case complete1:
         {
            uint32 pos2 = pos1;
            if( state == complete1 )
            {
               pos2--;
            }

            // todo: record this while scanning
            uint32 posColon = src.find( ":", pos0, pos2 );
            uint32 posPipe = src.find( "|", pos0, pos2 );
            Item *itm;

            if( posColon != String::npos ) {
               itm = findLocalVariable( src.subString( pos0, posColon ) );
            }
            else if( posPipe != String::npos )
            {
               // parse the format
               itm = findLocalVariable( src.subString( pos0, posPipe ) );
            }
            else {
               itm = findLocalVariable( src.subString( pos0, pos2 ) );
            }

            if ( itm == 0 )
            {
               return return_error_parse;
            }

            String temp;
            // do we have a format?
            if( posColon != String::npos )
            {
               Format fmt( src.subString( posColon+1, pos2 ) );
               if( ! fmt.isValid() )
               {
                  return return_error_parse_fmt;
               }

               if( ! fmt.format( this, *itm->dereference(), temp ) ) {
                  if( hadError() ) {
                     return return_error_internal;
                  }
                  return return_error_parse_fmt;
               }
            }
            // do we have a toString parameter?
            else if( posPipe != String::npos )
            {
               itemToString( temp, itm, src.subString( posPipe+1, pos2 ) );
            }
            else {
               // otherwise, add the toString version (todo format)
               // append to target.
               itemToString( temp, itm );
            }

            // having an error in an itemToString ?
            if( hadError() )
                  return return_error_internal;

            target.append( temp );
         }
         break;

         case noAction:
         break;

         default:
            return return_error_string;
      }

      pos0 = pos1;
      pos1 = src.find( "$", pos1 );
   }

   // add the last segment
   if( pos0 != pos1 )
   {
      target.append( src.subString( pos0, pos1 ) );
   }
   return return_ok;
}


Generated by  Doxygen 1.6.0   Back to index