--- parser3/src/classes/string.C 2024/09/07 15:01:38 1.252 +++ parser3/src/classes/string.C 2024/10/27 17:50:59 1.259 @@ -15,13 +15,14 @@ #include "pa_vtable.h" #include "pa_vbool.h" #include "pa_string.h" +#include "pa_varray.h" #include "pa_sql_connection.h" #include "pa_dictionary.h" #include "pa_vmethod_frame.h" #include "pa_vregex.h" #include "pa_charsets.h" -volatile const char * IDENT_STRING_C="$Id: string.C,v 1.252 2024/09/07 15:01:38 moko Exp $"; +volatile const char * IDENT_STRING_C="$Id: string.C,v 1.259 2024/10/27 17:50:59 moko Exp $"; // class @@ -147,7 +148,7 @@ static void _bool(Request& r, MethodPara // for some time due to stupid {} in original design const String& fmt=r.process_to_string(fmt_maybe_code); - const char* buf=format(r.get_self().as_double(), fmt.trim().cstrm()); + const char* buf=format_double(r.get_self().as_double(), fmt.trim().cstrm()); r.write(String(buf)); } @@ -208,6 +209,7 @@ static void _pos(Request& r, MethodParam struct Split_action_info { const String& src; ArrayString &result; + Split_action_info(const String& s, ArrayString& r) : src(s), result(r) {} }; static void split_action(Table& , ArrayString* row, int prestart, int prefinish, int poststart, int postfinish, void *info) { @@ -221,12 +223,11 @@ static void split_action(Table& , ArrayS } static void split_list(Value& delim_value, const String& string, ArrayString& result) { - if(Value* value=delim_value.as(VREGEX_TYPE)){ - VRegex *vregex=static_cast(value); + if(VRegex *vregex=dynamic_cast(&delim_value)){ vregex->study(); int matches_count=0; - Split_action_info ai = { string, result }; + Split_action_info ai(string, result); string.match(vregex, split_action, &ai, matches_count); } else @@ -237,6 +238,7 @@ static void split_list(Value& delim_valu #define SPLIT_RIGHT 0x0010 #define SPLIT_HORIZONTAL 0x0100 #define SPLIT_VERTICAL 0x1000 +#define SPLIT_ARRAY 0x10000 static int split_options(const String* options) { struct Split_option { @@ -245,10 +247,11 @@ static int split_options(const String* o int setBit; int checkBit; } split_option[]={ - {"l", "L", SPLIT_LEFT, SPLIT_RIGHT}, // 0xVHRL + {"l", "L", SPLIT_LEFT, SPLIT_RIGHT}, // 0xAVHRL {"r", "R", SPLIT_RIGHT, SPLIT_LEFT}, - {"h", "H", SPLIT_HORIZONTAL, SPLIT_VERTICAL}, - {"v", "V", SPLIT_VERTICAL, SPLIT_HORIZONTAL}, + {"h", "H", SPLIT_HORIZONTAL, SPLIT_VERTICAL | SPLIT_ARRAY}, + {"v", "V", SPLIT_VERTICAL, SPLIT_HORIZONTAL | SPLIT_ARRAY}, + {"a", "A", SPLIT_ARRAY, SPLIT_VERTICAL | SPLIT_HORIZONTAL}, {0, 0, 0, 0} }; @@ -278,8 +281,7 @@ static Table& split_vertical(ArrayString table+=row; } } else { // left - ArrayString::Iterator i(pieces); - while(i.has_next()) { + for(ArrayString::Iterator i(pieces); i; ) { Table::element_type row(new ArrayString); *row+=i.next(); table+=row; @@ -296,7 +298,7 @@ static Table& split_horizontal(ArrayStri for(int i=pieces.count(); --i>=0; ) *row+=pieces[i]; } else { // left - for(ArrayString::Iterator i(pieces); i.has_next(); ) + for(ArrayString::Iterator i(pieces); i; ) *row+=i.next(); } table+=row; @@ -304,6 +306,19 @@ static Table& split_horizontal(ArrayStri return table; } +static VArray& split_array(ArrayString& pieces, bool right) { + VArray& result=*new VArray(pieces.count()); + ArrayValue &array=result.array(); + if(right) { // right + for(int i=pieces.count(); --i>=0; ) + array+=new VString(*pieces[i]); + } else { // left + for(ArrayString::Iterator i(pieces); i; ) + array+=new VString(*i.next()); + } + return result; +} + static void split_with_options(Request& r, MethodParams& params, int bits) { const String& string=GET_SELF(r, VString).string(); size_t params_count=params.count(); @@ -320,19 +335,25 @@ static void split_with_options(Request& bool right=(bits & SPLIT_RIGHT) != 0; bool horizontal=(bits & SPLIT_HORIZONTAL) !=0; + bool array=(bits & SPLIT_ARRAY) !=0; const String* column_name=0; if(params_count>2){ column_name=¶ms.as_string(2, COLUMN_NAME_MUST_BE_STRING); - if (horizontal && !column_name->is_empty()) - throw Exception(PARSER_RUNTIME, column_name, "column name can't be specified with horisontal split"); - } - if(!column_name || column_name->is_empty()) - column_name=new String("piece"); - - Table& table=horizontal?split_horizontal(pieces, right):split_vertical(pieces, right, column_name); + if (horizontal && !column_name->is_empty()) + throw Exception(PARSER_RUNTIME, column_name, "column name cannot be specified when splitting into a table horizontal row"); + if (array && !column_name->is_empty()) + throw Exception(PARSER_RUNTIME, column_name, "column name cannot be specified when splitting into an array"); + } - r.write(*new VTable(&table)); + if(array){ + r.write(split_array(pieces, right)); + } else { + if(!column_name || column_name->is_empty()) + column_name=new String("piece"); + Table& table=horizontal ? split_horizontal(pieces, right) : split_vertical(pieces, right, column_name); + r.write(*new VTable(&table)); + } } static void _split(Request& r, MethodParams& params) { split_with_options(r, params, 0 /* maybe-determine from param #2 */); @@ -387,13 +408,12 @@ static void _match(Request& r, MethodPar Value& regexp=params.as_no_junction(0, "regexp must not be code"); Value* options=(params_count>1)?¶ms.as_no_junction(1, OPTIONS_MUST_NOT_BE_CODE):0; - VRegex* vregex; + VRegex* vregex=dynamic_cast(®exp); VRegexCleaner vrcleaner; - if(Value* value=regexp.as(VREGEX_TYPE)){ + if(vregex){ if(options && options->is_defined()) - throw Exception(PARSER_RUNTIME, 0, "you can not specify regex-object and options together"); - vregex=static_cast(value); + throw Exception(PARSER_RUNTIME, 0, "you cannot specify regex-object and options together"); } else { vregex=new VRegex(r.charsets.source(), ®exp.as_string(), (options) ? (&options->as_string()) : 0); vregex->study(); @@ -489,7 +509,7 @@ public: bool add_row(SQL_Error& /*error*/) { /* ignore */ return false; } bool add_row_cell(SQL_Error& error, const char* str, size_t) { if(got_cell) { - error=SQL_Error("result must not contain more then one row"); + error=SQL_Error("result must contain no more than one row"); return true; } try { @@ -794,7 +814,7 @@ static void _unescape(Request& r, Method } else if(mode==UNESCAPE_MODE_URI){ mode_js=false; } else { - throw Exception(PARSER_RUNTIME, &mode, "is invalid mode, must be either '" UNESCAPE_MODE_JS "' or '" UNESCAPE_MODE_URI "'"); + throw Exception(PARSER_RUNTIME, &mode, "is an invalid mode, must be either '" UNESCAPE_MODE_JS "' or '" UNESCAPE_MODE_URI "'"); } const char* unescaped=unescape_chars(src.cstr(), src.length(), from_charset, mode_js);