← index
ats/system/tee_streambuf.cpp
Source: ats/system/tee_streambuf.cpp
#include "tee_streambuf.hpp"
#include "code.hpp" 
#include <iostream>
#include <memory>

namespace interp {

    tee_streambuf::tee_streambuf(std::streambuf* sb1, std::streambuf* sb2)
        : sb1_(sb1), sb2_(sb2) {
        if (!sb1_ || !sb2_) {
            throw std::invalid_argument("Stream buffers cannot be null");
        }
    }

    std::streambuf::int_type tee_streambuf::overflow(int_type c) {
        if (traits_type::eq_int_type(c, traits_type::eof())) {
            return sync() == 0 ? traits_type::not_eof(c) : traits_type::eof();
        }
        bool eof1 = traits_type::eq_int_type(sb1_->sputc(c), traits_type::eof());
        bool eof2 = traits_type::eq_int_type(sb2_->sputc(c), traits_type::eof());
        if (eof1 || eof2) {
            return traits_type::eof();
        }
        return c;
    }

    int tee_streambuf::sync() {
        bool err1 = (sb1_->pubsync() == -1);
        bool err2 = (sb2_->pubsync() == -1);
        if (err1 || err2) {
            return -1; 
        }
        return 0; 
    }


    static std::unique_ptr<tee_streambuf> global_tee_sbuf = nullptr;
    static std::streambuf* original_interp_sbuf = nullptr;

    void setup_tee_for_interp_stream() {
        if (!global_tee_sbuf) {
            original_interp_sbuf = interp::stream.rdbuf();
            global_tee_sbuf = std::make_unique<tee_streambuf>(original_interp_sbuf, std::cout.rdbuf());
            static_cast<std::ostream&>(interp::stream).rdbuf(global_tee_sbuf.get());
        }
    }

    void cleanup_tee_for_interp_stream() {
        if (global_tee_sbuf && original_interp_sbuf) {
            static_cast<std::ostream&>(interp::stream).rdbuf(original_interp_sbuf);
            global_tee_sbuf.reset();
            original_interp_sbuf = nullptr;
        }
    }

}