Diff for /parser3/src/classes/table.C between versions 1.294 and 1.302

version 1.294, 2013/07/23 14:29:02 version 1.302, 2015/04/06 22:27:25
Line 124  struct TableSeparators { Line 124  struct TableSeparators {
                 }                  }
                 if(Value* vencloser=options.get(PA_COLUMN_ENCLOSER_NAME)) {                  if(Value* vencloser=options.get(PA_COLUMN_ENCLOSER_NAME)) {
                         sencloser=&vencloser->as_string();                          sencloser=&vencloser->as_string();
                           if(sencloser->is_empty()){
                                   encloser=0;
                           } else {
                         if(sencloser->length()!=1)                          if(sencloser->length()!=1)
                                 throw Exception(PARSER_RUNTIME,                                  throw Exception(PARSER_RUNTIME,
                                         sencloser,                                          sencloser,
                                         "encloser must be one character long");                                          "encloser must be one character long");
                         encloser=sencloser->first_char();                          encloser=sencloser->first_char();
                           }
                         result++;                          result++;
                 }                  }
                 return result;                  return result;
Line 181  static void _create(Request& r, MethodPa Line 185  static void _create(Request& r, MethodPa
         // data          // data
         Temp_lang temp_lang(r, String::L_PASS_APPENDED);          Temp_lang temp_lang(r, String::L_PASS_APPENDED);
         const String&  data=          const String&  data=
                 r.process_to_string(params.as_junction(data_param_index, "body must be code"));                  r.process_to_string(params.as_junction(data_param_index, "body must be table or code"));
   
         // parse columns          // parse columns
         size_t raw_pos_after=0;          size_t raw_pos_after=0;
Line 393  static void _load(Request& r, MethodPara Line 397  static void _load(Request& r, MethodPara
 }  }
   
 #if (!defined(NO_STRINGSTREAM) && !defined(FREEBSD4))  #if (!defined(NO_STRINGSTREAM) && !defined(FREEBSD4))
           #define USE_STRINGSTREAM
   #endif
   
   #ifdef USE_STRINGSTREAM
 #include "gc_allocator.h"  #include "gc_allocator.h"
   
 typedef std::basic_stringstream<char, std::char_traits<char>, gc_allocator<char> > pa_stringstream;  typedef std::basic_stringstream<char, std::char_traits<char>, gc_allocator<char> > pa_stringstream;
 typedef std::basic_string<char, std::char_traits<char>, gc_allocator<char> > pa_string;  typedef std::basic_string<char, std::char_traits<char>, gc_allocator<char> > pa_string;
   
 void maybe_enclose( pa_stringstream& to, const String& from, char encloser ) {  static void enclose( pa_stringstream& to, const String* from, char encloser ) {
         if(encloser) {          if(from){
                 to<<encloser;                  to<<encloser;
                 // while we have 'encloser'...                  // while we have 'encloser'...
                 size_t pos_after=0;                  size_t pos_after=0;
                 for( size_t pos_before; (pos_before=from.pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before) {                  for( size_t pos_before; (pos_before=from->pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before) {
                         pos_before++; // including first encloser (and skipping it for next pos)                          pos_before++; // including first encloser (and skipping it for next pos)
                         to<<from.mid(pos_after, pos_before).cstr();                          to<<from->mid(pos_after, pos_before).cstr();
                         to<<encloser; // doubling encloser                          to<<encloser; // doubling encloser
                 }                  }
                 // last piece                  // last piece
                 size_t from_length=from.length();                  size_t from_length=from->length();
                 if(pos_after<from_length)                  if(pos_after<from_length)
                         to<<from.mid(pos_after, from_length).cstr();                          to<<from->mid(pos_after, from_length).cstr();
   
                 to<<encloser;                  to<<encloser;
         } else          } else {
                 to<<from.cstr();                  to<<encloser<<encloser;
           }
   }
   
   static void table_to_csv(pa_stringstream& result, Table& table, TableSeparators& separators, bool output_column_names) {
           if(output_column_names) {
                   if(table.columns()) { // named table
                           if(separators.encloser){
                                   for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {
                                           enclose( result, i.next(), separators.encloser );
                                           if(i.has_next())
                                                   result<<separators.column;
                                   }
                           } else {
                                   for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {
                                           result<<i.next()->cstr();
                                           if(i.has_next())
                                                   result<<separators.column;
                                   }
                           }
                   } else { // nameless table [we were asked to output column names]
                           if(int lsize=table.count()?table[0]->count():0)
                                   for(int column=0; column<lsize; column++) {
                                           if(separators.encloser) {
                                                   result<<separators.encloser<<column<<separators.encloser;
                                           } else {
                                                   result<<column;
                                           }
                                           if(column<lsize-1){
                                                   result<<separators.column;
                                           }
                                   }
                           else
                                   result<<"empty nameless table";
                   }
                   result<<'\n';
           }
   
           // process data lines
           Array_iterator<ArrayString*> i(table);
           if(separators.encloser){
                   while(i.has_next()) {
                           for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {
                                   enclose( result, c.next(), separators.encloser );
                                   if(c.has_next())
                                           result<<separators.column;
                           }
                           result<<'\n';
                   }
           } else {
                   while(i.has_next()) {
                           for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {
                                   result<<c.next()->cstr();
                                   if(c.has_next())
                                           result<<separators.column;
                           }
                           result<<'\n';
                   }
           }
 }  }
   
 #else  #else
   
 void maybe_enclose( String& to, const String& from, char encloser, const String* sencloser ) {  void enclose( String& to, const String* from, char encloser, const String* sencloser ) {
         if(encloser) {          if(from){
                 to<<*sencloser;                  to<<*sencloser;
                 // while we have 'encloser'...                  // while we have 'encloser'...
                 size_t pos_after=0;                  size_t pos_after=0;
                 for( size_t pos_before; (pos_before=from.pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before) {                  for( size_t pos_before; (pos_before=from->pos( encloser, pos_after ))!=STRING_NOT_FOUND; pos_after=pos_before) {
                         pos_before++; // including first encloser (and skipping it for next pos)                          pos_before++; // including first encloser (and skipping it for next pos)
                         to<<from.mid(pos_after, pos_before);                          to<<from->mid(pos_after, pos_before);
                         to<<*sencloser; // doubling encloser                          to<<*sencloser; // doubling encloser
                 }                  }
                 // last piece                  // last piece
                 size_t from_length=from.length();                  size_t from_length=from->length();
                 if(pos_after<from_length)                  if(pos_after<from_length)
                         to<<from.mid(pos_after, from_length);                          to<<from->mid(pos_after, from_length);
   
                 to<<*sencloser;                  to<<*sencloser;
         } else          } else {
                 to<<from;                  to<<*sencloser<<*sencloser;
           }
 }  }
   
   static void table_to_csv(String& result, Table& table, TableSeparators& separators, bool output_column_names) {
           if(output_column_names) {
                   if(table.columns()) { // named table
                           if(separators.encloser) {
                                   for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {
                                           enclose( result, i.next(), separators.encloser, separators.sencloser );
                                           if(i.has_next())
                                                   result<<*separators.scolumn;
                                   }
                           } else {
                                   for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {
                                           result<<*i.next();
                                           if(i.has_next())
                                                   result<<*separators.scolumn;
                                   }
                           }
                   } else { // nameless table [we were asked to output column names]
                           if(int lsize=table.count()?table[0]->count():0)
                                   for(int column=0; column<lsize; column++) {
                                           if(separators.encloser) {
                                                   result<<*separators.sencloser<<String::Body::Format(column)<<*separators.sencloser;
                                           } else {
                                                   result<<String::Body::Format(column);
                                           }
                                           if(column<lsize-1){
                                                   result<<*separators.scolumn;
                                           }
                                   }
                           else
                                   result.append_help_length("empty nameless table", 0, String::L_CLEAN);
                   }
                   result.append_know_length("\n", 1, String::L_CLEAN);
           }
   
           // data lines
           Array_iterator<ArrayString*> i(table);
           if(separators.encloser){
                   while(i.has_next()) {
                           for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {
                                   enclose( result, c.next(), separators.encloser, separators.sencloser );
                                   if(c.has_next())
                                           result<<*separators.scolumn;
                           }
                           result.append_know_length("\n", 1, String::L_CLEAN);
                   }
           } else {
                   while(i.has_next()) {
                           for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {
                                   result<<*c.next();
                                   if(c.has_next())
                                           result<<*separators.scolumn;
                           }
                           result.append_know_length("\n", 1, String::L_CLEAN);
                   }
           }
   }
 #endif // don't use stringstream  #endif // don't use stringstream
   
   
 static void _save(Request& r, MethodParams& params) {  static void _save(Request& r, MethodParams& params) {
         const String& first_arg=params.as_string(0, FIRST_ARG_MUST_NOT_BE_CODE);          const String& first_arg=params.as_string(0, FIRST_ARG_MUST_NOT_BE_CODE);
         size_t param_index=1;          size_t param_index=1;
Line 479  static void _save(Request& r, MethodPara Line 600  static void _save(Request& r, MethodPara
   
         Table& table=GET_SELF(r, VTable).table();          Table& table=GET_SELF(r, VTable).table();
   
 #if (!defined(NO_STRINGSTREAM) && !defined(FREEBSD4))  #ifdef USE_STRINGSTREAM
   
         pa_stringstream ost(std::stringstream::out);          pa_stringstream ost(std::stringstream::out);
   
         // process header          table_to_csv(ost, table, separators, output_column_names);
         if(output_column_names) {  
                 if(table.columns()) { // named table  
                         for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {  
                                 maybe_enclose( ost, *i.next(), separators.encloser );  
                                 if(i.has_next()){  
                                         ost<<separators.column;  
                                 }  
                         }  
                 } else { // nameless table [we were asked to output column names]  
                         if(int lsize=table.count()?table[0]->count():0)  
                                 for(int column=0; column<lsize; column++) {  
                                         if(separators.encloser) {  
                                                 ost<<separators.encloser<<column<<separators.encloser;  
                                         } else {  
                                                 ost<<column;  
                                         }  
                                         if(column<lsize-1){  
                                                 ost<<separators.column;  
                                         }  
                                 }  
                         else  
                                 ost<<"empty nameless table";  
                 }  
                 ost<<'\n';  
         }  
   
         // process data lines  
         Array_iterator<ArrayString*> i(table);  
         while(i.has_next()) {  
                 for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {  
                         maybe_enclose( ost, *c.next(), separators.encloser );  
                         if(c.has_next())  
                                 ost<<separators.column;  
                 }  
                 ost<<'\n';  
         }  
   
         // write          // write
         {  
                 pa_string data=ost.str();                  pa_string data=ost.str();
                 const char* data_cstr=data.c_str();                  const char* data_cstr=data.c_str();
   
                 file_write(r.charsets, file_spec, data_cstr, data.length(), true /* as text */, do_append);                  file_write(r.charsets, file_spec, data_cstr, data.length(), true /* as text */, do_append);
         }  
   
 #else  #else
   
         String sdata;          String sdata;
         if(output_column_names) {  
                 if(table.columns()) { // named table  
                         for(Array_iterator<const String*> i(*table.columns()); i.has_next(); ) {  
                                 maybe_enclose( sdata, *i.next(), separators.encloser, separators.sencloser );  
                                 if(i.has_next())  
                                         sdata<<*separators.scolumn;  
                         }  
                 } else { // nameless table [we were asked to output column names]  
                         if(int lsize=table.count()?table[0]->count():0)  
                                 for(int column=0; column<lsize; column++) {  
                                         char *cindex_tab=new(PointerFreeGC) char[MAX_NUMBER];  
                                         sdata.append_know_length(cindex_tab,   
                                                 snprintf(cindex_tab, MAX_NUMBER,   
                                                         column<lsize-1?"%d%c":"%d", column, separators.column),  
                                                         String::L_CLEAN);  
                                 }  
                         else  
                                 sdata.append_help_length("empty nameless table", 0, String::L_CLEAN);  
                 }  
                 sdata.append_know_length("\n", 1, String::L_CLEAN);  
         }  
   
         // data lines          table_to_csv(sdata, table, separators, output_column_names);
         Array_iterator<ArrayString*> i(table);  
         while(i.has_next()) {  
                 for(Array_iterator<const String*> c(*i.next()); c.has_next(); ) {  
                         maybe_enclose( sdata, *c.next(), separators.encloser, separators.sencloser );  
                         if(c.has_next())  
                                 sdata<<*separators.scolumn;  
                 }  
                 sdata.append_know_length("\n", 1, String::L_CLEAN);  
         }  
   
         // write          // write
         {  
                 const char* data_cstr=sdata.cstr();                  const char* data_cstr=sdata.cstr();
                 file_write(r.charsets, file_spec, data_cstr, sdata.length(), true, do_append);          file_write(r.charsets, file_spec, data_cstr, sdata.length(), true /* as text */, do_append);
                 if(*data_cstr) // not empty (when empty it's not heap memory)                  if(*data_cstr) // not empty (when empty it's not heap memory)
                         pa_free((void*)data_cstr); // not needed anymore                          pa_free((void*)data_cstr); // not needed anymore
   #endif
   }
   
   static void _csv_string(Request& r, MethodParams& params) {
           bool output_column_names=true;
           size_t param_index=0;
           if(params.count()>0 && params[0].is_string()) {
                   if(params.as_string(0, FIRST_ARG_MUST_NOT_BE_CODE)=="nameless") {
                           output_column_names=false;
                           param_index++;
                   } else {
                           throw Exception(PARSER_RUNTIME,
                                   0,
                                   "bad mode (must be nameless)");
                   }
         }          }
   
 #endif // don't use stringstream          TableSeparators separators;
           if(param_index<params.count())
                   if(HashStringValue* options=params.as_hash(param_index++)) {
                           int valid_options=separators.load(*options);
                           if(valid_options!=options->count())
                                   throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION);
                   }
   
           Table& table=GET_SELF(r, VTable).table();
   
   #ifdef USE_STRINGSTREAM
           pa_stringstream ost(std::stringstream::out);
   
           table_to_csv(ost, table, separators, output_column_names);
   
           r.write_no_lang(*new VString(*new String(pa_strdup(ost.str().c_str()), String::L_CLEAN)));
   #else
           String sdata;
   
           table_to_csv(sdata, table, separators, output_column_names);
   
           r.write_no_lang(*new VString(*new String(sdata.cstr(), String::L_CLEAN)));
   #endif
 }  }
   
 static void _count(Request& r, MethodParams& params) {  static void _count(Request& r, MethodParams& params) {
Line 933  static void _sort(Request& r, MethodPara Line 1018  static void _sort(Request& r, MethodPara
         }          }
   
         // sort keys          // sort keys
         _qsort(seq, old_count, sizeof(Table_seq_item),           qsort(seq, old_count, sizeof(Table_seq_item), key_values_are_strings?sort_cmp_string:sort_cmp_double);
                 key_values_are_strings?sort_cmp_string:sort_cmp_double);  
   
         // reorder table as they require in 'seq'          // reorder table as they require in 'seq'
         for(i=0; i<old_count; i++)          for(i=0; i<old_count; i++)
Line 1029  static void _foreach(Request& r, MethodP Line 1113  static void _foreach(Request& r, MethodP
                         table.set_current(row);                          table.set_current(row);
   
                         if(rownum_var_name)                          if(rownum_var_name)
                                 var_context->put_element(*rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN)), false);                                  r.put_element(*var_context, *rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN)));
                         if(value_var_name)                          if(value_var_name)
                                 var_context->put_element(*value_var_name, new VTable(&table), false);                                  r.put_element(*var_context, *value_var_name, new VTable(&table));
   
                         StringOrValue sv_processed=r.process(body_code);                          StringOrValue sv_processed=r.process(body_code);
                         Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING);                          Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING);
Line 1054  static void _foreach(Request& r, MethodP Line 1138  static void _foreach(Request& r, MethodP
                         table.set_current(row);                          table.set_current(row);
     
                         if(rownum_var_name)                          if(rownum_var_name)
                                 var_context->put_element(*rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN)), false);                                  r.put_element(*var_context, *rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN)));
                         if(value_var_name)                          if(value_var_name)
                                 var_context->put_element(*value_var_name, new VTable(&table), false);                                  r.put_element(*var_context, *value_var_name, new VTable(&table));
   
                         r.process_write(body_code);                          r.process_write(body_code);
                         Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING);                          Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING);
