duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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 }