Diff for /parser3/src/classes/string.C between versions 1.64 and 1.78

version 1.64, 2001/07/20 09:40:46 version 1.78, 2001/10/09 07:06:00
Line 2 Line 2
         Parser: @b string parser class.          Parser: @b string parser class.
   
         Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
   
         Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)          Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
   
           $Id$
 */  */
 static const char *RCSId="$Id$";   
   
 #include "classes.h"  #include "classes.h"
 #include "pa_request.h"  #include "pa_request.h"
Line 15  static const char *RCSId="$Id$"; Line 15  static const char *RCSId="$Id$";
 #include "pa_vbool.h"  #include "pa_vbool.h"
 #include "pa_string.h"  #include "pa_string.h"
 #include "pa_sql_connection.h"  #include "pa_sql_connection.h"
   #include "pa_dictionary.h"
   
 // defines  // defines
   
Line 38  static void _length(Request& r, const St Line 39  static void _length(Request& r, const St
         r.write_no_lang(result);          r.write_no_lang(result);
 }  }
   
 static void _int(Request& r, const String& method_name, MethodParams *) {  static void _int(Request& r, const String& method_name, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
         Value& result=*new(pool) VInt(pool, r.self->as_int());          bool convert_problem=false; Exception rethrow_me;
           int converted;
           PTRY {
                   converted=r.self->as_int();
           }
           PCATCH(e) { // convert problem
                   if(convert_problem=params->size()==0) { // we have a problem when do not have default
                           rethrow_me=e;  
                           converted=0;
                   } else
                           converted=params->as_int(0, "default must be int", r); // (default)
           }
           PEND_CATCH
           if(convert_problem)
                   PTHROW(rethrow_me.type(), rethrow_me.code(), 
                           rethrow_me.problem_source(),
                           rethrow_me.comment());
   
           Value& result=*new(pool) VInt(pool, converted);
         result.set_name(method_name);          result.set_name(method_name);
         r.write_no_lang(result);          r.write_no_lang(result);
 }  }
   
 static void _double(Request& r, const String& method_name, MethodParams *) {  static void _double(Request& r, const String& method_name, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
         Value& result=*new(pool) VDouble(pool, r.self->as_double());          bool convert_problem=false; Exception rethrow_me;
           double converted;
           PTRY {
                   converted=r.self->as_double();
           }
           PCATCH(e) { // convert problem
                   if(convert_problem=params->size()==0) { // we have a problem when do not have default
                           rethrow_me=e;  
                           converted=0;
                   } else
                           converted=params->as_double(0, "default must be double", r); // (default)
           }
           PEND_CATCH
           if(convert_problem)
                   PTHROW(rethrow_me.type(), rethrow_me.code(), 
                           rethrow_me.problem_source(),
                           rethrow_me.comment());
   
           Value& result=*new(pool) VDouble(pool, converted);
         result.set_name(method_name);          result.set_name(method_name);
         r.write_no_lang(result);          r.write_no_lang(result);
 }  }
