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