[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/Knowledgator/GLiNER.cpp/main/src/tokenizer_utils.cpp [Back]  [Original]

#define PCRE2_CODE_UNIT_WIDTH 8
#include 
#include 
#include 
#include 
#include "GLiNER/tokenizer_utils.hpp"

namespace gliner
{

    // RAII wrapper for PCRE2 resources
    class PCRE2Resource
    {
    private:
        pcre2_code *pattern_;
        pcre2_match_data *match_data_;

    public:
        PCRE2Resource() : pattern_(nullptr), match_data_(nullptr) {}

        ~PCRE2Resource()
        {
            if (match_data_)
                pcre2_match_data_free(match_data_);
            if (pattern_)
                pcre2_code_free(pattern_);
        }

        // Prevent copying
        PCRE2Resource(const PCRE2Resource &) = delete;
        PCRE2Resource &operator=(const PCRE2Resource &) = delete;

        void compilePattern(const char *pattern)
        {
            int errorcode;
            PCRE2_SIZE erroroffset;

            pattern_ = pcre2_compile(
                reinterpret_cast(pattern),
                PCRE2_ZERO_TERMINATED,
                PCRE2_UTF | PCRE2_UCP,
                &errorcode,
                &erroroffset,
                nullptr);

            if (!pattern_)
            {
                PCRE2_UCHAR buffer[256];
                pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
                throw std::runtime_error("PCRE2 compilation failed at offset " +
                                         std::to_string(erroroffset) + ": " +
                                         reinterpret_cast(buffer));
            }

            // Enable JIT compilation for better performance
            pcre2_jit_compile(pattern_, PCRE2_JIT_COMPLETE);

            match_data_ = pcre2_match_data_create_from_pattern(pattern_, nullptr);
            if (!match_data_)
            {
                throw std::runtime_error("Failed to create PCRE2 match data");
            }
        }

        pcre2_code *pattern() const { return pattern_; }
        pcre2_match_data *match_data() const { return match_data_; }
        PCRE2_SIZE *getOvectorPointer() const
        {
            return pcre2_get_ovector_pointer(match_data_);
        }
    };

    struct WhitespaceTokenSplitter::Implementation
    {
        PCRE2Resource pcre2;
    };

    std::string LoadBytesFromFile(const std::string &path)
    {
        std::ifstream fs(path, std::ios::in | std::ios::binary);
        if (!fs)
        {
            throw std::runtime_error("Cannot open file: " + path);
        }

        // More efficient file reading using a single allocation
        fs.seekg(0, std::ios::end);
        std::string data;
        data.reserve(fs.tellg());
        fs.seekg(0, std::ios::beg);

        data.assign(
            std::istreambuf_iterator(fs),
            std::istreambuf_iterator());

        return data;
    }

    WhitespaceTokenSplitter::WhitespaceTokenSplitter()
        : pimpl(std::make_unique())
    {
        pimpl->pcre2.compilePattern("\\w+(?:[-_]\\w+)*|\\S");
    }

    WhitespaceTokenSplitter::~WhitespaceTokenSplitter() = default;

    std::vector WhitespaceTokenSplitter::call(const std::string &text)
    {
        std::vector tokens;
        tokens.reserve(text.length() / 4); // Estimate initial capacity

        PCRE2_SIZE *ovector = pimpl->pcre2.getOvectorPointer();
        const size_t subject_length = text.length();
        size_t start_offset = 0;

        while (true)
        {
            int rc = pcre2_match(
                pimpl->pcre2.pattern(),
                reinterpret_cast(text.c_str()),
                subject_length,
                start_offset,
                PCRE2_NO_UTF_CHECK,
                pimpl->pcre2.match_data(),
                nullptr);

            if (rc < 0)
            {
                if (rc != PCRE2_ERROR_NOMATCH)
                {
                    throw std::runtime_error("PCRE2 matching error: " + std::to_string(rc));
                }
                break;
            }

            const size_t start = ovector[0];
            const size_t end = ovector[1];

            tokens.push_back({start,
                              end,
                              text.substr(start, end - start)});

            start_offset = end;
        }

        return tokens;
    }

}

Web Proxy Viewer  |  New URL  |  Original Page