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