haqumei 0.3.1

Haqumei is a Japanese Grapheme-to-Phoneme (G2P) library implemented in Rust.
Documentation
#include <iostream>
#include <streambuf>
#include <string>

extern "C" void haqumei_rust_print(const char* msg, int is_stderr);

class RustLogBuf : public std::streambuf {
private:
    std::string buffer;
    int is_stderr;

    void flush_to_rust() {
        if (!buffer.empty()) {
            haqumei_rust_print(buffer.c_str(), is_stderr);
            buffer.clear();
        }
    }

protected:
    virtual int_type overflow(int_type c) override {
        if (c != traits_type::eof()) {
            char ch = traits_type::to_char_type(c);
            if (ch == '\n') {
                flush_to_rust();
            } else {
                buffer += ch;
            }
        }
        return c;
    }

    virtual std::streamsize xsputn(const char* s, std::streamsize n) override {
        for (std::streamsize i = 0; i < n; ++i) {
            if (s[i] == '\n') {
                flush_to_rust();
            } else {
                buffer += s[i];
            }
        }
        return n;
    }

    virtual int sync() override {
        return 0;
    }

public:
    RustLogBuf(int is_stderr) : is_stderr(is_stderr) {}
    virtual ~RustLogBuf() {
        flush_to_rust();
    }
};

static std::streambuf* orig_cout_buf = nullptr;
static std::streambuf* orig_cerr_buf = nullptr;
static RustLogBuf* rust_cout_buf = nullptr;
static RustLogBuf* rust_cerr_buf = nullptr;

extern "C" void setup_cpp_redirect() {
    if (!rust_cout_buf) {
        rust_cout_buf = new RustLogBuf(0);
        orig_cout_buf = std::cout.rdbuf(rust_cout_buf);
    }
    if (!rust_cerr_buf) {
        rust_cerr_buf = new RustLogBuf(1);
        orig_cerr_buf = std::cerr.rdbuf(rust_cerr_buf);
    }
}

extern "C" void teardown_cpp_redirect() {
    if (rust_cout_buf) {
        std::cout.rdbuf(orig_cout_buf);
        delete rust_cout_buf;
        rust_cout_buf = nullptr;
    }
    if (rust_cerr_buf) {
        std::cerr.rdbuf(orig_cerr_buf);
        delete rust_cerr_buf;
        rust_cerr_buf = nullptr;
    }
}