Annotation of parser3/src/types/pa_vtable.C, revision 1.40

1.1       parser      1: /** @file
                      2:        Parser: @b table class.
                      3: 
1.37      moko        4:        Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)
1.11      paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.14      paf         6: */
1.1       parser      7: 
                      8: #include "pa_vtable.h"
                      9: #include "pa_vstring.h"
1.5       parser     10: #include "pa_vhash.h"
1.22      paf        11: #include "pa_vvoid.h"
1.1       parser     12: 
1.40    ! moko       13: volatile const char * IDENT_PA_VTABLE_C="$Id: pa_vtable.C,v 1.39 2015/07/28 14:42:44 moko Exp $" IDENT_PA_VTABLE_H;
1.39      moko       14: 
                     15: // limits
                     16: #define MAX_COLUMNS 20000 // equal to MAX_LOOPS
1.37      moko       17: 
1.40    ! moko       18: const String table_fields_name(TABLE_FIELDS_ELEMENT_NAME);
        !            19: 
1.3       parser     20: #ifndef DOXYGEN
1.1       parser     21: struct Record_info {
1.22      paf        22:        Table* table;
                     23:        HashStringValue* hash;
1.1       parser     24: };
1.3       parser     25: #endif
1.29      misha      26: 
                     27: static void store_column_item_to_hash(const String* column_name, Record_info *info) {
                     28:        const String* column_item=info->table->item(*column_name);
                     29:        info->hash->put(*column_name, 
                     30:                (column_item && !column_item->is_empty())
                     31:                        ?new VString(*column_item)
                     32:                        :new VString()
                     33:        );
1.1       parser     34: }
1.29      misha      35: 
1.22      paf        36: Value* VTable::fields_element() {
1.29      misha      37:        Value& result=*new VHash;
1.22      paf        38:        Table& ltable=table();
1.29      misha      39:        if(!ltable.count())
                     40:                return &result;
                     41: 
                     42:        HashStringValue* hash=result.get_hash();
                     43: 
                     44:        if(Table::columns_type columns=ltable.columns()) { // named
                     45:                Record_info record_info={&ltable, hash};
1.1       parser     46:                columns->for_each(store_column_item_to_hash, &record_info);
1.29      misha      47:        } else { // nameless
                     48:                size_t row_size=ltable[ltable.current()]->count(); // number of columns in current row
                     49:                for(size_t index=0; index<row_size; index++){
                     50:                        const String* column_item=ltable.item(index);
                     51:                        hash->put(String::Body::Format(index), 
                     52:                                (column_item && !column_item->is_empty())
                     53:                                        ?new VString(*column_item)
                     54:                                        :new VString()
                     55:                        );
                     56:                }
1.1       parser     57:        }
1.29      misha      58: 
                     59:        return &result;
1.1       parser     60: }
                     61: 
1.31      misha      62: Value* VTable::get_element(const String& aname) {
1.40    ! moko       63: #ifdef FEATURE_GET_ELEMENT4CALL
1.1       parser     64:        // fields
1.40    ! moko       65:        if(aname==table_fields_name)
1.1       parser     66:                return fields_element();
                     67: 
1.40    ! moko       68:        // columns first
        !            69:        if(ftable) {
        !            70:                int index=ftable->column_name2index(aname, false);
        !            71:                if(index>=0) // column aname|number valid
        !            72:                {
        !            73:                        const String* string=ftable->item(index); // there is such column
        !            74:                        return new VString(string ? *string : String::Empty);
        !            75:                }
        !            76:        }
        !            77: 
1.2       parser     78:        // methods
1.31      misha      79:        if(Value* result=VStateless_object::get_element(aname))
1.2       parser     80:                return result;
                     81: 
1.40    ! moko       82:        throw Exception(PARSER_RUNTIME, &aname, "column not found");
        !            83: }
        !            84: 
        !            85: Value* VTable::get_element4call(const String& aname) {
        !            86: #endif
        !            87:        // fields
        !            88:        if(aname==table_fields_name)
        !            89:                return fields_element();
        !            90: 
        !            91:        // methods first
        !            92:        if(Value* result=VStateless_object::get_element(aname))
        !            93:                return result;
        !            94: 
1.1       parser     95:        // columns
                     96:        if(ftable) {
1.16      paf        97:                int index=ftable->column_name2index(aname, false);
                     98:                if(index>=0) // column aname|number valid
1.32      pretende   99:                {
                    100:                        const String* string=ftable->item(index); // there is such column
                    101:                        return new VString(string ? *string : String::Empty);
                    102:                }
1.1       parser    103:        }
                    104: 
1.39      moko      105:        throw Exception(PARSER_RUNTIME, &aname, "column not found");
1.1       parser    106: }
1.33      misha     107: 
1.39      moko      108: const VJunction* VTable::put_element(const String& aname, Value* avalue) {
                    109:        if(ftable) {
                    110:                int index=ftable->column_name2index(aname, false);
                    111:                if(index>=0) // column aname|number valid
                    112:                {
                    113:                        if(index > MAX_COLUMNS)
                    114:                                throw Exception(PARSER_RUNTIME, &aname, "too big column number");
                    115:                        if(!avalue->is_string())
                    116:                                throw Exception(PARSER_RUNTIME, 0, "column value must be string");
                    117:                        ftable->put_item(index, avalue->get_string());
                    118:                        return PUT_ELEMENT_REPLACED_ELEMENT;
                    119:                }
                    120:        }
                    121: 
                    122:        throw Exception(PARSER_RUNTIME, &aname, "column not found");
                    123: }
