Diff for /parser3/src/classes/array.C between versions 1.28 and 1.41

version 1.28, 2024/10/27 13:22:13 version 1.41, 2025/05/28 00:58:02
Line 1 Line 1
 /** @file  /** @file
         Parser: @b array parser class.          Parser: @b array parser class.
   
         Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com)
         Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
 */  */
   
Line 53  static void _copy_or_add(Request& r, Met Line 53  static void _copy_or_add(Request& r, Met
                                                 self_array.put(i.index(), i.value());                                                  self_array.put(i.index(), i.value());
                                 }                                  }
                         } else {                          } else {
                                 self_array.append(src->array());                                  self_array.copy(src->array());
                                   return;
                         }                          }
                 } else {                  } else {
                         HashStringValue* src_hash=vsrc.as_hash("param must be array or");                          HashStringValue* src_hash=vsrc.as_hash("param must be array or");
Line 587  static void _keys(Request& r, MethodPara Line 588  static void _keys(Request& r, MethodPara
         for(ArrayValue::Iterator i(array); i; i.next()){          for(ArrayValue::Iterator i(array); i; i.next()){
                 if(i.value()){                  if(i.value()){
                         Table::element_type row(new ArrayString(1));                          Table::element_type row(new ArrayString(1));
                         *row+=new String(i.key(), String::L_TAINTED);                          *row+=new String(pa_uitoa(i.index()));
                         *table+=row;                          *table+=row;
                 }                  }
         }          }
Line 639  static void _insert(Request& r, MethodPa Line 640  static void _insert(Request& r, MethodPa
   
 static void _delete(Request& r, MethodParams& params) {  static void _delete(Request& r, MethodParams& params) {
         ArrayValue& array=GET_SELF(r, VArray).array();          ArrayValue& array=GET_SELF(r, VArray).array();
         if(params.count()>0)          if(params.count()>0) {
                 array.clear(VArray::index(params.as_int(0, PARAM_INDEX, r)));                  if(params[0].is_string()) {
         else                          array.clear(VArray::index(*params[0].get_string()));
                   } else {
                           array.clear(VArray::index(params.as_int(0, PARAM_INDEX, r)));
                   }
           } else
                 array.clear();                  array.clear();
         array.invalidate();          array.invalidate();
 }  }
Line 652  static void _remove(Request& r, MethodPa Line 657  static void _remove(Request& r, MethodPa
         array.invalidate();          array.invalidate();
 }  }
   
 static void _pop(Request& r, MethodParams& params) {  static void _pop(Request& r, MethodParams&) {
         ArrayValue& array=GET_SELF(r, VArray).array();          ArrayValue& array=GET_SELF(r, VArray).array();
         Value *result=array.pop();          Value *result=array.pop();
         if(result){          if(result){
Line 665  static void _pop(Request& r, MethodParam Line 670  static void _pop(Request& r, MethodParam
   
 static void _contains(Request& r, MethodParams& params) {  static void _contains(Request& r, MethodParams& params) {
         VArray& self=GET_SELF(r, VArray);          VArray& self=GET_SELF(r, VArray);
         bool result=self.contains(VArray::index(params.as_int(0, PARAM_INDEX, r)));  
           bool result=self.contains(params[0].is_string() ? VArray::index(*params[0].get_string()) : VArray::index(params.as_int(0, PARAM_INDEX, r)));
         r.write(VBool::get(result));          r.write(VBool::get(result));
 }  }
   
Line 685  static void _for(Request& r, MethodParam Line 691  static void _for(Request& r, MethodParam
   
         if(delim_maybe_code){ // delimiter set          if(delim_maybe_code){ // delimiter set
                 bool need_delim=false;                  bool need_delim=false;
                 for(ArrayValue::Iterator i(array); i; i.next()){                  for(ArrayValue::RobustIterator i(array); i; i.next()){
                         if(key_var_name){                          if(key_var_name)
                                 VString* vkey=new VString(*new String(i.key(), String::L_TAINTED));                                  r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                 r.put_element(caller, *key_var_name, vkey);  
                         }  
   
                         if(value_var_name)                          if(value_var_name)
                                 r.put_element(caller, *value_var_name, i.value() ? i.value() : VVoid::get());                                  r.put_element(caller, *value_var_name, i.value() ? i.value() : VVoid::get());
   
Line 711  static void _for(Request& r, MethodParam Line 714  static void _for(Request& r, MethodParam
                                 break;                                  break;
                 }                  }
         } else {          } else {
                 for(ArrayValue::Iterator i(array); i; i.next()){                  for(ArrayValue::RobustIterator i(array); i; i.next()){
                         if(key_var_name){                          if(key_var_name)
                                 VString* vkey=new VString(*new String(i.key(), String::L_TAINTED));                                  r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                 r.put_element(caller, *key_var_name, vkey);  
                         }  
   
                         if(value_var_name)                          if(value_var_name)
                                 r.put_element(caller, *value_var_name, i.value() ? i.value() : VVoid::get());                                  r.put_element(caller, *value_var_name, i.value() ? i.value() : VVoid::get());
   
Line 744  static void _foreach(Request& r, MethodP Line 744  static void _foreach(Request& r, MethodP
   
         if(delim_maybe_code){ // delimiter set          if(delim_maybe_code){ // delimiter set
                 bool need_delim=false;                  bool need_delim=false;
                 for(ArrayValue::Iterator i(array); i; i.next()){                  for(ArrayValue::RobustIterator i(array); i; i.next()){
                         if(i.value()){                          if(i.value()){
                                 if(key_var_name){                                  if(key_var_name)
                                         VString* vkey=new VString(*new String(i.key(), String::L_TAINTED));                                          r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                         r.put_element(caller, *key_var_name, vkey);  
                                 }  
   
                                 if(value_var_name)                                  if(value_var_name)
                                         r.put_element(caller, *value_var_name, i.value());                                          r.put_element(caller, *value_var_name, i.value());
   
Line 772  static void _foreach(Request& r, MethodP Line 769  static void _foreach(Request& r, MethodP
                         }                          }
                 }                  }
         } else {          } else {
                 for(ArrayValue::Iterator i(array); i; i.next()){                  for(ArrayValue::RobustIterator i(array); i; i.next()){
                         if(i.value()){                          if(i.value()){
                                 if(key_var_name){                                  if(key_var_name)
                                         VString* vkey=new VString(*new String(i.key(), String::L_TAINTED));                                          r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                         r.put_element(caller, *key_var_name, vkey);  
                                 }  
   
                                 if(value_var_name)                                  if(value_var_name)
                                         r.put_element(caller, *value_var_name, i.value());                                          r.put_element(caller, *value_var_name, i.value());
   
Line 836  static void _sort(Request& r, MethodPara Line 830  static void _sort(Request& r, MethodPara
         int pos=0;          int pos=0;
         bool key_values_are_strings=true;          bool key_values_are_strings=true;
   
         for(ArrayValue::Iterator i(array); i; i.next() ){          for(ArrayValue::RobustIterator i(array); i; i.next() ){
                 if(i.value()){                  if(i.value()){
                         if(key_var)                          if(key_var)
                                 r.put_element(*context, *key_var, new VString(*new String(i.key(), String::L_TAINTED)));                                  r.put_element(*context, *key_var, VString::uitoa(i.index()));
                         if(value_var)                          if(value_var)
                                 r.put_element(*context, *value_var, i.value());                                  r.put_element(*context, *value_var, i.value());
   
Line 893  static void _at(Request& r, MethodParams Line 887  static void _at(Request& r, MethodParams
         ArrayValue& array=GET_SELF(r, VArray).array();          ArrayValue& array=GET_SELF(r, VArray).array();
         size_t count=array.used(); // not array.count()          size_t count=array.used(); // not array.count()
   
         int pos=0;  
   
         AtResultType result_type=AtResultTypeValue;          AtResultType result_type=AtResultTypeValue;
         if(params.count() > 1) {          if(params.count() > 1) {
                 const String& stype=params.as_string(1, "type must be string");                  const String& stype=params.as_string(1, "type must be string");
Line 906  static void _at(Request& r, MethodParams Line 898  static void _at(Request& r, MethodParams
                         throw Exception(PARSER_RUNTIME, &stype, "type must be 'key', 'value' or 'hash'");                          throw Exception(PARSER_RUNTIME, &stype, "type must be 'key', 'value' or 'hash'");
         }          }
   
         Value& vwhence=params[0];          int pos=params.as_index(0, count, r);
         if(vwhence.is_string()) {  
                 const String& swhence=*vwhence.get_string();  
                 if(swhence == "last")  
                         pos=count-1;  
                 else if(swhence != "first")  
                         throw Exception(PARSER_RUNTIME, &swhence, "whence must be 'first', 'last' or expression");  
         } else {  
                 pos=r.process(vwhence).as_int();  
                 if(pos < 0)  
                         pos+=count;  
         }  
   
         if(count && pos >= 0 && (size_t)pos < count){          if(count && pos >= 0 && (size_t)pos < count){
                 if(count == array.count()){                  if(count == array.count()){
                         switch(result_type) {  l1:                     switch(result_type) {
                                 case AtResultTypeKey:                                  case AtResultTypeKey:
                                         r.write(*new VString(*new String(pa_uitoa(pos), String::L_TAINTED)));                                          r.write(*VString::uitoa(pos));
                                         break;                                          break;
                                 case AtResultTypeValue:                                  case AtResultTypeValue:
                                         r.write(*array.get(pos));                                          r.write(*array.get(pos));
                                         break;                                          break;
                                 case AtResultTypeHash:                                  case AtResultTypeHash:
                                         r.write(SingleElementHash(pa_uitoa(pos), array.get(pos)));                                          r.write(SingleElementHash(String::Body::uitoa(pos), array.get(pos)));
                                         break;                                          break;
                         }                          }
                   } else if((size_t)pos == count-1){
                           pos=array.count()-1;
                           goto l1;
                 } else {                  } else {
                         for(ArrayValue::Iterator i(array); i; i.next() ){                          for(ArrayValue::Iterator i(array); i; i.next() ){
                                 if(i.value() && !(pos--)){                                  if(i.value() && !(pos--)){
                                         switch(result_type) {                                          switch(result_type) {
                                                 case AtResultTypeKey:                                                  case AtResultTypeKey:
                                                         r.write(*new VString(*new String(i.key(), String::L_TAINTED)));                                                          r.write(*VString::uitoa(i.index()));
                                                         break;                                                          break;
                                                 case AtResultTypeValue:                                                  case AtResultTypeValue:
                                                         r.write(*i.value());                                                          r.write(*i.value());
                                                         break;                                                          break;
                                                 case AtResultTypeHash:                                                  case AtResultTypeHash:
                                                         r.write(SingleElementHash(i.key(), i.value()));                                                          r.write(SingleElementHash(String::Body::uitoa(i.index()), i.value()));
                                                         break;                                                          break;
                                         }                                          }
                                         break;                                          break;
Line 953  static void _at(Request& r, MethodParams Line 937  static void _at(Request& r, MethodParams
         }          }
 }  }
   
   static void _set(Request& r, MethodParams& params) {
           ArrayValue& array=GET_SELF(r, VArray).array();
           size_t count=array.used(); // not array.count()
   
           int pos=params.as_index(0, count, r);
   
           if(count && pos >= 0 && (size_t)pos < count){
                   if(count == array.count()){
                           array.put(pos, &r.process(params[1]));
                           return;
                   } else if((size_t)pos == count-1){
                           array.put(array.count()-1, &r.process(params[1]));
                           return;
                   } else {
                           for(ArrayValue::Iterator i(array); i; i.next() ){
                                   if(i.value() && !(pos--)){
                                           array.put(i.index(), &r.process(params[1]));
                                           return;
                                   }
                           }
                   }
           }
   
           if(count)
                   throw Exception(PARSER_RUNTIME, 0, "index '%d' is out of range 0..%d", pos, count-1);
           throw Exception(PARSER_RUNTIME, 0, "index '%d' is out of range: array is empty", pos);
   }
   
 extern String table_reverse_name;  extern String table_reverse_name;
   
Line 994  static void _select(Request& r, MethodPa Line 1005  static void _select(Request& r, MethodPa
                         for(ArrayValue::ReverseIterator i(source_array); i; ){                          for(ArrayValue::ReverseIterator i(source_array); i; ){
                                 if(Value *value=i.prev()){ // here for correct i.key()                                  if(Value *value=i.prev()){ // here for correct i.key()
                                         if(key_var_name)                                          if(key_var_name)
                                                 r.put_element(caller, *key_var_name, new VString(*new String(i.key(), String::L_TAINTED)));                                                  r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                         if(value_var_name)                                          if(value_var_name)
                                                 r.put_element(caller, *value_var_name, value);                                                  r.put_element(caller, *value_var_name, value);
   
Line 1011  static void _select(Request& r, MethodPa Line 1022  static void _select(Request& r, MethodPa
                                 }                                  }
                         }                          }
                 } else {                  } else {
                         for(ArrayValue::Iterator i(source_array); i; i.next() ){                          for(ArrayValue::RobustIterator i(source_array); i; i.next() ){
                                 if(Value *value=i.value()){                                  if(Value *value=i.value()){
                                         if(key_var_name)                                          if(key_var_name)
                                                 r.put_element(caller, *key_var_name, new VString(*new String(i.key(), String::L_TAINTED)));                                                  r.put_element(caller, *key_var_name, VString::uitoa(i.index()));
                                         if(value_var_name)                                          if(value_var_name)
                                                 r.put_element(caller, *value_var_name, value);                                                  r.put_element(caller, *value_var_name, value);
   
Line 1083  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1094  MArray::MArray(): Methoded(VARRAY_TYPE)
         add_native_method("append", Method::CT_DYNAMIC, _create_or_append_or_push, 1, 10000);          add_native_method("append", Method::CT_DYNAMIC, _create_or_append_or_push, 1, 10000);
         // ^array.push[value[;value...]]          // ^array.push[value[;value...]]
         add_native_method("push", Method::CT_DYNAMIC, _create_or_append_or_push, 1, 10000);          add_native_method("push", Method::CT_DYNAMIC, _create_or_append_or_push, 1, 10000);
         // ^array.insert[index;value[;value...]]          // ^array.insert(index)[value[;value...]]
         add_native_method("insert", Method::CT_DYNAMIC, _insert, 2, 10000);          add_native_method("insert", Method::CT_DYNAMIC, _insert, 2, 10000);
   
         // ^array.left(n)          // ^array.left(n)
Line 1094  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1105  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.delete[index]          // ^array.delete(index) or ^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)
         add_native_method("remove", Method::CT_DYNAMIC, _remove, 1, 1);          add_native_method("remove", Method::CT_DYNAMIC, _remove, 1, 1);
         // ^array.pop[]          // ^array.pop[]
         add_native_method("pop", Method::CT_DYNAMIC, _pop, 0, 0);          add_native_method("pop", Method::CT_DYNAMIC, _pop, 0, 0);
   
         // ^array.contains[index]          // ^array.contains(index) ^array.contains[index]
         add_native_method("contains", Method::CT_DYNAMIC, _contains, 1, 1);          add_native_method("contains", Method::CT_DYNAMIC, _contains, 1, 1);
   
         // ^array::sql[query][options array]          // ^array::sql[query][options array]
Line 1132  MArray::MArray(): Methoded(VARRAY_TYPE) Line 1143  MArray::MArray(): Methoded(VARRAY_TYPE)
         add_native_method("compact", Method::CT_DYNAMIC, _compact, 0, 1);          add_native_method("compact", Method::CT_DYNAMIC, _compact, 0, 1);
   
         // ^array._at[first|last[;'key'|'value'|'hash']]          // ^array._at[first|last[;'key'|'value'|'hash']]
         // ^array._at([-+]offset)[['key'|'value'|'hash']]          // ^array._at([-+]index)[['key'|'value'|'hash']]
         add_native_method("_at", Method::CT_DYNAMIC, _at, 1, 2);          add_native_method("_at", Method::CT_DYNAMIC, _at, 1, 2);
   
           // ^array.set[first|last;value]
           // ^array.set([-+]index)[value]
           add_native_method("set", Method::CT_DYNAMIC, _set, 2, 2);
   
 #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);

Removed from v.1.28  
changed lines
  Added in v.1.41


E-mail: