4 * Copyright 2016 Microsoft
6 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12 #include "mono/metadata/dynamic-stream-internals.h"
13 #include "mono/metadata/metadata-internals.h"
14 #include "mono/utils/checked-build.h"
15 #include "mono/utils/mono-error-internals.h"
16 #include "object-internals.h"
19 mono_dynstream_init (MonoDynamicStream
*sh
)
21 MONO_REQ_GC_NEUTRAL_MODE
;
24 sh
->alloc_size
= 4096;
25 sh
->data
= (char *)g_malloc (4096);
26 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
27 mono_dynstream_insert_string (sh
, "");
31 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
33 MONO_REQ_GC_NEUTRAL_MODE
;
35 if (size
<= stream
->alloc_size
)
38 while (stream
->alloc_size
<= size
) {
39 if (stream
->alloc_size
< 4096)
40 stream
->alloc_size
= 4096;
42 stream
->alloc_size
*= 2;
45 stream
->data
= (char *)g_realloc (stream
->data
, stream
->alloc_size
);
49 mono_dynstream_insert_string (MonoDynamicStream
*sh
, const char *str
)
51 MONO_REQ_GC_NEUTRAL_MODE
;
55 gpointer oldkey
, oldval
;
57 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
58 return GPOINTER_TO_UINT (oldval
);
60 len
= strlen (str
) + 1;
63 make_room_in_stream (sh
, idx
+ len
);
66 * We strdup the string even if we already copy them in sh->data
67 * so that the string pointers in the hash remain valid even if
68 * we need to realloc sh->data. We may want to avoid that later.
70 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
71 memcpy (sh
->data
+ idx
, str
, len
);
77 mono_dynstream_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
, MonoError
*error
)
79 MONO_REQ_GC_UNSAFE_MODE
;
82 char *name
= mono_string_to_utf8_checked_internal (str
, error
);
83 return_val_if_nok (error
, -1);
85 idx
= mono_dynstream_insert_string (sh
, name
);
91 mono_dynstream_add_data (MonoDynamicStream
*stream
, gconstpointer data
, guint32 len
)
93 MONO_REQ_GC_NEUTRAL_MODE
;
97 make_room_in_stream (stream
, stream
->index
+ len
);
98 memcpy (stream
->data
+ stream
->index
, data
, len
);
100 stream
->index
+= len
;
102 * align index? Not without adding an additional param that controls it since
103 * we may store a blob value in pieces.
109 mono_dynstream_add_zero (MonoDynamicStream
*stream
, guint32 len
)
111 MONO_REQ_GC_NEUTRAL_MODE
;
115 make_room_in_stream (stream
, stream
->index
+ len
);
116 memset (stream
->data
+ stream
->index
, 0, len
);
118 stream
->index
+= len
;
123 mono_dynstream_data_align (MonoDynamicStream
*stream
)
125 MONO_REQ_GC_NEUTRAL_MODE
;
127 guint32 count
= stream
->index
% 4;
129 /* we assume the stream data will be aligned */
131 mono_dynstream_add_zero (stream
, 4 - count
);