Diff for /parser3/src/classes/array.C between versions 1.11 and 1.22

version 1.11, 2024/09/28 14:15:13 version 1.22, 2024/10/23 16:41:11
Line 46  static void _create_or_add(Request& r, M Line 46  static void _create_or_add(Request& r, M
   
                 if(VArray* src=dynamic_cast<VArray*>(&vsrc)) {                  if(VArray* src=dynamic_cast<VArray*>(&vsrc)) {
                         if(src==&self)                          if(src==&self)
                                 throw Exception(PARSER_RUNTIME, 0, "source and destination are the same array");                                  return;
                         self_array.append(src->array());                          if(self_array.count()){
                                   for(ArrayValue::Iterator i(src->array()); i; i.next()){
                                           if(i.value())
                                                   self_array.put(i.index(), i.value());
                                   }
                           } else {
                                   self_array.append(src->array());
                           }
                 } else {                  } else {
                         HashStringValue* src_hash=vsrc.get_hash();                          HashStringValue* src_hash=vsrc.as_hash("param must be array or");
                         if(!src_hash)                          if(!src_hash)
                                 return;                                  return;
                         for(HashStringValue::Iterator i(*src_hash); i; i.next()){                          for(HashStringValue::Iterator i(*src_hash); i; i.next()){
Line 119  static void _join(Request& r, MethodPara Line 126  static void _join(Request& r, MethodPara
                         }                          }
                 }                  }
         } else {          } else {
                 HashStringValue* src_hash=vsrc.get_hash();                  HashStringValue* src_hash=vsrc.as_hash("param must be array or");
                 if(!src_hash)                  if(!src_hash)
                         return;                          return;
                 if(o.defined){                  if(o.defined){
Line 150  class SparseArray_sql_event_handlers: pu Line 157  class SparseArray_sql_event_handlers: pu
         ArrayValue& result;          ArrayValue& result;
         Value* row_value;          Value* row_value;
         int column_index;          int column_index;
         ArrayString& columns;          ArrayString* columns;
         bool one_bool_column;          bool one_bool_column;
         Table2hash_value_type value_type;          Table2hash_value_type value_type;
         int columns_count;          int columns_count;
Line 162  public: Line 169  public:
                 result(aresult),                  result(aresult),
                 row_value(0),                  row_value(0),
                 column_index(0),                  column_index(0),
                 columns(*new ArrayString),                  columns(new ArrayString),
                 one_bool_column(false),                  one_bool_column(false),
                 value_type(avalue_type),                  value_type(avalue_type),
                 empty(0) {                  empty(0) {
Line 170  public: Line 177  public:
   
         bool add_column(SQL_Error& error, const char* str, size_t ) {          bool add_column(SQL_Error& error, const char* str, size_t ) {
                 try {                  try {
                         columns+=&STRING(str);                          if(columns_count){
                                   // another query in multi_statements mode
                                   columns=new ArrayString;
                                   columns_count=0;
                           }
                           *columns+=&STRING(str);
                         return false;                          return false;
                 } catch(...) {                  } catch(...) {
                         error=SQL_Error("exception occurred in Hash_sql_event_handlers::add_column");                          error=SQL_Error("exception occurred in Hash_sql_event_handlers::add_column");
Line 179  public: Line 191  public:
         }          }
   
         bool before_rows(SQL_Error& error) {          bool before_rows(SQL_Error& error) {
                 if(columns.count()<1) {                  columns_count=columns->count();
                   if(columns_count<1) {
                         error=SQL_Error("no columns");                          error=SQL_Error("no columns");
                         return true;                          return true;
                 }                  }
                 if(columns.count()==1) {                  if(columns_count==1) {
                         one_bool_column=true;                          one_bool_column=true;
                 } else {                  } else {
                         switch(value_type){                          switch(value_type){
                                 case C_STRING: {                                  case C_STRING: {
                                         if(columns.count()>2){                                          if(columns_count>2){
                                                 error=SQL_Error("only 2 columns allowed for $.type[string] and $.sparse(true).");                                                  error=SQL_Error("only 2 columns allowed for $.type[string] and $.sparse(true)");
                                                 return true;                                                  return true;
                                         }                                          }
                                         break;                                          break;
                                 }                                  }
                                 case C_TABLE: {                                  case C_TABLE: {
                                         // create empty table which we'll copy later                                          // create empty table which we'll copy later
                                         empty=new Table(&columns);                                          empty=new Table(columns);
                                         columns_count=columns.count();  
                                         break;                                          break;
                                 }                                  }
                         }                          }
Line 212  public: Line 224  public:
   
         bool add_row_cell(SQL_Error& error, const char *str, size_t ) {          bool add_row_cell(SQL_Error& error, const char *str, size_t ) {
                 try {                  try {
                           if(column_index==columns_count){
                                   // should never happen, buggy driver case
                                   error=SQL_Error("columns index exceed the columns count");
                                   return true;
                           }
   
                         bool duplicate=false;                          bool duplicate=false;
                         if(one_bool_column) {                          if(one_bool_column) {
                                 size_t index=str ? pa_atoui(str) : 0;                                  size_t index=str ? pa_atoui(str) : 0;
Line 248  public: Line 266  public:
                                                 ArrayString* row=new ArrayString(columns_count);                                                  ArrayString* row=new ArrayString(columns_count);
                                                 *row+=&STRING(str);                                                  *row+=&STRING(str);
                                                 *vtable->get_table()+=row;                                                  *vtable->get_table()+=row;
                                                   row_value=(Value*)row;
                                                 break;                                                  break;
                                         }                                          }
                                 }                                  }
Line 255  public: Line 274  public:
                                 const String& cell=STRING(str);                                  const String& cell=STRING(str);
                                 switch(value_type) {                                  switch(value_type) {
                                         case C_HASH: {                                          case C_HASH: {
                                                 row_value->get_hash()->put(*columns[column_index], new VString(cell));                                                  row_value->get_hash()->put(*columns->get(column_index), new VString(cell));
                                                 break;                                                  break;
                                         }                                          }
                                         case C_STRING: {                                          case C_STRING: {
Line 292  class Array_sql_event_handlers: public S Line 311  class Array_sql_event_handlers: public S
         ArrayValue& result;          ArrayValue& result;
         Value* row_value;          Value* row_value;
         int column_index;          int column_index;
         ArrayString& columns;          ArrayString* columns;
         Table2hash_value_type value_type;          Table2hash_value_type value_type;
         int columns_count;          int columns_count;
 public:  public:
Line 302  public: Line 321  public:
                 result(aresult),                  result(aresult),
                 row_value(0),                  row_value(0),
                 column_index(0),                  column_index(0),
                 columns(*new ArrayString),                  columns(new ArrayString),
                 value_type(avalue_type),                  value_type(avalue_type),
                 empty(0) {                  empty(0) {
         }          }
   
         bool add_column(SQL_Error& error, const char* str, size_t ) {          bool add_column(SQL_Error& error, const char* str, size_t ) {
                 try {                  try {
                         columns+=&STRING(str);                          if(columns_count){
                                   // another query in multi_statements mode
                                   columns=new ArrayString;
                                   columns_count=0;
                           }
                           *columns+=&STRING(str);
                         return false;                          return false;
                 } catch(...) {                  } catch(...) {
                         error=SQL_Error("exception occurred in Hash_sql_event_handlers::add_column");                          error=SQL_Error("exception occurred in Hash_sql_event_handlers::add_column");
Line 318  public: Line 342  public:
         }          }
   
         bool before_rows(SQL_Error& error) {          bool before_rows(SQL_Error& error) {
                 if(columns.count()<1) {                  columns_count=columns->count();
                   if(columns_count<1) {
                         error=SQL_Error("no columns");                          error=SQL_Error("no columns");
                         return true;                          return true;
                 }                  }
                 switch(value_type){                  switch(value_type){
                         case C_STRING: {                          case C_STRING: {
                                 if(columns.count()>1){                                  if(columns_count>1){
                                         error=SQL_Error("only one column allowed for $.type[string].");                                          error=SQL_Error("only one column allowed for $.type[string]");
                                         return true;                                          return true;
                                 }                                  }
                                 break;                                  break;
                         }                          }
                         case C_TABLE: {                          case C_TABLE: {
                                 // create empty table which we'll copy later                                  // create empty table which we'll copy later
                                 empty=new Table(&columns);                                  empty=new Table(columns);
                                 columns_count=columns.count();  
                                 break;                                  break;
                         }                          }
                 }                  }
Line 347  public: Line 371  public:
   
         bool add_row_cell(SQL_Error& error, const char *str, size_t ) {          bool add_row_cell(SQL_Error& error, const char *str, size_t ) {
                 try {                  try {
                           if(column_index==columns_count){
                                   // should never happen, buggy driver case
                                   error=SQL_Error("columns index exceed the columns count");
                                   return true;
                           }
   
                         if(column_index==0) {                          if(column_index==0) {
                                 switch(value_type){                                  switch(value_type){
                                         case C_HASH: {                                          case C_HASH: {
Line 365  public: Line 395  public:
                                                 // creating table of same structure as source                                                  // creating table of same structure as source
                                                 Table::Action_options table_options(0, 0);                                                  Table::Action_options table_options(0, 0);
                                                 VTable* vtable=new VTable(new Table(*empty, table_options/*no rows, just structure*/));                                                  VTable* vtable=new VTable(new Table(*empty, table_options/*no rows, just structure*/));
                                                 result+=vtable;  
   
                                                 ArrayString* row=new ArrayString(columns_count);                                                  ArrayString* row=new ArrayString(columns_count);
                                                 *vtable->get_table()+=row;                                                  *vtable->get_table()+=row;
                                                   row_value=(Value*)row;
                                                   result+=vtable;
                                                 break;                                                  break;
                                         }                                          }
                                 }                                  }
Line 377  public: Line 407  public:
                         const String& cell=STRING(str);                          const String& cell=STRING(str);
                         switch(value_type) {                          switch(value_type) {
                                 case C_HASH: {                                  case C_HASH: {
                                         row_value->get_hash()->put(*columns[column_index], new VString(cell));                                          row_value->get_hash()->put(*columns->get(column_index), new VString(cell));
                                         break;                                          break;
                                 }                                  }
                                 case C_STRING: {                                  case C_STRING: {
Line 422  static void _sql(Request& r, MethodParam Line 452  static void _sql(Request& r, MethodParam
         if(params.count()>1)          if(params.count()>1)
                 if(HashStringValue* options=params.as_hash(1, "sql options")) {                  if(HashStringValue* options=params.as_hash(1, "sql options")) {
                         int valid_options=0;                          int valid_options=0;
                           bool distinct_specified=false;
                         for(HashStringValue::Iterator i(*options); i; i.next() ){                          for(HashStringValue::Iterator i(*options); i; i.next() ){
                                 String::Body key=i.key();                                  String::Body key=i.key();
                                 Value* value=i.value();                                  Value* value=i.value();
Line 436  static void _sql(Request& r, MethodParam Line 467  static void _sql(Request& r, MethodParam
                                         valid_options++;                                          valid_options++;
                                 } else if (key == sql_distinct_name) {                                  } else if (key == sql_distinct_name) {
                                         distinct=r.process(*value).as_bool();                                          distinct=r.process(*value).as_bool();
                                           distinct_specified=true;
                                         valid_options++;                                          valid_options++;
                                 } else if (key == sql_value_type_name) {                                  } else if (key == sql_value_type_name) {
                                         sparse=r.process(*value).as_bool();                                          value_type=get_value_type(r.process(*value));
                                         valid_options++;                                          valid_options++;
                                 } else if (key == "sparse") {                                  } else if (key == "sparse") {
                                         value_type=get_value_type(r.process(*value));                                          sparse=r.process(*value).as_bool();
                                         valid_options++;                                          valid_options++;
                                 }                                  }
                         }                          }
                         if(valid_options!=options->count())                          if(valid_options!=options->count())
                                 throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);                                  throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                           if(distinct_specified && !sparse)
                                   throw Exception(PARSER_RUNTIME, 0, "'distinct' option can only be used when $.sparse(true) is specified");
                 }                  }
   
         SQL_Driver::Placeholder* placeholders=0;          SQL_Driver::Placeholder* placeholders=0;
Line 458  static void _sql(Request& r, MethodParam Line 492  static void _sql(Request& r, MethodParam
         const char* statement_cstr=statement_string.untaint_cstr(String::L_SQL, r.connection());          const char* statement_cstr=statement_string.untaint_cstr(String::L_SQL, r.connection());
   
         VArray& self=GET_SELF(r, VArray);          VArray& self=GET_SELF(r, VArray);
                   ArrayValue& array=self.array();
         self.array().clear(); self.invalidate(); // just in case if called as method  
           array.clear(); self.invalidate(); // just in case if called as method
   
         if(sparse){          if(sparse){
                 SparseArray_sql_event_handlers handlers(distinct, self.array(), value_type);                  SparseArray_sql_event_handlers handlers(distinct, array, value_type);
                 r.connection()->query(statement_cstr, placeholders_count, placeholders, offset, limit, handlers, statement_string);                  r.connection()->query(statement_cstr, placeholders_count, placeholders, offset, limit, handlers, statement_string);
         } else {          } else {
                 Array_sql_event_handlers handlers(self.array(), value_type);                  Array_sql_event_handlers handlers(array, value_type);
                 r.connection()->query(statement_cstr, placeholders_count, placeholders, offset, limit, handlers, statement_string);                  r.connection()->query(statement_cstr, placeholders_count, placeholders, offset, limit, handlers, statement_string);
         }          }
   
           array.confirm_all_used();
   
         if(bind)          if(bind)
                 unmarshal_bind_updates(*bind, placeholders_count, placeholders);                  unmarshal_bind_updates(*bind, placeholders_count, placeholders);
 }  }
   
   
   
 static void mid(Request& r, size_t offset=0, size_t limit=ARRAY_OPTION_LIMIT_ALL) {  static void mid(Request& r, size_t offset=0, size_t limit=ARRAY_OPTION_LIMIT_ALL) {
         ArrayValue& array=GET_SELF(r, VArray).array();          ArrayValue& array=GET_SELF(r, VArray).array();
         if(limit>0){          if(limit>0){
Line 491  static void mid(Request& r, size_t offse Line 527  static void mid(Request& r, size_t offse
                                 result_array+=i.value();                                  result_array+=i.value();
                         }                          }
                 }                  }
                   result_array.confirm_all_used();
                 r.write(*result);                  r.write(*result);
         } else {          } else {
                 r.write(*new VArray);                  r.write(*new VArray);
Line 507  static void _right(Request& r, MethodPar Line 544  static void _right(Request& r, MethodPar
   
         if(sn>0){          if(sn>0){
                 size_t used=GET_SELF(r, VArray).array().used();                  size_t used=GET_SELF(r, VArray).array().used();
                 if(sn<used){                  if((size_t)sn<used){
                         mid(r, used-sn, sn);                          mid(r, used-sn, sn);
                 } else {                  } else {
                         mid(r);                          mid(r);
Line 518  static void _right(Request& r, MethodPar Line 555  static void _right(Request& r, MethodPar
 }  }
   
 static void _mid(Request& r, MethodParams& params) {  static void _mid(Request& r, MethodParams& params) {
         const String& string=GET_SELF(r, VString).string();  
   
         int begin=params.as_int(0, "p must be int", r);          int begin=params.as_int(0, "p must be int", r);
   
         if(begin<0)          if(begin<0)
                 throw Exception(PARSER_RUNTIME, 0,  "p(%d) must be >=0", begin);                  throw Exception(PARSER_RUNTIME, 0,  "p(%d) must be >=0", begin);
   
         size_t end;  
         size_t length=0;  
   
         if(params.count()>1) {          if(params.count()>1) {
                 int n=params.as_int(1, "n must be int", r);                  int n=params.as_int(1, "n must be int", r);
                 if(n<0)                  if(n<0)
Line 823  static void _sort(Request& r, MethodPara Line 856  static void _sort(Request& r, MethodPara
                 for(pos=0; pos<count; pos++)                  for(pos=0; pos<count; pos++)
                         array+=seq[pos].array_data;                          array+=seq[pos].array_data;
   
           self.invalidate();
         delete[] seq;          delete[] seq;
 }  }
   
Line 832  enum AtResultType { Line 866  enum AtResultType {
         AtResultTypeHash = 2          AtResultTypeHash = 2
 };  };
   
 inline Value& SingleElementHash(String::Body akey, Value* avalue) {  static Value& SingleElementHash(String::Body akey, Value* avalue) {
         Value& result=*new VHash;          Value& result=*new VHash;
         result.put_element(*new String(akey, String::L_TAINTED), avalue);          result.put_element(*new String(akey, String::L_TAINTED), avalue);
         return result;          return result;
Line 870  static void _at(Request& r, MethodParams Line 904  static void _at(Request& r, MethodParams
         }          }
   
         if(count && pos >= 0 && (size_t)pos < count){          if(count && pos >= 0 && (size_t)pos < count){
                 switch(result_type) {                  if(count == array.count()){
                         case AtResultTypeKey:                          switch(result_type) {
                                 {                                  case AtResultTypeKey:
                                         for(ArrayValue::Iterator i(array); i; i.next() ){                                          r.write(*new VString(*new String(pa_uitoa(pos), String::L_TAINTED)));
                                                 if(i.value() && !(pos--)){                                          break;
                                   case AtResultTypeValue:
                                           r.write(*array[pos]);
                                           break;
                                   case AtResultTypeHash:
                                           r.write(SingleElementHash(pa_uitoa(pos), array[pos]));
                                           break;
                           }
                   } else {
                           for(ArrayValue::Iterator i(array); i; i.next() ){
                                   if(i.value() && !(pos--)){
                                           switch(result_type) {
                                                   case AtResultTypeKey:
                                                         r.write(*new VString(*new String(i.key(), String::L_TAINTED)));                                                          r.write(*new VString(*new String(i.key(), String::L_TAINTED)));
                                                         break;                                                          break;
                                                 }                                                  case AtResultTypeValue:
                                         }  
                                         break;  
                                 }  
                         case AtResultTypeValue:  
                                 {  
                                         for(ArrayValue::Iterator i(array); i; i.next() )  
                                                 if(i.value() &&!(pos--)){  
                                                         r.write(*i.value());                                                          r.write(*i.value());
                                                         break;                                                          break;
                                                 }                                                  case AtResultTypeHash:
                                         break;  
                                 }  
                         case AtResultTypeHash:  
                                 {  
                                         for(ArrayValue::Iterator i(array); i; i.next() )  
                                                 if(i.value() &&!(pos--)){  
                                                         r.write(SingleElementHash(i.key(), i.value()));                                                          r.write(SingleElementHash(i.key(), i.value()));
                                                         break;                                                          break;
                                                 }                                          }
                                         break;                                          break;
                                 }                                  }
                           }
                 }                  }
         }          }
 }  }
Line 983  static void _select(Request& r, MethodPa Line 1017  static void _select(Request& r, MethodPa
                 }                  }
         }          }
   
           result_array.confirm_all_used();
         r.write(*result);          r.write(*result);
 }  }
   
 static void _reverse(Request& r, MethodParams& params) {  static void _reverse(Request& r, MethodParams&) {
         ArrayValue& source_array=GET_SELF(r, VArray).array();          ArrayValue& source_array=GET_SELF(r, VArray).array();
   
         VArray& result=*new VArray(source_array.count());          VArray& result=*new VArray(source_array.count());
Line 999  static void _reverse(Request& r, MethodP Line 1034  static void _reverse(Request& r, MethodP
         r.write(result);          r.write(result);
 }  }
   
   static void _compact(Request& r, MethodParams&) {
           GET_SELF(r, VArray).array().compact();
   }
   
   
 // constructor  // constructor
   
 MArray::MArray(): Methoded(VARRAY_TYPE) {  MArray::MArray(): Methoded(VARRAY_TYPE) {
   
         // ^array::create[[copy_from]]          // ^array::copy[[copy_from]]
         add_native_method("create", Method::CT_DYNAMIC, _create_or_add, 0, 1);          add_native_method("copy", Method::CT_DYNAMIC, _create_or_add, 0, 1);
         // ^array.add[add_from]          // ^array.add[add_from]
         add_native_method("add", Method::CT_DYNAMIC, _create_or_add, 1, 1);          add_native_method("add", Method::CT_DYNAMIC, _create_or_add, 1, 1);
         // ^array.join[join_from[;options]]          // ^array.join[join_from[;options]]
         add_native_method("join", Method::CT_DYNAMIC, _join, 1, 2);          add_native_method("join", Method::CT_DYNAMIC, _join, 1, 2);
   
           // ^array::create[value;value]
           add_native_method("create", Method::CT_DYNAMIC, _append, 0, 10000);
           // ^array.append[value;value]
           add_native_method("append", Method::CT_DYNAMIC, _append, 1, 10000);
           // ^array.insert[index;value...]
           add_native_method("insert", Method::CT_DYNAMIC, _insert, 2, 10000);
   
         // ^array.left(n)          // ^array.left(n)
         add_native_method("left", Method::CT_DYNAMIC, _left, 1, 1);          add_native_method("left", Method::CT_DYNAMIC, _left, 1, 1);
         // ^array.right(n)          // ^array.right(n)
Line 1019  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1065  MArray::MArray(): Methoded(VARRAY_TYPE)
         // ^array.mid(p;n)          // ^array.mid(p;n)
         add_native_method("mid", Method::CT_DYNAMIC, _mid, 1, 2);          add_native_method("mid", Method::CT_DYNAMIC, _mid, 1, 2);
   
         // ^array::new[value;value]  
         add_native_method("new", Method::CT_DYNAMIC, _append, 0, 10000);  
         // ^array.append[value;value]  
         add_native_method("append", Method::CT_DYNAMIC, _append, 1, 10000);  
         // ^array.insert[index;value...]  
         add_native_method("insert", Method::CT_DYNAMIC, _insert, 2, 10000);  
   
         // ^array.delete[index]          // ^array.delete[index]
         add_native_method("delete", Method::CT_DYNAMIC, _delete, 0, 1);          add_native_method("delete", Method::CT_DYNAMIC, _delete, 0, 1);
         // ^array.remove[index]          // ^array.remove[index]
Line 1058  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1097  MArray::MArray(): Methoded(VARRAY_TYPE)
         // ^array.reverse[]          // ^array.reverse[]
         add_native_method("reverse", Method::CT_DYNAMIC, _reverse, 0, 0);          add_native_method("reverse", Method::CT_DYNAMIC, _reverse, 0, 0);
   
           // ^array.compact[]
           add_native_method("compact", Method::CT_DYNAMIC, _compact, 0, 0);
   
         // ^array._at[first|last[;'key'|'value'|'hash']]          // ^array._at[first|last[;'key'|'value'|'hash']]
         // ^array._at([-+]offset)[['key'|'value'|'hash']]          // ^array._at([-+]offset)[['key'|'value'|'hash']]
         add_native_method("_at", Method::CT_DYNAMIC, _at, 1, 2);          add_native_method("_at", Method::CT_DYNAMIC, _at, 1, 2);
Line 1065  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1107  MArray::MArray(): Methoded(VARRAY_TYPE)
 #ifdef FEATURE_GET_ELEMENT4CALL  #ifdef FEATURE_GET_ELEMENT4CALL
         // aliases without "_"          // aliases without "_"
         add_native_method("keys", Method::CT_DYNAMIC, _keys, 0, 1);          add_native_method("keys", Method::CT_DYNAMIC, _keys, 0, 1);
         add_native_method("count", Method::CT_DYNAMIC, _count, 0, 0);          add_native_method("count", Method::CT_DYNAMIC, _count, 0, 1);
         add_native_method("at", Method::CT_DYNAMIC, _at, 1, 2);          add_native_method("at", Method::CT_DYNAMIC, _at, 1, 2);
 #endif  #endif
   

Removed from v.1.11  
changed lines
  Added in v.1.22


E-mail: