Annotation of parser3/src/classes/hashfile.C, revision 1.38
1.1 parser 1: /** @file
2: Parser: @b hashfile parser class.
3:
1.36 paf 4: Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
1.22 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.24 paf 6: */
7:
1.38 ! misha 8: static const char * const IDENT="$Id: hashfile.C,v 1.37 2006/04/09 13:38:46 paf Exp $";
1.1 parser 9:
1.4 parser 10: #include "classes.h"
1.1 parser 11:
12: #include "pa_request.h"
1.24 paf 13: #include "pa_vmethod_frame.h"
1.1 parser 14: #include "pa_vhashfile.h"
15: #include "pa_vhash.h"
16:
17: // class
18:
19: class MHashfile : public Methoded {
20: public: // VStateless_class
1.34 paf 21: Value *create_new_value(Pool& apool, HashStringValue&) { return new VHashfile(apool); }
1.1 parser 22:
23: public:
1.24 paf 24: MHashfile();
1.1 parser 25: public: // Methoded
26: bool used_directly() { return true; }
27: };
28:
1.24 paf 29: // global variable
30:
31: DECLARE_CLASS_VAR(hashfile, new MHashfile, 0);
32:
1.37 paf 33: // externs
34:
35: extern String cycle_data_name;
36:
1.35 paf 37: // defines for statics
38:
39: #define OPEN_DATA_NAME "HASHFILE-OPEN-DATA"
40:
1.1 parser 41: // methods
42:
1.35 paf 43: typedef Hash<const String::Body, bool> HashStringBool;
44:
1.24 paf 45: static void _open(Request& r, MethodParams& params) {
1.35 paf 46: HashStringBool* file_list=static_cast<HashStringBool*>(r.classes_conf.get(OPEN_DATA_NAME));
47: if(!file_list) {
48: file_list=new HashStringBool();
49: r.classes_conf.put(OPEN_DATA_NAME, file_list);
50: }
51:
52: const String& file_spec=r.absolute(params.as_string(0, "filename must be string"));
53: if(file_list->get(file_spec))
54: throw Exception("parser.runtime",
55: 0,
56: "this hashfile is already opened, use existing variable");
57: file_list->put(file_spec, true);
58:
1.24 paf 59: VHashfile& self=GET_SELF(r, VHashfile);
1.35 paf 60: self.open(file_spec);
1.9 paf 61: }
1.1 parser 62:
1.31 paf 63: static void _hash(Request& r, MethodParams&) {
1.24 paf 64: VHashfile& self=GET_SELF(r, VHashfile);
1.5 parser 65:
66: // write out result
1.26 paf 67: VHash& result=*new VHash(*self.get_hash());
1.5 parser 68: r.write_no_lang(result);
69: }
1.26 paf 70:
1.24 paf 71: static void _delete(Request& r, MethodParams& params) {
72: VHashfile& self=GET_SELF(r, VHashfile);
1.8 parser 73:
1.30 paf 74: if(!params.count()) {
75: // ^hashfile.delete[] asked to delete hashfile itself
76: self.delete_files();
77: return;
78: }
1.25 paf 79: // key
80: const String &key=params.as_string(0, "key must be string");
81: // remove
82: self.remove(key);
1.8 parser 83: }
84:
1.24 paf 85: static void _clear(Request& r, MethodParams&) {
86: VHashfile& self=GET_SELF(r, VHashfile);
87: self.clear();
1.12 paf 88: }
89:
1.27 paf 90: #ifndef DOXYGEN
1.28 paf 91: struct Foreach_info {
1.27 paf 92: Request* r;
93: const String* key_var_name;
94: const String* value_var_name;
95: Value* body_code;
96: Value* delim_maybe_code;
97:
98: Value* var_context;
99: VString* vkey;
100: VString* vvalue;
101: bool need_delim;
102: };
103: #endif
1.37 paf 104: static bool one_foreach_cycle(const String::Body key, const String& value, void* ainfo) {
1.28 paf 105: Foreach_info& info=*static_cast<Foreach_info*>(ainfo);
1.27 paf 106: info.vkey->set_string(*new String(key, String::L_TAINTED));
107: info.vvalue->set_string(value);
1.34 paf 108: info.var_context->put_element(*info.var_context, *info.key_var_name, info.vkey, false);
109: info.var_context->put_element(*info.var_context, *info.value_var_name, info.vvalue, false);
1.27 paf 110:
111: StringOrValue sv_processed=info.r->process(*info.body_code);
1.37 paf 112: Request::Skip lskip=info.r->get_skip(); info.r->set_skip(Request::SKIP_NOTHING);
1.27 paf 113: const String* s_processed=sv_processed.get_string();
114: if(info.delim_maybe_code && s_processed && s_processed->length()) { // delimiter set and we have body
115: if(info.need_delim) // need delim & iteration produced string?
116: info.r->write_pass_lang(info.r->process(*info.delim_maybe_code));
117: info.need_delim=true;
118: }
119: info.r->write_pass_lang(sv_processed);
1.37 paf 120:
121: return lskip==Request::SKIP_BREAK;
1.27 paf 122: }
1.24 paf 123: static void _foreach(Request& r, MethodParams& params) {
1.37 paf 124: Temp_hash_value<const String::Body, void*>
125: cycle_data_setter(r.classes_conf, cycle_data_name, /*any not null flag*/&r);
126:
1.24 paf 127: VHashfile& self=GET_SELF(r, VHashfile);
128:
1.28 paf 129: Foreach_info info;
1.27 paf 130:
131: info.r=&r;
132: info.key_var_name=¶ms.as_string(0, "key-var name must be string");
133: info.value_var_name=¶ms.as_string(1, "value-var name must be string");
134: info.body_code=¶ms.as_junction(2, "body must be code");
135: info.delim_maybe_code=params.count()>3?params.get(3):0;
136:
137: info.var_context=info.body_code->get_junction()->wcontext;
138: info.vkey=new VString;
139: info.vvalue=new VString;
140:
141: info.need_delim=false;
142:
143: self.for_each(one_foreach_cycle, &info);
1.14 paf 144: }
145:
1.38 ! misha 146: static bool one_cleanup_cycle(const String::Body, const String&, void*) {
! 147: return false;
! 148: }
! 149: static void _cleanup(Request& r, MethodParams&) {
! 150: VHashfile& self=GET_SELF(r, VHashfile);
! 151:
! 152: self.for_each(one_cleanup_cycle, 0);
! 153: }
! 154:
! 155: static void _release(Request& r, MethodParams&) {
! 156: VHashfile& self=GET_SELF(r, VHashfile);
! 157: self.close();
! 158: }
! 159:
1.1 parser 160: // constructor
161:
1.24 paf 162: MHashfile::MHashfile(): Methoded("hashfile") {
1.38 ! misha 163: // ^hashfile::open[filename]
1.24 paf 164: add_native_method("open", Method::CT_DYNAMIC, _open, 1, 1);
1.38 ! misha 165: // ^hashfile.hash[]
1.26 paf 166: add_native_method("hash", Method::CT_DYNAMIC, _hash, 0, 0);
1.8 parser 167: // ^hashfile.delete[key]
1.30 paf 168: add_native_method("delete", Method::CT_DYNAMIC, _delete, 0, 1);
1.12 paf 169: // ^hashfile.clear[]
170: add_native_method("clear", Method::CT_DYNAMIC, _clear, 0, 0);
1.38 ! misha 171: // ^hashfile.flush[]
! 172: add_native_method("release", Method::CT_DYNAMIC, _release, 0, 0);
! 173: // ^hashfile.cleanup[]
! 174: add_native_method("cleanup", Method::CT_DYNAMIC, _cleanup, 0, 0);
! 175: add_native_method("defecate", Method::CT_DYNAMIC, _cleanup, 0, 0);
1.14 paf 176: // ^hashfile.foreach[key;value]{code}[delim]
1.27 paf 177: add_native_method("foreach", Method::CT_DYNAMIC, _foreach, 2+1, 2+1+1);
1.1 parser 178: }
E-mail: