This page documents the public rix/csv API.
Use CSV through the unified Rix facade:
#include <rix.hpp>Then access CSV with:
rix.csvThe CSV API provides helpers for:
parsing CSV text
writing CSV text
working with rows and fields
using parse options
using write options
transforming fields
filtering rowsThe CSV package is:
rix/csvFor facade usage, install:
vix add rix/rix
vix installIn vix.app:
deps = [
"rix/rix",
]For independent package usage, install:
vix add rix/csv
vix installIn vix.app:
deps = [
"rix/csv",
]Facade usage:
#include <rix.hpp>Independent usage:
#include <rix/csv.hpp>Most application examples should use the facade.
The CSV facade member is:
rix.csvExample:
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
return table.empty() ? 1 : 0;
}Common CSV operations are:
rix.csv.parse(...)
rix.csv.write(...)Use parse to convert CSV text into a table.
Use write to convert a table back into CSV text.
CSV data is represented as a table.
A table is a list of rows.
Each row is a list of fields.
Common shape:
Table
Row
Field
Field
Row
Field
FieldExample:
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
rix.debug.print("rows:", table.size());Use:
const auto table = rix.csv.parse(input);Example:
#include <rix.hpp>
int main()
{
const auto input =
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n";
const auto table = rix.csv.parse(input);
rix.debug.print("rows:", table.size());
return 0;
}Iterate over the table:
for (const auto &row : table)
{
rix.debug.inspect(row);
}Access a row by index:
const auto &header = table[0];Check that the table is not empty before indexing.
Fields are stored as strings.
Example:
for (const auto &row : table)
{
for (const auto &field : row)
{
rix.debug.print(field);
}
}Access a field by index:
const auto &name = table[1][0];
const auto &language = table[1][1];Check row sizes before indexing.
Wrong:
rix.debug.print(table[1][0]);Better:
if (table.size() > 1 && table[1].size() > 0)
{
rix.debug.print(table[1][0]);
}CSV input can be incomplete, so code should check sizes when reading by index.
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n");
for (const auto &row : table)
{
for (const auto &field : row)
{
rix.debug.print(field);
}
}
return 0;
}For real Vix application logs, prefer the Vix logging system.
For examples and small tools, rix.debug.print is fine.
Use:
const auto output = rix.csv.write(table);Example:
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
const auto output = rix.csv.write(table);
rix.debug.print(output);
return 0;
}Use write when you need to export table data as CSV text.
#include <rix.hpp>
int main()
{
const auto input =
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n";
const auto table = rix.csv.parse(input);
const auto output = rix.csv.write(table);
rix.debug.print(output);
return 0;
}This parses CSV text and writes it back as CSV text.
CSV parsing can use options when you need custom behavior.
Example shape:
rixlib::csv::ParseOptions options;
const auto table = rix.csv.parse(input, options);Use options for custom parsing behavior such as trimming, delimiter changes, field transforms, or row filtering when supported by the package version.
A field transformer can normalize fields while parsing.
Example:
rixlib::csv::ParseOptions 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 a field transformer when parsed values need light normalization.
A row filter can skip rows while parsing.
Example:
rixlib::csv::ParseOptions options;
options.row_filter = [](const rixlib::csv::Row &row) {
return !row.empty();
};
const auto table = rix.csv.parse(input, options);Use a row filter when you want to remove empty rows or application-specific rows.
#include <rix.hpp>
#include <string>
int main()
{
const std::string input =
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n"
"\n";
rixlib::csv::ParseOptions 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) {
return !row.empty();
};
const auto table = rix.csv.parse(input, options);
rix.debug.print("rows:", table.size());
for (const auto &row : table)
{
rix.debug.inspect(row);
}
return 0;
}Run:
vix run csv.cppCSV writing can use options when you need custom output behavior.
Example shape:
rixlib::csv::WriteOptions options;
const auto output = rix.csv.write(table, options);Use write options when you need to control output format such as delimiter or newline behavior when supported by the package version.
You can build a table manually.
Example shape:
rixlib::csv::Table table;
table.push_back({"name", "language"});
table.push_back({"Ada", "C++"});
table.push_back({"Gaspard", "Vix"});Then write it:
const auto output = rix.csv.write(table);#include <rix.hpp>
int main()
{
rixlib::csv::Table table;
table.push_back({"name", "language"});
table.push_back({"Ada", "C++"});
table.push_back({"Gaspard", "Vix.cpp"});
const auto output = rix.csv.write(table);
rix.debug.print(output);
return 0;
}Run:
vix run csv.cppCSV tables can be converted into PDF tables.
Example:
#include <rix.hpp>
int main()
{
const auto csv = rix.csv.parse(
"Name,Language,Project\n"
"Ada,C++,Rix\n"
"Gaspard,C++,Vix.cpp\n");
auto doc = rix.pdf.document();
auto &page = doc.add_page();
auto y = page.heading(
page.x_left(),
page.y_top(),
"CSV table",
1);
y -= 20.0F;
rixlib::pdf::Table table;
table.set_column_widths({
160.0F,
160.0F,
160.0F});
if (!csv.empty() && csv[0].size() >= 3)
{
table.add_header({
csv[0][0],
csv[0][1],
csv[0][2]});
}
for (std::size_t i = 1; i < csv.size(); ++i)
{
const auto &row = csv[i];
if (row.size() >= 3)
{
table.add_row({
row[0],
row[1],
row[2]});
}
}
page.table(
page.x_left(),
y,
table);
auto saved = rix.pdf.save(doc, "csv-table.pdf");
return saved.ok() ? 0 : 1;
}This example uses:
rix.csv
rix.pdfso the unified facade is the right dependency.
CSV examples often use debug output:
const auto table = rix.csv.parse(input);
rix.debug.print("rows:", table.size());
rix.debug.inspect(table);rix.debug is useful for examples, quick checks, and small tools.
For real Vix application logs, prefer the Vix logging system.
Create a Vix app:
vix new rix-csv-api --app
cd rix-csv-apiAdd Rix:
vix add rix/rix
vix installMake sure vix.app contains:
deps = [
"rix/rix",
]Use in src/main.cpp:
#include <rix.hpp>Build and run:
vix build
vix runCreate a file:
mkdir -p ~/rix-csv-api
cd ~/rix-csv-api
touch csv.cppAdd:
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name,language\n"
"Ada,C++\n");
rix.debug.print("rows:", table.size());
return 0;
}Run:
vix run csv.cppIf Rix is not available globally:
vix install -g rix/rix
vix run csv.cppInstall only CSV:
vix add rix/csv
vix installIn vix.app:
deps = [
"rix/csv",
]Then include:
#include <rix/csv.hpp>Example:
#include <rix/csv.hpp>
int main()
{
auto csv = rixlib::csv::module();
const auto table = csv.parse(
"name,language\n"
"Ada,C++\n");
return table.empty() ? 1 : 0;
}Use independent package APIs when you intentionally do not want the unified facade.
For most documentation and application examples, prefer:
#include <rix.hpp>and:
rix.csvUse feature macros when you want the facade style but only want CSV mounted:
#define RIX_ENABLE_CSV
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name\n"
"Ada\n");
return table.empty() ? 1 : 0;
}If you also want debug output:
#define RIX_ENABLE_CSV
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
const auto table = rix.csv.parse(
"name\n"
"Ada\n");
rix.debug.print("rows:", table.size());
return 0;
}#include <rix.hpp>
#include <sstream>
#include <string>
namespace
{
void print_table(const rixlib::csv::Table &table)
{
for (const auto &row : table)
{
std::ostringstream line;
for (std::size_t i = 0; i < row.size(); ++i)
{
if (i > 0)
{
line << " ";
}
line << row[i];
}
rix.debug.print(line.str());
}
}
}
int main()
{
const std::string input =
"name,language\n"
"Ada,C++\n"
"Gaspard,Vix\n";
const auto table = rix.csv.parse(input);
rix.debug.print("loaded rows:", table.size());
print_table(table);
return 0;
}Run:
vix run csv.cppIf your code uses:
#include <rix.hpp>install:
vix add rix/rix
vix installIf your code uses:
#include <rix/csv.hpp>install:
vix add rix/csv
vix installWrong:
packages = [
"rix/csv",
]Correct:
deps = [
"rix/csv",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
If your code uses:
#include <rix.hpp>then install:
vix add rix/rix
vix installIf your code uses:
#include <rix/csv.hpp>then install:
vix add rix/csv
vix installWrong:
rix.debug.print(row[2]);Better:
if (row.size() > 2)
{
rix.debug.print(row[2]);
}CSV files can have incomplete rows.
Check row sizes when reading fields by index.
rix.debug is useful for examples and small tools.
For real Vix application logs, prefer the Vix logging system.
Avoid this without a clear reason:
#include <rix.hpp>
#include <rix/csv.hpp>Use one style per file.
Facade:
#include <rix.hpp>Independent:
#include <rix/csv.hpp>Parse CSV:
const auto table = rix.csv.parse(input);Write CSV:
const auto output = rix.csv.write(table);Iterate rows:
for (const auto &row : table)
{
rix.debug.inspect(row);
}Use the facade for most examples:
#include <rix.hpp>and:
rix.csvFor project usage:
vix add rix/rix
vix installand keep:
deps = [
"rix/rix",
]For independent CSV usage:
vix add rix/csv
vix installand:
#include <rix/csv.hpp>Always check row sizes before indexed field access.
Continue with the debug API.
Next: Debug API