Annotation of parser3/src/classes/hashfile.C, revision 1.51
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.51 ! misha 8: static const char * const IDENT="$Id: hashfile.C,v 1.50 2009-07-29 05:01:33 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.51 ! misha 21: Value *create_new_value(Pool& apool) { 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.35 paf 33: // defines for statics
34:
35: #define OPEN_DATA_NAME "HASHFILE-OPEN-DATA"
36:
1.1 parser 37: // methods
38:
1.46 misha 39: typedef HashString<bool> HashStringBool;
1.35 paf 40:
1.24 paf 41: static void _open(Request& r, MethodParams& params) {
1.35 paf 42: HashStringBool* file_list=static_cast<HashStringBool*>(r.classes_conf.get(OPEN_DATA_NAME));
43: if(!file_list) {
44: file_list=new HashStringBool();
45: r.classes_conf.put(OPEN_DATA_NAME, file_list);
46: }
47:
1.41 misha 48: const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING));
1.35 paf 49: if(file_list->get(file_spec))
1.39 misha 50: throw Exception(PARSER_RUNTIME,
1.35 paf 51: 0,
52: "this hashfile is already opened, use existing variable");
53: file_list->put(file_spec, true);
54:
1.24 paf 55: VHashfile& self=GET_SELF(r, VHashfile);
1.35 paf 56: self.open(file_spec);
1.9 paf 57: }
1.1 parser 58:
1.31 paf 59: static void _hash(Request& r, MethodParams&) {
1.24 paf 60: VHashfile& self=GET_SELF(r, VHashfile);
1.5 parser 61:
62: // write out result
1.26 paf 63: VHash& result=*new VHash(*self.get_hash());
1.5 parser 64: r.write_no_lang(result);
65: }
1.26 paf 66:
1.24 paf 67: static void _delete(Request& r, MethodParams& params) {
68: VHashfile& self=GET_SELF(r, VHashfile);
1.8 parser 69:
1.30 paf 70: if(!params.count()) {
71: // ^hashfile.delete[] asked to delete hashfile itself
72: self.delete_files();
73: return;
74: }
1.25 paf 75: // key
76: const String &key=params.as_string(0, "key must be string");
77: // remove
78: self.remove(key);
1.8 parser 79: }
80:
1.24 paf 81: static void _clear(Request& r, MethodParams&) {
82: VHashfile& self=GET_SELF(r, VHashfile);
1.39 misha 83: self.delete_files();
1.12 paf 84: }
85:
1.27 paf 86: #ifndef DOXYGEN
1.28 paf 87: struct Foreach_info {
1.27 paf 88: Request* r;
89: const String* key_var_name;
90: const String* value_var_name;
91: Value* body_code;
92: Value* delim_maybe_code;
93:
94: Value* var_context;
95: bool need_delim;
96: };
97: #endif
1.42 misha 98: static bool one_foreach_cycle(
1.51 ! misha 99: const String::Body key,
! 100: const String& value,
! 101: void* ainfo) {
1.28 paf 102: Foreach_info& info=*static_cast<Foreach_info*>(ainfo);
1.44 misha 103: if(info.key_var_name){
1.49 misha 104: VString* vkey=new VString(*new String(key, String::L_TAINTED));
1.51 ! misha 105: info.var_context->put_element(*info.key_var_name, vkey, false);
1.44 misha 106: }
107: if(info.value_var_name){
1.49 misha 108: VString* vvalue=new VString(value);
1.51 ! misha 109: info.var_context->put_element(*info.value_var_name, vvalue, false);
1.44 misha 110: }
1.27 paf 111:
112: StringOrValue sv_processed=info.r->process(*info.body_code);
1.37 paf 113: Request::Skip lskip=info.r->get_skip(); info.r->set_skip(Request::SKIP_NOTHING);
1.42 misha 114:
1.27 paf 115: const String* s_processed=sv_processed.get_string();
1.45 misha 116: if(info.delim_maybe_code && s_processed && !s_processed->is_empty()) { // delimiter set and we have body
1.27 paf 117: if(info.need_delim) // need delim & iteration produced string?
118: info.r->write_pass_lang(info.r->process(*info.delim_maybe_code));
1.42 misha 119: else
120: info.need_delim=true;
1.27 paf 121: }
1.42 misha 122:
1.27 paf 123: info.r->write_pass_lang(sv_processed);
1.37 paf 124:
125: return lskip==Request::SKIP_BREAK;
1.27 paf 126: }
1.24 paf 127: static void _foreach(Request& r, MethodParams& params) {
1.50 misha 128: InCycle temp(r);
1.37 paf 129:
1.44 misha 130: const String& key_var_name=params.as_string(0, "key-var name must be string");
131: const String& value_var_name=params.as_string(1, "value-var name must be string");
132:
1.43 misha 133: Foreach_info info={
134: &r,
1.44 misha 135: key_var_name.is_empty()? 0 : &key_var_name,
136: value_var_name.is_empty()? 0 : &value_var_name,
1.43 misha 137: ¶ms.as_junction(2, "body must be code"),
1.44 misha 138: /*delimiter*/params.count()>3 ? params.get(3) : 0,
1.43 misha 139: /*var_context*/r.get_method_frame()->caller(),
1.44 misha 140: false
1.43 misha 141: };
142:
1.24 paf 143: VHashfile& self=GET_SELF(r, VHashfile);
1.27 paf 144: self.for_each(one_foreach_cycle, &info);
1.14 paf 145: }
146:
1.38 misha 147: static bool one_cleanup_cycle(const String::Body, const String&, void*) {
148: return false;
149: }
150: static void _cleanup(Request& r, MethodParams&) {
151: VHashfile& self=GET_SELF(r, VHashfile);
152:
153: self.for_each(one_cleanup_cycle, 0);
154: }
155:
156: static void _release(Request& r, MethodParams&) {
157: VHashfile& self=GET_SELF(r, VHashfile);
158: self.close();
159: }
160:
1.1 parser 161: // constructor
162:
1.24 paf 163: MHashfile::MHashfile(): Methoded("hashfile") {
1.38 misha 164: // ^hashfile::open[filename]
1.24 paf 165: add_native_method("open", Method::CT_DYNAMIC, _open, 1, 1);
1.38 misha 166: // ^hashfile.hash[]
1.26 paf 167: add_native_method("hash", Method::CT_DYNAMIC, _hash, 0, 0);
1.8 parser 168: // ^hashfile.delete[key]
1.30 paf 169: add_native_method("delete", Method::CT_DYNAMIC, _delete, 0, 1);
1.39 misha 170: // ^hashfile.clear[] -- for backward compatibility. use .delete[] instead.
1.12 paf 171: add_native_method("clear", Method::CT_DYNAMIC, _clear, 0, 0);
1.40 misha 172: // ^hashfile.release[]
1.38 misha 173: add_native_method("release", Method::CT_DYNAMIC, _release, 0, 0);
174: // ^hashfile.cleanup[]
175: add_native_method("cleanup", Method::CT_DYNAMIC, _cleanup, 0, 0);
176: add_native_method("defecate", Method::CT_DYNAMIC, _cleanup, 0, 0);
1.14 paf 177: // ^hashfile.foreach[key;value]{code}[delim]
1.27 paf 178: add_native_method("foreach", Method::CT_DYNAMIC, _foreach, 2+1, 2+1+1);
1.1 parser 179: }
E-mail: