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