Annotation of parser3/src/classes/hashfile.C, revision 1.45
1.1 parser 1: /** @file
2: Parser: @b hashfile parser class.
3:
1.45 ! misha 4: Copyright (c) 2001-2009 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.45 ! misha 8: static const char * const IDENT="$Id: hashfile.C,v 1.44 2008-05-19 08:56:59 misha 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:
1.41 misha 52: const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING));
1.35 paf 53: if(file_list->get(file_spec))
1.39 misha 54: throw Exception(PARSER_RUNTIME,
1.35 paf 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);
1.39 misha 87: self.delete_files();
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.42 misha 104: static bool one_foreach_cycle(
105: const String::Body key,
106: const String& value,
107: void* ainfo) {
1.28 paf 108: Foreach_info& info=*static_cast<Foreach_info*>(ainfo);
1.44 misha 109: if(info.key_var_name){
110: info.vkey->set_string(*new String(key, String::L_TAINTED));
111: info.var_context->put_element(*info.var_context, *info.key_var_name, info.vkey, false);
112: }
113: if(info.value_var_name){
114: info.vvalue->set_string(value);
115: info.var_context->put_element(*info.var_context, *info.value_var_name, info.vvalue, false);
116: }
1.27 paf 117:
118: StringOrValue sv_processed=info.r->process(*info.body_code);
1.37 paf 119: Request::Skip lskip=info.r->get_skip(); info.r->set_skip(Request::SKIP_NOTHING);
1.42 misha 120:
1.27 paf 121: const String* s_processed=sv_processed.get_string();
1.45 ! misha 122: if(info.delim_maybe_code && s_processed && !s_processed->is_empty()) { // delimiter set and we have body
1.27 paf 123: if(info.need_delim) // need delim & iteration produced string?
124: info.r->write_pass_lang(info.r->process(*info.delim_maybe_code));
1.42 misha 125: else
126: info.need_delim=true;
1.27 paf 127: }
1.42 misha 128:
1.27 paf 129: info.r->write_pass_lang(sv_processed);
1.37 paf 130:
131: return lskip==Request::SKIP_BREAK;
1.27 paf 132: }
1.24 paf 133: static void _foreach(Request& r, MethodParams& params) {
1.37 paf 134: Temp_hash_value<const String::Body, void*>
135: cycle_data_setter(r.classes_conf, cycle_data_name, /*any not null flag*/&r);
136:
1.44 misha 137: const String& key_var_name=params.as_string(0, "key-var name must be string");
138: const String& value_var_name=params.as_string(1, "value-var name must be string");
139:
1.43 misha 140: Foreach_info info={
141: &r,
1.44 misha 142: key_var_name.is_empty()? 0 : &key_var_name,
143: value_var_name.is_empty()? 0 : &value_var_name,
1.43 misha 144: ¶ms.as_junction(2, "body must be code"),
1.44 misha 145: /*delimiter*/params.count()>3 ? params.get(3) : 0,
1.43 misha 146: /*var_context*/r.get_method_frame()->caller(),
147: /*vkey=*/new VString,
148: /*vvalue=*/new VString,
1.44 misha 149: false
1.43 misha 150: };
151:
1.24 paf 152: VHashfile& self=GET_SELF(r, VHashfile);
1.27 paf 153: self.for_each(one_foreach_cycle, &info);
1.14 paf 154: }
155:
1.38 misha 156: static bool one_cleanup_cycle(const String::Body, const String&, void*) {
157: return false;
158: }
159: static void _cleanup(Request& r, MethodParams&) {
160: VHashfile& self=GET_SELF(r, VHashfile);
161:
162: self.for_each(one_cleanup_cycle, 0);
163: }
164:
165: static void _release(Request& r, MethodParams&) {
166: VHashfile& self=GET_SELF(r, VHashfile);
167: self.close();
168: }
169:
1.1 parser 170: // constructor
171:
1.24 paf 172: MHashfile::MHashfile(): Methoded("hashfile") {
1.38 misha 173: // ^hashfile::open[filename]
1.24 paf 174: add_native_method("open", Method::CT_DYNAMIC, _open, 1, 1);
1.38 misha 175: // ^hashfile.hash[]
1.26 paf 176: add_native_method("hash", Method::CT_DYNAMIC, _hash, 0, 0);
1.8 parser 177: // ^hashfile.delete[key]
1.30 paf 178: add_native_method("delete", Method::CT_DYNAMIC, _delete, 0, 1);
1.39 misha 179: // ^hashfile.clear[] -- for backward compatibility. use .delete[] instead.
1.12 paf 180: add_native_method("clear", Method::CT_DYNAMIC, _clear, 0, 0);
1.40 misha 181: // ^hashfile.release[]
1.38 misha 182: add_native_method("release", Method::CT_DYNAMIC, _release, 0, 0);
183: // ^hashfile.cleanup[]
184: add_native_method("cleanup", Method::CT_DYNAMIC, _cleanup, 0, 0);
185: add_native_method("defecate", Method::CT_DYNAMIC, _cleanup, 0, 0);
1.14 paf 186: // ^hashfile.foreach[key;value]{code}[delim]
1.27 paf 187: add_native_method("foreach", Method::CT_DYNAMIC, _foreach, 2+1, 2+1+1);
1.1 parser 188: }
E-mail: