Annotation of parser3/src/types/pa_value.C, revision 1.45
1.1 paf 1: /** @file
2: Parser: Value class.
3:
1.39 moko 4: Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)
1.1 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.2 paf 6: */
1.1 paf 7:
8: #include "pa_value.h"
9: #include "pa_vstateless_class.h"
1.4 paf 10: #include "pa_vmethod_frame.h"
1.10 paf 11: #include "pa_vdate.h"
12: #include "pa_vobject.h"
1.36 misha 13: #include "pa_request.h"
1.10 paf 14:
1.36 misha 15:
1.45 ! moko 16: volatile const char * IDENT_PA_VALUE_C="$Id: pa_value.C,v 1.44 2016/11/29 23:51:41 moko Exp $" IDENT_PA_VALUE_H IDENT_PA_PROPERTY_H;
1.32 moko 17:
1.10 paf 18: // globals
19:
20: const String name_name(NAME_NAME);
21:
22: const String value_name(VALUE_NAME);
1.12 paf 23: const String expires_name(EXPIRES_NAME);
1.10 paf 24: const String content_type_name(CONTENT_TYPE_NAME);
25:
26: // methods
27:
28: Junction* Value::get_junction() { return 0; }
29:
1.28 misha 30: Value* Value::get_element(const String& /*aname*/) {
1.41 moko 31: return bark("element can not be fetched from %s");
1.10 paf 32: }
33:
34: VFile* Value::as_vfile(String::Language /*lang*/, const Request_charsets* /*charsets*/) {
1.11 paf 35: bark("is '%s', it does not have file value"); return 0;
1.10 paf 36: }
1.1 paf 37:
1.45 ! moko 38: // Should be synced with MethodParams::as_hash
! 39: HashStringValue* Value::as_hash(const char* name) {
! 40: if(get_junction())
! 41: throw Exception(PARSER_RUNTIME, 0, "%s must not be code", name ? name : "options");
! 42: if(!is_defined()) // empty hash is not defined, but we don't need it anyway
! 43: return 0;
! 44: if(HashStringValue* result=get_hash())
! 45: return result;
! 46: if(is_string() && get_string()->trim().is_empty())
! 47: return 0;
! 48: throw Exception(PARSER_RUNTIME, 0, "%s must have hash representation", name ? name : "options");
! 49: }
! 50:
1.35 moko 51: const String* Value::get_json_string(Json_options& options) {
52: if(HashStringValue* hash=get_hash())
1.37 moko 53: return options.hash_json_string(hash);
1.35 moko 54:
55: if(!options.skip_unknown)
1.30 misha 56: throw Exception(PARSER_RUNTIME, 0, "Unsupported value's type (%s)", type());
1.35 moko 57:
1.30 misha 58: return new String("null");
59: }
60:
1.36 misha 61: const String* Value::default_method_2_json_string(Value& default_method, Json_options& options){
62: if(default_method.is_string()){
63: // specified as string with method name
64: const String& method_name=*default_method.get_string();
65: Method* method=this->get_class()->get_method(method_name);
66: if(!method) {
67: // class/object does not have method with specified name so serialize it as hash (default)
1.37 moko 68: return options.hash_json_string(get_hash());
1.36 misha 69: }
70:
71: Value *params[]={new VString(*new String(options.key, String::L_JSON)), options.params ? options.params : VVoid::get()};
72:
1.43 moko 73: METHOD_FRAME_ACTION(*method, options.r->method_frame, *this,{
74: frame.store_params(params, 2);
75: options.r->call(frame);
76: return &frame.result().as_string();
77: });
1.36 misha 78: } else {
79: // specified as method-junction
80: Junction* junction=default_method.get_junction();
81:
82: Value *params[]={new VString(*new String(options.key, String::L_JSON)), this, options.params ? options.params : VVoid::get()};
83:
1.43 moko 84: METHOD_FRAME_ACTION(*junction->method, options.r->method_frame, junction->self,{
85: frame.store_params(params, 3);
86: options.r->call(frame);
87: return &frame.result().as_string();
88: });
1.36 misha 89: }
90: }
91:
1.1 paf 92: /// call this before invoking to ensure proper actual numbered params count
1.42 moko 93: void Method::check_actual_numbered_params(Value& self, MethodParams* actual_numbered_params) const {
94: int actual_count=actual_numbered_params ? actual_numbered_params->count() : 0;
1.29 misha 95: if(actual_count<min_numbered_params_count || actual_count>max_numbered_params_count)
1.44 moko 96: throw Exception(PARSER_RUNTIME, name, "native method of '%s' accepts %s %d parameter(s) (%d present)",
1.42 moko 97: self.type(),
98: actual_count<min_numbered_params_count ? "minimum" : "maximum",
99: actual_count<min_numbered_params_count ? min_numbered_params_count : max_numbered_params_count,
100: actual_count);
1.1 paf 101: }
1.4 paf 102:
1.10 paf 103: // attributed meaning
104:
1.42 moko 105: static void append_attribute_meaning(String& result, Value& value, String::Language lang, bool forced) {
1.10 paf 106: if(const String* string=value.get_string())
107: result.append(*string, lang, forced);
108: else
1.28 misha 109: if(Value* vdate=value.as(VDATE_TYPE)) {
1.38 moko 110: result << *static_cast<VDate&>(*vdate).get_gmt_string();
1.10 paf 111: } else
1.38 moko 112: throw Exception(PARSER_RUNTIME, &result, "trying to append here neither string nor date (%s)", value.type());
1.10 paf 113: }
1.38 moko 114:
1.10 paf 115: #ifndef DOXYGEN
116: struct Attributed_meaning_info {
1.31 misha 117: String* header; // header line being constructed
1.10 paf 118: String::Language lang; // language in which to append to that line
1.31 misha 119: bool forced; // do they force that lang?
120: bool allow_bool; // allow bool types during print attributes
1.10 paf 121: };
122: #endif
1.42 moko 123:
124: static void append_attribute_subattribute(HashStringValue::key_type akey, HashStringValue::value_type avalue, Attributed_meaning_info *info) {
1.10 paf 125: if(akey==VALUE_NAME)
126: return;
127:
1.27 misha 128: if(avalue->is_bool() && (!info->allow_bool || avalue->as_bool()==false))
129: return;
130:
1.10 paf 131: // ...; charset=windows1251
132: *info->header << "; ";
133: info->header->append(String(akey, String::L_TAINTED), info->lang, info->forced);
1.31 misha 134: if(!avalue->is_bool()) {
135: if( akey==content_disposition_filename_name ) {
136: *info->header << "=\"";
137: append_attribute_meaning(*info->header, *avalue, info->lang, info->forced);
138: *info->header << "\"";
139: } else {
140: *info->header << "=";
141: append_attribute_meaning(*info->header, *avalue, info->lang, info->forced);
142: }
1.21 misha 143: }
1.10 paf 144: }
1.42 moko 145: const String& attributed_meaning_to_string(Value& meaning, String::Language lang, bool forced, bool allow_bool) {
1.10 paf 146: String& result=*new String;
147: if(HashStringValue *hash=meaning.get_hash()) {
148: // $value(value) $subattribute(subattribute value)
149: if(Value* value=hash->get(value_name))
150: append_attribute_meaning(result, *value, lang, forced);
151:
1.21 misha 152: Attributed_meaning_info attributed_meaning_info={&result, lang, false, allow_bool};
1.20 paf 153: hash->for_each<Attributed_meaning_info*>(append_attribute_subattribute, &attributed_meaning_info);
1.10 paf 154: } else // result value
155: append_attribute_meaning(result, meaning, lang, forced);
156:
157: return result;
158: }
E-mail: