少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
 * \file
 * MonoDynamicStream
 * Copyright 2016 Microsoft
 *
 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
 
#include <config.h>
#include <glib.h>
 
#include "mono/metadata/dynamic-stream-internals.h"
#include "mono/metadata/metadata-internals.h"
#include "mono/utils/checked-build.h"
#include "mono/utils/mono-error-internals.h"
 
void
mono_dynstream_init (MonoDynamicStream *sh)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    sh->index = 0;
    sh->alloc_size = 4096;
    sh->data = (char *)g_malloc (4096);
    sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
    mono_dynstream_insert_string (sh, "");
}
 
static void
make_room_in_stream (MonoDynamicStream *stream, int size)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    if (size <= stream->alloc_size)
        return;
    
    while (stream->alloc_size <= size) {
        if (stream->alloc_size < 4096)
            stream->alloc_size = 4096;
        else
            stream->alloc_size *= 2;
    }
    
    stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
}
 
guint32
mono_dynstream_insert_string (MonoDynamicStream *sh, const char *str)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    guint32 idx;
    guint32 len;
    gpointer oldkey, oldval;
 
    if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
        return GPOINTER_TO_UINT (oldval);
 
    len = strlen (str) + 1;
    idx = sh->index;
    
    make_room_in_stream (sh, idx + len);
 
    /*
     * We strdup the string even if we already copy them in sh->data
     * so that the string pointers in the hash remain valid even if
     * we need to realloc sh->data. We may want to avoid that later.
     */
    g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
    memcpy (sh->data + idx, str, len);
    sh->index += len;
    return idx;
}
 
guint32
mono_dynstream_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
{
    MONO_REQ_GC_UNSAFE_MODE;
 
    error_init (error);
    char *name = mono_string_to_utf8_checked (str, error);
    return_val_if_nok (error, -1);
    guint32 idx;
    idx = mono_dynstream_insert_string (sh, name);
    g_free (name);
    return idx;
}
 
guint32
mono_dynstream_add_data (MonoDynamicStream *stream, const char *data, guint32 len)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    guint32 idx;
    
    make_room_in_stream (stream, stream->index + len);
    memcpy (stream->data + stream->index, data, len);
    idx = stream->index;
    stream->index += len;
    /* 
     * align index? Not without adding an additional param that controls it since
     * we may store a blob value in pieces.
     */
    return idx;
}
 
guint32
mono_dynstream_add_zero (MonoDynamicStream *stream, guint32 len)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    guint32 idx;
    
    make_room_in_stream (stream, stream->index + len);
    memset (stream->data + stream->index, 0, len);
    idx = stream->index;
    stream->index += len;
    return idx;
}
 
void
mono_dynstream_data_align (MonoDynamicStream *stream)
{
    MONO_REQ_GC_NEUTRAL_MODE;
 
    guint32 count = stream->index % 4;
 
    /* we assume the stream data will be aligned */
    if (count)
        mono_dynstream_add_zero (stream, 4 - count);
}