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

cubeb_strings.c (2859B)


      1 /*
      2  * Copyright © 2011 Mozilla Foundation
      3  *
      4  * This program is made available under an ISC-style license.  See the
      5  * accompanying file LICENSE for details.
      6  */
      7 
      8 #include "cubeb_strings.h"
      9 
     10 #include <assert.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 
     14 #define CUBEB_STRINGS_INLINE_COUNT 4
     15 
     16 struct cubeb_strings {
     17   uint32_t size;
     18   uint32_t count;
     19   char ** data;
     20   char * small_store[CUBEB_STRINGS_INLINE_COUNT];
     21 };
     22 
     23 int
     24 cubeb_strings_init(cubeb_strings ** strings)
     25 {
     26   cubeb_strings * strs = NULL;
     27 
     28   if (!strings) {
     29     return CUBEB_ERROR;
     30   }
     31 
     32   strs = calloc(1, sizeof(cubeb_strings));
     33   assert(strs);
     34 
     35   if (!strs) {
     36     return CUBEB_ERROR;
     37   }
     38 
     39   strs->size = sizeof(strs->small_store) / sizeof(strs->small_store[0]);
     40   strs->count = 0;
     41   strs->data = strs->small_store;
     42 
     43   *strings = strs;
     44 
     45   return CUBEB_OK;
     46 }
     47 
     48 void
     49 cubeb_strings_destroy(cubeb_strings * strings)
     50 {
     51   char ** sp = NULL;
     52   char ** se = NULL;
     53 
     54   if (!strings) {
     55     return;
     56   }
     57 
     58   sp = strings->data;
     59   se = sp + strings->count;
     60 
     61   for (; sp != se; sp++) {
     62     if (*sp) {
     63       free(*sp);
     64     }
     65   }
     66 
     67   if (strings->data != strings->small_store) {
     68     free(strings->data);
     69   }
     70 
     71   free(strings);
     72 }
     73 
     74 /** Look for string in string storage.
     75     @param strings Opaque pointer to interned string storage.
     76     @param s String to look up.
     77     @retval Read-only string or NULL if not found. */
     78 static char const *
     79 cubeb_strings_lookup(cubeb_strings * strings, char const * s)
     80 {
     81   char ** sp = NULL;
     82   char ** se = NULL;
     83 
     84   if (!strings || !s) {
     85     return NULL;
     86   }
     87 
     88   sp = strings->data;
     89   se = sp + strings->count;
     90 
     91   for (; sp != se; sp++) {
     92     if (*sp && strcmp(*sp, s) == 0) {
     93       return *sp;
     94     }
     95   }
     96 
     97   return NULL;
     98 }
     99 
    100 static char const *
    101 cubeb_strings_push(cubeb_strings * strings, char const * s)
    102 {
    103   char * is = NULL;
    104 
    105   if (strings->count == strings->size) {
    106     char ** new_data;
    107     uint32_t value_size = sizeof(char const *);
    108     uint32_t new_size = strings->size * 2;
    109     if (!new_size || value_size > (uint32_t)-1 / new_size) {
    110       // overflow
    111       return NULL;
    112     }
    113 
    114     if (strings->small_store == strings->data) {
    115       // First time heap allocation.
    116       new_data = malloc(new_size * value_size);
    117       if (new_data) {
    118         memcpy(new_data, strings->small_store, sizeof(strings->small_store));
    119       }
    120     } else {
    121       new_data = realloc(strings->data, new_size * value_size);
    122     }
    123 
    124     if (!new_data) {
    125       // out of memory
    126       return NULL;
    127     }
    128 
    129     strings->size = new_size;
    130     strings->data = new_data;
    131   }
    132 
    133   is = strdup(s);
    134   strings->data[strings->count++] = is;
    135 
    136   return is;
    137 }
    138 
    139 char const *
    140 cubeb_strings_intern(cubeb_strings * strings, char const * s)
    141 {
    142   char const * is = NULL;
    143 
    144   if (!strings || !s) {
    145     return NULL;
    146   }
    147 
    148   is = cubeb_strings_lookup(strings, s);
    149   if (is) {
    150     return is;
    151   }
    152 
    153   return cubeb_strings_push(strings, s);
    154 }