std1.0.0-beta-7 SafeC docs

Source gui/gui_utf8.sc

View in the repository

// SafeC Standard Library — GUI: UTF-8 helpers (see gui_utf8.h).
#pragma once
#include <std/gui/gui_utf8.h>

namespace std {

// ── UTF-8 ─────────────────────────────────────────────────────────────────

unsigned int gui_utf8_next_n_(const &char s, unsigned long len, &unsigned long i) {
    unsafe {
        unsigned long p = *i;
        if (p >= len) { return 0U; }
        unsigned int c0 = (unsigned int)(unsigned char)s[p];
        if (c0 < 0x80U) { *i = p + 1UL; return c0; }
        int need = 0;
        unsigned int cp = 0U;
        if ((c0 & 0xE0U) == 0xC0U) { need = 1; cp = c0 & 0x1FU; }
        else if ((c0 & 0xF0U) == 0xE0U) { need = 2; cp = c0 & 0x0FU; }
        else if ((c0 & 0xF8U) == 0xF0U) { need = 3; cp = c0 & 0x07U; }
        else { *i = p + 1UL; return 0xFFFDU; }
        if (p + (unsigned long)need >= len) { *i = p + 1UL; return 0xFFFDU; }
        int k = 1;
        while (k <= need) {
            unsigned int c = (unsigned int)(unsigned char)s[p + (unsigned long)k];
            if ((c & 0xC0U) != 0x80U) { *i = p + 1UL; return 0xFFFDU; }
            cp = (cp << 6) | (c & 0x3FU);
            k = k + 1;
        }
        *i = p + 1UL + (unsigned long)need;
        if ((need == 1 && cp < 0x80U) || (need == 2 && cp < 0x800U) || (need == 3 && cp < 0x10000U) ||
            cp > 0x10FFFFU || (cp >= 0xD800U && cp <= 0xDFFFU)) {
            return 0xFFFDU;
        }
        return cp;
    }
}

unsigned int gui_utf8_next([]const char s_s, &unsigned long i) {
    unsigned long len = (unsigned long)s_s.len;
    char s_d_[1];
    const &char s = &s_d_[0];
    if (s_s.len > 0UL) { unsafe { s = (const &char)s_s.ptr; } }
    return gui_utf8_next_n_(s, len, i);
}

int gui_utf8_encode(unsigned int cp, &char out) {
    unsafe {
        if (cp < 0x80U) { out[0] = (char)cp; return 1; }
        if (cp < 0x800U) {
            out[0] = (char)(0xC0U | (cp >> 6));
            out[1] = (char)(0x80U | (cp & 0x3FU));
            return 2;
        }
        if (cp < 0x10000U) {
            out[0] = (char)(0xE0U | (cp >> 12));
            out[1] = (char)(0x80U | ((cp >> 6) & 0x3FU));
            out[2] = (char)(0x80U | (cp & 0x3FU));
            return 3;
        }
        if (cp > 0x10FFFFU) { cp = 0xFFFDU; return gui_utf8_encode(cp, out); }
        out[0] = (char)(0xF0U | (cp >> 18));
        out[1] = (char)(0x80U | ((cp >> 12) & 0x3FU));
        out[2] = (char)(0x80U | ((cp >> 6) & 0x3FU));
        out[3] = (char)(0x80U | (cp & 0x3FU));
        return 4;
    }
}

unsigned long gui_utf8_prev(const &char s, unsigned long i) {
    if (i == 0UL) { return 0UL; }
    unsafe {
        unsigned long p = i - 1UL;
        int steps = 0;
        while (p > 0UL && steps < 3 && (((unsigned int)(unsigned char)s[p]) & 0xC0U) == 0x80U) {
            p = p - 1UL;
            steps = steps + 1;
        }
        return p;
    }
}

} // namespace std