CSV API
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 rowsPackage
The 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",
]Header
Facade usage:
#include <rix.hpp>Independent usage:
#include <rix/csv.hpp>Most application examples should use the facade.
Facade member
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;
}Main operations
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.
Table type
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());Parse CSV text
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;
}Access rows
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.
Access fields
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.
Safe 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.
Print a table
#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.
Write CSV text
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.
Round trip 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);
const auto output = rix.csv.write(table);
rix.debug.print(output);
return 0;
}This parses CSV text and writes it back as CSV text.
Parse with options
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.
Field transformer
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.
Row filter
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.
Complete parse options example
#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.cppWrite with options
CSV 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.
Table construction
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);Complete write example
#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 and PDF
CSV 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 and debug
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.
Use in a Vix project
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 runSingle-file usage
Create 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.cppIndependent usage
Install 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.csvEnable only CSV in the facade
Use 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;
}Complete CSV example
#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.cppCommon mistakes
Forgetting to install Rix
If 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 installPutting Rix in packages
Wrong:
packages = [
"rix/csv",
]Correct:
deps = [
"rix/csv",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
Installing rix/csv but including <rix.hpp>
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 installAccessing fields without checking row size
Wrong:
rix.debug.print(row[2]);Better:
if (row.size() > 2)
{
rix.debug.print(row[2]);
}Assuming all rows have the same number of fields
CSV files can have incomplete rows.
Check row sizes when reading fields by index.
Using debug output as production logging
rix.debug is useful for examples and small tools.
For real Vix application logs, prefer the Vix logging system.
Mixing facade and independent usage
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>What you should remember
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.
Next step
Continue with the debug API.
Next: Debug API