#include "../include/al/str.h" // https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/strtol.c;h=09d4333ed05f497ec00b7192204644349441e58d;hb=HEAD#l130 s64 al_str_to_long(str *s, u32 base, bool *error) { u64 ret = 0; u32 i = 0; bool neg = 0; while (al_isspace(al_str_at(s, i)) && i < s->length) { i++; } if (al_str_at(s, i) == '-') { neg = true; i++; } else if (al_str_at(s, i) == '+') { i++; } if (al_str_at(s, i) == '0' && ((base == 16 && (al_str_at(s, i + 1) == 'x' || al_str_at(s, i + 1) == 'X')) || (base == 2 && (al_str_at(s, i + 1) == 'b' || al_str_at(s, i + 1) == 'B')))) { i += 2; } u64 cutoff = neg ? ((u64)INT64_MAX + 1) : (u64)INT64_MAX; u64 add_limit = cutoff % base; cutoff /= base; *error = false; for (; i < s->length; i++) { uchar c = (uchar)al_str_at(s, i); if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'Z') c -= 'A' - 10; else if (c >= 'a' && c <= 'z') c -= 'a' - 10; else { // Character not valid for expressing a number. *error = true; break; } if (c >= base || ret > cutoff || (ret == cutoff && c > add_limit)) { // Either the character is invalid for the requested base or // attempting to add it would cause an overflow. *error = true; break; } ret = ret * base + c; } return neg ? -(s64)ret : (s64)ret; } bool al_str_get_line(str *buffer, char sep, str *line) { u32 bytes = 0; // line must be zero'd before calling get_line() for the first time. if (line->data == NULL) { *line = *buffer; } else { // Move to the start of the next line, if it exists. line->data += line->length + 1; if ((bytes = (u32)(line->data - buffer->data)) >= buffer->length) { // No more lines. return false; } } if ((bytes = buffer->length - bytes) == 0) { // buffer is completely empty. return false; } char *nl = (char *)al_memchr(line->data, sep, bytes); // If we couldn't find a separator, move to the end of the buffer. line->length = !nl ? bytes : (u32)(nl - line->data); return true; }