flatten 20260225

This commit is contained in:
Timothy Prepscius
2026-02-25 12:39:24 -05:00
commit fa54be052a
315 changed files with 49791 additions and 0 deletions

168
tjp/core/csv/Csv.cpp Normal file
View File

@@ -0,0 +1,168 @@
// TJP COPYRIGHT HEADER
#include "Csv.hpp"
// Adapted from
// https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c
#include <tjp/core/iterators/enumerate.hpp>
#include <sstream>
namespace tjp {
namespace core {
CSV::CSV(std::istream& str_, bool readHeader_) :
str(str_)
{
if (readHeader_)
readHeader();
}
void CSV::readHeader ()
{
readNextRow();
int i=0;
for (auto &s : m_data)
{
m_header[s] = i;
++i;
}
}
std::string const& CSV::operator[](std::size_t index) const
{
return m_data[index];
}
std::string const& CSV::operator[](const std::string &index) const
{
auto i = m_header.find(index);
return m_data[i->second];
}
std::size_t CSV::size() const
{
return m_data.size();
}
bool CSV::readNextRow()
{
std::string line;
std::getline(str, line);
if (!line.empty() && line.back() == '\r')
line.resize(line.size()-1);
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while(std::getline(lineStream, cell, ','))
{
m_data.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (!lineStream && cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data.push_back("");
}
return str.good();
}
FastCSV::FastCSV(std::istream& str_, bool readHeader_) :
str(str_),
lineTokens(Tokenizer::Tokens("\n")),
csvTokens(Tokenizer::Tokens(","))
{
const auto bufferSize = 1024;
char buffer[bufferSize];
while (str_)
{
str_.read(buffer, bufferSize);
data.insert(data.end(), buffer, buffer + str_.gcount());
}
tokenizer = Tokenizer(data.data(), data.size(), lineTokens);
if (readHeader_)
readHeader();
}
void FastCSV::readHeader ()
{
readNextRow();
int i=0;
for (auto &s : m_data)
{
m_header[s] = i;
++i;
}
}
FastCSV::Result FastCSV::operator[](std::size_t index) const
{
return Result(m_data[index]);
}
FastCSV::Segment FastCSV::segment(std::size_t index) const
{
return m_data[index];
};
std::size_t FastCSV::index(const Segment &index) const
{
auto i = m_header.find(index);
if (i == m_header.end())
return -1;
return i->second;
}
FastCSV::Result FastCSV::operator[](const Segment &index) const
{
auto i = m_header.find(index);
return Result(m_data[i->second]);
}
std::size_t FastCSV::size() const
{
return m_data.size();
}
bool FastCSV::readNextRow()
{
Segment line;
char token;
bool result = tokenizer.next(line, token);
if (!result)
return false;
if (!line.empty() && line.back() == '\r')
line.remove_suffix(1);
Tokenizer lineTokenizer(line.data(), line.size(), csvTokens);
Segment cell;
char cellToken;
m_data.clear();
while (lineTokenizer.next(cell, cellToken))
{
m_data.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data.push_back(Segment());
}
return true;
}
} // namespace
} // namespace

208
tjp/core/csv/Csv.h Normal file
View File

@@ -0,0 +1,208 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <iterator>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <tjp/core/string/Tokenizer.hpp>
// Adapted from
// https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c
#include <tjp/core/iterators/enumerate.hpp>
namespace tjp {
namespace core {
class CSV
{
public:
CSV(std::istream& str_, bool readHeader_ = true) :
str(str_)
{
if (readHeader_)
readHeader();
}
void readHeader ()
{
readNextRow();
int i=0;
for (auto &s : m_data)
{
m_header[s] = i;
++i;
}
}
public:
std::string const& operator[](std::size_t index) const
{
return m_data[index];
}
std::string const& operator[](const std::string &index) const
{
auto i = m_header.find(index);
return m_data[i->second];
}
std::size_t size() const
{
return m_data.size();
}
bool readNextRow()
{
std::string line;
std::getline(str, line);
if (!line.empty() && line.back() == '\r')
line.resize(line.size()-1);
std::stringstream lineStream(line);
std::string cell;
m_data.clear();
while(std::getline(lineStream, cell, ','))
{
m_data.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (!lineStream && cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data.push_back("");
}
return str.good();
}
protected:
std::istream& str;
std::map<std::string, size_t> m_header;
std::vector<std::string> m_data;
};
class FastCSV
{
protected:
typedef std::string_view Segment;
typedef std::string Result;
std::vector<char> data;
typedef Tokenizer<Segment, TokenVector> Tokenizer;
Tokenizer::Tokens lineTokens;
Tokenizer::Tokens csvTokens;
Tokenizer tokenizer;
public:
FastCSV(std::istream& str_, bool readHeader_ = true) :
str(str_),
lineTokens(Tokenizer::Tokens("\n")),
csvTokens(Tokenizer::Tokens(","))
{
const auto bufferSize = 1024;
char buffer[bufferSize];
while (str_)
{
str_.read(buffer, bufferSize);
data.insert(data.end(), buffer, buffer + str_.gcount());
}
tokenizer = Tokenizer(data.data(), data.size(), lineTokens);
if (readHeader_)
readHeader();
}
void readHeader ()
{
readNextRow();
int i=0;
for (auto &s : m_data)
{
m_header[s] = i;
++i;
}
}
public:
Result operator[](std::size_t index) const
{
return Result(m_data[index]);
}
Segment segment(std::size_t index) const
{
return m_data[index];
};
std::size_t index(const Segment &index) const
{
auto i = m_header.find(index);
if (i == m_header.end())
return -1;
return i->second;
}
Result operator[](const Segment &index) const
{
auto i = m_header.find(index);
return Result(m_data[i->second]);
}
std::size_t size() const
{
return m_data.size();
}
bool readNextRow()
{
Segment line;
char token;
bool result = tokenizer.next(line, token);
if (!result)
return false;
if (!line.empty() && line.back() == '\r')
line.remove_suffix(1);
Tokenizer lineTokenizer(line.data(), line.size(), csvTokens);
Segment cell;
char cellToken;
m_data.clear();
while (lineTokenizer.next(cell, cellToken))
{
m_data.push_back(cell);
}
// This checks for a trailing comma with no data after it.
if (cell.empty())
{
// If there was a trailing comma then add an empty element.
m_data.push_back(Segment());
}
return true;
}
protected:
std::istream& str;
std::map<Segment, size_t> m_header;
std::vector<Segment> m_data;
};
} // namespace
} // namespace

82
tjp/core/csv/Csv.hpp Normal file
View File

@@ -0,0 +1,82 @@
// TJP COPYRIGHT HEADER
#pragma once
#include <iosfwd>
#include <vector>
#include <string>
#include <map>
#include <tjp/core/string/Tokenizer.hpp>
// Adapted from
// https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c
#include <tjp/core/iterators/enumerate.hpp>
namespace tjp {
namespace core {
class CSV
{
public:
CSV(std::istream& str_, bool readHeader_ = true);
void readHeader ();
public:
std::string const& operator[](std::size_t index) const;
std::string const& operator[](const std::string &index) const;
std::size_t size() const;
bool readNextRow();
protected:
std::istream& str;
std::map<std::string, size_t> m_header;
std::vector<std::string> m_data;
};
class FastCSV
{
protected:
typedef std::string_view Segment;
typedef std::string Result;
std::vector<char> data;
typedef core::Tokenizer<Segment, TokenVector> Tokenizer;
Tokenizer::Tokens lineTokens;
Tokenizer::Tokens csvTokens;
Tokenizer tokenizer;
public:
FastCSV(std::istream& str_, bool readHeader_ = true);
void readHeader ();
public:
Result operator[](std::size_t index) const;
Segment segment(std::size_t index) const;
std::size_t index(const Segment &index) const;
Result operator[](const Segment &index) const;
std::size_t size() const;
bool readNextRow();
protected:
std::istream& str;
std::map<Segment, size_t> m_header;
std::vector<Segment> m_data;
};
} // namespace
} // namespace

View File

@@ -0,0 +1,16 @@
// TJP COPYRIGHT HEADER
#include <tjp/core/csv/Csv.h>
using namespace tjp::core;
void compile()
{
std::ifstream file("plop.csv");
CSV csv(file);
while(csv.readNextRow())
{
std::cout << "4th Element(" << csv[3] << ")\n";
}
}