| File: | src/pmc/string.pmc |
| Coverage: | 71.8% |
| line | stmt | code |
|---|---|---|
| 1 | /* | |
| 2 | Copyright (C) 2003-2009, Parrot Foundation. | |
| 3 | $Id: string.pmc 41447 2009-09-24 19:30:17Z NotFound $ | |
| 4 | ||
| 5 - 19 | =head1 NAME src/pmc/string.pmc - String PMC Class =head1 DESCRIPTION C<String> extends C<scalar> to provide a string for languages that want a C<string> type without going to an S register. It acts as a wrapper for the functions in F<src/string.c>. =head2 Methods =over 4 =cut | |
| 20 | ||
| 21 | */ | |
| 22 | ||
| 23 | pmclass String extends scalar provides string provides scalar auto_attrs { | |
| 24 | ATTR STRING * str_val; | |
| 25 | ||
| 26 | /* | |
| 27 | ||
| 28 - 32 | =item C<void init()> Initializes the string. =cut | |
| 33 | ||
| 34 | */ | |
| 35 | ||
| 36 | VTABLE void init() { | |
| 37 | 12947340 | STRING *str_val = Parrot_str_new_noinit(INTERP, enum_stringrep_one, 0); |
| 38 | 12947340 | SET_ATTR_str_val(INTERP, SELF, str_val); |
| 39 | ||
| 40 | 12947340 | PObj_custom_mark_SET(SELF); |
| 41 | } | |
| 42 | ||
| 43 | /* | |
| 44 | ||
| 45 - 49 | =item C<PMC instantiate_str(STRING *rep)> Class method to construct a String from the string representation C<rep>. =cut | |
| 50 | ||
| 51 | */ | |
| 52 | VTABLE PMC *instantiate_str(STRING *rep, INTVAL flags) { | |
| 53 | PMC *res; | |
| 54 | 12 | const INTVAL type = SELF->vtable->base_type; |
| 55 | ||
| 56 | 12 | if (flags & PObj_constant_FLAG) |
| 57 | 12 | res = constant_pmc_new(INTERP, type); |
| 58 | else | |
| 59 | 0 | res = pmc_new(INTERP, type); |
| 60 | ||
| 61 | 12 | SET_ATTR_str_val(INTERP, res, rep); |
| 62 | 12 | return res; |
| 63 | } | |
| 64 | ||
| 65 | /* | |
| 66 | ||
| 67 - 71 | =item C<void mark()> Marks the string as live. =cut | |
| 72 | ||
| 73 | */ | |
| 74 | ||
| 75 | VTABLE void mark() { | |
| 76 | STRING *str_val; | |
| 77 | 65491260 | GET_ATTR_str_val(INTERP, SELF, str_val); |
| 78 | 65491260 | Parrot_gc_mark_STRING_alive(INTERP, str_val); |
| 79 | } | |
| 80 | ||
| 81 | /* | |
| 82 | ||
| 83 - 87 | =item C<PMC *clone()> Creates a copy of the string. =cut | |
| 88 | ||
| 89 | */ | |
| 90 | ||
| 91 | VTABLE PMC *clone() { | |
| 92 | 69446 | PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 93 | 69446 | VTABLE_set_string_native(INTERP, dest, Parrot_str_copy(INTERP, SELF.get_string())); |
| 94 | 69446 | return dest; |
| 95 | } | |
| 96 | ||
| 97 | /* | |
| 98 | ||
| 99 - 103 | =item C<INTVAL get_integer()> Returns the integer representation of the string. =cut | |
| 104 | ||
| 105 | */ | |
| 106 | ||
| 107 | VTABLE INTVAL get_integer() { | |
| 108 | 3850 | STRING * const s = SELF.get_string(); |
| 109 | 3850 | return Parrot_str_to_int(INTERP, s); |
| 110 | } | |
| 111 | ||
| 112 | /* | |
| 113 | ||
| 114 - 118 | =item C<FLOATVAL get_number()> Returns the floating-point representation of the string. =cut | |
| 119 | ||
| 120 | */ | |
| 121 | ||
| 122 | VTABLE FLOATVAL get_number() { | |
| 123 | 601430 | STRING * const s = SELF.get_string(); |
| 124 | 601430 | return Parrot_str_to_num(INTERP, s); |
| 125 | } | |
| 126 | ||
| 127 | /* | |
| 128 | ||
| 129 - 133 | =item C<PMC *get_bignum()> Returns the big numbers representation of the string. =cut | |
| 134 | ||
| 135 | */ | |
| 136 | ||
| 137 | VTABLE PMC *get_bignum() { | |
| 138 | 0 | STRING * const s = SELF.get_string(); |
| 139 | 0 | PMC * const ret = pmc_new(INTERP, enum_class_BigInt); |
| 140 | 0 | VTABLE_set_string_native(INTERP, ret, s); |
| 141 | 0 | return ret; |
| 142 | } | |
| 143 | ||
| 144 | /* | |
| 145 | ||
| 146 - 150 | =item C<STRING *get_string()> Returns the string itself. =cut | |
| 151 | ||
| 152 | */ | |
| 153 | ||
| 154 | VTABLE STRING *get_string() { | |
| 155 | STRING *str_val; | |
| 156 | 4552672 | GET_ATTR_str_val(INTERP, SELF, str_val); |
| 157 | 4552672 | return str_val ? Parrot_str_copy(INTERP, str_val) : NULL; |
| 158 | } | |
| 159 | ||
| 160 | /* | |
| 161 | ||
| 162 - 166 | =item C<INTVAL get_bool()> Returns the boolean value of the string. =cut | |
| 167 | ||
| 168 | */ | |
| 169 | ||
| 170 | VTABLE INTVAL get_bool() { | |
| 171 | 53090 | STRING * const s = SELF.get_string(); |
| 172 | 53090 | return Parrot_str_boolean(INTERP, s); |
| 173 | } | |
| 174 | ||
| 175 | /* | |
| 176 | ||
| 177 - 183 | =item C<VOID set_integer_native(INTVAL value)> =item C<VOID set_bool(INTVAL value)> Sets the value of the string to the integer C<value>. =cut | |
| 184 | ||
| 185 | */ | |
| 186 | ||
| 187 | VTABLE void set_integer_native(INTVAL value) { | |
| 188 | 272 | SELF.set_string_native(Parrot_str_from_int(INTERP, value)); |
| 189 | } | |
| 190 | ||
| 191 | VTABLE void set_bool(INTVAL value) { | |
| 192 | 0 | SELF.set_string_native(Parrot_str_from_int(INTERP, value)); |
| 193 | } | |
| 194 | ||
| 195 | /* | |
| 196 | ||
| 197 - 201 | =item C<VOID set_number_native(FLOATVAL value)> Sets the value of the string to the floating-point C<value>. =cut | |
| 202 | ||
| 203 | */ | |
| 204 | ||
| 205 | VTABLE void set_number_native(FLOATVAL value) { | |
| 206 | 134 | SELF.set_string_native(Parrot_str_from_num(INTERP, value)); |
| 207 | } | |
| 208 | ||
| 209 | ||
| 210 | /* | |
| 211 | ||
| 212 - 216 | =item C<VOID set_string_native(STRING *value)> Sets the value of the string to that of the specified C<string>. =cut | |
| 217 | ||
| 218 | */ | |
| 219 | ||
| 220 | VTABLE void set_string_native(STRING *value) { | |
| 221 | /* in lieu of a STRINGNULL, promote any NULL STRINGs to empty ones */ | |
| 222 | 3567018 | if (!value) |
| 223 | 8198 | value = Parrot_str_new(INTERP, NULL, 0); |
| 224 | ||
| 225 | /* Only allow constant PMCs to embed constant strings */ | |
| 226 | 3567018 | if (PObj_constant_TEST(SELF) && !PObj_constant_TEST(value)) { |
| 227 | 2520 | char *copy = Parrot_str_to_cstring(INTERP, value); |
| 228 | 2520 | value = Parrot_str_new_init(INTERP, copy, strlen(copy), |
| 229 | PARROT_DEFAULT_ENCODING, PARROT_DEFAULT_CHARSET, | |
| 230 | PObj_constant_FLAG); | |
| 231 | 2520 | Parrot_str_free_cstring(copy); |
| 232 | } | |
| 233 | ||
| 234 | 3567018 | SET_ATTR_str_val(INTERP, SELF, value); |
| 235 | } | |
| 236 | ||
| 237 | /* | |
| 238 | ||
| 239 - 243 | =item C<VOID assign_string_native(STRING *value)> Sets the value of the string to a copy of the specified C<string>. =cut | |
| 244 | ||
| 245 | */ | |
| 246 | ||
| 247 | VTABLE void assign_string_native(STRING *value) { | |
| 248 | 7684 | if (!STRING_IS_NULL(value)) |
| 249 | 7672 | SET_ATTR_str_val(INTERP, SELF, |
| 250 | Parrot_str_set(INTERP, SELF.get_string(), value)); | |
| 251 | else | |
| 252 | 12 | SET_ATTR_str_val(INTERP, SELF, NULL); |
| 253 | } | |
| 254 | ||
| 255 | /* | |
| 256 | ||
| 257 - 262 | =item C<VOID set_pmc(PMC *value)> Sets the value of the string to the string value of the specified C<PMC>. =cut | |
| 263 | ||
| 264 | */ | |
| 265 | VTABLE void set_pmc(PMC *value) { | |
| 266 | 0 | SELF.set_string_native(VTABLE_get_string(INTERP, value)); |
| 267 | } | |
| 268 | ||
| 269 | /* | |
| 270 | ||
| 271 - 305 | =item C<PMC *bitwise_ors(PMC *value, PMC *dest)> =item C<PMC *bitwise_ors_str(PMC *value, PMC *dest)> =item C<PMC *bitwise_ands(PMC *value, PMC *dest)> =item C<PMC *bitwise_ands_str(PMC *value, PMC *dest)> =item C<PMC *bitwise_xors(PMC *value, PMC *dest)> =item C<PMC *bitwise_xors_str(PMC *value, PMC *dest)> =item C<void bitwise_nots(PMC *value)> These functions perform bitwise operations on entire strings, and place the result in C<dest>. =item C<void i_bitwise_ors(PMC *value)> =item C<void i_bitwise_ors_str(PMC *value)> =item C<void i_bitwise_ands(PMC *value)> =item C<void i_bitwise_ands_str(PMC *value)> =item C<void i_bitwise_xors(PMC *value)> =item C<void i_bitwise_xors_str(PMC *value)> =item C<void i_bitwise_nots(PMC *value)> These functions perform bitwise operations on entire strings in place. =cut | |
| 306 | ||
| 307 | */ | |
| 308 | VTABLE PMC *bitwise_ors(PMC *value, PMC *dest) { | |
| 309 | 72 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 310 | 72 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 311 | ||
| 312 | 72 | if (!dest) |
| 313 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 314 | ||
| 315 | 72 | VTABLE_set_string_native(INTERP, dest, |
| 316 | Parrot_str_bitwise_or(INTERP, s, v, NULL)); | |
| 317 | ||
| 318 | 72 | return dest; |
| 319 | } | |
| 320 | ||
| 321 | VTABLE PMC *bitwise_ors_str(STRING *value, PMC *dest) { | |
| 322 | 0 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 323 | ||
| 324 | 0 | if (!dest) |
| 325 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 326 | ||
| 327 | 0 | VTABLE_set_string_native(INTERP, dest, |
| 328 | Parrot_str_bitwise_or(INTERP, s, value, NULL)); | |
| 329 | ||
| 330 | 0 | return dest; |
| 331 | } | |
| 332 | ||
| 333 | VTABLE void i_bitwise_ors(PMC *value) { | |
| 334 | 72 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 335 | 72 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 336 | 72 | SELF.set_string_native(Parrot_str_bitwise_or(INTERP, s, v, &s)); |
| 337 | } | |
| 338 | ||
| 339 | VTABLE void i_bitwise_ors_str(STRING *value) { | |
| 340 | 0 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 341 | 0 | SELF.set_string_native(Parrot_str_bitwise_or(INTERP, s, value, &s)); |
| 342 | } | |
| 343 | ||
| 344 | VTABLE PMC *bitwise_ands(PMC *value, PMC *dest) { | |
| 345 | 12 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 346 | 12 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 347 | ||
| 348 | 12 | if (!dest) |
| 349 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 350 | ||
| 351 | 12 | VTABLE_set_string_native(INTERP, dest, |
| 352 | Parrot_str_bitwise_and(INTERP, s, v, NULL)); | |
| 353 | ||
| 354 | 12 | return dest; |
| 355 | } | |
| 356 | ||
| 357 | VTABLE PMC *bitwise_ands_str(STRING *value, PMC *dest) { | |
| 358 | 0 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 359 | ||
| 360 | 0 | if (!dest) |
| 361 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 362 | ||
| 363 | 0 | VTABLE_set_string_native(INTERP, dest, |
| 364 | Parrot_str_bitwise_and(INTERP, s, value, NULL)); | |
| 365 | ||
| 366 | 0 | return dest; |
| 367 | } | |
| 368 | ||
| 369 | ||
| 370 | VTABLE void i_bitwise_ands(PMC *value) { | |
| 371 | 60 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 372 | 60 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 373 | 60 | SELF.set_string_native(Parrot_str_bitwise_and(INTERP, s, v, &s)); |
| 374 | } | |
| 375 | ||
| 376 | VTABLE void i_bitwise_ands_str(STRING *value) { | |
| 377 | 0 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 378 | 0 | SELF.set_string_native(Parrot_str_bitwise_and(INTERP, s, value, &s)); |
| 379 | } | |
| 380 | ||
| 381 | VTABLE PMC *bitwise_xors(PMC *value, PMC *dest) { | |
| 382 | 84 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 383 | 84 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 384 | ||
| 385 | 84 | if (!dest) |
| 386 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 387 | ||
| 388 | 84 | VTABLE_set_string_native(INTERP, dest, |
| 389 | Parrot_str_bitwise_xor(INTERP, s, v, NULL)); | |
| 390 | ||
| 391 | 84 | return dest; |
| 392 | } | |
| 393 | ||
| 394 | VTABLE PMC *bitwise_xors_str(STRING *value, PMC *dest) { | |
| 395 | 0 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 396 | ||
| 397 | 0 | if (!dest) |
| 398 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 399 | ||
| 400 | 0 | VTABLE_set_string_native(INTERP, dest, |
| 401 | Parrot_str_bitwise_xor(INTERP, s, value, NULL)); | |
| 402 | ||
| 403 | 0 | return dest; |
| 404 | } | |
| 405 | ||
| 406 | VTABLE void i_bitwise_xors(PMC *value) { | |
| 407 | 84 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 408 | 84 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 409 | 84 | SELF.set_string_native(Parrot_str_bitwise_xor(INTERP, s, v, &s)); |
| 410 | } | |
| 411 | ||
| 412 | VTABLE void i_bitwise_xors_str(STRING *value) { | |
| 413 | 0 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 414 | 0 | SELF.set_string_native(Parrot_str_bitwise_xor(INTERP, s, value, &s)); |
| 415 | } | |
| 416 | ||
| 417 | VTABLE PMC *bitwise_nots(PMC *dest) { | |
| 418 | 36 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 419 | ||
| 420 | 36 | if (!dest) |
| 421 | 0 | dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 422 | ||
| 423 | 36 | VTABLE_set_string_native(INTERP, dest, |
| 424 | Parrot_str_bitwise_not(INTERP, s, NULL)); | |
| 425 | ||
| 426 | 36 | return dest; |
| 427 | } | |
| 428 | ||
| 429 | VTABLE void i_bitwise_nots() { | |
| 430 | 0 | STRING *s = VTABLE_get_string(INTERP, SELF); |
| 431 | 0 | VTABLE_set_string_native( |
| 432 | INTERP, SELF, Parrot_str_bitwise_not(INTERP, s, &s)); | |
| 433 | } | |
| 434 | ||
| 435 | /* | |
| 436 | ||
| 437 - 442 | =item C<INTVAL is_equal(PMC *value)> Compares the string with C<value>; returns true if they match. =cut | |
| 443 | ||
| 444 | */ | |
| 445 | VTABLE INTVAL is_equal(PMC *value) { | |
| 446 | 210 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 447 | 210 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 448 | 210 | return (INTVAL)(Parrot_str_equal(INTERP, s, v)); |
| 449 | } | |
| 450 | ||
| 451 | MULTI INTVAL is_equal(PMC *value) { | |
| 452 | 0 | return SELF.is_equal(value); |
| 453 | } | |
| 454 | ||
| 455 | /* | |
| 456 | ||
| 457 - 462 | =item C<INTVAL is_equal_num(PMC *value)> Compares the numerical value of the string with that of C<value>; returns true if they match. =cut | |
| 463 | ||
| 464 | */ | |
| 465 | ||
| 466 | VTABLE INTVAL is_equal_num(PMC *value) { | |
| 467 | 0 | const FLOATVAL sf = Parrot_str_to_num(INTERP, VTABLE_get_string(INTERP, SELF)); |
| 468 | 0 | const FLOATVAL vf = VTABLE_get_number(INTERP, value); |
| 469 | 0 | return (INTVAL)(sf == vf); |
| 470 | } | |
| 471 | ||
| 472 | /* | |
| 473 | ||
| 474 - 478 | =item C<INTVAL is_equal_string(PMC *value)> Compares the string with C<value>; returns FALSE if they match. =cut | |
| 479 | ||
| 480 | */ | |
| 481 | ||
| 482 | VTABLE INTVAL is_equal_string(PMC *value) { | |
| 483 | 36 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 484 | 36 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 485 | 36 | return Parrot_str_equal(INTERP, s, v); |
| 486 | } | |
| 487 | ||
| 488 | /* | |
| 489 | ||
| 490 - 496 | =item C<INTVAL cmp(PMC *value)> Compares the string with C<value>; returns -1 if the string is smaller, 0 if they are equal, and 1 if C<value> is smaller. =cut | |
| 497 | ||
| 498 | */ | |
| 499 | VTABLE INTVAL cmp(PMC *value) { | |
| 500 | 52648 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 501 | 52648 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 502 | 52648 | return Parrot_str_compare(INTERP, s, v); |
| 503 | } | |
| 504 | ||
| 505 | /* | |
| 506 | ||
| 507 - 513 | =item C<INTVAL cmp_num(PMC *value)> Compares the numerical value of the string with that of C<value>; returns -1 if the string is smaller, 0 if they are equal, and 1 if C<value> is smaller. =cut | |
| 514 | ||
| 515 | */ | |
| 516 | VTABLE INTVAL cmp_num(PMC *value) { | |
| 517 | 0 | const FLOATVAL sf = Parrot_str_to_num(INTERP, VTABLE_get_string(INTERP, SELF)); |
| 518 | 0 | const FLOATVAL vf = VTABLE_get_number(INTERP, value); |
| 519 | ||
| 520 | 0 | if (sf < vf) |
| 521 | 0 | return (INTVAL)(-1); |
| 522 | ||
| 523 | 0 | if (sf > vf) |
| 524 | 0 | return (INTVAL)(1); |
| 525 | ||
| 526 | 0 | return (INTVAL)(0); |
| 527 | } | |
| 528 | ||
| 529 | /* | |
| 530 | ||
| 531 - 537 | =item C<INTVAL cmp_string(PMC *value)> Compares the string with C<value>; returns -1 if the string is smaller, 0 if they are equal, and 1 if C<value> is smaller. =cut | |
| 538 | ||
| 539 | */ | |
| 540 | VTABLE INTVAL cmp_string(PMC *value) { | |
| 541 | 36 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 542 | 36 | STRING * const v = VTABLE_get_string(INTERP, value); |
| 543 | 36 | return Parrot_str_compare(INTERP, s, v); |
| 544 | } | |
| 545 | ||
| 546 | /* | |
| 547 | ||
| 548 - 553 | =item C<void substr(INTVAL offset, INTVAL length, PMC *dest)> Extracts the substring starting at C<offset>, with size C<length>, and places it in C<dest>. =cut | |
| 554 | ||
| 555 | */ | |
| 556 | VTABLE void substr(INTVAL offset, INTVAL length, PMC *dest) { | |
| 557 | 0 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 558 | 0 | STRING * const s2 = Parrot_str_substr(INTERP, s, offset, length, NULL, 0); |
| 559 | 0 | VTABLE_set_string_native(INTERP, dest, s2); |
| 560 | } | |
| 561 | ||
| 562 | /* | |
| 563 | ||
| 564 - 569 | =item C<STRING *substr_str(INTVAL offset, INTVAL length)> Extracts the substring starting at C<offset>, with size C<length>, and returns it. =cut | |
| 570 | ||
| 571 | */ | |
| 572 | VTABLE STRING *substr_str(INTVAL offset, INTVAL length) { | |
| 573 | 21236 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 574 | 21236 | return Parrot_str_substr(INTERP, s, offset, length, NULL, 0); |
| 575 | } | |
| 576 | ||
| 577 | /* | |
| 578 | ||
| 579 - 584 | =item C<INTVAL exists_keyed(PMC *key)> Returns true if the C<key>'th character in the string exists. Negative numbers count from the end. =cut | |
| 585 | ||
| 586 | */ | |
| 587 | ||
| 588 | VTABLE INTVAL exists_keyed(PMC *key) { | |
| 589 | 0 | const INTVAL n = Parrot_str_byte_length(INTERP, VTABLE_get_string(INTERP, SELF)); |
| 590 | 0 | const INTVAL k = VTABLE_get_integer(INTERP, key); |
| 591 | 0 | return (INTVAL)((k>=0 && k<=n) || (k<0 && -k<=n)); |
| 592 | } | |
| 593 | ||
| 594 | /* | |
| 595 | ||
| 596 - 613 | =item C<STRING *get_string_keyed(PMC *key)> Returns the C<key>'th character in the string. Negative numbers count from the end. =item C<INTVAL get_integer_keyed(PMC *key)> Returns the integer value (ord) at C<*key>. =item C<void set_string_keyed(PMC *key, STRING *val)> Replace the string at C<key> with C<value>. =item C<void set_integer_keyed(PMC *key, INTVAL val)> Replace the string at C<key> with the chr of C<value>. =cut | |
| 614 | ||
| 615 | */ | |
| 616 | ||
| 617 | VTABLE STRING *get_string_keyed(PMC *key) { | |
| 618 | 0 | return SELF.get_string_keyed_int(VTABLE_get_integer(INTERP, key)); |
| 619 | } | |
| 620 | ||
| 621 | VTABLE STRING *get_string_keyed_int(INTVAL pos) { | |
| 622 | 312 | STRING * const s = SELF.get_string(); |
| 623 | 312 | return Parrot_str_substr(INTERP, s, pos, 1, NULL, 0); |
| 624 | } | |
| 625 | ||
| 626 | VTABLE INTVAL get_integer_keyed(PMC *key) { | |
| 627 | 0 | return SELF.get_integer_keyed_int(VTABLE_get_integer(INTERP, key)); |
| 628 | } | |
| 629 | ||
| 630 | VTABLE INTVAL get_integer_keyed_int(INTVAL pos) { | |
| 631 | 216 | STRING * const s = SELF.get_string(); |
| 632 | 216 | return string_ord(INTERP, s, pos); |
| 633 | } | |
| 634 | ||
| 635 | VTABLE PMC *get_pmc_keyed(PMC *key) { | |
| 636 | 0 | return SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key)); |
| 637 | } | |
| 638 | ||
| 639 | VTABLE PMC *get_pmc_keyed_int(INTVAL pos) { | |
| 640 | 12 | PMC * const dest = pmc_new(INTERP, SELF->vtable->base_type); |
| 641 | 12 | VTABLE_set_string_native(INTERP, dest, SELF.get_string_keyed_int(pos)); |
| 642 | 12 | return dest; |
| 643 | } | |
| 644 | ||
| 645 | VTABLE void set_string_keyed(PMC *key, STRING * const value) { | |
| 646 | 0 | SELF.set_string_keyed_int(VTABLE_get_integer(INTERP, key), value); |
| 647 | } | |
| 648 | ||
| 649 | VTABLE void set_string_keyed_int(INTVAL pos, STRING * const value) { | |
| 650 | 36 | STRING * const s = SELF.get_string(); |
| 651 | 36 | const INTVAL len = Parrot_str_byte_length(INTERP, value); |
| 652 | 36 | Parrot_str_replace(INTERP, s, pos, len, value, NULL); |
| 653 | 36 | VTABLE_set_string_native(INTERP, SELF, s); |
| 654 | } | |
| 655 | ||
| 656 | VTABLE void set_integer_keyed(PMC *key, INTVAL value) { | |
| 657 | 0 | SELF.set_integer_keyed_int(VTABLE_get_integer(INTERP, key), value); |
| 658 | } | |
| 659 | ||
| 660 | VTABLE void set_integer_keyed_int(INTVAL pos, INTVAL value) { | |
| 661 | 24 | STRING * const s = SELF.get_string(); |
| 662 | 24 | STRING * const c = string_chr(INTERP, (UINTVAL) value); |
| 663 | 24 | Parrot_str_replace(INTERP, s, pos, 1, c, NULL); |
| 664 | 24 | VTABLE_set_string_native(INTERP, SELF, s); |
| 665 | } | |
| 666 | ||
| 667 | VTABLE void set_pmc_keyed(PMC *key, PMC *value) { | |
| 668 | 0 | SELF.set_pmc_keyed_int(VTABLE_get_integer(INTERP, key), value); |
| 669 | } | |
| 670 | ||
| 671 | VTABLE void set_pmc_keyed_int(INTVAL pos, PMC *value) { | |
| 672 | 12 | SELF.set_string_keyed_int(pos, VTABLE_get_string(INTERP, value)); |
| 673 | } | |
| 674 | /* | |
| 675 | ||
| 676 - 680 | =item C<void replace(STRING *orig, STRING *_new)> Replace every occurrence of C<orig> with C<_new>. =cut | |
| 681 | ||
| 682 | */ | |
| 683 | ||
| 684 | METHOD replace(STRING *orig, STRING *_new) { | |
| 685 | 36 | const INTVAL old_len = Parrot_str_byte_length(INTERP, orig); |
| 686 | 36 | const INTVAL new_len = Parrot_str_byte_length(INTERP, _new); |
| 687 | 36 | STRING * const s = VTABLE_get_string(INTERP, SELF); |
| 688 | 36 | INTVAL i = 0; |
| 689 | ||
| 690 | 132 | while (-1 != (i = Parrot_str_find_index(INTERP, s, orig, i))) { |
| 691 | 60 | (void)Parrot_str_replace(INTERP, s, i, old_len, _new, NULL); |
| 692 | 60 | i += new_len; |
| 693 | } | |
| 694 | ||
| 695 | 36 | VTABLE_set_string_native(INTERP, SELF, s); |
| 696 | } | |
| 697 | /* | |
| 698 | ||
| 699 - 710 | =item C<PMC *to_int(INTVAL base)> Return the integer equivalent of SELF, which is assumed to be a C<base> digit string. The String is assumed to be in an ascii-compatible encoding. The String is considered being unsigned, and no I<+> or I<-> chars are processed. C<base> has to be within [2..36]. If any chars in the String aren't converted, an exception is thrown. TODO Currently overflow to BigInt is B<not> handled nor detected. =cut | |
| 711 | ||
| 712 | */ | |
| 713 | ||
| 714 | METHOD to_int(INTVAL base) { | |
| 715 | PMC *result = pmc_new(INTERP, Parrot_get_ctx_HLL_type(interp, | |
| 716 | 124 | enum_class_Integer)); |
| 717 | ||
| 718 | /* TODO verify encoding */ | |
| 719 | 124 | const STRING *me = VTABLE_get_string(INTERP, SELF); |
| 720 | 124 | char *str = Parrot_str_to_cstring(INTERP, me); |
| 721 | 124 | UINTVAL i = 0; |
| 722 | 124 | size_t j = 0; |
| 723 | 124 | size_t len = strlen(str); |
| 724 | ||
| 725 | 124 | if (base < 2 || base > 36) |
| 726 | 12 | Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, |
| 727 | "invalid conversion to int - bad base %d", base); | |
| 728 | ||
| 729 | 612 | while (j < len) { |
| 730 | 400 | const unsigned char c = str[j]; |
| 731 | int dig; | |
| 732 | ||
| 733 | 400 | if (isdigit((unsigned char)c)) |
| 734 | 370 | dig = c - '0'; |
| 735 | 60 | else if (c >= 'a' && c <= 'z') |
| 736 | 30 | dig = c - 'a' + 10; |
| 737 | 0 | else if (c >= 'A' && c <= 'Z') |
| 738 | 0 | dig = c - 'A' + 10; |
| 739 | else | |
| 740 | break; | |
| 741 | ||
| 742 | 400 | if (dig >= base) |
| 743 | 12 | break; |
| 744 | ||
| 745 | 388 | i = i * base + dig; |
| 746 | 388 | j++; |
| 747 | } | |
| 748 | ||
| 749 | 112 | if (j < len) { |
| 750 | 12 | char ch = str[j]; |
| 751 | 12 | Parrot_str_free_cstring(str); |
| 752 | 12 | Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, |
| 753 | "invalid conversion to int - bad char %c", ch); | |
| 754 | } | |
| 755 | ||
| 756 | 100 | Parrot_str_free_cstring(str); |
| 757 | /* TODO: autopromote to BigInt instead of casting away the high bit */ | |
| 758 | 100 | VTABLE_set_integer_native(INTERP, result, (INTVAL)i); |
| 759 | RETURN(PMC *result); | |
| 760 | } | |
| 761 | /* | |
| 762 | ||
| 763 | =back | |
| 764 | ||
| 765 - 784 | =head2 Iterator Interface =over 4 =item C<PMC *slice(PMC *key, INTVAL f)> Return a new iterator for the slice PMC C<key> if f==0. Return a new pythonic slice if f == 1. =item C<PMC *get_iter(PMC *key)> Return a new iterator for this string. =item C<INTVAL elements()> Return length of the string. =cut | |
| 785 | ||
| 786 | */ | |
| 787 | ||
| 788 | VTABLE INTVAL elements() { | |
| 789 | 228 | return Parrot_str_byte_length(INTERP, VTABLE_get_string(INTERP, SELF)); |
| 790 | } | |
| 791 | ||
| 792 | VTABLE PMC *slice(PMC *key, INTVAL f) { | |
| 793 | 0 | if (f == 0) { |
| 794 | 0 | STRING *name = CONST_STRING(interp, "set_key"); |
| 795 | 0 | PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF); |
| 796 | 0 | Parrot_PCCINVOKE(interp, iter, name, "P->", key); |
| 797 | 0 | return iter; |
| 798 | } | |
| 799 | ||
| 800 | 0 | Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, |
| 801 | 36 | "String: Unknown slice type"); |
| 802 | 36 | } |
| 803 | ||
| 804 | VTABLE PMC *get_iter() { | |
| 805 | 132 | return pmc_new_init(INTERP, enum_class_StringIterator, SELF); |
| 806 | } | |
| 807 | ||
| 808 | /* | |
| 809 | ||
| 810 | =back | |
| 811 | ||
| 812 - 820 | =head2 Freeze/thaw Interface =over 4 =item C<void freeze(visit_info *info)> Used to archive the string. =cut | |
| 821 | ||
| 822 | */ | |
| 823 | VTABLE void freeze(visit_info *info) { | |
| 824 | 12110 | IMAGE_IO * const io = info->image_io; |
| 825 | 12110 | SUPER(info); |
| 826 | 12110 | VTABLE_push_string(INTERP, io, VTABLE_get_string(INTERP, SELF)); |
| 827 | } | |
| 828 | ||
| 829 | /* | |
| 830 | ||
| 831 - 835 | =item C<void thaw(visit_info *info)> Used to unarchive the string. =cut | |
| 836 | ||
| 837 | */ | |
| 838 | VTABLE void thaw(visit_info *info) { | |
| 839 | 9462178 | IMAGE_IO * const io = info->image_io; |
| 840 | 9462178 | SUPER(info); |
| 841 | 9462178 | if (info->extra_flags == EXTRA_IS_NULL) |
| 842 | 9462178 | SET_ATTR_str_val(INTERP, SELF, VTABLE_shift_string(INTERP, io)); |
| 843 | } | |
| 844 | /* | |
| 845 | ||
| 846 | =back | |
| 847 | ||
| 848 - 856 | =head2 NCI methods =over 4 =item C<PMC *lower()> Downcase this string =cut | |
| 857 | ||
| 858 | */ | |
| 859 | ||
| 860 | METHOD lower() { | |
| 861 | STRING * const s = Parrot_str_downcase(INTERP, | |
| 862 | 24 | VTABLE_get_string(INTERP, SELF)); |
| 863 | ||
| 864 | RETURN(STRING *s); | |
| 865 | } | |
| 866 | ||
| 867 | /* | |
| 868 | ||
| 869 - 873 | =item C<void trans(STRING *src, PMC *trams_table)> Translate ascii string C<src> with entries from C<trans_table>. =cut | |
| 874 | ||
| 875 | */ | |
| 876 | ||
| 877 | METHOD trans(STRING *src, PMC *table) { | |
| 878 | unsigned char *p; | |
| 879 | INTVAL *tr_data; | |
| 880 | INTVAL i; | |
| 881 | ||
| 882 | 12 | const INTVAL len = Parrot_str_byte_length(interp, src); |
| 883 | ||
| 884 | 12 | if (!len) |
| 885 | RETURN(void); | |
| 886 | ||
| 887 | 12 | if (src->charset != Parrot_ascii_charset_ptr) |
| 888 | 0 | Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING, |
| 889 | "Can't translate non-ascii"); | |
| 890 | ||
| 891 | 12 | p = (unsigned char *)Buffer_bufstart(src); |
| 892 | 124 | /* TODO verify trans table */ |
| 893 | ||
| 894 | 12 | GETATTR_FixedIntegerArray_int_array(INTERP, table, tr_data); |
| 895 | ||
| 896 | 156 | for (i = 0; i < len; ++i, ++p) { |
| 897 | 144 | const unsigned char ch = (unsigned char)tr_data[*p]; |
| 898 | 144 | if (ch) |
| 899 | 132 | *p = ch; |
| 900 | } | |
| 901 | } | |
| 902 | ||
| 903 | /* | |
| 904 | ||
| 905 - 909 | =item C<void reverse(STRING *src)> Reverse the ascii STRING C<src> in place. =cut | |
| 910 | ||
| 911 | */ | |
| 912 | ||
| 913 | METHOD reverse(STRING *src) { | |
| 914 | INTVAL i; | |
| 915 | unsigned char *p; | |
| 916 | 12 | INTVAL len = Parrot_str_byte_length(interp, src); |
| 917 | ||
| 918 | 12 | if (!len) |
| 919 | RETURN(void); | |
| 920 | ||
| 921 | 12 | if (src->charset != Parrot_ascii_charset_ptr) |
| 922 | 0 | Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING, |
| 923 | "Can't reverse non-ascii"); | |
| 924 | ||
| 925 | 12 | p = (unsigned char *)Buffer_bufstart(src); |
| 926 | ||
| 927 | 48 | for (i = 0, --len; i < len; ++i, --len) { |
| 928 | 36 | const unsigned char ch = p[len]; |
| 929 | ||
| 930 | 36 | p[len] = p[i]; |
| 931 | 36 | p[i] = ch; |
| 932 | } | |
| 933 | } | |
| 934 | ||
| 935 | /* | |
| 936 | ||
| 937 - 941 | =item C<INTEGER is_integer(STRING *src)> Checks if the ascii STRING C<str> is just an integer. =cut | |
| 942 | ||
| 943 | */ | |
| 944 | ||
| 945 | METHOD is_integer(STRING *src) { | |
| 946 | INTVAL i; | |
| 947 | unsigned char *p; | |
| 948 | 72 | const INTVAL len = Parrot_str_byte_length(interp, src); |
| 949 | ||
| 950 | 172 | if (!len) |
| 951 | RETURN(INTVAL 0); | |
| 952 | ||
| 953 | 72 | if (src->charset != Parrot_ascii_charset_ptr) |
| 954 | 0 | Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING, |
| 955 | "Can't is_integer non-ascii"); | |
| 956 | ||
| 957 | 72 | i = 0; |
| 958 | 72 | p = (unsigned char *)Buffer_bufstart(src); |
| 959 | ||
| 960 | 72 | if (p[i] == '-' || p[i] == '+' || |
| 961 | (p[i] >= '0' && p[i] <= '9')) { | |
| 962 | 108 | for (i = 1; i < len; ++i) |
| 963 | 72 | if (p[i] < '0' || p[i] > '9') |
| 964 | RETURN(INTVAL 0); | |
| 965 | ||
| 966 | RETURN(INTVAL 1); | |
| 967 | } | |
| 968 | else | |
| 969 | RETURN(INTVAL 0); | |
| 970 | } | |
| 971 | ||
| 972 | VTABLE PMC *share_ro() { | |
| 973 | STRING *str_val; | |
| 974 | 0 | PMC * const ret = SUPER(); |
| 975 | ||
| 976 | 0 | GET_ATTR_str_val(INTERP, SELF, str_val); |
| 977 | 0 | if (!STRING_IS_NULL(str_val)) { |
| 978 | /* prevent wrong garbage collection */ | |
| 979 | 0 | PObj_is_shared_SET(str_val); |
| 980 | } | |
| 981 | 0 | return ret; |
| 982 | } | |
| 983 | ||
| 984 | VTABLE STRING* get_repr() { | |
| 985 | 0 | return VTABLE_get_string(INTERP, SELF); |
| 986 | } | |
| 987 | ||
| 988 | /* | |
| 989 | ||
| 990 - 994 | =item C<INTEGER reverse_index(STRING *substring, INTVAL start)> Find last occurrence of C<substring>, but not after the C<start> position. =cut | |
| 995 | ||
| 996 | */ | |
| 997 | ||
| 998 | METHOD reverse_index(STRING *substring, INTVAL start) { | |
| 999 | 72 | STRING * const src = VTABLE_get_string(INTERP, SELF); |
| 1000 | 72 | INTVAL res = -1; |
| 1001 | UINTVAL len; | |
| 1002 | ||
| 1003 | 72 | if (start < 0) |
| 1004 | RETURN(INTVAL res); | |
| 1005 | ||
| 1006 | 60 | len = Parrot_str_byte_length(interp, src); |
| 1007 | ||
| 1008 | 60 | if (!len) |
| 1009 | RETURN(INTVAL res); | |
| 1010 | ||
| 1011 | 48 | if (start >= (INTVAL)len) |
| 1012 | RETURN(INTVAL res); | |
| 1013 | ||
| 1014 | 36 | if (!Parrot_str_byte_length(interp, substring)) |
| 1015 | RETURN(INTVAL res); | |
| 1016 | ||
| 1017 | 24 | res = CHARSET_RINDEX(INTERP, src, substring, (UINTVAL)start); |
| 1018 | RETURN(INTVAL res); | |
| 1019 | } | |
| 1020 | } | |
| 1021 | ||
| 1022 | /* | |
| 1023 | ||
| 1024 | =back | |
| 1025 | ||
| 1026 | =cut | |
| 1027 | ||
| 1028 | */ | |
| 1029 | ||
| 1030 | ||
| 1031 | /* | |
| 1032 | * Local variables: | |
| 1033 | * c-file-style: "parrot" | |
| 1034 | * End: | |
| 1035 | * vim: expandtab shiftwidth=4: | |
| 1036 | */ | |