PDF-Make

 view release on metacpan or  search on metacpan

src/pdfmake_markup.c  view on Meta::CPAN

            fail(s, line, col, "invalid UTF-8: truncated sequence");
            return 0;
        }

        {
            int i;
            for (i = 1; i <= extra; i++) {
                unsigned char cc = (unsigned char)p[i];
                if ((cc & 0xC0) != 0x80) {
                    fail(s, line, col,
                         "invalid UTF-8: byte 0x%02X is not a continuation", cc);
                    return 0;
                }
                cp = (cp << 6) | (cc & 0x3Fu);
            }
        }

        if ((extra == 1 && cp < 0x80) ||
            (extra == 2 && cp < 0x800) ||
            (extra == 3 && cp < 0x10000)) {
            fail(s, line, col, "invalid UTF-8: overlong encoding");
            return 0;
        }
        if (cp >= 0xD800 && cp <= 0xDFFF) {
            fail(s, line, col, "invalid UTF-8: encoded surrogate U+%04lX",
                 (unsigned long)cp);
            return 0;
        }
        if (cp > 0x10FFFF) {
            fail(s, line, col, "invalid UTF-8: code point above U+10FFFF");
            return 0;
        }

        p += extra + 1;
        col++;
    }
    return 1;
}

pdfmake_markup_doc_t *pdfmake_markup_parse(const char *src, size_t len) {
    pdfmake_markup_doc_t *doc;
    scan_t s;

    doc = (pdfmake_markup_doc_t *)calloc(1, sizeof(*doc));
    if (!doc) return NULL;
    doc->arena = pdfmake_arena_new();
    if (!doc->arena) { free(doc); return NULL; }
    doc->ok = 1;

    if (!src) { src = ""; len = 0; }

    s.p     = src;
    s.end   = src + len;
    s.line  = 1;
    s.col   = 1;
    s.doc   = doc;
    s.depth = 0;

    if (!validate_utf8(&s, s.p, s.end)) return doc;

    /* Skip a UTF-8 BOM: editors add it, and it is not the author's fault. */
    if (len >= 3 && (unsigned char)src[0] == 0xEF &&
        (unsigned char)src[1] == 0xBB && (unsigned char)src[2] == 0xBF) {
        s.p += 3;
    }

    skip_space(&s);
    while (!at_end(&s) && s.doc->ok && peek(&s) == '<' &&
           peek_at(&s, 1) == '!' && peek_at(&s, 2) == '-') {
        skip_comment(&s);
        skip_space(&s);
    }

    if (at_end(&s)) {
        if (doc->ok)
            fail(&s, 1, 1, "empty document: expected <doc>");
        return doc;
    }

    if (peek(&s) != '<') {
        fail(&s, s.line, s.col, "text outside <doc>");
        return doc;
    }

    {
        /* The root must be <doc>. Checking here rather than in parse_element
         * keeps the error specific: "expected <doc>" beats "unknown tag". */
        const char *q = s.p + 1;
        size_t qlen = 0;
        while (q + qlen < s.end && is_name_char(q[qlen])) qlen++;
        if (qlen != 3 || memcmp(q, "doc", 3) != 0) {
            fail(&s, s.line, s.col,
                 "the root element must be <doc>, found '<%.*s>'",
                 (int)(qlen > 32 ? 32 : qlen), q);
            return doc;
        }
    }

    {
        pdfmake_markup_node_t *holder =
            node_new(&s, PDFMAKE_MARKUP_ELEM, 1, 1);
        if (!holder) { fail(&s, 1, 1, "out of memory"); return doc; }
        holder->tag = PDFMAKE_MK_INVALID;
        parse_element(&s, holder);
        if (doc->ok) doc->root = holder->first_child;
    }

    if (doc->ok) {
        skip_space(&s);
        while (!at_end(&s) && peek(&s) == '<' && peek_at(&s, 1) == '!' &&
               peek_at(&s, 2) == '-') {
            skip_comment(&s);
            skip_space(&s);
        }
        if (!at_end(&s))
            fail(&s, s.line, s.col, "content after </doc>");
    }

    return doc;
}



( run in 5.046 seconds using v1.01-cache-2.11-cpan-8dfa8b56332 )