Annotation of parser3/src/classes/table.C, revision 1.11
1.1 paf 1: /*
2: Parser
3: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
4: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
5:
1.11 ! paf 6: $Id: table.C,v 1.10 2001/03/12 21:54:18 paf Exp $
1.1 paf 7: */
8:
9: #include "pa_request.h"
10: #include "_table.h"
11: #include "pa_vtable.h"
1.2 paf 12: #include "pa_common.h"
1.6 paf 13: #include "pa_vint.h"
1.1 paf 14:
15: // global var
16:
17: VClass *table_class;
18:
19: // methods
20:
21:
22: // TODO: проверить ^set в ^menu & co
23:
1.2 paf 24: static void set_or_load(
25: Request& r,
26: const String& method_name, Array *params,
27: bool is_load) {
1.1 paf 28: Pool& pool=r.pool();
29: // data is last parameter
30: Value *vdata=static_cast<Value *>(params->get(params->size()-1));
1.4 paf 31: // forcing
32: // [this param type]
33: // [this param type]
1.3 paf 34: r.fail_if_junction_(true, *vdata,
35: method_name, "body must not be a junction");
1.1 paf 36:
1.2 paf 37: // data or file_name
38: char *data_or_filename=vdata->as_string().cstr();
39: // data
40: char *data=is_load?file_read(pool, r.absolute(data_or_filename)):data_or_filename;
1.1 paf 41:
42: // parse columns
43: Array *columns;
44: #ifndef NO_STRING_ORIGIN
45: const Origin& origin=method_name.origin();
1.2 paf 46: const char *file=origin.file;
1.1 paf 47: uint line=origin.line;
48: #endif
49: if(params->size()==2) {
50: columns=0;
51: } else {
52: columns=new(pool) Array(pool);
53:
54: if(char *row_chars=getrow(&data))
55: do {
56: String *name=new(pool) String(pool);
57: name->APPEND(lsplit(&row_chars, '\t'), 0, file, line++);
58: *columns+=name;
59: } while(row_chars);
60: }
61:
62: // parse cells
63: Table& table=*new(pool) Table(pool, method_name, columns);
64: char *row_chars;
65: while(row_chars=getrow(&data)) {
66: Array *row=new(pool) Array(pool);
67: while(char *cell_chars=lsplit(&row_chars, '\t')) {
68: String *cell=new(pool) String(pool);
69: cell->APPEND(cell_chars, 0, file, line);
70: *row+=cell;
71: }
72: line++;
73: table+=row;
74: };
75:
76: // replace any previous table value
77: r.self->as_vtable().set_table(table);
78: }
79:
1.2 paf 80:
81: static void _set(Request& r, const String& method_name, Array *params) {
82: set_or_load(r, method_name, params, false);
83: }
84:
85: static void _load(Request& r, const String& method_name, Array *params) {
86: set_or_load(r, method_name, params, true);
87: }
88:
1.6 paf 89: static void _count(Request& r, const String&, Array *) {
90: Pool& pool=r.pool();
91: Value& value=*new(pool) VInt(pool, r.self->as_vtable().table().size());
92: r.wcontext->write(value, String::Untaint_lang::NO /*always object, not string*/);
93: }
94:
95: static void _line(Request& r, const String&, Array *) {
96: Pool& pool=r.pool();
97: Value& value=*new(pool) VInt(pool, 1+r.self->as_vtable().table().get_current());
98: r.wcontext->write(value, String::Untaint_lang::NO /*always object, not string*/);
99: }
100:
101: static void _offset(Request& r, const String&, Array *params) {
102: Pool& pool=r.pool();
103: Table& table=r.self->as_vtable().table();
104: if(params->size()) {
105: if(int size=table.size()) {
1.9 paf 106: int offset=
107: (int)r.process(*static_cast<Value *>(params->get(0))).get_double();
1.6 paf 108: table.set_current((table.get_current()+offset+size)%size);
109: }
110: } else {
111: Value& value=*new(pool) VInt(pool, table.get_current());
112: r.wcontext->write(value, String::Untaint_lang::NO /*always object, not string*/);
113: }
114: }
115:
1.7 paf 116: static void _menu(Request& r, const String& method_name, Array *params) {
117: Value& body_code=*static_cast<Value *>(params->get(0));
118: // forcing ^menu{this param type}
119: r.fail_if_junction_(false, body_code,
120: method_name, "body must be junction");
121:
122: Value *delim_code=params->size()==2?static_cast<Value *>(params->get(1)):0;
123:
124: Table& table=r.self->as_vtable().table();
125: bool need_delim=false;
126: for(int i=0; i<table.size(); i++) {
127: table.set_current(i);
128:
1.11 ! paf 129: RTRY
! 130: Value& processed_body=r.process(body_code);
! 131: RCATCH(e)
! 132: if(e.type()==ET_SILENT && e.code()==EC_BREAK)
! 133: e.set_handled();
! 134: RFINALLY
! 135: REND_TRY
1.7 paf 136: if(delim_code) { // delimiter set?
137: const String *string=processed_body.get_string();
138: if(need_delim && string && string->size()) // need delim & iteration produced string?
139: r.write_pass_lang(r.process(*delim_code));
140: need_delim=true;
141: }
142: r.write_pass_lang(processed_body);
143: }
144: }
145:
1.8 paf 146: static void _empty(Request& r, const String&, Array *params) {
147: Table& table=r.self->as_vtable().table();
148: if(table.size()==0) {
149: Value& value=r.process(*static_cast<Value *>(params->get(0)));
150: r.write_pass_lang(value);
151: } else if(params->size()==2) {
152: Value& value=r.process(*static_cast<Value *>(params->get(1)));
153: r.write_pass_lang(value);
154: }
155: }
156:
1.1 paf 157: void initialize_table_class(Pool& pool, VClass& vclass) {
1.10 paf 158: // ^table.set[data]
159: // ^table.set[nameless;data]
1.1 paf 160: vclass.add_native_method("set", _set, 1, 2);
1.2 paf 161:
1.10 paf 162: // ^table.load[file]
163: // ^table.load[nameless;file]
1.2 paf 164: vclass.add_native_method("load", _load, 1, 2);
1.6 paf 165:
166: // ^table.count[]
167: vclass.add_native_method("count", _count, 0, 0);
168:
169: // ^table.line[]
170: vclass.add_native_method("line", _line, 0, 0);
171:
1.10 paf 172: // ^table.offset[]
173: // ^table.offset[offset]
1.6 paf 174: vclass.add_native_method("offset", _offset, 0, 1);
1.7 paf 175:
1.10 paf 176: // ^table.menu{code}
177: // ^table.menu{code}[delim]
1.7 paf 178: vclass.add_native_method("menu", _menu, 1, 2);
1.8 paf 179:
1.10 paf 180: // ^table.empty{code-when-empty}
181: // ^table.empty{code-when-empty}{code-when-not}
1.8 paf 182: vclass.add_native_method("empty", _empty, 1, 2);
183:
1.1 paf 184: }
E-mail: