Annotation of parser3/src/classes/string.C, revision 1.125.2.15.2.11
1.24 paf 1: /** @file
2: Parser: @b string parser class.
3:
1.125.2.1 paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.97 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.113 paf 6: */
1.24 paf 7:
1.125.2.15.2. 1(paf 8:3): static const char* IDENT_STRING_C="$Date: 2003/03/24 10:21:28 $";
1.1 paf 9:
1.43 paf 10: #include "classes.h"
1.125.2.4 paf 11: #include "pa_vmethod_frame.h"
12:
1.1 paf 13: #include "pa_request.h"
14: #include "pa_vdouble.h"
15: #include "pa_vint.h"
1.17 paf 16: #include "pa_vtable.h"
1.25 paf 17: #include "pa_vbool.h"
1.27 paf 18: #include "pa_string.h"
1.53 parser 19: #include "pa_sql_connection.h"
1.71 parser 20: #include "pa_dictionary.h"
1.119 paf 21: #include "pa_vmethod_frame.h"
1.1 paf 22:
1.41 paf 23: // class
24:
1.125.2.9 paf 25: class MString: public Methoded {
1.41 paf 26: public:
1.125.2.7 paf 27: MString();
1.44 paf 28: public: // Methoded
1.53 parser 29: bool used_directly() { return true; }
1.41 paf 30: };
1.1 paf 31:
1.125.2.7 paf 32: // global variable
33:
1.125.2.12 paf 34: DECLARE_CLASS_VAR(string, new MString, 0);
1.125.2.7 paf 35:
1.125.2.8 paf 36: // defines for statics
37:
38: #define MATCH_VAR_NAME "match"
39:
40: // statics
41:
1.125.2.15.2. 1(paf 42:3): static const String match_var_name(MATCH_VAR_NAME);
1.125.2.8 paf 43:
1.1 paf 44: // methods
45:
1.125.2.15.2. (paf 46:): static void _length(Request& r, MethodParams* ) {
47:): double result=GET_SELF(r, VString).string()->length();
48:): r.write_no_lang(Value*(new VDouble(result)));
1.1 paf 49: }
50:
1.125.2.15.2. (paf 51:): static void _int(Request& r, MethodParams* params) {
52:): const String& self_string=r.get_self()->get_string();
1.72 parser 53: int converted;
1.125.2.15.2. (paf 54:): Value* default_code=params->count()>0?params->as_junction(0, "default must be int")
55:): :0; // (default)
1.84 parser 56: try {
1.121 paf 57: if(!self_string || self_string->is_empty())
58: throw Exception("parser.runtime",
1.125.2.5 paf 59: method_name,
1.121 paf 60: "parameter is empty string, error converting");
61: converted=self_string->as_int();
1.84 parser 62: } catch(...) { // convert problem
63: if(!default_code) // we have a problem when no default
1.125.2.2 paf 64: rethrow;
1.84 parser 65: else
1.125.2.7 paf 66: converted=r.process_to_value(default_code)->as_int();
1.72 parser 67: }
1.125.2.15.2. (paf 68:): r.write_no_lang(Value*(new VInt(converted)));
1.1 paf 69: }
70:
1.125.2.15.2. (paf 71:): static void _double(Request& r, MethodParams* params) {
72:): const String& self_string=GET_SELF(r, VString).string();
1.72 parser 73: double converted;
1.125.2.15.2. (paf 74:): Value* default_code=params->count()>0?params->as_junction(0, "default must be double")
75:): :0; // (default)
1.84 parser 76: try {
1.121 paf 77: if(!self_string || self_string->is_empty())
78: throw Exception("parser.runtime",
1.125.2.5 paf 79: method_name,
1.121 paf 80: "parameter is empty string, error converting");
81: converted=self_string->as_double();
1.84 parser 82: } catch(...) { // convert problem
83: if(!default_code) // we have a problem when no default
1.125.2.2 paf 84: rethrow;
1.84 parser 85: else
1.125.2.7 paf 86: converted=r.process_to_value(default_code)->as_double();
1.72 parser 87: }
88:
1.125.2.15.2. (paf 89:): r.write_no_lang(Value*(new VDouble(converted)));
1.1 paf 90: }
91:
1.125.2.15.2. (paf 92:): /*not static*/void _string_format(Request& r, MethodParams* params) {
1.9 paf 93:
1.125.2.15.2. (paf 94:): Value* fmt_maybe_code=(*params)[0];
1.95 paf 95: // for some time due to stupid {} in original design
1.125.2.15.2. (paf 96:): const String& fmt=r.process_to_string(fmt_maybe_code);
1.9 paf 97:
1.125.2.15.2. (paf 98:): const char* buf=format(r.get_self()->as_double(), fmt->cstr());
1.63 parser 99:
1.125.2.7 paf 100: String result;
1.63 parser 101: result.APPEND_CLEAN(buf, 0,
1.125.2.5 paf 102: method_name->origin().file,
103: method_name->origin().line);
1.63 parser 104: r.write_no_lang(result);
1.9 paf 105: }
1.11 paf 106:
1.125.2.15.2. (paf 107:): static void _left(Request& r, const String& /*method_name*/, MethodParams* params) {
1.125.2.10 paf 108: size_t n=(size_t)params->as_int(0, "n must be int", r);
1.15 paf 109:
1.125.2.15.2. (paf 110:): const String& string=GET_SELF(r, VString).string();
1.125.2.7 paf 111: r.write_assign_lang(*string->mid(0, n));
1.15 paf 112: }
113:
1.125.2.15.2. (paf 114:): static void _right(Request& r, const String& /*method_name*/, MethodParams* params) {
1.125.2.10 paf 115: size_t n=(size_t)params->as_int(0, "n must be int", r);
1.15 paf 116:
1.125.2.15.2. (paf 117:): const String& string=GET_SELF(r, VString).string();
118:): r.write_assign_lang(*string->mid(string->length()-n, string->length()));
1.15 paf 119: }
120:
1.125.2.15.2. (paf 121:): static void _mid(Request& r, const String& /*method_name*/, MethodParams* params) {
122:): const String& string=GET_SELF(r, VString).string();
1.83 parser 123:
1.125.2.10 paf 124: size_t p=(size_t)max(0, params->as_int(0, "p must be int", r));
125: size_t n=params->count()>1?
1.125.2.15.2. (paf 126:): (size_t)max(0, params->as_int(1, "n must be int", r)):string->length();
1.15 paf 127:
1.125.2.7 paf 128: r.write_assign_lang(*string->mid(p, p+n));
1.15 paf 129: }
130:
1.125.2.15.2. (paf 131:): static void _pos(Request& r, MethodParams* params) {
132:): Value* substr=params->as_no_junction(0, "substr must not be code");
1.16 paf 133:
1.125.2.15.2. (paf 134:): const String& string=GET_SELF(r, VString).string();
135:): r.write_assign_lang(Value*(new VInt(string->pos(*substr->as_string()))));
1.16 paf 136: }
137:
1.125.2.15.2. (paf 138:): static void split_list(Request& r,
1.125.2.10 paf 139: MethodParams* params, int paramIndex,
1.125.2.7 paf 140: String& string,
141: ArrayString& result) {
1.125.2.15.2. (paf 142:): Value* delim_value=params->as_no_junction(paramIndex, "delimiter must not be code");
1.23 paf 143:
1.125.2.15.2. (paf 144:): string.split(result, 0, *delim_value->as_string());
1.19 paf 145: }
146:
1.118 paf 147: #define SPLIT_LEFT 0x0001
148: #define SPLIT_RIGHT 0x0010
149: #define SPLIT_HORIZONTAL 0x0100
150: #define SPLIT_VERTICAL 0x1000
151:
1.125.2.15.2. (paf 152:): static int split_options(const String& options) {
1.118 paf 153: struct Split_option {
1.125.2.1 paf 154: const char* keyL;
155: const char* keyU;
1.118 paf 156: int setBit;
157: int checkBit;
158: } split_option[]={
159: {"l", "L", SPLIT_LEFT, SPLIT_RIGHT}, // 0xVHRL
160: {"r", "R", SPLIT_RIGHT, SPLIT_LEFT},
161: {"h", "H", SPLIT_HORIZONTAL, SPLIT_VERTICAL},
162: {"v", "V", SPLIT_VERTICAL, SPLIT_HORIZONTAL},
163: {0}
164: };
165:
166: int result=0;
167: if(options) {
168: for(Split_option *o=split_option; o->keyL; o++)
169: if(options->pos(o->keyL)>=0
170: || (o->keyU && options->pos(o->keyU)>=0)) {
171: if(result & o->checkBit)
172: throw Exception("parser.runtime",
173: options,
174: "conflicting split options");
175: result |= o->setBit;
176: }
177: }
178:
179: return result;
180: }
181:
1.125.2.15.2. (paf 182:): static Table* split_vertical(Request& r, const String& string, ArrayString& pieces, bool right) {
1.61 parser 183:
1.125.2.7 paf 184: Table::columns_type columns(new ArrayString);
1.125.2.15.2. (paf 185:): *columns+=String* (new String("piece"));
1.19 paf 186:
1.125.2.15.2. (paf 187:): Table* table(new Table(string, columns, pieces.count()));
1.118 paf 188: if(right) { // right
1.125.2.7 paf 189: for(int i=pieces.count(); --i>=0; ) {
190: Table::element_type row(new ArrayString);
191: *row+=pieces[i];
192: *table+=row;
1.118 paf 193: }
194: } else { // left
1.125.2.15.2. (paf 195:): Array_iterator<String*> i(pieces);
1.118 paf 196: while(i.has_next()) {
1.125.2.7 paf 197: Table::element_type row(new ArrayString);
198: *row+=i.next();
199: *table+=row;
1.118 paf 200: }
1.61 parser 201: }
1.118 paf 202:
1.125.2.7 paf 203: return table;
1.19 paf 204: }
205:
1.125.2.15.2. (paf 206:): static Table* split_horizontal(Request& r, const String& string, ArrayString& pieces, bool right) {
1.118 paf 207:
1.125.2.15.2. (paf 208:): Table* table(new Table(string, Table::columns_type(0) /* nameless */));
1.125.2.7 paf 209: Table::element_type row(new ArrayString(pieces.count()));
1.118 paf 210: if(right) { // right
1.125.2.7 paf 211: for(int i=pieces.count(); --i>=0; ) {
212: *row+=pieces[i];
1.118 paf 213: }
214: } else { // left
1.125.2.15.2. (paf 215:): Array_iterator<String*> i(pieces);
1.118 paf 216: while(i.has_next()) {
1.125.2.7 paf 217: *row+=i.next();
1.118 paf 218: }
219: }
1.125.2.7 paf 220: *table+=row;
1.118 paf 221:
1.125.2.7 paf 222: return table;
1.118 paf 223: }
224:
1.125.2.15.2. (paf 225:): static void split_with_options(Request& r, MethodParams* params,
1.118 paf 226: int bits) {
1.125.2.15.2. (paf 227:): const String& string=GET_SELF(r, VString).string();
1.19 paf 228:
1.125.2.7 paf 229: ArrayString pieces;
230: split_list(r, method_name, params, 0, *string, pieces);
1.19 paf 231:
1.118 paf 232: if(!bits) {
1.125.2.15.2. (paf 233:): const String& options(0);
1.125.2.10 paf 234: if(params->count()>1) {
235: options=params->as_string(1, "options must not be code");
1.118 paf 236: }
237: bits=split_options(options);
238: }
1.21 paf 239:
1.118 paf 240: bool right=(bits & SPLIT_RIGHT) != 0;
241: bool horizontal=(bits & SPLIT_HORIZONTAL) !=0;
1.125.2.15.2. (paf 242:): Table* table=horizontal?split_horizontal(r, string, pieces, right)
1.125.2.7 paf 243: :split_vertical(r, string, pieces, right);
1.17 paf 244:
1.125.2.15.2. 0(paf 245:3): r.write_no_lang(*new VTable(table));
1.118 paf 246: }
1.125.2.15.2. (paf 247:): static void _split(Request& r, MethodParams* params) {
1.118 paf 248: split_with_options(r, method_name, params, 0 /* maybe-determine from param #2 */);
249: }
1.125.2.15.2. (paf 250:): static void _lsplit(Request& r, MethodParams* params) {
1.118 paf 251: split_with_options(r, method_name, params, SPLIT_LEFT);
252: }
1.125.2.15.2. (paf 253:): static void _rsplit(Request& r, MethodParams* params) {
1.118 paf 254: split_with_options(r, method_name, params, SPLIT_RIGHT);
1.17 paf 255: }
256:
1.125.2.15.2. (paf 257:): static void search_action(Table* table, Table::element_type row, int, int, int, int, void *) {
1.28 paf 258: if(row)
1.125.2.7 paf 259: *table+=row;
1.27 paf 260: }
261:
1.74 parser 262: #ifndef DOXYGEN
1.27 paf 263: struct Replace_action_info {
1.125.2.15.2. 1(paf 264:3): Request* request;
265:3): const String* src; String* dest;
(paf 266:): VTable* vtable;
267:): Value* replacement_code;
1.27 paf 268: };
1.74 parser 269: #endif
1.105 paf 270: /// @todo they can do $global[$result] there, getting pointer to later-invalid local var, kill this
1.125.2.15.2. (paf 271:): static void replace_action(Table* table, ArrayString* row,
0(paf 272:3): int prestart, int prefinish,
273:3): int poststart, int postfinish,
274:3): void *info) {
1.27 paf 275: Replace_action_info& ai=*static_cast<Replace_action_info *>(info);
1.31 paf 276: if(row) { // begin&middle
1.104 paf 277: // piece from last match['prestart'] to beginning of this match['prefinish']
278: if(prestart!=prefinish)
279: *ai.dest << ai.src->mid(prestart, prefinish);//ai.dest->APPEND_CONST("-");
1.51 parser 280: // store found parts in one-record VTable
1.125.2.7 paf 281: if(table->count()) // middle
282: table->put(0, row);
1.32 paf 283: else // begin
1.125.2.7 paf 284: *table+=row;
1.30 paf 285: { // execute 'replacement_code' in 'table' context
1.105 paf 286: ai.vtable->set_table(table);
1.30 paf 287:
1.125.2.7 paf 288: *ai.dest << ai.request->process_to_string(ai.replacement_code);
1.29 paf 289: }
290: } else // end
1.125.2.15.2. 0(paf 291:3): *ai.dest << ai.src.mid(poststart, postfinish);
1.27 paf 292: }
293:
1.50 parser 294: /// @todo use pcre:study somehow
1.125.2.15.2. (paf 295:): static void _match(Request& r, MethodParams* params) {
296:): Value& regexp=params->as_no_junction(0, "regexp must not be code");
1.38 paf 297:
1.125.2.15.2. (paf 298:): const String& options=
1.125.2.10 paf 299: params->count()>1?
1.125.2.15.2. (paf 300:): params->as_no_junction(1, "options must not be code")->as_string():0;
1.24 paf 301:
1.125.2.15.2. (paf 302:): Temp_lang temp_lang(r, String::L_PASS_APPENDED);
303:): const String& src=GET_SELF(r, VString).string();
1.125.2.14 paf 304: bool just_matched;
1.125.2.10 paf 305: if(params->count()<3) { // search
1.125.2.15.2. (paf 306:): Table* table=src.match(r.charsets.source(),
1.125.2.5 paf 307: method_name,
1.125.2.15.2. (paf 308:): *regexp->as_string(), options,
1.64 parser 309: search_action, 0,
1.125.2.14 paf 310: just_matched);
1.125.2.15.2. (paf 311:): Value* result;
1.125.2.14 paf 312: if(table)
1.125.2.15.2. (paf 313:): result=Value*(new VTable(table)); // table of pre/match/post+substrings
1.64 parser 314: else
1.125.2.15.2. (paf 315:): result=Value*(new VBool(just_matched));
1.125.2.7 paf 316: r.write_assign_lang(result);
1.27 paf 317: } else { // replace
1.125.2.15.2. (paf 318:): Value* replacement_code=params->as_junction(2, "replacement param must be code");
1.24 paf 319:
1.125.2.7 paf 320: String result;
1.125.2.15.2. (paf 321:): VTable* vtable(new VTable);
1.125.2.7 paf 322: Replace_action_info info;
323: info.request=&r;
324: info.origin=method_name;
325: info.src=src;
326: info.dest=&result;
327: info.vtable=vtable;
328: info.replacement_code=replacement_code;
1.105 paf 329: Temp_value_element temp_match_var(
1.125.2.7 paf 330: *replacement_code->get_junction()->method_frame,
331: match_var_name, vtable);
332: src->match(r.charsets.source(),
1.125.2.5 paf 333: method_name,
1.125.2.7 paf 334: *r.process_to_string(regexp), options,
1.125.2.14 paf 335: replace_action, &info,
336: just_matched);
1.102 paf 337: r.write_assign_lang(result);
1.27 paf 338: }
1.24 paf 339: }
340:
1.125.2.15.2. (paf 341:): static void change_case(Request& r, MethodParams* params,
1.49 parser 342: String::Change_case_kind kind) {
1.125.2.15.2. (paf 343:): const String& src=GET_SELF(r, VString).string();
1.49 parser 344:
1.125.2.15.2. 0(paf 345:3): r.write_assign_lang(src.change_case(r.charsets.source(), kind));
1.49 parser 346: }
1.125.2.15.2. (paf 347:): static void _upper(Request& r, MethodParams* params) {
1.49 parser 348: change_case(r, method_name, params, String::CC_UPPER);
349: }
1.125.2.15.2. (paf 350:): static void _lower(Request& r, MethodParams* params) {
1.49 parser 351: change_case(r, method_name, params, String::CC_LOWER);
352: }
353:
1.65 parser 354: #ifndef DOXYGEN
1.125.2.7 paf 355: class String_sql_event_handlers: public SQL_Driver_query_event_handlers {
1.125.2.15.2. (paf 356:): const String& statement_string; const char* statement_cstr;
1.125.2.7 paf 357: bool got_column;
1.65 parser 358: public:
1.125.2.7 paf 359: bool got_cell;
1.125.2.15.2. (paf 360:): const String& result;
1.125.2.7 paf 361: public:
1.125.2.15 paf 362: String_sql_event_handlers(
1.125.2.15.2. (paf 363:): const String& astatement_string, const char* astatement_cstr):
1.125.2.15 paf 364: statement_string(astatement_string), statement_cstr(astatement_cstr),
365: got_column(false),
366: got_cell(false),
1.125.2.7 paf 367: result(new String) {}
1.65 parser 368:
1.124 paf 369: bool add_column(SQL_Error& error, void *ptr, size_t size) {
370: if(got_column) {
371: error=SQL_Error("parser.runtime",
1.125.2.7 paf 372: //statement_string,
1.65 parser 373: "result must contain exactly one column");
1.124 paf 374: return true;
375: }
1.65 parser 376: got_column=true;
1.124 paf 377: return false;
1.65 parser 378: }
1.124 paf 379: bool before_rows(SQL_Error& /*error*/ ) { /* ignore */ return false; }
380: bool add_row(SQL_Error& /*error*/) { /* ignore */ return false; }
381: bool add_row_cell(SQL_Error& error, void *ptr, size_t size) {
382: if(got_cell) {
383: error=SQL_Error("parser.runtime",
1.125.2.7 paf 384: //statement_string,
1.65 parser 385: "result must not contain more then one row");
1.124 paf 386: return true;
387: }
1.65 parser 388:
1.124 paf 389: try {
390: got_cell=true;
1.125.2.1 paf 391: result->APPEND_TAINTED((const char* )ptr, size, statement_cstr, 0);
1.124 paf 392: return false;
393: } catch(...) {
394: error=SQL_Error("exception occured in String_sql_event_handlers::add_row_cell");
395: return true;
396: }
1.65 parser 397: }
398: };
399: #endif
1.125.2.15.2. (paf 400:): extern const String& sql_limit_name;
401:): extern const String& sql_offset_name;
402:): extern const String& sql_default_name;
403:): extern const String& sql_distinct_name;
404:): const String& sql_result_string(Request& r, MethodParams* params,
405:): HashStringValue*& options, Value*& default_code) {
1.53 parser 406:
1.125.2.15.2. (paf 407:): Value* statement=params->as_junction(0, "statement must be code");
1.53 parser 408:
1.70 parser 409: ulong limit=0;
410: ulong offset=0;
1.125.2.15.2. (paf 411:): default_code=0;
1.125.2.10 paf 412: if(params->count()>1) {
1.125.2.15.2. (paf 413:): Value* voptions=params->as_no_junction(1, "options must be hash, not code");
1.125.2.7 paf 414: if(!voptions->is_string())
1.125.2.15.2. (paf 415:): if(options=voptions->get_hash()) {
416:): if(Value* vlimit=options->get(sql_limit_name))
1.125.2.7 paf 417: limit=(ulong)r.process_to_value(vlimit)->as_double();
1.125.2.15.2. (paf 418:): if(Value* voffset=options->get(sql_offset_name))
1.125.2.7 paf 419: offset=(ulong)r.process_to_value(voffset)->as_double();
420: if(default_code=options->get(sql_default_name)) {
1.125.2.15.2. (paf 421:): if(Junction* default_junction=default_code->get_junction())
1.119 paf 422: ;//default_junction->change_context(statement.get_junction());
1.110 paf 423: else
1.98 paf 424: throw Exception("parser.runtime",
1.125.2.5 paf 425: method_name,
1.81 parser 426: "default option must be code");
427: }
1.73 parser 428: } else
1.98 paf 429: throw Exception("parser.runtime",
1.125.2.5 paf 430: method_name,
1.73 parser 431: "options must be hash");
1.70 parser 432: } else
433: options=0;
434:
1.125.2.15.2. (paf 435:): Temp_lang temp_lang(r, String::L_SQL);
436:): const String& statement_string=r.process_to_string(statement);
1.125.2.1 paf 437: const char* statement_cstr=
1.125.2.15.2. (paf 438:): statement_string->cstr(String::L_UNSPECIFIED, r.connection());
1.125.2.7 paf 439: String_sql_event_handlers handlers(statement_string, statement_cstr);
1.125.2.15.2. (paf 440:): r.connection()->query(
1.117 paf 441: statement_cstr, offset, limit,
442: handlers,
443: statement_string);
1.53 parser 444:
1.65 parser 445: if(!handlers.got_cell)
1.125.2.15.2. (paf 446:): return 0; // no lines, caller should return second param[default value]
1.62 parser 447:
1.65 parser 448: return handlers.result;
1.53 parser 449: }
450:
1.125.2.15.2. (paf 451:): static void _sql(Request& r, MethodParams* params) {
1.53 parser 452:
1.125.2.7 paf 453: HashStringValue* options;
1.125.2.15.2. (paf 454:): Value* default_code;
455:): const String& string=sql_result_string(r, method_name, params, options, default_code);
1.62 parser 456: if(!string) {
1.81 parser 457: if(default_code) {
1.125.2.7 paf 458: string=r.process_to_string(default_code);
1.81 parser 459: if(!string)
1.125.2.15.2. (paf 460:): string=String* (new String);
1.68 parser 461: } else
1.98 paf 462: throw Exception("parser.runtime",
1.125.2.5 paf 463: method_name,
1.81 parser 464: "produced no result, but no default option specified");
1.62 parser 465: }
1.100 paf 466:
1.102 paf 467: r.write_assign_lang(*string);
1.53 parser 468: }
469:
1.125.2.15.2. (paf 470:): static void _replace(Request& r, MethodParams* params) {
471:): const String& src=GET_SELF(r, VString).string();
1.71 parser 472:
1.125.2.10 paf 473: Table* table=params->as_no_junction(0, "parameter must not be code")->get_table();
1.71 parser 474: if(!table)
1.98 paf 475: throw Exception("parser.runtime",
1.125.2.5 paf 476: method_name,
1.71 parser 477: "parameter must be table");
478:
1.125.2.15.2. (paf 479:): Table* tp(table);
1.125.2.13 paf 480: Dictionary dict2(tp, 1/*am not sure why using the =default parameter causes compile errors in replace*/ );
1.125.2.15.2. (paf 481:): r.write_assign_lang(*src->replace(dict2));
1.71 parser 482: }
1.79 parser 483:
1.125.2.15.2. (paf 484:): static void _save(Request& r, MethodParams* params) {
485:): const String& file_name=params->as_string(params->count()-1,
1.87 paf 486: "file name must be string");
1.79 parser 487:
1.125.2.15.2. (paf 488:): const String& src=GET_SELF(r, VString).string();
1.79 parser 489:
1.87 paf 490: bool do_append=false;
1.125.2.10 paf 491: if(params->count()>1) {
1.125.2.15.2. (paf 492:): const String& mode=params->as_string(0, "mode must be string");
1.125.2.7 paf 493: if(*mode=="append")
1.87 paf 494: do_append=true;
495: else
1.98 paf 496: throw Exception("parser.runtime",
1.125.2.7 paf 497: mode,
1.87 paf 498: "unknown mode, must be 'append'");
499: }
500:
1.79 parser 501: // write
1.125.2.15.2. (paf 502:): const char* buf=src->cstr(String::L_UNSPECIFIED, r.connection(0/*no error if none*/));
1.94 paf 503: file_write(r.absolute(file_name),
1.89 paf 504: buf, strlen(buf), true, do_append);
1.79 parser 505: }
506:
1.125.2.15.2. (paf 507:): static void _normalize(Request& r, MethodParams* /*params*/) {
508:): const String& src=GET_SELF(r, VString).string();
1.125.2.7 paf 509:
510: r.write_assign_lang(*src->join_chains(r.pool()));
1.109 paf 511: }
512:
1.41 paf 513: // constructor
514:
1.125.2.7 paf 515: MString::MString(): Methoded("string") {
1.1 paf 516: // ^string.length[]
1.41 paf 517: add_native_method("length", Method::CT_DYNAMIC, _length, 0, 0);
1.6 paf 518:
1.1 paf 519: // ^string.int[]
1.72 parser 520: // ^string.int(default)
521: add_native_method("int", Method::CT_DYNAMIC, _int, 0, 1);
1.1 paf 522: // ^string.double[]
1.72 parser 523: // ^string.double(default)
524: add_native_method("double", Method::CT_DYNAMIC, _double, 0, 1);
1.9 paf 525:
1.24 paf 526: // ^string.format{format}
1.41 paf 527: add_native_method("format", Method::CT_DYNAMIC, _string_format, 1, 1);
1.14 paf 528:
1.15 paf 529: // ^string.left(n)
1.41 paf 530: add_native_method("left", Method::CT_DYNAMIC, _left, 1, 1);
1.15 paf 531: // ^string.right(n)
1.41 paf 532: add_native_method("right", Method::CT_DYNAMIC, _right, 1, 1);
1.15 paf 533: // ^string.mid(p;n)
1.82 parser 534: add_native_method("mid", Method::CT_DYNAMIC, _mid, 1, 2);
1.16 paf 535:
536: // ^string.pos[substr]
1.41 paf 537: add_native_method("pos", Method::CT_DYNAMIC, _pos, 1, 1);
1.17 paf 538:
1.118 paf 539: // ^string.split[delim]
540: // ^string.split[delim][options]
541: add_native_method("split", Method::CT_DYNAMIC, _split, 1, 2);
542: // old names for backward compatibility
543: // ^string.lsplit[delim]
544: add_native_method("lsplit", Method::CT_DYNAMIC, _lsplit, 1, 1);
545: // ^string.rsplit[delim]
546: add_native_method("rsplit", Method::CT_DYNAMIC, _rsplit, 1, 1);
547:
1.32 paf 548: // ^string.match[regexp][options]
549: // ^string.match[regexp][options]{replacement-code}
1.41 paf 550: add_native_method("match", Method::CT_DYNAMIC, _match, 1, 3);
1.49 parser 551:
552: // ^string.toupper[]
553: add_native_method("upper", Method::CT_DYNAMIC, _upper, 0, 0);
554: // ^string.tolower[]
555: add_native_method("lower", Method::CT_DYNAMIC, _lower, 0, 0);
1.53 parser 556:
1.70 parser 557: // ^sql[query]
558: // ^sql[query][$.limit(1) $.offset(2) $.default[n/a]]
1.67 parser 559: add_native_method("sql", Method::CT_STATIC, _sql, 1, 2);
1.71 parser 560:
561: // ^string.replace[table]
562: add_native_method("replace", Method::CT_DYNAMIC, _replace, 1, 1);
1.79 parser 563:
564: // ^string.save[file]
1.87 paf 565: add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2);
1.109 paf 566:
1.112 paf 567: // ^string.normalize[]
568: add_native_method("normalize", Method::CT_DYNAMIC, _normalize, 0, 0);
1.2 paf 569: }
E-mail: