2 * dynamic-stream.c: MonoDynamicStream
3 * Copyright 2016 Microsoft
5 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11 #include "mono/metadata/dynamic-stream-internals.h"
12 #include "mono/metadata/metadata-internals.h"
13 #include "mono/utils/checked-build.h"
14 #include "mono/utils/mono-error-internals.h"
17 mono_dynstream_init (MonoDynamicStream *sh)
19 MONO_REQ_GC_NEUTRAL_MODE;
22 sh->alloc_size = 4096;
23 sh->data = (char *)g_malloc (4096);
24 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
25 mono_dynstream_insert_string (sh, "");
29 make_room_in_stream (MonoDynamicStream *stream, int size)
31 MONO_REQ_GC_NEUTRAL_MODE;
33 if (size <= stream->alloc_size)
36 while (stream->alloc_size <= size) {
37 if (stream->alloc_size < 4096)
38 stream->alloc_size = 4096;
40 stream->alloc_size *= 2;
43 stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
47 mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str)
49 MONO_REQ_GC_NEUTRAL_MODE;
53 gpointer oldkey, oldval;
55 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
56 return GPOINTER_TO_UINT (oldval);
58 len = strlen (str) + 1;
61 make_room_in_stream (sh, idx + len);
64 * We strdup the string even if we already copy them in sh->data
65 * so that the string pointers in the hash remain valid even if
66 * we need to realloc sh->data. We may want to avoid that later.
68 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
69 memcpy (sh->data + idx, str, len);
75 mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
77 MONO_REQ_GC_UNSAFE_MODE;
79 mono_error_init (error);
80 char *name = mono_string_to_utf8_checked (str, error);
81 return_val_if_nok (error, -1);
83 idx = mono_dynstream_insert_string (sh, name);
89 mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len)
91 MONO_REQ_GC_NEUTRAL_MODE;
95 make_room_in_stream (stream, stream->index + len);
96 memcpy (stream->data + stream->index, data, len);
100 * align index? Not without adding an additional param that controls it since
101 * we may store a blob value in pieces.
107 mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len)
109 MONO_REQ_GC_NEUTRAL_MODE;
113 make_room_in_stream (stream, stream->index + len);
114 memset (stream->data + stream->index, 0, len);
116 stream->index += len;
121 mono_dynstream_data_align (MonoDynamicStream *stream)
123 MONO_REQ_GC_NEUTRAL_MODE;
125 guint32 count = stream->index % 4;
127 /* we assume the stream data will be aligned */
129 mono_dynstream_add_zero (stream, 4 - count);