Line 1180  static void marshal_bind( Line 1264  static void marshal_bind(
 // not static, used elsewhere  // not static, used elsewhere
 int marshal_binds(HashStringValue& hash, SQL_Driver::Placeholder*& placeholders) {  int marshal_binds(HashStringValue& hash, SQL_Driver::Placeholder*& placeholders) {
         int hash_count=hash.count();          int hash_count=hash.count();
         placeholders=new(UseGC) SQL_Driver::Placeholder[hash_count];          placeholders=new SQL_Driver::Placeholder[hash_count];
         SQL_Driver::Placeholder* ptr=placeholders;          SQL_Driver::Placeholder* ptr=placeholders;
         hash.for_each<SQL_Driver::Placeholder**>(marshal_bind, &ptr);          hash.for_each<SQL_Driver::Placeholder**>(marshal_bind, &ptr);
         return hash_count;          return hash_count;
Line 1360  MTable::MTable(): Methoded("table") { Line 1444  MTable::MTable(): Methoded("table") {
   
         // add_native_method("save_old", Method::CT_DYNAMIC, _save_old, 1, 3);          // add_native_method("save_old", Method::CT_DYNAMIC, _save_old, 1, 3);
   
           // ^table.csv-string[]
           // ^table.csv-string[nameless]
           // ^table.csv-string[nameless;$.encloser["] $.separator[,]]
           add_native_method("csv-string", Method::CT_DYNAMIC, _csv_string, 0, 2);
   
         // ^table.count[]          // ^table.count[]
         // ^table.count[rows]          // ^table.count[rows]
         // ^table.count[columns]          // ^table.count[columns]

Removed from v.1.294  
changed lines
  Added in v.1.302


E-mail: