2121#include "buffer.h"
2222#include "buffer_class.h"
2323
24- VALUE cMessagePack_Buffer ;
24+ VALUE cMessagePack_Buffer = Qnil ;
25+ VALUE cMessagePack_HeldBuffer = Qnil ;
2526
2627static ID s_read ;
2728static ID s_readpartial ;
@@ -34,6 +35,73 @@ static VALUE sym_read_reference_threshold;
3435static VALUE sym_write_reference_threshold ;
3536static VALUE sym_io_buffer_size ;
3637
38+ typedef struct msgpack_held_buffer_t msgpack_held_buffer_t ;
39+ struct msgpack_held_buffer_t {
40+ size_t size ;
41+ VALUE mapped_strings [];
42+ };
43+
44+ static void HeldBuffer_mark (void * data )
45+ {
46+ msgpack_held_buffer_t * held_buffer = (msgpack_held_buffer_t * )data ;
47+ for (size_t index = 0 ; index < held_buffer -> size ; index ++ ) {
48+ rb_gc_mark (held_buffer -> mapped_strings [index ]);
49+ }
50+ }
51+
52+ static size_t HeldBuffer_memsize (const void * data )
53+ {
54+ const msgpack_held_buffer_t * held_buffer = (msgpack_held_buffer_t * )data ;
55+ return sizeof (size_t ) + sizeof (VALUE ) * held_buffer -> size ;
56+ }
57+
58+ static const rb_data_type_t held_buffer_data_type = {
59+ .wrap_struct_name = "msgpack:held_buffer" ,
60+ .function = {
61+ .dmark = HeldBuffer_mark ,
62+ .dfree = RUBY_TYPED_DEFAULT_FREE ,
63+ .dsize = HeldBuffer_memsize ,
64+ },
65+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
66+ };
67+
68+ VALUE MessagePack_Buffer_hold (msgpack_buffer_t * buffer )
69+ {
70+ size_t mapped_strings_count = 0 ;
71+ msgpack_buffer_chunk_t * c = buffer -> head ;
72+ while (c != & buffer -> tail ) {
73+ if (c -> mapped_string != NO_MAPPED_STRING ) {
74+ mapped_strings_count ++ ;
75+ }
76+ c = c -> next ;
77+ }
78+ if (c -> mapped_string != NO_MAPPED_STRING ) {
79+ mapped_strings_count ++ ;
80+ }
81+
82+ if (mapped_strings_count == 0 ) {
83+ return Qnil ;
84+ }
85+
86+ msgpack_held_buffer_t * held_buffer = xmalloc (sizeof (msgpack_held_buffer_t ) + mapped_strings_count * sizeof (VALUE ));
87+
88+ c = buffer -> head ;
89+ mapped_strings_count = 0 ;
90+ while (c != & buffer -> tail ) {
91+ if (c -> mapped_string != NO_MAPPED_STRING ) {
92+ held_buffer -> mapped_strings [mapped_strings_count ] = c -> mapped_string ;
93+ mapped_strings_count ++ ;
94+ }
95+ c = c -> next ;
96+ }
97+ if (c -> mapped_string != NO_MAPPED_STRING ) {
98+ held_buffer -> mapped_strings [mapped_strings_count ] = c -> mapped_string ;
99+ mapped_strings_count ++ ;
100+ }
101+ held_buffer -> size = mapped_strings_count ;
102+ return TypedData_Wrap_Struct (cMessagePack_HeldBuffer , & held_buffer_data_type , held_buffer );
103+ }
104+
37105
38106#define CHECK_STRING_TYPE (value ) \
39107 value = rb_check_string_type(value); \
@@ -520,6 +588,9 @@ void MessagePack_Buffer_module_init(VALUE mMessagePack)
520588
521589 msgpack_buffer_static_init ();
522590
591+ cMessagePack_HeldBuffer = rb_define_class_under (mMessagePack , "HeldBuffer" , rb_cBasicObject );
592+ rb_undef_alloc_func (cMessagePack_HeldBuffer );
593+
523594 cMessagePack_Buffer = rb_define_class_under (mMessagePack , "Buffer" , rb_cObject );
524595
525596 rb_define_alloc_func (cMessagePack_Buffer , Buffer_alloc );
0 commit comments