Skip to content
wangjunbo4Public

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

tablio

Zero-annotation C++ serialization library for CSV and Parquet, powered by static reflection (Boost.PFR).

Define plain structs — no macros, no code generators, no base classes. tablio derives field names, types, and counts at compile time, then reads/writes tabular files automatically.

Features

  • Zero boilerplate — plain aggregate structs, no annotations required
  • Compile-time reflection — field names and types resolved via boost::pfr
  • CSV — header-aware reader/writer with column-name matching (order-independent)
  • Parquet — automatic Arrow schema generation with ZSTD compression
  • Array support — std::vector<T>, std::array<T,N>, and C-style arrays (pipe-delimited in CSV)
  • Expandable columns — customize how array fields map to CSV columns (collapsed or expanded)
  • Enum support — automatic conversion via underlying type

Quick Start

#include "tablio/io.h"

struct Person {
    int         id;
    std::string name;
    double      score;
};

// Write
std::vector<Person> people = {{1, "Alice", 95.5}, {2, "Bob", 87.3}};
io::CsvWriter<Person>::write("people.csv", people);
io::ParquetWriter<Person>::write("people.parquet", people);

// Read (column-name matching, order-independent)
auto from_csv = io::CsvReader<Person>::read("people.csv");
auto from_pq  = io::ParquetReader<Person>::read("people.parquet");

Requirements

Dependency Version Notes
C++ ≥ 20 C++23 recommended
Apache Arrow ≥ 10.0 libarrow.a, libparquet.a and bundled deps
Boost.PFR 2.2.0 Header-only, bundled in pfr/

Build Integration

CMake

include_directories(tablio/ tablio/pfr/)
target_link_libraries(your_target
    ${ARROW_LIBS} ${PARQUET_LIBS}
)

Command Line

g++ -std=c++23 -I tablio/ -I tablio/pfr/ \
    your_code.cpp \
    -lparquet -larrow -larrow_bundled_dependencies \
    -lsnappy -lre2 -lpthread -ldl -lz

Supported Types

C++ Type CSV Serialization Arrow / Parquet Type
int std::from_chars / std::format int32
long long std::from_chars / std::format int64
float std::from_chars / std::format float32
double std::from_chars / std::format float64
bool "1" / "true" ↔ 0 / 1 boolean
std::string direct utf8
enum via underlying type same as underlying
std::vector<T> pipe-delimited (|) list<T>
std::array<T, N> pipe-delimited (|) list<T>
T[N] (C array) pipe-delimited (|) list<T>

T can be any of the scalar types above. Unsupported types produce compile-time errors.

Array Fields

Array fields are pipe-delimited in CSV by default:

struct Trade {
    int                     id;
    std::vector<int>        prices;    // "100|200|300" in CSV
    std::array<float, 3>    factors;   // "0.1|0.2|0.3" in CSV
};

Expanded Column Mode

Flatten std::array fields into multiple CSV columns instead of a single pipe-delimited column:

struct Tick {
    int                  id;
    std::array<float, 5> askPrices;
    std::array<float, 5> bidPrices;
};

// Expand askPrices into askPrices1..askPrices5, keep bidPrices collapsed
template <>
struct io::field_handler<Tick, 1> : io::expanded_array_handler<Tick, 1> {};

Custom Column Names

Override column naming entirely for full control:

template <>
struct io::field_handler<CustomTick, 1> {
    using field_type = std::array<float, 5>;
    static constexpr std::size_t column_count = 5;

    static std::string column_name(std::size_t i) {
        return std::format("price_{}", i + 1);
    }
    static std::string to_string(const CustomTick& obj, std::size_t i) {
        return io::field_to_string(boost::pfr::get<1>(obj)[i]);
    }
    static void from_string(CustomTick& obj, std::string_view sv, std::size_t i) {
        io::string_to_field(sv, boost::pfr::get<1>(obj)[i]);
    }
};

Struct Requirements

Structs must be simple aggregate types:

  • No base classes
  • No user-defined constructors (or = default)
  • No const members
  • No reference members
  • No C-style arrays for get_name support (use std::array<T, N> instead)
  • Defined at global or namespace scope (not in anonymous namespaces or function-local)

API Reference

CsvWriter<T>

static void write(const std::filesystem::path& path, const std::vector<T>& data);

Writes a header row with field names, then one row per record. Numeric types use std::format("{}", val).

CsvReader<T>

static std::vector<T> read(const std::filesystem::path& path);

Reads the header row to map column names to struct fields (order-independent). Missing columns keep default values. Numeric types use std::from_chars.

ParquetWriter<T>

// Default options (ZSTD level 6, 1M rows per row group)
static void write(const std::filesystem::path& path, const std::vector<T>& data);

// Custom options
static void write(const std::filesystem::path& path, const std::vector<T>& data,
                  const ParquetOptions& opts);

Derives Arrow schema from field types at compile time, builds arrays, and writes Parquet.

ParquetOptions

Field Type Default Description
compression parquet::Compression::type ZSTD Compression codec (ZSTD, SNAPPY, GZIP, LZ4, etc.)
compression_level int 6 Compression level (codec-dependent)
row_group_size int64_t 1048576 (1M) Rows per row group — larger values improve compression and scan efficiency for large files

Example:

io::ParquetOptions opts;
opts.compression       = parquet::Compression::ZSTD;
opts.compression_level = 9;
opts.row_group_size    = 5 * 1024 * 1024;  // 5M rows per batch
io::ParquetWriter<Tick>::write("large.parquet", data, opts);

ParquetReader<T>

static std::vector<T> read(const std::filesystem::path& path);

Opens a Parquet file, matches columns by name, and reads all rows into structs.

How It Works

Struct definition
    │
    ├── boost::pfr::tuple_size_v<T>     → field count (compile time)
    ├── boost::pfr::get_name<I, T>()    → field names (compile time)
    ├── boost::pfr::tuple_element_t     → field types (compile time)
    └── boost::pfr::for_each_field()    → field iteration (runtime)

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages