revolver

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

platform_string.c (8347B)


      1 //////////////////////////////////////////////////////////////////
      2 // platform_string.h
      3 
      4 //////////////////////////////////////////////////////////////////
      5 // char
      6 
      7 
      8 RV_READ_ONLY RV_INTERNAL u8 char_integer_symbol_reverse[128] = {
      9     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     10     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     11     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     12     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     13     0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     14     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     15     0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     16     0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
     17 };
     18 
     19 RV_GLOBAL bool32 rv_char_is_space(u8 c)
     20 {
     21     return c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f' || c == '\v';
     22 }
     23 
     24 RV_GLOBAL bool32 rv_char_is_upper(u8 c)
     25 {
     26     return 'A' <= c && c <= 'Z';
     27 }
     28 
     29 RV_GLOBAL bool32 rv_char_is_lower(u8 c)
     30 {
     31     return 'a' <= c && c <= 'z';
     32 }
     33 
     34 RV_GLOBAL bool32 rv_char_is_alpha(u8 c)
     35 {
     36     return rv_char_is_upper(c) || rv_char_is_lower(c);
     37 }
     38 
     39 RV_GLOBAL bool32 rv_char_is_slash(u8 c)
     40 {
     41     return c == '/' || c == '\\';
     42 }
     43 
     44 RV_GLOBAL bool32 rv_char_is_digit(u8 c, s32 base)
     45 {
     46     bool32 result = 0;
     47     if (base >= 0 && base <= 16) {
     48         u8 val = char_integer_symbol_reverse[c];
     49         if (val < base) {
     50             result = 1;
     51         }
     52     }
     53     return result;
     54 }
     55 
     56 RV_GLOBAL u8 rv_char_to_lower(u8 c)
     57 {
     58     if (rv_char_is_upper(c)) {
     59         c += ('a' - 'A');
     60     }
     61     return c;
     62 }
     63 
     64 RV_GLOBAL u8 rv_char_to_upper(u8 c)
     65 {
     66     if (rv_char_is_lower(c)) {
     67         c += ('A' - 'a');
     68     }
     69     return c;
     70 }
     71 
     72 RV_GLOBAL u8 rv_char_to_correct_slash(u8 c)
     73 {
     74     if(rv_char_is_slash(c)) {
     75         c = '/';
     76     }
     77     return c;
     78 }
     79 
     80 //////////////////////////////////////////////////////////////////
     81 // c strings
     82 
     83 RV_GLOBAL s64 rv_cstrlen(const char* c_str)
     84 {
     85     s64 res = 0;
     86     while (*c_str++) res++;
     87     return res;
     88 }
     89 
     90 //////////////////////////////////////////////////////////////////
     91 // constructors
     92 
     93 RV_GLOBAL rv_str8 rv_str8_range(u8* first, u8* one_past_last)
     94 {
     95     return rv_s8(first, (s64)(one_past_last - first));
     96 }
     97 
     98 
     99 //////////////////////////////////////////////////////////////////
    100 // conversions
    101 
    102 RV_GLOBAL s64 rv_sign_from_str8(rv_str8 string, rv_str8* string_tail)
    103 {
    104     // count negative signs
    105     u64 neg_count = 0;
    106     u64 i = 0;
    107     for (; i < string.len; i += 1) {
    108         if (string.str[i] == '-') {
    109             neg_count += 1;
    110         }
    111         else if (string.str[i] != '+') {
    112             break;
    113         }
    114     }
    115 
    116     // output part of string after signs
    117     *string_tail = rv_str8_skip(string, i);
    118 
    119     // output integer sign
    120     s64 sign = (neg_count & 1) ? -1 : +1;
    121     return sign;
    122 }
    123 
    124 
    125 RV_GLOBAL u64 rv_u64_from_str8(rv_str8 string, u32 radix)
    126 {
    127     u64 x = 0;
    128     if (1 < radix && radix <= 16) {
    129         for (u64 i = 0; i < string.len; i += 1) {
    130             x *= radix;
    131             x += char_integer_symbol_reverse[string.str[i]&0x7F];
    132         }
    133     }
    134     return x;
    135 }
    136 
    137 
    138 RV_GLOBAL s64 rv_s64_from_str8(rv_str8 string, s32 radix)
    139 {
    140     s64 sign = rv_sign_from_str8(string, &string);
    141     s64 x = (s64)rv_u64_from_str8(string, radix) * sign;
    142     return x;
    143 }
    144 
    145 RV_GLOBAL rv_str8 str8_from_s64(rv_arena* arena, s64 integer, s32 radix, u8 min_digits, u8 digit_group_separator);
    146 
    147 //////////////////////////////////////////////////////////////////
    148 // matching
    149 
    150 RV_GLOBAL bool32 rv_str8_match(rv_str8 a, rv_str8 b, rv_str8_match_flags flags)
    151 {
    152     bool32 result = 0;
    153     if (a.len == b.len || (flags & rv_str8_match_flag_right_side_sloppy)){
    154         bool32 case_insensitive = (flags & rv_str8_match_flag_case_insensetive);
    155         bool32 slash_insensitive = (flags & rv_str8_match_flag_slash_insensetive);
    156         s64 len = rv_min(a.len, b.len);
    157         result = 1;
    158         for (s64 i = 0; i < len; i += 1){
    159             u8 at = a.str[i];
    160             u8 bt = b.str[i];
    161             if (case_insensitive){
    162                 at = rv_char_to_upper(at);
    163                 bt = rv_char_to_upper(bt);
    164             }
    165             if (slash_insensitive){
    166                 at = rv_char_to_correct_slash(at);
    167                 bt = rv_char_to_correct_slash(bt);
    168             }
    169             if (at != bt){
    170                 result = 0;
    171                 break;
    172             }
    173         }
    174     }
    175     return result;
    176 }
    177 
    178 RV_GLOBAL s64 rv_str8_find_needle(rv_str8 string, s64 start_pos, rv_str8 needle, rv_str8_match_flags flags)
    179 {
    180     u8* p = string.str + start_pos;
    181     s64 stop_offset = rv_max(string.len + 1, needle.len) - needle.len;
    182     u8* stop_p = string.str + stop_offset;
    183 
    184     if (string.len > 0 && needle.len > 0) {
    185         u8* string_opl = string.str + string.len;
    186 
    187         rv_str8 needle_tail = rv_str8_skip(needle, 1);
    188         rv_str8_match_flags adjusted_flags = flags | rv_str8_match_flag_right_side_sloppy;
    189         u8 needle_first_rv_char_adjusted = needle.str[0];
    190 
    191         if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
    192             needle_first_rv_char_adjusted = rv_char_to_upper(needle_first_rv_char_adjusted);
    193         }
    194 
    195         for (;p < stop_p; p += 1) {
    196             u8 haystack_rv_char_adjusted = *p;
    197 
    198             if (adjusted_flags & rv_str8_match_flag_case_insensetive) {
    199                 haystack_rv_char_adjusted = rv_char_to_upper(haystack_rv_char_adjusted);
    200             }
    201 
    202             if (haystack_rv_char_adjusted == needle_first_rv_char_adjusted) {
    203                 if (rv_str8_match(rv_str8_range(p + 1, string_opl), needle_tail, adjusted_flags)) {
    204                     break;
    205                 }
    206             }
    207         }
    208     }
    209     s64 result = string.len;
    210     if (p < stop_p) {
    211         result = (s64)(p - string.str);
    212     }
    213     return result;
    214 }
    215 
    216 //////////////////////////////////////////////////////////////////
    217 // slicing
    218 
    219 RV_GLOBAL rv_str8 rv_str8_substr(rv_str8 str, rv_range range)
    220 {
    221     range.min = rv_min(range.min, str.len);
    222     range.max = rv_min(range.max, str.len);
    223     str.str += range.min;
    224     str.len = rv_range_diff(range);
    225     return str;
    226 }
    227 
    228 RV_GLOBAL rv_str8 rv_str8_prefix(rv_str8 str, s64 len)
    229 {
    230     str.len = rv_min(len, str.len);
    231     return str;
    232 }
    233 
    234 RV_GLOBAL rv_str8 rv_str8_skip(rv_str8 str, s64 amt)
    235 {
    236     amt = rv_min(amt, str.len);
    237     str.str += amt;
    238     str.len -= amt;
    239     return str;
    240 }
    241 
    242 RV_GLOBAL rv_str8 rv_str8_postfix(rv_str8 str, s64 len)
    243 {
    244     len = rv_min(len, str.len);
    245     str.str = (str.str + str.len) - len;
    246     str.len = len;
    247     return str;
    248 }
    249 
    250 RV_GLOBAL rv_str8 rv_str8_chop(rv_str8 str, s64 amt)
    251 {
    252     amt = rv_min(amt, str.len);
    253     str.len -= amt;
    254     return str;
    255 }
    256 
    257 RV_GLOBAL rv_str8 rv_str8_skip_chop_whitespace(rv_str8 string)
    258 {
    259     u8* first = string.str;
    260     u8* opl = first + string.len;
    261     for (;first < opl; first += 1) {
    262         if (!rv_char_is_space(*first)) {
    263             break;
    264         }
    265     }
    266     for (;opl > first;) {
    267         opl -= 1;
    268         if (!rv_char_is_space(*opl)) {
    269             opl += 1;
    270             break;
    271         }
    272     }
    273     rv_str8 result = rv_str8_range(first, opl);
    274     return result;
    275 }
    276 
    277 //////////////////////////////////////////////////////////////////
    278 // misc
    279 
    280 RV_GLOBAL rv_str8 rv_str8_copy(rv_arena* arena, rv_str8 s)
    281 {
    282     rv_str8 str;
    283     str.len = s.len;
    284     str.str = rv_push_array_no_zero(arena, u8, str.len + 1);
    285     rv_mem_copy(str.str, s.str, s.len);
    286     str.str[str.len] = 0;
    287     return str;
    288 }
    289 
    290 RV_GLOBAL rv_str8 rv_read_file(rv_arena* arena, rv_str8 filename)
    291 {
    292     u8* buffer = NULL;
    293     s64 len = 0;
    294 
    295     FILE* fp = NULL;
    296     {
    297         rv_temp_arena scratch = rv_scratch_begin((rv_arena*[]){arena}, 1);
    298         rv_str8 filename_copy = rv_str8_copy(scratch.arena, filename);
    299         fp = fopen((char*)filename_copy.str, "rb");
    300         rv_scratch_end(scratch);
    301     }
    302 
    303     if (fp) {
    304         fseek(fp, 0, SEEK_END);
    305         len = ftell(fp);
    306         fseek(fp, 0, SEEK_SET);
    307 
    308         buffer = rv_push_array_no_zero(arena, u8, len + 1);
    309         fread(buffer, 1, len, fp);
    310 
    311         fclose(fp);
    312     } else {
    313         fprintf(stderr, "rv_read_file, unable to rad file '%.*s' (%d: %s)\n", rv_s8v(filename), errno, strerror(errno));
    314         rv_unreachable();
    315     }
    316 
    317     return rv_s8(buffer, len);
    318 }