CSV API Reference
This page summarizes the public API exposed by rix/csv.
The documentation examples use the unified Rix facade:
#include <rix.hpp>and access CSV through:
rix.csvThe lower-level CSV types live under:
rixlib::csvUse the facade for application code.
Use lower-level types when you need explicit table, row, or options types.
Facade entry point
The CSV module is mounted at:
rix.csvCommon usage:
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
const auto output = rix.csv.write(table);Headers
Recommended public header:
#include <rix.hpp>Independent package header:
#include <rix/csv.hpp>Use <rix.hpp> when you want the unified facade:
rix.csv
rix.debug
rix.auth
rix.pdfUse <rix/csv.hpp> when you want only the CSV package.
Namespace
CSV types live in:
rixlib::csvCommon types:
rixlib::csv::Table
rixlib::csv::Row
rixlib::csv::Optionsrix.csv
rix.csv exposes the public CSV module.
It provides the main CSV operations:
parse(...)
write(...)
version()
version_major()
version_minor()
version_patch()
version_number()parse
Table parse(std::string_view input) const;Parses CSV text into a table.
Example:
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n");Read values:
rix.debug.print(table[0][0]);
rix.debug.print(table[1][0]);For the example above:
table[0][0] -> name
table[0][1] -> language
table[1][0] -> Ada
table[1][1] -> C++parse with options
Table parse(
std::string_view input,
const Options &options) const;Parses CSV text with custom options.
Example:
rixlib::csv::Options options;
options.field_transformer = [](std::string value) {
if (value == "Vix")
{
return std::string{"Vix.cpp"};
}
return value;
};
const auto table = rix.csv.parse(input, options);Use options when parsing should transform fields or filter rows.
write
std::string write(const Table &table) const;Writes a table into CSV text.
Example:
rixlib::csv::Table table;
table.push_back({"name", "language"});
table.push_back({"Ada", "C++"});
table.push_back({"Gaspard", "Vix"});
const auto output = rix.csv.write(table);
rix.debug.print(output);Expected output:
name,language
Ada,C++
Gaspard,VixUse write instead of building CSV manually.
The writer handles CSV escaping for commas, quotes, and newlines.
Table
A Table represents CSV rows.
Conceptually:
Table
-> Row
-> FieldCommon usage:
rixlib::csv::Table table;
table.push_back({"name", "language"});
table.push_back({"Ada", "C++"});A table can be iterated:
for (const auto &row : table)
{
for (const auto &field : row)
{
rix.debug.print(field);
}
}A table can be indexed:
rix.debug.print(table[0][0]);Check that the table is not empty before indexing:
if (!table.empty())
{
rix.debug.print(table[0][0]);
}Row
A Row represents one CSV row.
A row contains fields.
Common usage:
rixlib::csv::Row row;
row.push_back("Ada");
row.push_back("C++");Rows are normally created directly inside a table:
table.push_back({"Ada", "C++"});A row can be iterated:
for (const auto &field : row)
{
rix.debug.print(field);
}A row can be indexed:
rix.debug.print(row[0]);Check row size before indexing external CSV data:
if (row.size() >= 2)
{
rix.debug.print(row[0], row[1]);
}Field values
A field is represented as a string value.
Example:
const auto table = rix.csv.parse("name,language\nAda,C++\n");
const std::string name = table[1][0];
const std::string language = table[1][1];CSV values are text.
If your application needs numbers, booleans, dates, or custom types, parse those values after reading the field.
Options
Options customizes parsing behavior.
Create an options object:
rixlib::csv::Options options;Pass it to parsing:
const auto table = rix.csv.parse(input, options);Options::field_transformer
A field transformer receives one field value and returns the value that should be stored in the parsed table.
Example:
options.field_transformer = [](std::string value) {
if (value == "Vix")
{
return std::string{"Vix.cpp"};
}
return value;
};Use it for:
normalizing values
trimming spaces
renaming imported values
mapping old values to new values
small parse-time cleanupExample trim-style transformer:
options.field_transformer = [](std::string value) {
while (!value.empty() && value.front() == ' ')
{
value.erase(value.begin());
}
while (!value.empty() && value.back() == ' ')
{
value.pop_back();
}
return value;
};Options::row_filter
A row filter receives a parsed row and decides whether it should be kept.
Example:
options.row_filter = [](const rixlib::csv::Row &row) {
if (!row.empty() && row[0] == "Skip")
{
return false;
}
return true;
};Return:
true -> keep the row
false -> remove the rowUse it for:
skipping empty rows
skipping comment rows
removing invalid rows
filtering imported dataComplete options example
#include <rix.hpp>
#include <string>
int main()
{
const std::string input =
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n"
"Skip,Ignored\n";
rixlib::csv::Options options;
options.field_transformer = [](std::string value) {
if (value == "Vix")
{
return std::string{"Vix.cpp"};
}
return value;
};
options.row_filter = [](const rixlib::csv::Row &row) {
if (!row.empty() && row[0] == "Skip")
{
return false;
}
return true;
};
const auto table = rix.csv.parse(input, options);
rix.debug.print("rows:", table.size());
return 0;
}Version helpers
The CSV module exposes package version helpers.
std::string version() const;
int version_major() const noexcept;
int version_minor() const noexcept;
int version_patch() const noexcept;
int version_number() const noexcept;Example:
auto version = rix.csv.version();
rix.debug.print("csv version:", version);Use these helpers in diagnostics, examples, or compatibility checks.
Parse pattern
Use this pattern when reading CSV from trusted small input:
const auto table = rix.csv.parse(input);
for (const auto &row : table)
{
for (const auto &field : row)
{
rix.debug.print(field);
}
}Use this pattern when reading external input:
const auto table = rix.csv.parse(input);
if (table.empty())
{
rix.debug.eprint("CSV is empty");
return 1;
}
for (std::size_t i = 1; i < table.size(); ++i)
{
const auto &row = table[i];
if (row.size() < 2)
{
rix.debug.eprint("invalid row:", i);
continue;
}
rix.debug.print("name:", row[0]);
rix.debug.print("language:", row[1]);
}Write pattern
Use this pattern when generating CSV:
rixlib::csv::Table table;
table.push_back({"name", "project"});
table.push_back({"Ada", "Rix"});
table.push_back({"Gaspard", "Vix.cpp"});
const auto output = rix.csv.write(table);Save it with normal C++ file output:
#include <fstream>
std::ofstream file("report.csv");
if (!file)
{
rix.debug.eprint("failed to open report.csv");
return 1;
}
file << output;CSV escaping behavior
When writing CSV, fields that need escaping should be quoted.
Examples:
Hello, world
She said "hello"
line one
line twoExpected CSV-safe output shape:
"Hello, world"
"She said ""hello"""
"line one
line two"Use rix.csv.write(table) instead of manual string concatenation.
Header convention
CSV headers are normal rows.
If your CSV has a header, treat the first row as the header:
const auto &header = table[0];Then process data rows from index 1:
for (std::size_t i = 1; i < table.size(); ++i)
{
const auto &row = table[i];
}If your CSV has no header, process every row as data:
for (const auto &row : table)
{
rix.debug.print(row.size());
}Single-file usage
For quick examples:
vix run csv.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run csv.cppProject usage
For a Vix project, add Rix:
vix add rix/rix
vix installIn vix.app:
deps = [
"rix/rix",
]A small manifest can look like this:
name = "csv-app"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]Build and run:
vix build
vix runIndependent package usage
If the project only needs CSV, install:
vix add rix/csv
vix installIn vix.app:
deps = [
"rix/csv",
]Then include:
#include <rix/csv.hpp>Use this style when you do not need the unified rix.* facade.
Lightweight facade usage
If you want the unified facade but only want CSV mounted:
#define RIX_ENABLE_CSV
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse("name,lang\nAda,C++\n");
return 0;
}When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
Common mistakes
Calling table[0] on an empty table
Wrong:
const auto &header = table[0];Better:
if (!table.empty())
{
const auto &header = table[0];
}Calling row[1] without checking row size
Wrong:
rix.debug.print(row[0], row[1]);Better:
if (row.size() >= 2)
{
rix.debug.print(row[0], row[1]);
}Splitting CSV manually
Wrong:
std::getline(stream, field, ',');Better:
const auto table = rix.csv.parse(input);Manual splitting breaks with quoted commas, quotes, and newlines.
Building CSV manually
Wrong:
output += name + "," + language + "\n";Better:
table.push_back({name, language});
const auto output = rix.csv.write(table);Putting Rix packages in packages
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
API summary
Main facade:
rix.csv.parse(input)
rix.csv.parse(input, options)
rix.csv.write(table)
rix.csv.version()Main types:
rixlib::csv::Table
rixlib::csv::Row
rixlib::csv::OptionsMain options:
options.field_transformer
options.row_filterRecommended include:
#include <rix.hpp>Independent include:
#include <rix/csv.hpp>Security and data notes
CSV is plain text.
Do not use CSV as a secure storage format.
Do not store production secrets in CSV files.
Be careful with user data exports.
Validate external CSV before using field indexes.
Use database storage for durable application state.
Use JSON when the data is nested or structured beyond simple rows and columns.
What you should remember
Parse CSV:
const auto table = rix.csv.parse(input);Parse with options:
rixlib::csv::Options options;
const auto table = rix.csv.parse(input, options);Write CSV:
const auto output = rix.csv.write(table);Create a table:
rixlib::csv::Table table;
table.push_back({"name", "language"});Validate before indexing external input:
if (row.size() >= 2)
{
rix.debug.print(row[0], row[1]);
}Use deps for Rix packages in vix.app:
deps = [
"rix/rix",
]Next step
Continue with the debug package.
Next: Debug