Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/rcheevos/src/rc_util.c
4246 views
1
#include "rc_util.h"
2
3
#include "rc_compat.h"
4
#include "rc_error.h"
5
6
#include <stdlib.h>
7
#include <string.h>
8
9
#undef DEBUG_BUFFERS
10
11
/* --- rc_buffer --- */
12
13
void rc_buffer_init(rc_buffer_t* buffer)
14
{
15
buffer->chunk.write = buffer->chunk.start = &buffer->data[0];
16
buffer->chunk.end = &buffer->data[sizeof(buffer->data)];
17
buffer->chunk.next = NULL;
18
/* leave buffer->data uninitialized */
19
}
20
21
void rc_buffer_destroy(rc_buffer_t* buffer)
22
{
23
rc_buffer_chunk_t* chunk;
24
#ifdef DEBUG_BUFFERS
25
int count = 0;
26
int wasted = 0;
27
int total = 0;
28
#endif
29
30
/* first chunk is not allocated. skip it. */
31
chunk = buffer->chunk.next;
32
33
/* deallocate any additional buffers */
34
while (chunk)
35
{
36
rc_buffer_chunk_t* next = chunk->next;
37
#ifdef DEBUG_BUFFERS
38
total += (int)(chunk->end - chunk->start);
39
wasted += (int)(chunk->end - chunk->write);
40
++count;
41
#endif
42
#ifdef DEBUG_BUFFERS
43
printf("< free %p.%p\n", (void*)buffer, (void*)chunk);
44
#endif
45
free(chunk);
46
chunk = next;
47
}
48
49
#ifdef DEBUG_BUFFERS
50
printf("-- %d allocated buffers (%d/%d used, %d wasted, %0.2f%% efficiency)\n", count,
51
total - wasted, total, wasted, (float)(100.0 - (wasted * 100.0) / total));
52
#endif
53
}
54
55
uint8_t* rc_buffer_reserve(rc_buffer_t* buffer, size_t amount)
56
{
57
rc_buffer_chunk_t* chunk = &buffer->chunk;
58
size_t remaining;
59
while (chunk)
60
{
61
remaining = chunk->end - chunk->write;
62
if (remaining >= amount)
63
return chunk->write;
64
65
if (!chunk->next)
66
{
67
/* allocate a chunk of memory that is a multiple of 256-bytes. the first 32 bytes will be associated
68
* to the chunk header, and the remaining will be used for data.
69
*/
70
const size_t chunk_header_size = sizeof(rc_buffer_chunk_t);
71
const size_t alloc_size = (chunk_header_size + amount + 0xFF) & ~0xFF;
72
chunk->next = (rc_buffer_chunk_t*)malloc(alloc_size);
73
if (!chunk->next)
74
break;
75
76
#ifdef DEBUG_BUFFERS
77
printf("> alloc %p.%p\n", (void*)buffer, (void*)chunk->next);
78
#endif
79
80
chunk->next->start = (uint8_t*)chunk->next + chunk_header_size;
81
chunk->next->write = chunk->next->start;
82
chunk->next->end = (uint8_t*)chunk->next + alloc_size;
83
chunk->next->next = NULL;
84
}
85
86
chunk = chunk->next;
87
}
88
89
return NULL;
90
}
91
92
void rc_buffer_consume(rc_buffer_t* buffer, const uint8_t* start, uint8_t* end)
93
{
94
rc_buffer_chunk_t* chunk = &buffer->chunk;
95
do
96
{
97
if (chunk->write == start)
98
{
99
size_t offset = (end - chunk->start);
100
offset = (offset + 7) & ~7;
101
chunk->write = &chunk->start[offset];
102
103
if (chunk->write > chunk->end)
104
chunk->write = chunk->end;
105
break;
106
}
107
108
chunk = chunk->next;
109
} while (chunk);
110
}
111
112
void* rc_buffer_alloc(rc_buffer_t* buffer, size_t amount)
113
{
114
uint8_t* ptr = rc_buffer_reserve(buffer, amount);
115
rc_buffer_consume(buffer, ptr, ptr + amount);
116
return (void*)ptr;
117
}
118
119
char* rc_buffer_strncpy(rc_buffer_t* buffer, const char* src, size_t len)
120
{
121
uint8_t* dst = rc_buffer_reserve(buffer, len + 1);
122
memcpy(dst, src, len);
123
dst[len] = '\0';
124
rc_buffer_consume(buffer, dst, dst + len + 2);
125
return (char*)dst;
126
}
127
128
char* rc_buffer_strcpy(rc_buffer_t* buffer, const char* src)
129
{
130
return rc_buffer_strncpy(buffer, src, strlen(src));
131
}
132
133
/* --- other --- */
134
135
void rc_format_md5(char checksum[33], const uint8_t digest[16])
136
{
137
snprintf(checksum, 33, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
138
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7],
139
digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]
140
);
141
}
142
143
uint32_t rc_djb2(const char* input)
144
{
145
uint32_t result = 5381;
146
char c;
147
148
while ((c = *input++) != '\0')
149
result = ((result << 5) + result) + c; /* result = result * 33 + c */
150
151
return result;
152
}
153
154
const char* rc_error_str(int ret)
155
{
156
switch (ret) {
157
case RC_OK: return "OK";
158
case RC_INVALID_FUNC_OPERAND: return "Invalid function operand";
159
case RC_INVALID_MEMORY_OPERAND: return "Invalid memory operand";
160
case RC_INVALID_CONST_OPERAND: return "Invalid constant operand";
161
case RC_INVALID_FP_OPERAND: return "Invalid floating-point operand";
162
case RC_INVALID_CONDITION_TYPE: return "Invalid condition type";
163
case RC_INVALID_OPERATOR: return "Invalid operator";
164
case RC_INVALID_REQUIRED_HITS: return "Invalid required hits";
165
case RC_DUPLICATED_START: return "Duplicated start condition";
166
case RC_DUPLICATED_CANCEL: return "Duplicated cancel condition";
167
case RC_DUPLICATED_SUBMIT: return "Duplicated submit condition";
168
case RC_DUPLICATED_VALUE: return "Duplicated value expression";
169
case RC_DUPLICATED_PROGRESS: return "Duplicated progress expression";
170
case RC_MISSING_START: return "Missing start condition";
171
case RC_MISSING_CANCEL: return "Missing cancel condition";
172
case RC_MISSING_SUBMIT: return "Missing submit condition";
173
case RC_MISSING_VALUE: return "Missing value expression";
174
case RC_INVALID_LBOARD_FIELD: return "Invalid field in leaderboard";
175
case RC_MISSING_DISPLAY_STRING: return "Missing display string";
176
case RC_OUT_OF_MEMORY: return "Out of memory";
177
case RC_INVALID_VALUE_FLAG: return "Invalid flag in value expression";
178
case RC_MISSING_VALUE_MEASURED: return "Missing measured flag in value expression";
179
case RC_MULTIPLE_MEASURED: return "Multiple measured targets";
180
case RC_INVALID_MEASURED_TARGET: return "Invalid measured target";
181
case RC_INVALID_COMPARISON: return "Invalid comparison";
182
case RC_INVALID_STATE: return "Invalid state";
183
case RC_INVALID_JSON: return "Invalid JSON";
184
case RC_API_FAILURE: return "API call failed";
185
case RC_LOGIN_REQUIRED: return "Login required";
186
case RC_NO_GAME_LOADED: return "No game loaded";
187
case RC_HARDCORE_DISABLED: return "Hardcore disabled";
188
case RC_ABORTED: return "Aborted";
189
case RC_NO_RESPONSE: return "No response";
190
case RC_ACCESS_DENIED: return "Access denied";
191
case RC_INVALID_CREDENTIALS: return "Invalid credentials";
192
case RC_EXPIRED_TOKEN: return "Expired token";
193
case RC_INSUFFICIENT_BUFFER: return "Buffer not large enough";
194
case RC_INVALID_VARIABLE_NAME: return "Invalid variable name";
195
case RC_UNKNOWN_VARIABLE_NAME: return "Unknown variable name";
196
case RC_NOT_FOUND: return "Not found";
197
default: return "Unknown error";
198
}
199
}
200
201