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