Annotation of parser3/src/types/pa_vtable.C, revision 1.61
1.1 parser 1: /** @file
2: Parser: @b table class.
3:
1.59 moko 4: Copyright (c) 2001-2026 Art. Lebedev Studio (https://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.61 ! moko 14: volatile const char * IDENT_PA_VTABLE_C="$Id: pa_vtable.C,v 1.60 2026/10/06 15:47:08 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.61 ! moko 55: MAYBE_GET_SPECIAL_OR_METHOD(VStateless_object::get_element(aname));
1.40 moko 56:
1.1 parser 57: // columns
58: if(ftable) {
1.16 paf 59: int index=ftable->column_name2index(aname, false);
60: if(index>=0) // column aname|number valid
1.32 pretende 61: {
62: const String* string=ftable->item(index); // there is such column
1.60 moko 63: return string ? new VString(*string) : VString::empty();
1.32 pretende 64: }
1.1 parser 65: }
66:
1.39 moko 67: throw Exception(PARSER_RUNTIME, &aname, "column not found");
1.1 parser 68: }
1.33 misha 69:
1.39 moko 70: const VJunction* VTable::put_element(const String& aname, Value* avalue) {
71: if(ftable) {
72: int index=ftable->column_name2index(aname, false);
73: if(index>=0) // column aname|number valid
74: {
1.46 moko 75: if(index > pa_loop_limit)
1.39 moko 76: throw Exception(PARSER_RUNTIME, &aname, "too big column number");
1.48 moko 77: const String *svalue=avalue->get_string();
78: if(!svalue)
79: throw Exception(PARSER_RUNTIME, 0, "column value must be string compatible");
80: ftable->put_item(index, svalue);
1.49 moko 81: return 0;
1.39 moko 82: }
83: }
84:
85: throw Exception(PARSER_RUNTIME, &aname, "column not found");
86: }
1.36 moko 87:
88: String& VTable::get_json_string_array(String& result, const char *indent) {
89: // [
90: // ["c1", "c2", "c3" ...] || null (for nameless),
91: // ["v11", "v12", "v13" ...],
92: // ["v21", "v22", "v23" ...],
93: // ...
94: // ]
1.33 misha 95: Table& ltable=table();
1.35 moko 96:
1.36 moko 97: // columns
98: if(ltable.columns()){
99: // named
100: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
101:
102: bool need_delim=false;
1.54 moko 103: for(Array_iterator<const String*> c(*ltable.columns()); c; ) {
1.36 moko 104: if(need_delim)
105: result << "\",\"";
106: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
107: need_delim=true;
108: }
109: result << "\"]";
110: } else {
111: // nameless
112: indent ? result << "\n\t" << indent << "null" : result << "\nnull";
113: }
114:
115: // data
116: if(ltable.count()){
117: result << ",";
1.54 moko 118: for(Array_iterator<ArrayString*> r(ltable); r; ) {
1.36 moko 119: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
1.33 misha 120: bool need_delim=false;
1.54 moko 121: for(Array_iterator<const String*> c(*r.next()); c; ) {
1.33 misha 122: if(need_delim)
123: result << "\",\"";
124: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
125: need_delim=true;
126: }
1.54 moko 127: r ? result << "\"]," : result << "\"]";
1.35 moko 128: }
1.36 moko 129: }
130:
131: result << "\n" << indent;
132: return result;
133: }
134:
135: String& VTable::get_json_string_object(String& result, const char *indent) {
136: // [
137: // {"c1":"v11", "c2":"v12", "c3":"v13"},
138: // {"c1":"v21", "c2":"v22", "c3":"v23"},
139: // ...
140: // ]
141: Table& ltable=table();
142: ArrayString* columns=ltable.columns();
143: size_t columns_count = (columns) ? columns->count() : 0;
144:
1.54 moko 145: for(Array_iterator<ArrayString*> r(ltable); r; ) {
1.36 moko 146: indent ? result << "\n\t" << indent << "{\"" : result << "\n{\"";
1.33 misha 147:
1.36 moko 148: ArrayString* row=r.next();
149: for(size_t index=0; index<row->count(); index++){
150: if(index)
151: result << "\",\"";
1.56 moko 152: result.append(index < columns_count ? *columns->get(index) : String(pa_uitoa(index)), String::L_JSON, true/*forced lang*/);
1.36 moko 153: result << "\":\"";
154: result.append(*row->get(index), String::L_JSON, true/*forced lang*/);
1.33 misha 155: }
1.54 moko 156: r ? result << "\"}," : result << "\"}\n" << indent;
1.36 moko 157: }
158: return result;
159: }
160:
161: String& VTable::get_json_string_compact(String& result, const char *indent) {
162: // [
163: // "v11",
164: // ["v21", "v22", "v23" ...],
165: // ...
166: // ]
167: Table& ltable=table();
168:
1.54 moko 169: for(Array_iterator<ArrayString*> r(ltable); r; ) {
1.36 moko 170: ArrayString& line=*r.next();
171: if (line.count()==1){
172: indent ? result << "\n\t" << indent << "\"" : result << "\n\"";
1.33 misha 173:
1.36 moko 174: result.append(*line[0], String::L_JSON, true/*forced lang*/);
1.54 moko 175: r ? result << "\"," : result << "\"\n" << indent;
1.36 moko 176: } else {
177: indent ? result << "\n\t" << indent << "[\"" : result << "\n[\"";
1.33 misha 178:
1.36 moko 179: bool need_delim=false;
1.54 moko 180: for(Array_iterator<const String*> c(line); c; ) {
1.36 moko 181: if(need_delim)
1.33 misha 182: result << "\",\"";
1.36 moko 183: result.append(*c.next(), String::L_JSON, true/*forced lang*/);
184: need_delim=true;
1.33 misha 185: }
1.54 moko 186: r ? result << "\"]," : result << "\"]\n" << indent;
1.36 moko 187: }
188: }
189: return result;
190: }
191:
1.38 moko 192: const String* VTable::get_json_string(Json_options& options) {
1.36 moko 193: String* result = new String("[", String::L_AS_IS);
1.33 misha 194:
1.38 moko 195: switch(options.table){
1.36 moko 196: case Json_options::T_ARRAY:
1.38 moko 197: result=&get_json_string_array(*result, options.indent);
1.36 moko 198: break;
199: case Json_options::T_OBJECT:
1.38 moko 200: result=&get_json_string_object(*result, options.indent);
1.36 moko 201: break;
202: case Json_options::T_COMPACT:
1.38 moko 203: result=&get_json_string_compact(*result, options.indent);
1.36 moko 204: break;
1.33 misha 205: }
206:
1.36 moko 207: *result << "]";
208: return result;
209: }
E-mail: