// returns # of characters in utf-8 string (excluding nul terminator) size_t String::utf8_len(const char *s) { if (s == nullptr) { throw ReferenceError(); } if (!*s) { return 0; } size_t n = 0; while(*s) { if ((*s & 0x80) == 0x80) { // negative value if ((*s & 0xe0) == 0xc0) { // 1 more byte s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; n++; } else { if ((*s & 0xf0) == 0xe0) { // 2 more bytes s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; n++; } else { if ((*s & 0xf8) == 0xf0) { // 3 more bytes s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } s++; n++; } else { throw StringEncodingError(); } } } } else { s++; n++; } } return n; }
void VbpValidator::processReference(Reference reference) { if (!reference.existsInRegistry()) { ReferenceError referenceError = ReferenceError(reference); this->referenceErrors.push_back(referenceError); } //TODO: include filepath checks }
void String::utf8_encode(const rune *r, char *s, size_t n) { if (r == nullptr || s == nullptr) { throw ReferenceError(); } if (!n) { throw ValueError(); } rune code; while(*r && n > 0) { code = *r; if (code < 0x80) { if (n <= 1) { throw StringEncodingError("String::utf8_encode(): buffer too small"); } *s++ = code; n--; } else { if (code < 0x800) { if (n <= 2) { throw StringEncodingError("String::utf8_encode(): buffer too small"); } *s++ = ((code & 0x7c0) >> 6) | 0xc0; *s++ = (code & 0x3f) | 0x80; n -= 2; } else { if ((code >= 0x800 && code < 0xd800) || (code >= 0xe000 && code < 0x10000)) { if (n <= 3) { throw StringEncodingError("String::utf8_encode(): buffer too small"); } *s++ = ((code & 0xf000) >> 12) | 0xe0; *s++ = ((code & 0xfc0) >> 6) | 0x80; *s++ = (code & 0x3f) | 0x80; n -= 3; } else { if (code > 0x10000 && code <= 0x10ffff) { if (n <= 4) { throw StringEncodingError("String::utf8_encode(): buffer too small"); } *s++ = ((code & 0x1c0000) >> 18) | 0xf0; *s++ = ((code & 0x3f000) >> 12) | 0x80; *s++ = ((code & 0xfc0) >> 6) | 0x80; *s++ = (code & 0x3f) | 0x80; n -= 4; } else { throw StringEncodingError(); } } }
void drop_privs(const char *username) { if (username == nullptr) { throw ReferenceError(); } struct passwd *pw = ::getpwnam(username); if (pw == nullptr) { char buf[256]; std::snprintf(buf, sizeof(buf), "failed to drop privileges: no such user '%s'", username); panic(buf); } drop_privs(pw->pw_uid, pw->pw_gid); }
// default argument sep = ' ' String String::join(const Array<String>& a, rune sep) const { if (!a.len()) { return String(); } // first calculate total size size_t rune_size = utf8_encoded_size(sep); size_t total = 0; const char *p; for(size_t i = 0; i < a.len(); i++) { p = a[i].c_str(); if (p == nullptr) { throw ReferenceError(); } total += std::strlen(p) + rune_size; } total -= rune_size; // make the joined string String s; s.grow(total + 1); s.s_data[0] = 0; if (a[0].s_data != nullptr) { std::strcpy(s.s_data, a[0].s_data); } rune r[2] = { sep, 0 }; char rs[5]; utf8_encode(r, rs, sizeof(rs)); for(size_t i = 1; i < a.len(); i++) { std::strcat(s.s_data, rs); if (a[i].s_data) { std::strcat(s.s_data, a[i].s_data); } } s.s_len = utf8_len(s.s_data); return s; }
void String::utf8_decode(const char *s, rune *r, size_t n) { if (s == nullptr || r == nullptr) { throw ReferenceError(); } if (!n) { throw ValueError(); } rune code; while(*s && n > 0) { if ((*s & 0x80) == 0x80) { // negative value if ((*s & 0xe0) == 0xc0) { // 1 more byte code = (*s & 0x1f) << 6; s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= (*s & 0x3f); s++; *r = code; r++; n--; } else { if ((*s & 0xf0) == 0xe0) { // 2 more bytes code = (*s & 0xf) << 12; s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= ((*s & 0x3f) << 6); s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= (*s & 0x3f); s++; *r = code; r++; n--; } else { if ((*s & 0xf8) == 0xf0) { // 3 more bytes code = (*s & 7) << 18; s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= ((*s & 0x3f) << 12); s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= ((*s & 0x3f) << 6); s++; if ((*s & 0xc0) != 0x80) { throw StringEncodingError(); } code |= (*s & 0x3f); s++; *r = code; r++; n--; } else { throw StringEncodingError(); } } } } else { *r = *s & 0x7f; r++; s++; n--; } } *r = 0; }