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