--- parser3/src/classes/json.C 2016/11/03 16:17:37 1.49 +++ parser3/src/classes/json.C 2023/10/01 15:14:44 1.58 @@ -1,7 +1,8 @@ /** @file Parser: @b json parser class. - Copyright (c) 2000-2015 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2000-2023 Art. Lebedev Studio (http://www.artlebedev.com) + Authors: Konstantin Morshnev */ #include "classes.h" @@ -18,7 +19,7 @@ #include "pa_vxdoc.h" #endif -volatile const char * IDENT_JSON_C="$Id: json.C,v 1.49 2016/11/03 16:17:37 moko Exp $"; +volatile const char * IDENT_JSON_C="$Id: json.C,v 1.58 2023/10/01 15:14:44 moko Exp $"; // class @@ -32,7 +33,7 @@ public: DECLARE_CLASS_VAR(json, new MJson); // methods -struct Json { +struct Json : public PA_Allocated { Stack stack; Stack key_stack; @@ -66,7 +67,7 @@ struct Json { static void set_json_value(Json *json, Value *value){ VHash *top = json->stack.top_value(); if(json->key == NULL){ - top->hash().put(String(format(top->get_hash()->count(), 0)), value); + top->hash().put(format(top->get_hash()->count(), 0), value); } else { switch (json->distinct){ case Json::D_EXCEPTION: @@ -366,7 +367,7 @@ const uint ANTI_ENDLESS_JSON_STRING_RECO char *get_indent(uint level){ static char* cache[ANTI_ENDLESS_JSON_STRING_RECOURSION]={}; if (!cache[level]){ - char *result = static_cast(pa_gc_malloc_atomic(level+1)); + char *result = static_cast(pa_malloc_atomic(level+1)); memset(result, '\t', level); result[level]='\0'; return cache[level]=result; @@ -374,6 +375,21 @@ char *get_indent(uint level){ return cache[level]; } +String *get_delim(uint level){ + static String* cache[ANTI_ENDLESS_JSON_STRING_RECOURSION]={}; + + if (!cache[level]){ + char *result = static_cast(pa_malloc_atomic(level+2+1+1)); + result[0]=','; + result[1]='\n'; + memset(result+2, '\t', level); + result[level+2]='"'; + result[level+3]='\0'; + return cache[level] = new String(result, String::L_AS_IS); + } + return cache[level]; +} + class Json_string_recoursion { Json_options& foptions; public: @@ -406,7 +422,7 @@ const String* Json_options::hash_json_st result << *delim; } else { result << indent << "\""; - delim = new String(",\n", String::L_AS_IS); *delim << indent << "\""; + delim = get_delim(json_string_recoursion); } result << String(i.key(), String::L_JSON) << "\":" << value_json_string(i.key(), *i.value(), *this); } @@ -472,6 +488,9 @@ static void _string(Request& r, MethodPa if(key == "skip-unknown"){ json.skip_unknown=r.process(*value).as_bool(); valid_options++; + } else if(key == "one-line"){ + json.one_line=r.process(*value).as_bool(); + valid_options++; } else if(key == "date" && value->is_string()){ const String& svalue=value->as_string(); if(!json.set_date_format(svalue)) @@ -532,13 +551,20 @@ static void _string(Request& r, MethodPa const String& result_string=value_json_string(String::Body(), r.process(params[0]), json); String::Body result_body=result_string.cstr_to_string_body_untaint(String::L_JSON, r.connection(false), &r.charsets); + if(json.one_line){ + char *result=result_body.cstrm(); + for(char *c=result;*c;c++) + if(*c=='\n') + *c=' '; + result_body=result; + } r.write(*new String(result_body, String::L_AS_IS)); - } +} // constructor MJson::MJson(): Methoded("json") { add_native_method("parse", Method::CT_STATIC, _parse, 1, 2); - add_native_method("string", Method::CT_ANY, _string, 1, 2); + add_native_method("string", Method::CT_STATIC, _string, 1, 2); }