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