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