#include "cstr.h" /** DOC * @type function * @name string_length * * @param char *str * @return u64 * * @description * Computes the length of an `ASCII` cstr. */ u64 cstr_length(const char *str) { const char *p = str; while (*p) ++p; return p - str; } /** DOC * @type function * @name cstr_compare * * @param const char *a * @param const char *b * @return u8 * * @description * Compares two strings. * Returns 1 if a has a higher alphabethical value. * Returns -1 if a has a lower alphabethical value. * Returns 0 if strings are equal. */ i8 cstr_compare(const char *a, const char *b) { while (*a && *b) { if (*a < *b) return -1; if (*a > *b) return 1; ++a; ++b; } if (*a < *b) return -1; if (*a > *b) return 1; return 0; } /** DOC * @type function * @name cstr_split * * @param char *cstr * @param char split * @return u64 * * @description * Splits a string on every `split` char. * Returns the number of splits. * ``WARNING`` This function does replace all `split` char with `0`. * The old string does not exist after calling this function. */ u64 cstr_split(char *cstr, char split) { u64 splits = 1; while (*cstr) { if (*cstr == split) { *cstr = 0; ++splits; } ++cstr; } return splits; } /** DOC * @type function * @name cstr_split * * @param char *cstr * @param char split * @return u64 * * @description * Splits a string on every `split` char. * Returns the number of splits. * ``WARNING`` This function does replace all `split` char with `0`. * The old string does not exist after calling this function. */ u64 cstr_split_with_cancel(char *cstr, char split, char cancel) { u64 splits = 1; u8 is_in_cancel = 0; while (*cstr) { if (*cstr == cancel) { is_in_cancel = !is_in_cancel; } if (*cstr == split && !is_in_cancel) { *cstr = 0; ++splits; } ++cstr; } return splits; } /** DOC * @type function * @name next_split * * @param const char *previous; * @return const char* * * @description * Returns the next split of a `split list` created by `cstr_split`. */ const char *next_split(const char *previous) { while (*previous) ++previous; return previous + 1; } /** DOC * @type function * @name strip_front * * @param char *cstr * @param char strip * @return u64 * * @description * Remove `strip` from front. */ u64 strip_front(char *cstr, char strip) { char *front = cstr; while (*front && *front == strip) ++front; while (*front) { *cstr = *front; ++cstr; ++front; } while (*cstr) { *cstr = 0; ++cstr; } return front - cstr; } /** DOC * @type function * @name strip_back * * @param char *cstr * @param char stip * @return u64 * * @description * Removes `strip` char from back of the cstr. */ u64 strip_back(char *cstr, char strip) { u64 diff = 0; while (*cstr) ++cstr; --cstr; while (*cstr == strip) { *cstr = 0; ++diff; } return diff; } /** DOC * @type function * @name strip_cstr * * @param char *cstr * @param char strip * @return u64 * * @description * Strips `strip` char from start and end of the string. */ u64 strip_cstr(char *cstr, char strip) { return strip_front(cstr, strip) + strip_back(cstr, strip); } u64 number_of_lines(const char *cstr) { u64 lines = 0; while (*cstr) { if (*cstr == '\n') ++lines; ++cstr; } return lines; } substr_t getline(const char *cstr, u64 n) { substr_t line; line.begin = (char *)cstr; line.end = line.begin; while (*line.end && *line.end != '\n') ++line.end; for (int i = 0; i < n; ++i) line = nextline(line); return line; } substr_t nextline(substr_t line) { if (!(*line.end || *(line.end + 1))) { line.begin = 0; line.end = 0; return line; } line.begin = ++line.end; while (*line.end && *line.end != '\n') ++line.end; return line; } /* DOC * @type function * @name string_utf8_length * * @param char *str * @return u64 * * @description * Computes the length of a `UTF-8` cstr. */ u64 cstr_utf8_length(const char * str) { const char *p = str; u64 length = 0; int a = 0; while (*p) { next_utf8(&p); ++length; } return length; } /** DOC * @type function * @name next_utf8 * * @param char **c * @return u8 * * @description * Set `c` to the next `UTF-8` char. * Returns the difference relative to `ASCII` chars. */ u8 next_utf8(const char **c) { int a; switch (**c & 0xf0) { case 0xf0: a = 4; break; case 0xe0: a = 3; break; case 0xc0: a = 2; break; default: a = 1; break; } *c += a; return a; } /** DOC * @type function * @name previous_utf8 * * @param char **c * @return u8 * * @description * Set `c` to the previous `UTF-8` char. * Returns the difference relative to `ASCII` chars. */ u8 previous_utf8(const char **c) { int a = 1; --(*c); while ((**c & 0xc0) == 0x80) { --(*c); ++a; } return a; } /** DOC * @type function * @name u64_to_cstr * * @param u64 n * @param char *cstr * @param u64 length * * @description * Writes the string representation of `n` to the `cstr`. */ void u64_to_cstr(u64 n, char *cstr, u64 length) { char *p = cstr + length - 1; u64 d = 0; int i = 0; for (;n && i < length; ++i) { *(p--) = (n % 10) + '0'; n /= 10; } if (p == cstr + length - 1) { *(p--) = '0'; } *p = 0; d = p - cstr + 1; for (i = 0; i < length - d; ++i) cstr[i] = cstr[i + d]; } /** DOC * @type function * @name i64_to_cstr * * @param i64 n * @param char *cstr * @param u64 length * * @description * Writes the string representation of `n` to the `cstr`. */ void i64_to_cstr(i64 n, char *cstr, u64 length) { if (n < 0) { *cstr = '-'; n = -n; u64_to_cstr((u64)n, cstr + 1, length - 1); } else { u64_to_cstr((u64)n, cstr, length); } } /** DOC * @type function * @name cstr_to_u64 * * @param const char *cstr * @return u64 * * @description * Parses an `u64` to cstr. */ u64 cstr_to_u64(const char *cstr) { u64 n = 0; u64 e = 1; const char *p = cstr; while (*p) { if ((const unsigned char)(*p - '0') > 9) return 0; ++p; } --p; while (p >= cstr) { n += (*p - '0') * e; e *= 10; --p; } return n; } /** DOC * @type function * @name cstr_to_i64 */ i64 cstr_to_i64(const char *cstr) { i64 n = 0; if (*cstr == '-') { n = (i64)cstr_to_u64(cstr + 1); n = -n; } else { n = (i64)cstr_to_u64(cstr); } return n; }