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
);