Line 70  static void _double(Request& r, const St Line 107  static void _double(Request& r, const St
 static void _left(Request& r, const String&, MethodParams *params) {  static void _left(Request& r, const String&, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         size_t n=(size_t)r.process(params->get(0)).as_double();          size_t n=(size_t)params->as_int(0, "n must be int", r);
                   
         const String& string=*static_cast<VString *>(r.self)->get_string();          const String& string=*static_cast<VString *>(r.self)->get_string();
         r.write_assign_lang(*new(pool) VString(string.mid(0, n)));          r.write_assign_lang(*new(pool) VString(string.mid(0, n)));
Line 79  static void _left(Request& r, const Stri Line 116  static void _left(Request& r, const Stri
 static void _right(Request& r, const String&, MethodParams *params) {  static void _right(Request& r, const String&, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         size_t n=(size_t)r.process(params->get(0)).as_double();          size_t n=(size_t)params->as_int(0, "n must be int", r);
                   
         const String& string=*static_cast<VString *>(r.self)->get_string();          const String& string=*static_cast<VString *>(r.self)->get_string();
         r.write_assign_lang(*new(pool) VString(string.mid(string.size()-n, string.size())));          r.write_assign_lang(*new(pool) VString(string.mid(string.size()-n, string.size())));
Line 88  static void _right(Request& r, const Str Line 125  static void _right(Request& r, const Str
 static void _mid(Request& r, const String&, MethodParams *params) {  static void _mid(Request& r, const String&, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         size_t p=(size_t)r.process(params->get(0)).as_double();          size_t p=(size_t)params->as_int(0, "p must be int", r);
         size_t n=(size_t)r.process(params->get(1)).as_double();          size_t n=(size_t)params->as_int(1, "n must be int", r);
                   
         const String& string=*static_cast<VString *>(r.self)->get_string();          const String& string=*static_cast<VString *>(r.self)->get_string();
         r.write_assign_lang(*new(pool) VString(string.mid(p, p+n)));          r.write_assign_lang(*new(pool) VString(string.mid(p, p+n)));
Line 124  static void _lsplit(Request& r, const St Line 161  static void _lsplit(Request& r, const St
   
         Table& table=*new(pool) Table(pool, &string,           Table& table=*new(pool) Table(pool, &string, 
                 &columns, pieces.size());                  &columns, pieces.size());
         int size=pieces.quick_size();          Array_iter i(pieces);
         for(int i=0; i<size; i++) {          while(i.has_next()) {
                 Array& row=*new(pool) Array(pool);                  Array& row=*new(pool) Array(pool);
                 row+=pieces.quick_get(i);                  row+=i.next();
                 table+=&row;                  table+=&row;
         }          }
         r.write_no_lang(*new(pool) VTable(pool, &table));          r.write_no_lang(*new(pool) VTable(pool, &table));
Line 159  static void search_action(Table& table, Line 196  static void search_action(Table& table,
                 table+=row;                  table+=row;
 }  }
   
 /// used by string: _match / replace_action  #ifndef DOXYGEN
 struct Replace_action_info {  struct Replace_action_info {
         Request *request;  const String *origin;          Request *request;  const String *origin;
         const String *src;  String *dest;          const String *src;  String *dest;
         Value *replacement_code;          Value *replacement_code;
         const String *post_match;          const String *post_match;
 };  };
   #endif
 static void replace_action(Table& table, Array *row, int start, int finish,   static void replace_action(Table& table, Array *row, int start, int finish, 
                                                            void *info) {                                                             void *info) {
         Replace_action_info& ai=*static_cast<Replace_action_info *>(info);          Replace_action_info& ai=*static_cast<Replace_action_info *>(info);
Line 183  static void replace_action(Table& table, Line 221  static void replace_action(Table& table,
                         vtable.set_name(*ai.origin);                          vtable.set_name(*ai.origin);
   
                         Junction *junction=ai.replacement_code->get_junction();                          Junction *junction=ai.replacement_code->get_junction();
                         junction->rcontext=/*must be some way to get to                           Value *saved_match_var_value=junction->root->get_element(*match_var_name);
                                                            outside world junction->root=*/&vtable;                          junction->root->put_element(*match_var_name, &vtable);
                         Value& replaced=ai.request->process(*ai.replacement_code, ai.origin, false);                          Value& replaced=ai.request->process(*ai.replacement_code, ai.origin, false);
                           junction->root->put_element(*match_var_name, saved_match_var_value);
   
                         /*                          /*
                         ai.dest->APPEND_CONST("(");                          ai.dest->APPEND_CONST("(");
Line 215  static void _match(Request& r, const Str Line 254  static void _match(Request& r, const Str
         Table *table;          Table *table;
         if(params->size()<3) { // search          if(params->size()<3) { // search
                 bool was_global;                  bool was_global;
                 bool matched=src.match(r.pcre_tables,                  bool matched=src.match(r.pcre_tables(),
                         &method_name,                           &method_name, 
                         regexp.as_string(), options,                          regexp.as_string(), options,
                         &table,                          &table,
Line 237  static void _match(Request& r, const Str Line 276  static void _match(Request& r, const Str
                         &replacement_code,                          &replacement_code,
                         &src                          &src
                 };                  };
                 src.match(r.pcre_tables,                  src.match(r.pcre_tables(),
                         &method_name,                           &method_name, 
                         r.process(regexp).as_string(), options,                          r.process(regexp).as_string(), options,
                         &table,                          &table,
Line 253  static void change_case(Request& r, cons Line 292  static void change_case(Request& r, cons
         Pool& pool=r.pool();          Pool& pool=r.pool();
         const String& src=*static_cast<VString *>(r.self)->get_string();          const String& src=*static_cast<VString *>(r.self)->get_string();
   
         r.write_assign_lang(*new(pool) VString(src.change_case(pool, r.pcre_tables,          r.write_assign_lang(*new(pool) VString(src.change_case(pool, r.pcre_tables(),
                 kind)));                  kind)));
 }  }
 static void _upper(Request& r, const String& method_name, MethodParams *params) {  static void _upper(Request& r, const String& method_name, MethodParams *params) {
Line 263  static void _lower(Request& r, const Str Line 302  static void _lower(Request& r, const Str
         change_case(r, method_name, params, String::CC_LOWER);          change_case(r, method_name, params, String::CC_LOWER);
 }  }
   
 const String* sql_result_string(Request& r, const String& method_name, MethodParams *params) {  #ifndef DOXYGEN
   class String_sql_event_handlers : public SQL_Driver_query_event_handlers {
   public:
           String_sql_event_handlers(Pool& apool, 
                   const String& astatement_string, const char *astatement_cstr) :
                   pool(apool), 
                   statement_string(astatement_string),
                   statement_cstr(astatement_cstr),
                   got_column(false), got_cell(false) {
                   result=new(pool) String(pool);
           }
   
           void add_column(void *ptr, size_t size) {
                   if(got_column)
                           PTHROW(0, 0,
                                   &statement_string,
                                   "result must contain exactly one column");
                   got_column=true;
           }
           void before_rows() { /* ignore */ }
           void add_row() { /* ignore */ }
           void add_row_cell(void *ptr, size_t size) {
                   if(got_cell)
                           PTHROW(0, 0,
                                   &statement_string,
                                   "result must not contain more then one row");
                   got_cell=true;
   
                   result->APPEND_TAINTED((const char *)ptr, size, statement_cstr, 0);
           }
   
   private:
           Pool& pool;
           const String& statement_string; const char *statement_cstr;
           bool got_column;
   public:
           bool got_cell;
           String *result;
   };
   #endif
   const String* sql_result_string(Request& r, const String& method_name, MethodParams *params,
                                                                   Hash *&options) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         if(!r.connection)          if(!r.connection)
Line 273  const String* sql_result_string(Request& Line 353  const String* sql_result_string(Request&
   
         Value& statement=params->as_junction(0, "statement must be code");          Value& statement=params->as_junction(0, "statement must be code");
   
         ulong offset=(ulong)(params->size()>2?params->as_int(2, r):0);          ulong limit=0;
           ulong offset=0;
           if(params->size()>1) {
                   Value& voptions=params->as_no_junction(1, "options must be hash, not code");
                   if(voptions.is_defined())
                           if(options=voptions.get_hash()) {
                                   if(Value *vlimit=(Value *)options->get(*sql_limit_name))
                                           limit=(ulong)r.process(*vlimit).as_double();
                                   if(Value *voffset=(Value *)options->get(*sql_offset_name))
                                           offset=(ulong)r.process(*voffset).as_double();
                           } else
                                   PTHROW(0, 0,
                                           &method_name,
                                           "options must be hash");
           } else
                   options=0;
   
         Temp_lang temp_lang(r, String::UL_SQL);          Temp_lang temp_lang(r, String::UL_SQL);
         const String& statement_string=r.process(statement).as_string();          const String& statement_string=r.process(statement).as_string();
         const char *statement_cstr=          const char *statement_cstr=
                 statement_string.cstr(String::UL_UNSPECIFIED, r.connection);                  statement_string.cstr(String::UL_UNSPECIFIED, r.connection);
         unsigned int sql_column_count; SQL_Driver::Cell *sql_columns;          String_sql_event_handlers handlers(pool, statement_string, statement_cstr);
         unsigned long sql_row_count; SQL_Driver::Cell **sql_rows;  
         bool need_rethrow=false; Exception rethrow_me;          bool need_rethrow=false; Exception rethrow_me;
         PTRY {          PTRY {
                 r.connection->query(                  r.connection->query(
                         statement_cstr, offset, 0,                          statement_cstr, offset, limit, 
                         &sql_column_count, &sql_columns,                          handlers);
                         &sql_row_count, &sql_rows);  
         }          }
         PCATCH(e) { // query problem          PCATCH(e) { // query problem
                 rethrow_me=e;  need_rethrow=true;                  rethrow_me=e;  need_rethrow=true;
Line 297  const String* sql_result_string(Request& Line 390  const String* sql_result_string(Request&
                         &statement_string, // setting more specific source [were url]                          &statement_string, // setting more specific source [were url]
                         rethrow_me.comment());                          rethrow_me.comment());
                   
         if(sql_column_count!=1)          if(!handlers.got_cell)
                 PTHROW(0, 0,                  return 0; // no lines, caller should return second param[default value]
                         &statement_string,  
                         "result must contain exactly one column");  
   
         if(!sql_row_count)          return handlers.result;
                 return 0; // no lines, should return second param[default value]  
   
         if(sql_row_count>1)  
                 PTHROW(0, 0,  
                         &statement_string,  
                         "result must not contain more then one row");     
   
         String *result=new(pool) String(pool);  
         SQL_Driver::Cell& cell=sql_rows[0][0];  
         result->APPEND_TAINTED(  
                 (const char *)cell.ptr, cell.size,  
                 statement_cstr, 0);  
           
         return result;  
 }  }
   
 static void _sql(Request& r, const String& method_name, MethodParams *params) {  static void _sql(Request& r, const String& method_name, MethodParams *params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         const String *string=sql_result_string(r, method_name, params);          Hash *options;
           const String *string=sql_result_string(r, method_name, params, options);
         if(!string) {          if(!string) {
                 Value& default_code=params->as_junction(1, "default result must code");                  if(options) {
                 Value& processed_code=r.process(default_code);                          if(Value *vdefault=(Value *)options->get(*sql_default_name)) {
                 string=processed_code.get_string();                                  if(!vdefault->get_junction())
                 if(!string)                                          PTHROW(0, 0,
                         string=empty_string;                                                  &method_name,
                                                   "default option must be code");
                                   string=r.process(*vdefault).get_string();
                                   if(!string)
                                           string=empty_string;
                           } else
                                   PTHROW(0, 0,
                                           &method_name,
                                           "produced no result, but no default option specified");
                   } else
                           PTHROW(0, 0,
                                   &method_name,
                                   "produced no result, but no options (no default) specified");
         }          }
         VString& result=*new(pool) VString(*string);          VString& result=*new(pool) VString(*string);
         result.set_name(method_name);          result.set_name(method_name);
         r.write_assign_lang(result);          r.write_assign_lang(result);
 }  }
   
   static void _replace(Request& r, const String& method_name, MethodParams *params) {
           Pool& pool=r.pool();
           const String& src=*static_cast<VString *>(r.self)->get_string();
   
           Table *table=params->as_no_junction(0, "parameter must not be code").get_table();
           if(!table)
                   PTHROW(0, 0,
                           &method_name,
                           "parameter must be table");
   
           Dictionary dict(*table);
           r.write_assign_lang(*new(pool) VString(src.replace(pool, dict)));
   }
 // constructor  // constructor
   
 MString::MString(Pool& apool) : Methoded(apool) {  MString::MString(Pool& apool) : Methoded(apool) {
Line 345  MString::MString(Pool& apool) : Methoded Line 448  MString::MString(Pool& apool) : Methoded
         add_native_method("length", Method::CT_DYNAMIC, _length, 0, 0);          add_native_method("length", Method::CT_DYNAMIC, _length, 0, 0);
                   
         // ^string.int[]          // ^string.int[]
         add_native_method("int", Method::CT_DYNAMIC, _int, 0, 0);          // ^string.int(default)
                   add_native_method("int", Method::CT_DYNAMIC, _int, 0, 1);
         // ^string.double[]          // ^string.double[]
         add_native_method("double", Method::CT_DYNAMIC, _double, 0, 0);          // ^string.double(default)
           add_native_method("double", Method::CT_DYNAMIC, _double, 0, 1);
   
         // ^string.format{format}          // ^string.format{format}
         add_native_method("format", Method::CT_DYNAMIC, _string_format, 1, 1);          add_native_method("format", Method::CT_DYNAMIC, _string_format, 1, 1);
Line 377  MString::MString(Pool& apool) : Methoded Line 481  MString::MString(Pool& apool) : Methoded
         // ^string.tolower[]          // ^string.tolower[]
         add_native_method("lower", Method::CT_DYNAMIC, _lower, 0, 0);          add_native_method("lower", Method::CT_DYNAMIC, _lower, 0, 0);
   
         // ^string:sql[query]{default}          // ^sql[query]
         // ^string:sql[query]{default}(offset)          // ^sql[query][$.limit(1) $.offset(2) $.default[n/a]]
         add_native_method("sql", Method::CT_STATIC, _sql, 2, 3);          add_native_method("sql", Method::CT_STATIC, _sql, 1, 2);
   
           // ^string.replace[table]
           add_native_method("replace", Method::CT_DYNAMIC, _replace, 1, 1);
 }         }       
   
 // global variable  // global variable

Removed from v.1.64  
changed lines
  Added in v.1.78


E-mail: