int str_time(char *str, ulong time) { ulong secs = (time /= 1000000ULL) % 60ULL; ulong mins = (time /= 60ULL) % 60ULL; ulong hrs = (time /= 60ULL) % 24ULL; time /= 24ULL; return time ? sprintf(str, "%dD+%02d:%02d:%02d", time, hrs, mins, secs) : sprintf(str, "%02d:%02d:%02d", hrs, mins, secs); } int str_mtime(char *str, ulong time) { int pos = str_time(str, time); return pos + sprintf(str+pos, ".%03d", (time / 1000ULL) % 1000ULL); } int str_utime(char *str, ulong time) { int pos = str_time(str, time); return pos + sprintf(str+pos, ".%03d+%03d", (time / 1000ULL) % 1000ULL, time % 1000ULL); } int str_strip(const char *str, char *buf, int size, int len, char newl, char tab, char unk) { int off = 0; int pos = 0; char c; while(((len < 0) || (off < len)) && (c = str[off++]) && (pos < size - 1)) { if(c == '\n') { buf[pos++] = newl; if(!newl) { return pos - 1; } } else if((c == '\t') && tab) { for(int z = 0; (z < 4) && (pos < size - 1); z++) buf[pos++] = tab; } else if(c == CHR_UNK) { if(unk) buf[pos++] = unk; } else if((c < 0) || (c >= CHR_SPC)) { buf[pos++] = c; } } buf[pos] = 0; return pos; } // void str_stripq(char *str) { // char c; // int pos = 0; // while(c = str[pos]) { // if((c >= 0) && (c < CHR_SPC)) { // str[pos] = '\x1f'; // } // pos++; // } // } uint utf_read(const char **ptr) { uint ch; byte utf; char c = *((*ptr)++); for(utf = 0; (utf < 6) && (c & (0x80 >> utf)); utf++) { ; } if(utf == 1) return CHR_UNK; for(ch = ((!utf) || ((((uint)c) << 6) | (((**ptr) & 0x3f) & ~(0xff >> utf)))) ? (c & (0x7f >> utf)) : 0; utf > 1; utf--) { if(((c = **ptr) & 0xc0) == 0x80) { // if(ch) { ch <<= 6; ch |= c & 0x3f; // } } else { return c ? CHR_UNK : 0; } (*ptr)++; } // fprintf(stderr, "%d / %c\n", ch, ch); return (utf && !ch) ? CHR_UNK : ch; } uint utf_readn(const char *ptr, int *pos) { const char *str = &ptr[*pos]; uint ch = utf_read(&str); *pos = (int)(str-ptr); return ch; } byte utf_write(char **ptr, int *len, uint ch) { uint test; uint mask = 0xffffff80; char utf; char c; if(ch & 0x80000000) { return 1; } for(utf = 0; ch & mask & ~(test = (0xffffffff << ((utf + 1) * 6 + (5 - utf)))); utf++) { mask &= test; } // fprintf(stderr, "%d\n", utf); if(utf + 1 >= (*len)) { return 0; } (*len) -= utf + 1; *((*ptr)++) = utf ? (~(0x7f >> utf) | (((uint)(ch >> (utf * 6))) & (0x3f >> utf))) : ch; for(--utf; utf >= 0; utf--) { *((*ptr)++) = 0x80 | (((uint)(ch >> (utf * 6))) & 0x3f); } return 1; } byte utf_rwriten(char *ptr, int *pos, int len, uint ch) { char *str = &ptr[*pos]; len -= (*pos); byte res = utf_write(&str, &len, ch); *pos = (int)(str-ptr); return res; } uint utf_rread(const char **ptr, const char *start) { const char *tp = *ptr; uint ch; char c; do { if(tp == start) return 0; tp--; } while(((c = (*tp)) & 0xc0) == 0x80); *ptr = tp; return (ch = utf_read(&tp)) ? ch : CHR_UNK; } uint utf_rreadn(const char *ptr, int *pos) { const char *str = &ptr[*pos]; uint ch = utf_rread(&str, ptr); *pos = (int)(str-ptr); return ch; } int utf_len(const char *str) { int len; for(len = 0; utf_read(&str); len++) { ; } return len; } char str_lower(char c) { return ((c >= 'A') && (c <= 'Z')) ? (c + 32) : c; } char str_upper(char c) { return ((c >= 'a') && (c <= 'z')) ? (c - 32) : c; } byte str_eq_lower(const char *str1, const char *str2) { int pos = 0; char c; while(c = str_lower(str1[pos])) { if(str_lower(str2[pos++]) != c) return 0; } return str2[pos] ? 0 : 1; } int str_cmp_lower(const char *str1, const char *str2) { int pos = 0; char c; while(c = str_lower(str2[pos])) { if(str_lower(str1[pos++]) != c) return 0; } return str1[pos] ? pos : 0x7fffffff; } byte str_parse_int(const char *str, int *value, int base) { char c; byte tbase = 0; int pos = 0; int digits = 0; long v = 0; long nbase = base ? (base < 0 ? -base : base) : 10; long nsign = 1; while(c = str_lower(str[pos++])) { if(pos == 1 && ((c == '+') || ((c == '-') && (base >= 0)))) nsign = (c == '+') ? 1 : -1; else if(pos == 1 && c == '0') { tbase = 1; digits++; } else if(tbase && pos == 2 && c == 'x') { nbase = 16; digits--; } else if(((nbase == 16) && (c >= 'a' && c <= 'f')) || (c >= '0' && c <= '9')) { v *= nbase; v += ((long)((c >= '0' && c <= '9') ? (c - '0') : (10 + (c - 'a')))); digits++; } else return 0; } if(!digits) return 0; v *= nsign; // errno = 0; // long v = strtol(str, NULL, (base < 0) ? -base : base); if((base < 0) ? (v < 0LL || v > 0xffffffffLL) : (v < -0x80000000LL || v > 0x7fffffffLL)) { return 0; } *value = (int)((base < 0) ? (v & 0xffffffff) : (((v >> 32) & 0x80000000) | (v & 0x7fffffff))); return 1; } byte str_parse_enum(const char *str, const char **names, int states, int *value) { int comp; int max = 0; int best = 0; if(str_parse_int(str, &comp, 0) && (comp >= 0) && (comp < states)) { *value = comp; return 1; } for(int z = 0; z < states; z++) { if((comp = str_cmp_lower(names[z], str)) > best) { max = comp; best = z; } } if(max) { *value = best; return 1; } return 0; } // char char_to_dc32(char c) { // // }