| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2014 Google Inc. All rights reserved. | 2 // Copyright 2014 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 // strings rather than Ruby strings: traversing the Map requires conversion to | 56 // strings rather than Ruby strings: traversing the Map requires conversion to |
| 57 // Ruby string values on every traversal, potentially creating more garbage. We | 57 // Ruby string values on every traversal, potentially creating more garbage. We |
| 58 // should consider ways to cache a Ruby version of the key if this becomes an | 58 // should consider ways to cache a Ruby version of the key if this becomes an |
| 59 // issue later. | 59 // issue later. |
| 60 | 60 |
| 61 // Forms a key to use with the underlying strtable from a Ruby key value. |buf| | 61 // Forms a key to use with the underlying strtable from a Ruby key value. |buf| |
| 62 // must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to | 62 // must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to |
| 63 // construct a key byte sequence if needed. |out_key| and |out_length| provide | 63 // construct a key byte sequence if needed. |out_key| and |out_length| provide |
| 64 // the resulting key data/length. | 64 // the resulting key data/length. |
| 65 #define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t) | 65 #define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t) |
| 66 static VALUE table_key(Map* self, VALUE key, | 66 static void table_key(Map* self, VALUE key, |
| 67 char* buf, | 67 char* buf, |
| 68 const char** out_key, | 68 const char** out_key, |
| 69 size_t* out_length) { | 69 size_t* out_length) { |
| 70 switch (self->key_type) { | 70 switch (self->key_type) { |
| 71 case UPB_TYPE_BYTES: | 71 case UPB_TYPE_BYTES: |
| 72 case UPB_TYPE_STRING: | 72 case UPB_TYPE_STRING: |
| 73 // Strings: use string content directly. | 73 // Strings: use string content directly. |
| 74 Check_Type(key, T_STRING); | 74 Check_Type(key, T_STRING); |
| 75 key = native_slot_encode_and_freeze_string(self->key_type, key); | 75 native_slot_validate_string_encoding(self->key_type, key); |
| 76 *out_key = RSTRING_PTR(key); | 76 *out_key = RSTRING_PTR(key); |
| 77 *out_length = RSTRING_LEN(key); | 77 *out_length = RSTRING_LEN(key); |
| 78 break; | 78 break; |
| 79 | 79 |
| 80 case UPB_TYPE_BOOL: | 80 case UPB_TYPE_BOOL: |
| 81 case UPB_TYPE_INT32: | 81 case UPB_TYPE_INT32: |
| 82 case UPB_TYPE_INT64: | 82 case UPB_TYPE_INT64: |
| 83 case UPB_TYPE_UINT32: | 83 case UPB_TYPE_UINT32: |
| 84 case UPB_TYPE_UINT64: | 84 case UPB_TYPE_UINT64: |
| 85 native_slot_set(self->key_type, Qnil, buf, key); | 85 native_slot_set(self->key_type, Qnil, buf, key); |
| 86 *out_key = buf; | 86 *out_key = buf; |
| 87 *out_length = native_slot_size(self->key_type); | 87 *out_length = native_slot_size(self->key_type); |
| 88 break; | 88 break; |
| 89 | 89 |
| 90 default: | 90 default: |
| 91 // Map constructor should not allow a Map with another key type to be | 91 // Map constructor should not allow a Map with another key type to be |
| 92 // constructed. | 92 // constructed. |
| 93 assert(false); | 93 assert(false); |
| 94 break; | 94 break; |
| 95 } | 95 } |
| 96 | |
| 97 return key; | |
| 98 } | 96 } |
| 99 | 97 |
| 100 static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { | 98 static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) { |
| 101 switch (self->key_type) { | 99 switch (self->key_type) { |
| 102 case UPB_TYPE_BYTES: | 100 case UPB_TYPE_BYTES: |
| 103 case UPB_TYPE_STRING: { | 101 case UPB_TYPE_STRING: { |
| 104 VALUE ret = rb_str_new(buf, length); | 102 VALUE ret = rb_str_new(buf, length); |
| 105 rb_enc_associate(ret, | 103 rb_enc_associate(ret, |
| 106 (self->key_type == UPB_TYPE_BYTES) ? | 104 (self->key_type == UPB_TYPE_BYTES) ? |
| 107 kRubyString8bitEncoding : kRubyStringUtf8Encoding); | 105 kRubyString8bitEncoding : kRubyStringUtf8Encoding); |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 * Accesses the element at the given key. Throws an exception if the key type is | 350 * Accesses the element at the given key. Throws an exception if the key type is |
| 353 * incorrect. Returns nil when the key is not present in the map. | 351 * incorrect. Returns nil when the key is not present in the map. |
| 354 */ | 352 */ |
| 355 VALUE Map_index(VALUE _self, VALUE key) { | 353 VALUE Map_index(VALUE _self, VALUE key) { |
| 356 Map* self = ruby_to_Map(_self); | 354 Map* self = ruby_to_Map(_self); |
| 357 | 355 |
| 358 char keybuf[TABLE_KEY_BUF_LENGTH]; | 356 char keybuf[TABLE_KEY_BUF_LENGTH]; |
| 359 const char* keyval = NULL; | 357 const char* keyval = NULL; |
| 360 size_t length = 0; | 358 size_t length = 0; |
| 361 upb_value v; | 359 upb_value v; |
| 362 key = table_key(self, key, keybuf, &keyval, &length); | 360 table_key(self, key, keybuf, &keyval, &length); |
| 363 | 361 |
| 364 if (upb_strtable_lookup2(&self->table, keyval, length, &v)) { | 362 if (upb_strtable_lookup2(&self->table, keyval, length, &v)) { |
| 365 void* mem = value_memory(&v); | 363 void* mem = value_memory(&v); |
| 366 return native_slot_get(self->value_type, self->value_type_class, mem); | 364 return native_slot_get(self->value_type, self->value_type_class, mem); |
| 367 } else { | 365 } else { |
| 368 return Qnil; | 366 return Qnil; |
| 369 } | 367 } |
| 370 } | 368 } |
| 371 | 369 |
| 372 /* | 370 /* |
| 373 * call-seq: | 371 * call-seq: |
| 374 * Map.[]=(key, value) => value | 372 * Map.[]=(key, value) => value |
| 375 * | 373 * |
| 376 * Inserts or overwrites the value at the given key with the given new value. | 374 * Inserts or overwrites the value at the given key with the given new value. |
| 377 * Throws an exception if the key type is incorrect. Returns the new value that | 375 * Throws an exception if the key type is incorrect. Returns the new value that |
| 378 * was just inserted. | 376 * was just inserted. |
| 379 */ | 377 */ |
| 380 VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { | 378 VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { |
| 381 Map* self = ruby_to_Map(_self); | 379 Map* self = ruby_to_Map(_self); |
| 382 | 380 |
| 383 char keybuf[TABLE_KEY_BUF_LENGTH]; | 381 char keybuf[TABLE_KEY_BUF_LENGTH]; |
| 384 const char* keyval = NULL; | 382 const char* keyval = NULL; |
| 385 size_t length = 0; | 383 size_t length = 0; |
| 386 upb_value v; | 384 upb_value v; |
| 387 void* mem; | 385 void* mem; |
| 388 key = table_key(self, key, keybuf, &keyval, &length); | 386 table_key(self, key, keybuf, &keyval, &length); |
| 389 | 387 |
| 390 mem = value_memory(&v); | 388 mem = value_memory(&v); |
| 391 native_slot_set(self->value_type, self->value_type_class, mem, value); | 389 native_slot_set(self->value_type, self->value_type_class, mem, value); |
| 392 | 390 |
| 393 // Replace any existing value by issuing a 'remove' operation first. | 391 // Replace any existing value by issuing a 'remove' operation first. |
| 394 upb_strtable_remove2(&self->table, keyval, length, NULL); | 392 upb_strtable_remove2(&self->table, keyval, length, NULL); |
| 395 if (!upb_strtable_insert2(&self->table, keyval, length, v)) { | 393 if (!upb_strtable_insert2(&self->table, keyval, length, v)) { |
| 396 rb_raise(rb_eRuntimeError, "Could not insert into table"); | 394 rb_raise(rb_eRuntimeError, "Could not insert into table"); |
| 397 } | 395 } |
| 398 | 396 |
| 399 // Ruby hashmap's :[]= method also returns the inserted value. | 397 // Ruby hashmap's :[]= method also returns the inserted value. |
| 400 return value; | 398 return value; |
| 401 } | 399 } |
| 402 | 400 |
| 403 /* | 401 /* |
| 404 * call-seq: | 402 * call-seq: |
| 405 * Map.has_key?(key) => bool | 403 * Map.has_key?(key) => bool |
| 406 * | 404 * |
| 407 * Returns true if the given key is present in the map. Throws an exception if | 405 * Returns true if the given key is present in the map. Throws an exception if |
| 408 * the key has the wrong type. | 406 * the key has the wrong type. |
| 409 */ | 407 */ |
| 410 VALUE Map_has_key(VALUE _self, VALUE key) { | 408 VALUE Map_has_key(VALUE _self, VALUE key) { |
| 411 Map* self = ruby_to_Map(_self); | 409 Map* self = ruby_to_Map(_self); |
| 412 | 410 |
| 413 char keybuf[TABLE_KEY_BUF_LENGTH]; | 411 char keybuf[TABLE_KEY_BUF_LENGTH]; |
| 414 const char* keyval = NULL; | 412 const char* keyval = NULL; |
| 415 size_t length = 0; | 413 size_t length = 0; |
| 416 key = table_key(self, key, keybuf, &keyval, &length); | 414 table_key(self, key, keybuf, &keyval, &length); |
| 417 | 415 |
| 418 if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) { | 416 if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) { |
| 419 return Qtrue; | 417 return Qtrue; |
| 420 } else { | 418 } else { |
| 421 return Qfalse; | 419 return Qfalse; |
| 422 } | 420 } |
| 423 } | 421 } |
| 424 | 422 |
| 425 /* | 423 /* |
| 426 * call-seq: | 424 * call-seq: |
| 427 * Map.delete(key) => old_value | 425 * Map.delete(key) => old_value |
| 428 * | 426 * |
| 429 * Deletes the value at the given key, if any, returning either the old value or | 427 * Deletes the value at the given key, if any, returning either the old value or |
| 430 * nil if none was present. Throws an exception if the key is of the wrong type. | 428 * nil if none was present. Throws an exception if the key is of the wrong type. |
| 431 */ | 429 */ |
| 432 VALUE Map_delete(VALUE _self, VALUE key) { | 430 VALUE Map_delete(VALUE _self, VALUE key) { |
| 433 Map* self = ruby_to_Map(_self); | 431 Map* self = ruby_to_Map(_self); |
| 434 | 432 |
| 435 char keybuf[TABLE_KEY_BUF_LENGTH]; | 433 char keybuf[TABLE_KEY_BUF_LENGTH]; |
| 436 const char* keyval = NULL; | 434 const char* keyval = NULL; |
| 437 size_t length = 0; | 435 size_t length = 0; |
| 438 upb_value v; | 436 upb_value v; |
| 439 key = table_key(self, key, keybuf, &keyval, &length); | 437 table_key(self, key, keybuf, &keyval, &length); |
| 440 | 438 |
| 441 if (upb_strtable_remove2(&self->table, keyval, length, &v)) { | 439 if (upb_strtable_remove2(&self->table, keyval, length, &v)) { |
| 442 void* mem = value_memory(&v); | 440 void* mem = value_memory(&v); |
| 443 return native_slot_get(self->value_type, self->value_type_class, mem); | 441 return native_slot_get(self->value_type, self->value_type_class, mem); |
| 444 } else { | 442 } else { |
| 445 return Qnil; | 443 return Qnil; |
| 446 } | 444 } |
| 447 } | 445 } |
| 448 | 446 |
| 449 /* | 447 /* |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 rb_define_method(klass, "delete", Map_delete, 1); | 799 rb_define_method(klass, "delete", Map_delete, 1); |
| 802 rb_define_method(klass, "clear", Map_clear, 0); | 800 rb_define_method(klass, "clear", Map_clear, 0); |
| 803 rb_define_method(klass, "length", Map_length, 0); | 801 rb_define_method(klass, "length", Map_length, 0); |
| 804 rb_define_method(klass, "dup", Map_dup, 0); | 802 rb_define_method(klass, "dup", Map_dup, 0); |
| 805 rb_define_method(klass, "==", Map_eq, 1); | 803 rb_define_method(klass, "==", Map_eq, 1); |
| 806 rb_define_method(klass, "hash", Map_hash, 0); | 804 rb_define_method(klass, "hash", Map_hash, 0); |
| 807 rb_define_method(klass, "inspect", Map_inspect, 0); | 805 rb_define_method(klass, "inspect", Map_inspect, 0); |
| 808 rb_define_method(klass, "merge", Map_merge, 1); | 806 rb_define_method(klass, "merge", Map_merge, 1); |
| 809 rb_include_module(klass, rb_mEnumerable); | 807 rb_include_module(klass, rb_mEnumerable); |
| 810 } | 808 } |
| OLD | NEW |