Annotation of parser3/src/types/pa_vtable.C, revision 1.44
1.1 parser 1: /** @file
2: Parser: @b table class.
3:
1.43 moko 4: Copyright (c) 2001-2015 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.44 ! moko 13: volatile const char * IDENT_PA_VTABLE_C="$Id: pa_vtable.C,v 1.43 2015/10/26 01:22:03 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={<able, 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.1 parser 63: // fields
1.40 moko 64: if(aname==table_fields_name)
1.1 parser 65: return fields_element();
66:
1.44 ! moko 67: #ifdef FEATURE_GET_ELEMENT4CALL
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.42 moko 78: #ifndef OPTIMIZE_BYTECODE_GET_ELEMENT__SPECIAL
1.44 ! moko 79: // CLASS, CLASS_NAME
1.31 misha 80: if(Value* result=VStateless_object::get_element(aname))
1.2 parser 81: return result;
1.42 moko 82: #endif
1.2 parser 83:
1.40 moko 84: throw Exception(PARSER_RUNTIME, &aname, "column not found");
85: }
86:
87: Value* VTable::get_element4call(const String& aname) {
1.44 ! moko 88: // methods
! 89: return VStateless_object::get_element(aname);
! 90: }
1.40 moko 91:
1.44 ! moko 92: #else
1.40 moko 93: // methods first
94: if(Value* result=VStateless_object::get_element(aname))
95: return result;
96:
1.1 parser 97: // columns
98: if(ftable) {
1.16 paf 99: int index=ftable->column_name2index(aname, false);
100: if(index>=0) // column aname|number valid
1.32 pretende 101: {
102: const String* string=ftable->item(index); // there is such column
103: return new VString(string ? *string : String::Empty);
104: }
1.1 parser 105: }
106:
1.39 moko 107: throw Exception(PARSER_RUNTIME, &aname, "column not found");
1.1 parser 108: }
1.44 ! moko 109: #endif
1.33 misha 110:
1.39 moko 111: const VJunction* VTable::put_element(const String& aname, Value* avalue) {
112: if(ftable) {
113: int index=ftable->column_name2index(aname, false);
114: if(index>=0) // column aname|number valid
115: {
116: if(index > MAX_COLUMNS)
117: throw Exception(PARSER_RUNTIME, &aname, "too big column number");
118: if(!avalue->is_string())
119: throw Exception(PARSER_RUNTIME, 0, "column value must be string");
120: ftable->put_item(index, avalue->get_string());
121: return PUT_ELEMENT_REPLACED_ELEMENT;
122: }
123: }
124:
125: throw Exception(PARSER_RUNTIME, &aname, "column not found");
126: }
1.36 moko 127:
128: String& VTable::get_json_string_array(String& result, const char *indent) {
129: // [
130: // ["c1", "c2", "c3" ...] || null (for nameless),
131: // ["v11", "v12", "v13" ...],
132: // ["v21", "v22", "v23" ...],
133: // ...
134: // ]
1.33 misha 135: Table& ltable=table();
1.35 moko 136:
1.36 moko 137: // columns
138: if(ltable.columns()){
139: // named
140: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
141:
142: bool need_delim=false;
143: for(Array_iterator<const String*> c(*ltable.columns()); c.has_next(); ) {
144: if(need_delim)
145: result << "\",\"";
146: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
147: need_delim=true;
148: }
149: result << "\"]";
150: } else {
151: // nameless
152: indent ? result << "\n\t" << indent << "null" : result << "\nnull";
153: }
154:
155: // data
156: if(ltable.count()){
157: result << ",";
158: for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
159: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
1.33 misha 160: bool need_delim=false;
1.36 moko 161: for(Array_iterator<const String*> c(*r.next()); c.has_next(); ) {
1.33 misha 162: if(need_delim)
163: result << "\",\"";
164: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
165: need_delim=true;
166: }
1.36 moko 167: r.has_next() ? result << "\"]," : result << "\"]";
1.35 moko 168: }
1.36 moko 169: }
170:
171: result << "\n" << indent;
172: return result;
173: }
174:
175: String& VTable::get_json_string_object(String& result, const char *indent) {
176: // [
177: // {"c1":"v11", "c2":"v12", "c3":"v13"},
178: // {"c1":"v21", "c2":"v22", "c3":"v23"},
179: // ...
180: // ]
181: Table& ltable=table();
182: ArrayString* columns=ltable.columns();
183: size_t columns_count = (columns) ? columns->count() : 0;
184:
185: for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
186: indent ? result << "\n\t" << indent << "{\"" : result << "\n{\"";
1.33 misha 187:
1.36 moko 188: ArrayString* row=r.next();
189: for(size_t index=0; index<row->count(); index++){
190: if(index)
191: result << "\",\"";
192: result.append(index < columns_count ? *columns->get(index) : String(format(index, 0)), String::L_JSON, true/*forced lang*/);
193: result << "\":\"";
194: result.append(*row->get(index), String::L_JSON, true/*forced lang*/);
1.33 misha 195: }
1.36 moko 196: r.has_next() ? result << "\"}," : result << "\"}\n" << indent;
197: }
198: return result;
199: }
200:
201: String& VTable::get_json_string_compact(String& result, const char *indent) {
202: // [
203: // "v11",
204: // ["v21", "v22", "v23" ...],
205: // ...
206: // ]
207: Table& ltable=table();
208:
209: for(Array_iterator<ArrayString*> r(ltable); r.has_next(); ) {
210: ArrayString& line=*r.next();
211: if (line.count()==1){
212: indent ? result << "\n\t" << indent << "\"" : result << "\n\"";
1.33 misha 213:
1.36 moko 214: result.append(*line[0], String::L_JSON, true/*forced lang*/);
215: r.has_next() ? result << "\"," : result << "\"\n" << indent;
216: } else {
217: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
1.33 misha 218:
1.36 moko 219: bool need_delim=false;
220: for(Array_iterator<const String*> c(line); c.has_next(); ) {
221: if(need_delim)
1.33 misha 222: result << "\",\"";
1.36 moko 223: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
224: need_delim=true;
1.33 misha 225: }
1.36 moko 226: r.has_next() ? result << "\"]," : result << "\"]\n" << indent;
227: }
228: }
229: return result;
230: }
231:
1.38 moko 232: const String* VTable::get_json_string(Json_options& options) {
1.36 moko 233: String* result = new String("[", String::L_AS_IS);
1.33 misha 234:
1.38 moko 235: switch(options.table){
1.36 moko 236: case Json_options::T_ARRAY:
1.38 moko 237: result=&get_json_string_array(*result, options.indent);
1.36 moko 238: break;
239: case Json_options::T_OBJECT:
1.38 moko 240: result=&get_json_string_object(*result, options.indent);
1.36 moko 241: break;
242: case Json_options::T_COMPACT:
1.38 moko 243: result=&get_json_string_compact(*result, options.indent);
1.36 moko 244: break;
1.33 misha 245: }
246:
1.36 moko 247: *result << "]";
248: return result;
249: }
E-mail: