Annotation of parser3/src/classes/hash.C, revision 1.25
1.1 paf 1: /** @file
2: Parser: @b hash parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.19 parser 5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.1 paf 6:
1.25 ! paf 7: $Id: hash.C,v 1.24 2001/10/23 14:43:44 parser Exp $
1.1 paf 8: */
9:
10: #include "classes.h"
11: #include "pa_request.h"
12: #include "pa_vhash.h"
1.6 parser 13: #include "pa_vvoid.h"
1.2 parser 14: #include "pa_sql_connection.h"
1.9 parser 15: #include "pa_vtable.h"
1.22 parser 16: #include "pa_vbool.h"
1.2 parser 17:
18: // defines
19:
20: #define HASH_CLASS_NAME "hash"
1.1 paf 21:
22: // class
23:
24: class MHash : public Methoded {
1.2 parser 25: public: // VStateless_class
26: Value *create_new_value(Pool& pool) { return new(pool) VHash(pool); }
27:
1.1 paf 28: public:
29: MHash(Pool& pool);
30: public: // Methoded
1.2 parser 31: bool used_directly() { return true; }
1.1 paf 32: };
33:
34: // methods
35:
1.11 parser 36: #ifndef DOXYGEN
37: class Hash_sql_event_handlers : public SQL_Driver_query_event_handlers {
38: public:
39: Hash_sql_event_handlers(Pool& apool, const String& amethod_name,
40: const String& astatement_string, const char *astatement_cstr,
41: Hash& arows_hash) :
42: pool(apool),
43: method_name(amethod_name),
44: statement_string(astatement_string),
45: statement_cstr(astatement_cstr),
46: rows_hash(arows_hash),
47: columns(pool),
48: row_index(0) {
49: }
50: void add_column(void *ptr, size_t size) {
51: String *column=new(pool) String(pool);
52: column->APPEND_TAINTED(
53: (const char *)ptr, size,
54: statement_cstr, 0);
55: columns+=column;
56: }
57: void before_rows() {
58: if(columns.size()<=1)
1.23 parser 59: throw Exception(0, 0,
1.11 parser 60: &method_name,
61: "column count must be more than 1 to create a hash");
62: }
63: void add_row() {
64: column_index=0;
65: }
66: void add_row_cell(void *ptr, size_t size) {
67: String *cell=new(pool) String(pool);
68: if(size)
69: cell->APPEND_TAINTED(
70: (const char *)ptr, size,
71: statement_cstr, row_index++);
72: if(column_index==0) {
73: VHash *row_vhash=new(pool) VHash(pool);
1.24 parser 74: row_hash=row_vhash->get_hash(0);
1.11 parser 75: rows_hash.put(*cell, row_vhash);
76: } else
77: row_hash->put(*columns.get_string(column_index), new(pool) VString(*cell));
1.12 parser 78: column_index++;
1.11 parser 79: }
80:
81: private:
82: Pool& pool;
83: const String& method_name;
84: const String& statement_string; const char *statement_cstr;
85: Hash& rows_hash;
86: Hash *row_hash;
87: int column_index;
88: Array columns;
89: int row_index;
90: };
91: #endif
92:
1.22 parser 93: static void copy_all_overwrite_to(const Hash::Key& key, Hash::Val *value, void *info) {
1.20 parser 94: Hash& dest=*static_cast<Hash *>(info);
95: dest.put(key, value);
96: }
97:
1.22 parser 98: static void _create_or_add(Request& r, const String& method_name, MethodParams *params) {
1.20 parser 99: Pool& pool=r.pool();
100:
101: if(params->size()) {
1.22 parser 102: Value& vb=params->as_no_junction(0, "param must be hash");
1.24 parser 103: if(Hash *b=vb.get_hash(&method_name))
1.22 parser 104: b->for_each(copy_all_overwrite_to, &static_cast<VHash *>(r.self)->hash());
1.20 parser 105: }
106: }
107:
1.22 parser 108: static void remove_key_from(const Hash::Key& key, Hash::Val *value, void *info) {
109: Hash& dest=*static_cast<Hash *>(info);
1.25 ! paf 110: dest.remove(key);
1.22 parser 111: }
112:
113: static void _sub(Request& r, const String& method_name, MethodParams *params) {
114: Pool& pool=r.pool();
115:
116: Value& vb=params->as_no_junction(0, "param must be hash");
1.24 parser 117: if(Hash *b=vb.get_hash(&method_name))
1.22 parser 118: b->for_each(remove_key_from, &static_cast<VHash *>(r.self)->hash());
119: }
120:
121: static void copy_all_dontoverwrite_to(const Hash::Key& key, Hash::Val *value, void *info) {
122: Hash& dest=*static_cast<Hash *>(info);
123: dest.put_dont_replace(key, value);
124: }
125:
126: static void _union(Request& r, const String& method_name, MethodParams *params) {
127: Pool& pool=r.pool();
128:
129: // dest = copy of self
130: Hash& dest=*new(pool) Hash(static_cast<VHash *>(r.self)->hash());
131: // dest += b
132: Value& vb=params->as_no_junction(0, "param must be hash");
1.24 parser 133: if(Hash *b=vb.get_hash(&method_name))
1.22 parser 134: b->for_each(copy_all_dontoverwrite_to, &dest);
135:
136: // return result
137: Value& result=*new(pool) VHash(pool, dest);
138: result.set_name(method_name);
139: r.write_no_lang(result);
140: }
141:
142: #ifndef DOXYGEN
143: struct Copy_intersection_to_info {
144: Hash *b;
145: Hash *dest;
146: };
147: #endif
148:
149: static void copy_intersection_to(const Hash::Key& key, Hash::Val *value, void *info) {
150: Copy_intersection_to_info& i=*static_cast<Copy_intersection_to_info *>(info);
151:
152: if(i.b->get(key))
153: i.dest->put_dont_replace(key, value);
154: }
155:
156: static void _intersection(Request& r, const String& method_name, MethodParams *params) {
157: Pool& pool=r.pool();
158:
159: // dest = copy of self
160: Hash& dest=*new(pool) Hash(pool);
161: // dest += b
162: Value& vb=params->as_no_junction(0, "param must be hash");
1.24 parser 163: if(Hash *b=vb.get_hash(&method_name)) {
1.22 parser 164: Copy_intersection_to_info info={
165: b,
166: &dest
167: };
168: static_cast<VHash *>(r.self)->hash().for_each(copy_intersection_to, &info);
169: }
170:
171: // return result
172: Value& result=*new(pool) VHash(pool, dest);
173: result.set_name(method_name);
174: r.write_no_lang(result);
175: }
176:
177: static void *intersects(const Hash::Key& key, Hash::Val *value, void *info) {
178: return static_cast<Hash *>(info)->get(key);
179: }
180:
181: static void _intersects(Request& r, const String& method_name, MethodParams *params) {
182: Pool& pool=r.pool();
183:
184: bool yes=false;
185:
186: // dest = copy of self
187: Hash& dest=*new(pool) Hash(pool);
188: // dest += b
189: Value& vb=params->as_no_junction(0, "param must be hash");
1.24 parser 190: if(Hash *b=vb.get_hash(&method_name))
1.22 parser 191: yes=static_cast<VHash *>(r.self)->hash().first_that(intersects, b)!=0;
192:
193: // return result
194: Value& result=*new(pool) VBool(pool, yes);
195: result.set_name(method_name);
196: r.write_no_lang(result);
197: }
198:
199:
1.2 parser 200: static void _sql(Request& r, const String& method_name, MethodParams *params) {
201: Pool& pool=r.pool();
202:
203: if(!r.connection)
1.23 parser 204: throw Exception(0, 0,
1.2 parser 205: &method_name,
206: "without connect");
207:
1.10 parser 208: Value& statement=params->as_junction(0, "statement must be code");
1.2 parser 209:
210: ulong limit=0;
211: if(params->size()>1) {
1.10 parser 212: Value& limit_code=params->as_junction(1, "limit must be expression");
1.2 parser 213: limit=(uint)r.process(limit_code).as_double();
214: }
215:
216: ulong offset=0;
217: if(params->size()>2) {
1.10 parser 218: Value& offset_code=params->as_junction(2, "offset must be expression");
1.2 parser 219: offset=(ulong)r.process(offset_code).as_double();
220: }
221:
222: Temp_lang temp_lang(r, String::UL_SQL);
223: const String& statement_string=r.process(statement).as_string();
224: const char *statement_cstr=
225: statement_string.cstr(String::UL_UNSPECIFIED, r.connection);
1.11 parser 226: Hash& hash=static_cast<VHash *>(r.self)->hash();
227: hash.clear();
228: Hash_sql_event_handlers handlers(pool, method_name,
229: statement_string, statement_cstr, hash);
1.23 parser 230:
231: r.connection->query(
232: statement_cstr, offset, limit,
233: handlers);
1.2 parser 234: }
235:
1.9 parser 236: static void keys_collector(const Hash::Key& key, Hash::Val *value, void *info) {
237: Table& table=*static_cast<Table *>(info);
238: Pool& pool=table.pool();
239:
240: Array& row=*new(pool) Array(pool);
241: row+=&key;
242: table+=&row;
243: }
244: static void _keys(Request& r, const String& method_name, MethodParams *) {
245: Pool& pool=r.pool();
246:
247: Array& columns=*new(pool) Array(pool);
248: columns+=new(pool) String(pool, "key");
249: Table& table=*new(pool) Table(pool, &method_name, &columns);
250:
251: static_cast<VHash *>(r.self)->hash().for_each(keys_collector, &table);
252:
253: VTable& result=*new(pool) VTable(pool, &table);
254: result.set_name(method_name);
255: r.write_no_lang(result);
256: }
257:
1.16 parser 258: static void _count(Request& r, const String& method_name, MethodParams *) {
259: Pool& pool=r.pool();
260:
1.22 parser 261: Value& result=*new(pool) VInt(pool, static_cast<VHash *>(r.self)->hash().size());
262: result.set_name(method_name);
263: r.write_no_lang(result);
1.16 parser 264: }
265:
1.25 ! paf 266: static void _delete(Request& r, const String& method_name, MethodParams *params) {
! 267: Pool& pool=r.pool();
! 268:
! 269: static_cast<VHash *>(r.self)->hash().remove(params->as_string(0, "key must be string"));
! 270: }
! 271:
1.1 paf 272: // constructor
273:
274: MHash::MHash(Pool& apool) : Methoded(apool) {
1.2 parser 275: set_name(*NEW String(pool(), HASH_CLASS_NAME));
1.20 parser 276:
1.21 parser 277: // ^hash::create[[copy_from]]
1.22 parser 278: add_native_method("create", Method::CT_DYNAMIC, _create_or_add, 0, 1);
279: // ^hash.add[add_from]
280: add_native_method("add", Method::CT_DYNAMIC, _create_or_add, 1, 1);
281: // ^hash.sub[sub_from]
282: add_native_method("sub", Method::CT_DYNAMIC, _sub, 1, 1);
283: // ^a.union[b] = hash
284: add_native_method("union", Method::CT_DYNAMIC, _union, 1, 1);
285: // ^a.intersection[b] = hash
286: add_native_method("intersection", Method::CT_DYNAMIC, _intersection, 1, 1);
287: // ^a.intersects[b] = bool
288: add_native_method("intersects", Method::CT_DYNAMIC, _intersects, 1, 1);
1.25 ! paf 289:
! 290: // ^a.delete[key]
! 291: add_native_method("delete", Method::CT_DYNAMIC, _delete, 1, 1);
1.2 parser 292:
293: // ^hash:sql[query][(count[;offset])]
294: add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 3);
295:
1.14 parser 296: // ^hash._keys[]
1.13 parser 297: add_native_method("_keys", Method::CT_DYNAMIC, _keys, 0, 0);
1.16 parser 298:
299: // ^hash._count[]
300: add_native_method("_count", Method::CT_DYNAMIC, _count, 0, 0);
1.1 paf 301: }
302:
303: // global variable
304:
305: Methoded *hash_base_class;
306:
307: // creator
308:
309: Methoded *MHash_create(Pool& pool) {
310: return hash_base_class=new(pool) MHash(pool);
311: }
E-mail: