mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
refactor: refactor sound csv loading code
This commit is contained in:
parent
a3b9d2693c
commit
d814fe7b95
34
src/ObjCommon/Csv/CsvHeaderRow.cpp
Normal file
34
src/ObjCommon/Csv/CsvHeaderRow.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "Csv/CsvHeaderRow.h"
|
||||
|
||||
CsvHeaderRow::CsvHeaderRow() = default;
|
||||
|
||||
bool CsvHeaderRow::Read(const CsvInputStream& inputStream)
|
||||
{
|
||||
if (!m_header_row.empty())
|
||||
return false;
|
||||
|
||||
return inputStream.NextRow(m_header_row);
|
||||
}
|
||||
|
||||
const std::string& CsvHeaderRow::HeaderNameForColumn(const unsigned columnIndex) const
|
||||
{
|
||||
return m_header_row[columnIndex];
|
||||
}
|
||||
|
||||
bool CsvHeaderRow::RequireIndexForHeader(const std::string& headerName, unsigned& out) const
|
||||
{
|
||||
const auto existingHeader = std::ranges::find(m_header_row, headerName);
|
||||
if (existingHeader == m_header_row.end())
|
||||
return false;
|
||||
|
||||
out = std::distance(m_header_row.begin(), existingHeader);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<unsigned> CsvHeaderRow::GetIndexForHeader(const std::string& headerName) const
|
||||
{
|
||||
unsigned result;
|
||||
if (!RequireIndexForHeader(headerName, result))
|
||||
return std::nullopt;
|
||||
return result;
|
||||
}
|
22
src/ObjCommon/Csv/CsvHeaderRow.h
Normal file
22
src/ObjCommon/Csv/CsvHeaderRow.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "Csv/CsvStream.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CsvHeaderRow
|
||||
{
|
||||
public:
|
||||
CsvHeaderRow();
|
||||
|
||||
bool Read(const CsvInputStream& inputStream);
|
||||
|
||||
const std::string& HeaderNameForColumn(unsigned columnIndex) const;
|
||||
bool RequireIndexForHeader(const std::string& headerName, unsigned& out) const;
|
||||
[[nodiscard]] std::optional<unsigned> GetIndexForHeader(const std::string& headerName) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_header_row;
|
||||
};
|
@ -1,14 +1,86 @@
|
||||
#include "CsvStream.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
constexpr char CSV_SEPARATOR = ',';
|
||||
|
||||
CsvCell::CsvCell(std::string value)
|
||||
: m_value(std::move(value))
|
||||
{
|
||||
}
|
||||
|
||||
bool CsvCell::AsFloat(float& out) const
|
||||
{
|
||||
const char* startPtr = m_value.c_str();
|
||||
char* endPtr;
|
||||
out = std::strtof(startPtr, &endPtr);
|
||||
|
||||
if (endPtr == startPtr)
|
||||
return false;
|
||||
|
||||
for (const auto* c = endPtr; *c; c++)
|
||||
{
|
||||
if (!isspace(*c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsvCell::AsInt32(int32_t& out) const
|
||||
{
|
||||
const char* startPtr = m_value.c_str();
|
||||
char* endPtr;
|
||||
out = std::strtol(startPtr, &endPtr, 0);
|
||||
|
||||
if (endPtr == startPtr)
|
||||
return false;
|
||||
|
||||
for (const auto* c = endPtr; *c; c++)
|
||||
{
|
||||
if (!isspace(*c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CsvCell::AsUInt32(uint32_t& out) const
|
||||
{
|
||||
const char* startPtr = m_value.c_str();
|
||||
char* endPtr;
|
||||
out = std::strtoul(startPtr, &endPtr, 0);
|
||||
|
||||
if (endPtr == startPtr)
|
||||
return false;
|
||||
|
||||
for (const auto* c = endPtr; *c; c++)
|
||||
{
|
||||
if (!isspace(*c))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CsvInputStream::CsvInputStream(std::istream& stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
bool CsvInputStream::NextRow(std::vector<CsvCell>& out) const
|
||||
{
|
||||
if (!out.empty())
|
||||
out.clear();
|
||||
|
||||
return EmitNextRow(
|
||||
[&out](std::string value)
|
||||
{
|
||||
out.emplace_back(std::move(value));
|
||||
});
|
||||
}
|
||||
|
||||
bool CsvInputStream::NextRow(std::vector<std::string>& out) const
|
||||
{
|
||||
if (!out.empty())
|
||||
|
@ -1,16 +1,30 @@
|
||||
#pragma once
|
||||
#include "Utils/MemoryManager.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CsvCell
|
||||
{
|
||||
public:
|
||||
explicit CsvCell(std::string value);
|
||||
|
||||
bool AsFloat(float& out) const;
|
||||
bool AsInt32(int32_t& out) const;
|
||||
bool AsUInt32(uint32_t& out) const;
|
||||
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
class CsvInputStream
|
||||
{
|
||||
public:
|
||||
explicit CsvInputStream(std::istream& stream);
|
||||
|
||||
bool NextRow(std::vector<CsvCell>& out) const;
|
||||
bool NextRow(std::vector<std::string>& out) const;
|
||||
bool NextRow(std::vector<const char*>& out, MemoryManager& memory) const;
|
||||
|
||||
|
@ -1,80 +0,0 @@
|
||||
#include "Csv/ParsedCsv.h"
|
||||
|
||||
ParsedCsvRow::ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row)
|
||||
: headers(headers),
|
||||
values(std::move(row))
|
||||
{
|
||||
}
|
||||
|
||||
std::string ParsedCsvRow::GetValue(const std::string& header, const bool required) const
|
||||
{
|
||||
if (this->headers.find(header) == this->headers.end())
|
||||
{
|
||||
if (required)
|
||||
std::cerr << "ERROR: Required column \"" << header << "\" was not found\n";
|
||||
else
|
||||
std::cerr << "WARNING: Expected column \"" << header << "\" was not found\n";
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto& value = this->values.at(this->headers[header]);
|
||||
if (required && value.empty())
|
||||
{
|
||||
std::cerr << "ERROR: Required column \"" << header << "\" does not have a value\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
float ParsedCsvRow::GetValueFloat(const std::string& header, const bool required) const
|
||||
{
|
||||
const auto& value = this->GetValue(header, required);
|
||||
if (!value.empty())
|
||||
{
|
||||
std::istringstream ss(value);
|
||||
float out;
|
||||
ss >> out;
|
||||
return out;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
ParsedCsv::ParsedCsv(const CsvInputStream& inputStream, const bool hasHeaders)
|
||||
{
|
||||
std::vector<std::vector<std::string>> csvLines;
|
||||
std::vector<std::string> currentLine;
|
||||
|
||||
while (inputStream.NextRow(currentLine))
|
||||
{
|
||||
csvLines.emplace_back(std::move(currentLine));
|
||||
currentLine = std::vector<std::string>();
|
||||
}
|
||||
|
||||
if (hasHeaders)
|
||||
{
|
||||
const auto& headersRow = csvLines[0];
|
||||
for (auto i = 0u; i < headersRow.size(); i++)
|
||||
{
|
||||
this->headers[headersRow[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = hasHeaders ? 1u : 0u; i < csvLines.size(); i++)
|
||||
{
|
||||
auto& rowValues = csvLines[i];
|
||||
this->rows.emplace_back(this->headers, std::move(rowValues));
|
||||
}
|
||||
}
|
||||
|
||||
size_t ParsedCsv::Size() const
|
||||
{
|
||||
return this->rows.size();
|
||||
}
|
||||
|
||||
ParsedCsvRow ParsedCsv::operator[](const size_t index) const
|
||||
{
|
||||
return this->rows.at(index);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Csv/CsvStream.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
class ParsedCsvRow
|
||||
{
|
||||
std::unordered_map<std::string, size_t>& headers;
|
||||
std::vector<std::string> values;
|
||||
|
||||
public:
|
||||
explicit ParsedCsvRow(std::unordered_map<std::string, size_t>& headers, std::vector<std::string> row);
|
||||
_NODISCARD std::string GetValue(const std::string& header, bool required = false) const;
|
||||
_NODISCARD float GetValueFloat(const std::string& header, bool required = false) const;
|
||||
|
||||
template<typename T> T GetValueInt(const std::string& header, const bool required = false) const
|
||||
{
|
||||
const auto& value = this->GetValue(header, required);
|
||||
if (!value.empty())
|
||||
{
|
||||
std::istringstream ss(value);
|
||||
long long out;
|
||||
ss >> out;
|
||||
return static_cast<T>(out);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class ParsedCsv
|
||||
{
|
||||
std::unordered_map<std::string, size_t> headers;
|
||||
std::vector<ParsedCsvRow> rows;
|
||||
|
||||
public:
|
||||
explicit ParsedCsv(const CsvInputStream& inputStream, bool hasHeaders = true);
|
||||
|
||||
_NODISCARD size_t Size() const;
|
||||
|
||||
ParsedCsvRow operator[](size_t index) const;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user