1.36      moko      124: 
                    125: String& VTable::get_json_string_array(String& result, const char *indent) {
                    126:        // [
                    127:        //              ["c1",  "c2",  "c3"  ...] || null (for nameless),
                    128:        //              ["v11", "v12", "v13" ...],
                    129:        //              ["v21", "v22", "v23" ...],
                    130:        //              ...
                    131:        // ]
1.33      misha     132:        Table& ltable=table();
1.35      moko      133: 
1.36      moko      134:        // columns
                    135:        if(ltable.columns()){
                    136:                // named
                    137:                indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
                    138: 
                    139:                bool need_delim=false;
                    140:                for(Array_iterator<const String*> c(*ltable.columns()); c.has_next(); ) {
                    141:                        if(need_delim)
                    142:                                result << "\",\"";
                    143:                        result.append(*c.next(), String::L_JSON, true/*forced lang*/);
                    144:                        need_delim=true;
                    145:                }
                    146:                result << "\"]";
                    147:        } else {
                    148:                // nameless
                    149:                indent ? result << "\n\t" << indent << "null" : result << "\nnull";
                    150:        }
                    151: 
                    152:        // data
                    153:        if(ltable.count()){
                    154:                result << ",";
                    155:                for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
                    156:                        indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
1.33      misha     157:                        bool need_delim=false;
1.36      moko      158:                        for(Array_iterator<const String*> c(*r.next()); c.has_next(); ) {
1.33      misha     159:                                if(need_delim)
                    160:                                        result << "\",\"";
                    161:                                result.append(*c.next(), String::L_JSON, true/*forced lang*/);
                    162:                                need_delim=true;
                    163:                        }
1.36      moko      164:                        r.has_next() ? result << "\"]," : result << "\"]";
1.35      moko      165:                }
1.36      moko      166:        }
                    167: 
                    168:        result << "\n" << indent; 
                    169:        return result;
                    170: }
                    171: 
                    172: String& VTable::get_json_string_object(String& result, const char *indent) {
                    173:        // [
                    174:        //              {"c1":"v11", "c2":"v12", "c3":"v13"},
                    175:        //              {"c1":"v21", "c2":"v22", "c3":"v23"},
                    176:        //              ...
                    177:        // ]
                    178:        Table& ltable=table();
                    179:        ArrayString* columns=ltable.columns();
                    180:        size_t columns_count = (columns) ? columns->count() : 0;
                    181: 
                    182:        for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
                    183:                indent ? result << "\n\t" << indent << "{\"" : result << "\n{\"";
1.33      misha     184: 
1.36      moko      185:                ArrayString* row=r.next();
                    186:                for(size_t index=0; index<row->count(); index++){
                    187:                        if(index)
                    188:                                result << "\",\"";
                    189:                        result.append(index < columns_count ? *columns->get(index) : String(format(index, 0)), String::L_JSON, true/*forced lang*/);
                    190:                        result << "\":\"";
                    191:                        result.append(*row->get(index), String::L_JSON, true/*forced lang*/);
1.33      misha     192:                }
1.36      moko      193:                r.has_next() ? result << "\"}," : result << "\"}\n" << indent;
                    194:        }
                    195:        return result;
                    196: }
                    197: 
                    198: String& VTable::get_json_string_compact(String& result, const char *indent) {
                    199:        // [
                    200:        //              "v11",
                    201:        //              ["v21", "v22", "v23" ...],
                    202:        //              ...
                    203:        // ]
                    204:        Table& ltable=table();
                    205: 
                    206:        for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
                    207:                ArrayString& line=*r.next();
                    208:                if (line.count()==1){
                    209:                        indent ? result << "\n\t" << indent << "\"" : result << "\n\"";
1.33      misha     210: 
1.36      moko      211:                        result.append(*line[0], String::L_JSON, true/*forced lang*/);
                    212:                        r.has_next() ? result << "\"," : result << "\"\n" << indent;
                    213:                } else {
                    214:                        indent ? result << "\n\t" << indent << "[\"" :  result << "\n[\"";
1.33      misha     215: 
1.36      moko      216:                        bool need_delim=false;
                    217:                        for(Array_iterator<const String*> c(line); c.has_next(); ) {
                    218:                                if(need_delim)
1.33      misha     219:                                        result << "\",\"";
1.36      moko      220:                                result.append(*c.next(), String::L_JSON, true/*forced lang*/);
                    221:                                need_delim=true;
1.33      misha     222:                        }
1.36      moko      223:                        r.has_next() ? result << "\"]," : result  << "\"]\n" << indent;
                    224:                }
                    225:        }
                    226:        return result;
                    227: }
                    228: 
1.38      moko      229: const String* VTable::get_json_string(Json_options& options) {
1.36      moko      230:        String* result = new String("[", String::L_AS_IS);
1.33      misha     231: 
1.38      moko      232:        switch(options.table){
1.36      moko      233:        case Json_options::T_ARRAY:
1.38      moko      234:                result=&get_json_string_array(*result, options.indent);
1.36      moko      235:                break;
                    236:        case Json_options::T_OBJECT:
1.38      moko      237:                result=&get_json_string_object(*result, options.indent);
1.36      moko      238:                break;
                    239:        case Json_options::T_COMPACT:
1.38      moko      240:                result=&get_json_string_compact(*result, options.indent);
1.36      moko      241:                break;
1.33      misha     242:        }
                    243: 
1.36      moko      244:        *result << "]";
                    245:        return result;
                    246: }

E-mail: