1/* 2Copyright (C) 2001-2014, Parrot Foundation. 3 4=head1 NAME 5 6src/pmc/fixedbooleanarray.pmc - FixedBooleanArray PMC 7 8=head1 DESCRIPTION 9 10Fixed size array for booleans only. 11 12The C<FixedBooleanArray> PMC implements an array of fixed size, which 13stores booleans. It uses the C<Boolean> PMC for all conversions. The 14C<FixedBooleanArray> PMC is extended by the C<ResizableBooleanArray> 15PMC. 16 17=head2 Functions 18 19=over 4 20 21=item C<static UINTVAL get_size_in_bytes(UINTVAL size)> 22 23Auxiliar function to avoid repeating the size evaluation. 24 25=cut 26 27*/ 28 29#define BITS_PER_CHAR 8 30 31/* HEADERIZER HFILE: none */ 32/* HEADERIZER BEGIN: static */ 33/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 34 35PARROT_INLINE 36PARROT_CONST_FUNCTION 37static UINTVAL get_size_in_bytes(UINTVAL size); 38 39#define ASSERT_ARGS_get_size_in_bytes __attribute__unused__ int _ASSERT_ARGS_CHECK = (0) 40/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 41/* HEADERIZER END: static */ 42 43PARROT_INLINE 44PARROT_CONST_FUNCTION 45static UINTVAL 46get_size_in_bytes(UINTVAL size) 47{ 48 ASSERT_ARGS(get_size_in_bytes) 49 50 return (size + BITS_PER_CHAR - 1) / BITS_PER_CHAR; 51} 52 53 54pmclass FixedBooleanArray auto_attrs provides array { 55 ATTR UINTVAL size; /* # of bits this fba holds */ 56 ATTR UINTVAL resize_threshold; /* max capacity before resizing */ 57 ATTR unsigned char * bit_array; /* where the bits go */ 58 59/* 60 61=back 62 63=head2 Vtable functions 64 65=over 4 66 67=item C<void init()> 68 69Initializes the array. 70 71=cut 72 73*/ 74 75 VTABLE void init() { 76 PObj_custom_destroy_SET(SELF); 77 } 78 79/* 80 81=item C<void init_int(INTVAL size)> 82 83Initializes the array. 84 85=cut 86 87*/ 88 89 VTABLE void init_int(INTVAL size) { 90 const size_t size_in_bytes = get_size_in_bytes(size); 91 92 if (size < 0) 93 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 94 "illegal argument"); 95 96 SET_ATTR_size(INTERP, SELF, size); 97 SET_ATTR_resize_threshold(INTERP, SELF, size_in_bytes * BITS_PER_CHAR); 98 SET_ATTR_bit_array(INTERP, SELF, mem_gc_allocate_n_zeroed_typed(INTERP, size_in_bytes, 99 unsigned char)); 100 PObj_custom_destroy_SET(SELF); 101 } 102 103 104/* 105 106=item C<void destroy()> 107 108Destroys the array. 109 110=cut 111 112*/ 113 114 VTABLE void destroy() :no_wb { 115 unsigned char *bit_array; 116 GET_ATTR_bit_array(INTERP, SELF, bit_array); 117 if (bit_array) 118 mem_gc_free(INTERP, bit_array); 119 } 120 121/* 122 123=item C<PMC *clone()> 124 125Creates and returns a copy of the array. 126 127=cut 128 129*/ 130 131 VTABLE PMC *clone() :no_wb { 132 unsigned char * my_bit_array; 133 UINTVAL resize_threshold, size; 134 PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type); 135 136 GET_ATTR_bit_array(INTERP, SELF, my_bit_array); 137 GET_ATTR_size(INTERP, SELF, size); 138 GET_ATTR_resize_threshold(INTERP, SELF, resize_threshold); 139 140 if (my_bit_array) { 141 unsigned char * clone_bit_array; 142 const size_t size_in_bytes = get_size_in_bytes(resize_threshold); 143 144 SET_ATTR_size(INTERP, dest, size); 145 SET_ATTR_resize_threshold(INTERP, dest, resize_threshold); 146 147 clone_bit_array = mem_gc_allocate_n_typed(INTERP, size_in_bytes, unsigned char); 148 memcpy(clone_bit_array, my_bit_array, size_in_bytes); 149 150 SET_ATTR_bit_array(INTERP, dest, clone_bit_array); 151 } 152 153 PObj_custom_destroy_SET(dest); 154 return dest; 155 } 156 157/* 158 159=item C<INTVAL get_bool()> 160 161Returns whether the array has any elements (meaning been initialized, for a 162fixed sized array). 163 164=cut 165 166*/ 167 VTABLE INTVAL get_bool() :no_wb { 168 return SELF.elements() ? 1 : 0; 169 } 170 171/* 172 173=item C<INTVAL elements()> 174 175=cut 176 177*/ 178 179 VTABLE INTVAL elements() :no_wb { 180 UINTVAL size; 181 GET_ATTR_size(INTERP, SELF, size); 182 return size; 183 } 184 185/* 186 187=item C<INTVAL get_integer()> 188 189Returns the number of elements in the array. 190 191=cut 192 193*/ 194 195 VTABLE INTVAL get_integer() :no_wb { 196 return SELF.elements(); 197 } 198 199/* 200 201=item C<INTVAL get_integer_keyed_int(INTVAL key)> 202 203Returns the integer value of the element at index C<key>. 204 205=cut 206 207*/ 208 209 VTABLE INTVAL get_integer_keyed_int(INTVAL key) :no_wb { 210 UINTVAL size; 211 const unsigned char * bit_array; 212 GET_ATTR_bit_array(INTERP, SELF, bit_array); 213 GET_ATTR_size(INTERP, SELF, size); 214 215 if (key < 0) 216 key += size; 217 if (key < 0 || (UINTVAL)key >= size) 218 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 219 "index out of bounds"); 220 221 return (bit_array[key / BITS_PER_CHAR] & (1 << (key % BITS_PER_CHAR))) ? 1 : 0; 222 } 223 224/* 225 226=item C<INTVAL get_integer_keyed(PMC *key)> 227 228Returns the integer value of the element at index C<*key>. 229 230=cut 231 232*/ 233 234 VTABLE INTVAL get_integer_keyed(PMC *key) :no_wb { 235 /* simple int keys only */ 236 const INTVAL k = VTABLE_get_integer(INTERP, key); 237 return SELF.get_integer_keyed_int(k); 238 } 239 240 241/* 242 243=item C<FLOATVAL get_number_keyed_int(INTVAL key)> 244 245Returns the floating-point value of the element at index C<key>. 246 247=cut 248 249*/ 250 251 VTABLE FLOATVAL get_number_keyed_int(INTVAL key) :no_wb { 252 const INTVAL i = SELF.get_integer_keyed_int(key); 253 return (FLOATVAL)i; 254 } 255 256/* 257 258=item C<FLOATVAL get_number_keyed(PMC *key)> 259 260Returns the floating-point value of the element at index C<*key>. 261 262=cut 263 264*/ 265 266 VTABLE FLOATVAL get_number_keyed(PMC *key) :no_wb { 267 const INTVAL k = VTABLE_get_integer(INTERP, key); 268 return SELF.get_number_keyed_int(k); 269 } 270 271/* 272 273=item C<STRING *get_string()> 274 275Returns the Parrot string representation of the array. 276 277=cut 278 279*/ 280 281 VTABLE STRING *get_string() :no_wb { 282 STRING *str = STRINGNULL; 283 UINTVAL i; 284 const UINTVAL elems = SELF.elements(); 285 286 const STRING * const zero = CONST_STRING(INTERP, "0"); 287 const STRING * const one = CONST_STRING(INTERP, "1"); 288 289 for (i = 0; i < elems; ++i) { 290 str = Parrot_str_concat(INTERP, str, 291 SELF.get_integer_keyed_int((INTVAL)i) ? one : zero); 292 } 293 294 return str; 295 296 } 297 298/* 299 300=item C<STRING *get_string_keyed_int(INTVAL key)> 301 302Returns the Parrot string value of the element at index C<key>. 303 304=cut 305 306*/ 307 308 VTABLE STRING *get_string_keyed_int(INTVAL key) :no_wb { 309 PMC * const val = SELF.get_pmc_keyed_int(key); 310 return VTABLE_get_string(INTERP, val); 311 } 312 313/* 314 315=item C<STRING *get_string_keyed(PMC *key)> 316 317Returns the Parrot string value of the element at index C<*key>. 318 319=cut 320 321*/ 322 323 VTABLE STRING *get_string_keyed(PMC *key) :no_wb { 324 const INTVAL k = VTABLE_get_integer(INTERP, key); 325 return SELF.get_string_keyed_int(k); 326 } 327 328 329/* 330 331=item C<PMC *get_pmc_keyed_int(INTVAL key)> 332 333Returns the PMC value of the element at index C<key>. 334 335=cut 336 337*/ 338 339 VTABLE PMC *get_pmc_keyed_int(INTVAL key) :no_wb { 340 return Parrot_pmc_new_init_int(INTERP, enum_class_Boolean, 341 SELF.get_integer_keyed_int(key)); 342 } 343 344/* 345 346=item C<PMC *get_pmc_keyed(PMC *key)> 347 348Returns the PMC value of the element at index C<*key>. 349 350=cut 351 352*/ 353 354 VTABLE PMC *get_pmc_keyed(PMC *key) :no_wb { 355 const INTVAL k = VTABLE_get_integer(INTERP, key); 356 return SELF.get_pmc_keyed_int(k); 357 } 358 359/* 360 361=item C<void set_integer_native(INTVAL size)> 362 363Resizes the array to C<size> elements. 364 365=cut 366 367*/ 368 369 VTABLE void set_integer_native(INTVAL size) { 370 const size_t size_in_bytes = get_size_in_bytes(size); 371 UINTVAL old_size; 372 unsigned char *bit_array; 373 374 GET_ATTR_size(INTERP, SELF, old_size); 375 if (old_size || size < 1) 376 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 377 "Can't resize"); 378 379 SET_ATTR_size(INTERP, SELF, size); 380 SET_ATTR_resize_threshold(INTERP, SELF, size_in_bytes * BITS_PER_CHAR); 381 bit_array = mem_gc_allocate_n_typed(INTERP, size_in_bytes, unsigned char); 382 memset(bit_array, 0, size_in_bytes); 383 SET_ATTR_bit_array(INTERP, SELF, bit_array); 384 } 385 386/* 387 388=item C<void set_integer_keyed_int(INTVAL key, INTVAL value)> 389 390Sets the integer value of the element at index C<key> to C<value>. 391 392=cut 393 394*/ 395 396 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) { 397 UINTVAL size; 398 unsigned char * bit_array; 399 GET_ATTR_bit_array(INTERP, SELF, bit_array); 400 GET_ATTR_size(INTERP, SELF, size); 401 402 if (key < 0) 403 key += size; 404 if (key < 0 || (UINTVAL)key >= size) 405 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_OUT_OF_BOUNDS, 406 "index out of bounds"); 407 408 if (value) 409 bit_array[key/BITS_PER_CHAR] |= (1 << (key % BITS_PER_CHAR)); 410 else 411 bit_array[key/BITS_PER_CHAR] &= ~(1 << (key % BITS_PER_CHAR)); 412 } 413 414/* 415 416=item C<void set_integer_keyed(PMC *key, INTVAL value)> 417 418Sets the integer value of the element at index C<key> to C<value>. 419 420=cut 421 422*/ 423 424 VTABLE void set_integer_keyed(PMC *key, INTVAL value) :manual_wb { 425 const INTVAL k = VTABLE_get_integer(INTERP, key); 426 SELF.set_integer_keyed_int(k, value); 427 } 428 429/* 430 431=item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)> 432 433Sets the floating-point value of the element at index C<key> to 434C<value>. 435 436=cut 437 438*/ 439 440 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) :manual_wb { 441 SELF.set_integer_keyed_int(key, !FLOAT_IS_ZERO(value)); 442 } 443 444/* 445 446=item C<void set_number_keyed(PMC *key, FLOATVAL value)> 447 448Sets the floating-point value of the element at index C<key> to 449C<value>. 450 451=cut 452 453*/ 454 455 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) :manual_wb { 456 const INTVAL k = VTABLE_get_integer(INTERP, key); 457 SELF.set_number_keyed_int(k, value); 458 } 459 460/* 461 462=item C<void set_string_keyed_int(INTVAL key, STRING *value)> 463 464Sets the Parrot string value of the element at index C<key> to C<value>. 465 466=cut 467 468*/ 469 470 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) :manual_wb { 471 INTVAL tempInt; 472 PMC * const tempPMC = Parrot_pmc_new(INTERP, enum_class_Boolean); 473 474 VTABLE_set_string_native(INTERP, tempPMC, value); 475 tempInt = VTABLE_get_integer(INTERP, tempPMC); 476 477 SELF.set_integer_keyed_int(key, tempInt); 478 } 479 480/* 481 482=item C<void set_string_keyed(PMC *key, STRING *value)> 483 484Sets the string value of the element at index C<key> to 485C<value>. 486 487=cut 488 489*/ 490 491 VTABLE void set_string_keyed(PMC *key, STRING *value) :manual_wb { 492 const INTVAL k = VTABLE_get_integer(INTERP, key); 493 SELF.set_string_keyed_int(k, value); 494 } 495 496/* 497 498=item C<void set_pmc_keyed_int(INTVAL key, PMC *src)> 499 500Sets the PMC value of the element at index C<key> to C<*src>. 501 502=cut 503 504*/ 505 506 VTABLE void set_pmc_keyed_int(INTVAL key, PMC *src) :manual_wb { 507 const INTVAL tempInt = VTABLE_get_integer(INTERP, src); 508 SELF.set_integer_keyed_int(key, tempInt); 509 } 510 511/* 512 513=item C<void set_pmc_keyed(PMC *key, PMC *value)> 514 515Sets the string value of the element at index C<key> to 516C<value>. 517 518=cut 519 520*/ 521 522 VTABLE void set_pmc_keyed(PMC *key, PMC *value) :manual_wb { 523 const INTVAL k = VTABLE_get_integer(INTERP, key); 524 SELF.set_pmc_keyed_int(k, value); 525 } 526 527/* 528 529=item C<PMC *get_iter()> 530 531Return a new iterator for SELF. 532 533=cut 534 535*/ 536 537 VTABLE PMC *get_iter() :no_wb { 538 return Parrot_pmc_new_init(INTERP, enum_class_ArrayIterator, SELF); 539 } 540 541 542 543/* 544 545=back 546 547=head2 Freeze/thaw Interface 548 549=over 4 550 551=item C<void freeze(PMC *info)> 552 553Used to archive the string. 554 555=cut 556 557*/ 558 VTABLE void freeze(PMC *info) :no_wb { 559 UINTVAL size, resize_threshold; 560 unsigned char * bit_array; 561 STRING * s; 562 GET_ATTR_size(INTERP, SELF, size); 563 GET_ATTR_resize_threshold(INTERP, SELF, resize_threshold); 564 GET_ATTR_bit_array(INTERP, SELF, bit_array); 565 566 s = Parrot_str_new_init(INTERP, (char*)bit_array, 567 (resize_threshold / BITS_PER_CHAR), 568 Parrot_binary_encoding_ptr, 0); 569 570 VTABLE_push_integer(INTERP, info, size); 571 VTABLE_push_string(INTERP, info, s); 572 } 573 574/* 575 576=item C<void thaw(PMC *info)> 577 578Used to unarchive the string. 579 580=cut 581 582*/ 583 VTABLE void thaw(PMC *info) { 584 SUPER(info); 585 586 { 587 const INTVAL size = VTABLE_shift_integer(INTERP, info); 588 STRING * const s = VTABLE_shift_string(INTERP, info); 589 const size_t size_in_bytes = get_size_in_bytes(size); 590 unsigned char *bit_array; 591 592 SELF.set_integer_native(size); 593 594 if (s->bufused < size_in_bytes) 595 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_BAD_BUFFER_SIZE, 596 "FixedBooleanArray: invalid buffer size during thaw"); 597 598 GET_ATTR_bit_array(INTERP, SELF, bit_array); 599 memcpy(bit_array, s->strstart, size_in_bytes); 600 } 601 } 602 603/* 604 605=back 606 607=head2 Methods 608 609=over 4 610 611=item C<METHOD fill(INTVAL fill)> 612 613Sets all of the entries to true if fill is a true value, otherwise 614sets them all to false. 615 616=cut 617 618*/ 619 620 METHOD fill(INTVAL fill) { 621 UINTVAL size; 622 unsigned char * bit_array; 623 size_t size_in_bytes; 624 625 GET_ATTR_bit_array(INTERP, SELF, bit_array); 626 GET_ATTR_size(INTERP, SELF, size); 627 size_in_bytes = get_size_in_bytes(size); 628 629 if (size_in_bytes) 630 memset(bit_array, fill ? 0xff : 0, size_in_bytes); 631 } 632} 633 634/* 635 636=back 637 638=head1 SEE ALSO 639 640F<docs/pdds/pdd17_basic_types.pod>. 641 642=cut 643 644*/ 645 646/* 647 * Local variables: 648 * c-file-style: "parrot" 649 * End: 650 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : 651 */ 652