Annotation of parser3/src/classes/hash.C, revision 1.22
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.22 ! parser 7: $Id: hash.C,v 1.21 2001/10/11 12:04:19 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)
59: PTHROW(0, 0,
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);
74: row_hash=row_vhash->get_hash();
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");
! 103: if(Hash *b=vb.get_hash())
! 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);
! 110: dest.put(key, 0);
! 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");
! 117: if(Hash *b=vb.get_hash())
! 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");
! 133: if(Hash *b=vb.get_hash())
! 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");
! 163: if(Hash *b=vb.get_hash()) {
! 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");
! 190: if(Hash *b=vb.get_hash())
! 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)
204: PTHROW(0, 0,
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.2 parser 230: bool need_rethrow=false; Exception rethrow_me;
231: PTRY {
232: r.connection->query(
233: statement_cstr, offset, limit,
1.11 parser 234: handlers);
1.2 parser 235: }
1.3 parser 236: PCATCH(e) { // query problem
1.2 parser 237: rethrow_me=e; need_rethrow=true;
238: }
239: PEND_CATCH
240: if(need_rethrow)
241: PTHROW(rethrow_me.type(), rethrow_me.code(),
242: &statement_string, // setting more specific source [were url]
243: rethrow_me.comment());
244: }
245:
1.9 parser 246: static void keys_collector(const Hash::Key& key, Hash::Val *value, void *info) {
247: Table& table=*static_cast<Table *>(info);
248: Pool& pool=table.pool();
249:
250: Array& row=*new(pool) Array(pool);
251: row+=&key;
252: table+=&row;
253: }
254: static void _keys(Request& r, const String& method_name, MethodParams *) {
255: Pool& pool=r.pool();
256:
257: Array& columns=*new(pool) Array(pool);
258: columns+=new(pool) String(pool, "key");
259: Table& table=*new(pool) Table(pool, &method_name, &columns);
260:
261: static_cast<VHash *>(r.self)->hash().for_each(keys_collector, &table);
262:
263: VTable& result=*new(pool) VTable(pool, &table);
264: result.set_name(method_name);
265: r.write_no_lang(result);
266: }
267:
1.16 parser 268: static void _count(Request& r, const String& method_name, MethodParams *) {
269: Pool& pool=r.pool();
270:
1.22 ! parser 271: Value& result=*new(pool) VInt(pool, static_cast<VHash *>(r.self)->hash().size());
! 272: result.set_name(method_name);
! 273: r.write_no_lang(result);
1.16 parser 274: }
275:
1.1 paf 276: // constructor
277:
278: MHash::MHash(Pool& apool) : Methoded(apool) {
1.2 parser 279: set_name(*NEW String(pool(), HASH_CLASS_NAME));
1.20 parser 280:
1.21 parser 281: // ^hash::create[[copy_from]]
1.22 ! parser 282: add_native_method("create", Method::CT_DYNAMIC, _create_or_add, 0, 1);
! 283: // ^hash.add[add_from]
! 284: add_native_method("add", Method::CT_DYNAMIC, _create_or_add, 1, 1);
! 285: // ^hash.sub[sub_from]
! 286: add_native_method("sub", Method::CT_DYNAMIC, _sub, 1, 1);
! 287: // ^a.union[b] = hash
! 288: add_native_method("union", Method::CT_DYNAMIC, _union, 1, 1);
! 289: // ^a.intersection[b] = hash
! 290: add_native_method("intersection", Method::CT_DYNAMIC, _intersection, 1, 1);
! 291: // ^a.intersects[b] = bool
! 292: add_native_method("intersects", Method::CT_DYNAMIC, _intersects, 1, 1);
1.2 parser 293:
294: // ^hash:sql[query][(count[;offset])]
295: add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 3);
296:
1.14 parser 297: // ^hash._keys[]
1.13 parser 298: add_native_method("_keys", Method::CT_DYNAMIC, _keys, 0, 0);
1.16 parser 299:
300: // ^hash._count[]
301: add_native_method("_count", Method::CT_DYNAMIC, _count, 0, 0);
1.1 paf 302: }
303:
304: // global variable
305:
306: Methoded *hash_base_class;
307:
308: // creator
309:
310: Methoded *MHash_create(Pool& pool) {
311: return hash_base_class=new(pool) MHash(pool);
312: }
E-mail: