← source index

src/CSV.h

104 lines  ·  2.9 K  ·  cpp
#pragma once

#include "../Include.h"
#include "TickEntry.h"
#include "SlidingWindow.h"

template <std::size_t Size>
class CSV
{
public:
    CSV(const CSV&) = delete;
    CSV& operator=(const CSV&) = delete;

    CSV(CSV&&) = default;
    CSV& operator=(CSV&&) = default;

    explicit CSV(const std::string& file)
      : mFile(file, std::ios::binary)
      , mCurrentBufSize(0)
    {
        assert(mFile.is_open());
    }

    bool push(const TickEntry& tick, const SlidingWindowData& data)
    {
        if(!mFile.good()) return false;

        char tsBuf[32];
        char tradeIdBuf[32];
        char pxBuf[32];
        char meanBuf[32];
        char medianBuf[32];
        char lowBuf[32];
        char highBuf[32];

        size_t tsBufSize = Helper::parseNsTs(tick.mTsNano, tsBuf);
        auto [tradeIdEnd, tradeIdEc] = std::to_chars(tradeIdBuf, tradeIdBuf + sizeof(tradeIdBuf), tick.mTradeId);
        if(tradeIdEc != std::errc{}) return false;
        size_t tradeIdBufSize = static_cast<size_t>(tradeIdEnd - tradeIdBuf);
        size_t pxBufSize = Helper::parseFromPx(tick.mPrice, pxBuf);
        size_t meanBufSize = Helper::parseFromPx(data.mMean, meanBuf);
        size_t medianBufSize = Helper::parseFromPx(data.mMedian, medianBuf);
        size_t lowBufSize = Helper::parseFromPx(data.mLow, lowBuf);
        size_t highBufSize = Helper::parseFromPx(data.mHigh, highBuf);

        size_t totalSize = tsBufSize + tradeIdBufSize + pxBufSize +
                            meanBufSize + medianBufSize + lowBufSize +
                            highBufSize;

        const size_t rowSize = totalSize + 6 + 1;   // separators + newline
        assert(rowSize <= Size);
        if(mCurrentBufSize + rowSize > Size)
            flush();

        char* dst = mBuf + mCurrentBufSize;
        std::copy(tsBuf, tsBuf + tsBufSize, dst);
        dst += tsBufSize;
        *dst = ','; dst++;
        std::copy(tradeIdBuf, tradeIdBuf + tradeIdBufSize, dst);
        dst += tradeIdBufSize;
        *dst = ','; dst++;
        std::copy(pxBuf, pxBuf + pxBufSize, dst);
        dst += pxBufSize;
        *dst = ','; dst++;
        std::copy(meanBuf, meanBuf + meanBufSize, dst);
        dst += meanBufSize;
        *dst = ','; dst++;
        std::copy(medianBuf, medianBuf + medianBufSize, dst);
        dst += medianBufSize;
        *dst = ','; dst++;
        std::copy(lowBuf, lowBuf + lowBufSize, dst);
        dst += lowBufSize;
        *dst = ','; dst++;
        std::copy(highBuf, highBuf + highBufSize, dst);
        dst += highBufSize;

        *dst++ = '\n';
        mCurrentBufSize += rowSize;
        
        return true;
    }

    ~CSV()
    {
        flush();
        if(mFile.good()) mFile.close();
    }

private:
    void flush()
    {
        if(!mFile.good()) return;

        mFile.write(mBuf, mCurrentBufSize);
        mFile.flush();
        mCurrentBufSize = 0;
    }

private:
    std::ofstream mFile;
    size_t mCurrentBufSize;
    char mBuf[Size];
};