Annotation of parser3/src/types/pa_value.C, revision 1.50

1.1       paf         1: /** @file
                      2:        Parser: Value class.
                      3: 
1.49      moko        4:        Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com)
                      5:        Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <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.50    ! moko       16: volatile const char * IDENT_PA_VALUE_C="$Id: pa_value.C,v 1.49 2023/09/26 20:49:11 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: 
1.48      moko       34: VFile* Value::as_vfile() {
                     35:        throw Exception(PARSER_RUNTIME, 0, "parameter is '%s', it does not have file value", type());
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.50    ! moko      109:                if(VDate* vdate=dynamic_cast<VDate*>(&value)) {
        !           110:                        result << *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: