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