Built & tested gs_csv.h
This commit is contained in:
parent
4085d3acf9
commit
743181fe9b
|
@ -507,7 +507,7 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
|||
{
|
||||
OutputDebugStringA("Setting Working Directory\n");
|
||||
OutputDebugStringA(WorkingDirectory.Str);
|
||||
|
||||
OutputDebugStringA("\n");
|
||||
Result = SetCurrentDirectory(WorkingDirectory.Str);
|
||||
if (!Result)
|
||||
{
|
||||
|
@ -525,6 +525,8 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
|||
|
||||
#include "../../gs_libs/gs_path.h"
|
||||
|
||||
#include "../../gs_libs/gs_csv.h"
|
||||
|
||||
int WINAPI
|
||||
WinMain (
|
||||
HINSTANCE HInstance,
|
||||
|
@ -541,13 +543,29 @@ WinMain (
|
|||
|
||||
ThreadContext.Allocator.Debug = &AllocDebug;
|
||||
|
||||
gs_file_info A = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium"));
|
||||
|
||||
gs_file_info B = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium\\"));
|
||||
|
||||
|
||||
if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1;
|
||||
|
||||
|
||||
gs_file TestFile = ReadEntireFile(ThreadContext.FileHandler, ConstString("data/flower_codes.tsv"));
|
||||
gs_const_string TestFileStr = {};
|
||||
TestFileStr.Str = (char*)TestFile.Memory;
|
||||
TestFileStr.Length = TestFile.Size;
|
||||
gscsv_sheet Sheet = CSV_Parse(TestFileStr, { '\t' }, ThreadContext.Transient);
|
||||
|
||||
gs_string Out = PushString(ThreadContext.Transient, TestFile.Size * 2);
|
||||
|
||||
for (u64 y = 0; y < Sheet.RowCount; y++)
|
||||
{
|
||||
for (u64 x = 0; x < Sheet.ColumnCount; x++)
|
||||
{
|
||||
gs_const_string Cell = CSVSheet_GetCell(Sheet, x, y);
|
||||
AppendPrintF(&Out, "%S\t", Cell);
|
||||
}
|
||||
AppendPrintF(&Out, "\n");
|
||||
}
|
||||
NullTerminate(&Out);
|
||||
OutputDebugStringA(Out.Str);
|
||||
|
||||
MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
|
||||
Win32UpdateWindowDimension(&MainWindow);
|
||||
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/* date = March 24th 2021 5:53 pm */
|
||||
|
||||
#ifndef GS_CSV_H
|
||||
#define GS_CSV_H
|
||||
|
||||
struct gscsv_cell
|
||||
{
|
||||
gs_const_string Value;
|
||||
};
|
||||
|
||||
struct gscsv_row
|
||||
{
|
||||
u64* CellIndices;
|
||||
};
|
||||
|
||||
struct gscsv_sheet
|
||||
{
|
||||
char SeparatorChar;
|
||||
gscsv_cell* Cells;
|
||||
gscsv_row* Rows;
|
||||
u64 RowCount;
|
||||
u64 ColumnCount;
|
||||
};
|
||||
|
||||
struct gscsv_sheet_desc
|
||||
{
|
||||
char SeparatorChar;
|
||||
};
|
||||
|
||||
struct gscsv_parser
|
||||
{
|
||||
gs_const_string Str;
|
||||
u64 At;
|
||||
u64 Line;
|
||||
};
|
||||
|
||||
internal void
|
||||
CSVParser_Reset(gscsv_parser* Parser)
|
||||
{
|
||||
Parser->At = 0;
|
||||
}
|
||||
|
||||
internal char
|
||||
CSVParser_CharAt(gscsv_parser Parser)
|
||||
{
|
||||
char Result = Parser.Str.Str[Parser.At];
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal bool
|
||||
CSVParser_CanAdvance(gscsv_parser Parser) {
|
||||
bool Result = Parser.At < Parser.Str.Length;
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
CSVParser_Advance(gscsv_parser* Parser)
|
||||
{
|
||||
if (CSVParser_CanAdvance(*Parser)) {
|
||||
if (IsNewline(CSVParser_CharAt(*Parser)))
|
||||
{
|
||||
Parser->Line += 1;
|
||||
}
|
||||
Parser->At += 1;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
CSVParser_AdvancePastChar(gscsv_parser* Parser, char Char)
|
||||
{
|
||||
while (CSVParser_CanAdvance(*Parser) && CSVParser_CharAt(*Parser) != Char)
|
||||
{
|
||||
CSVParser_Advance(Parser);
|
||||
}
|
||||
|
||||
if (CSVParser_CanAdvance(*Parser))
|
||||
{
|
||||
Assert(CSVParser_CharAt(*Parser) == Char);
|
||||
CSVParser_Advance(Parser);
|
||||
}
|
||||
}
|
||||
|
||||
internal u64
|
||||
CSVParser_AdvancePastSeparatorOrNewline(gscsv_parser* Parser, char SeparatorChar)
|
||||
{
|
||||
u64 PointBeforeSeparator = 0;
|
||||
|
||||
while (CSVParser_CanAdvance(*Parser) &&
|
||||
!(CSVParser_CharAt(*Parser) == SeparatorChar ||
|
||||
IsNewline(CSVParser_CharAt(*Parser))))
|
||||
{
|
||||
CSVParser_Advance(Parser);
|
||||
}
|
||||
|
||||
PointBeforeSeparator = Parser->At;
|
||||
|
||||
if (CSVParser_CanAdvance(*Parser))
|
||||
{
|
||||
while(IsNewline(CSVParser_CharAt(*Parser))) {
|
||||
CSVParser_Advance(Parser);
|
||||
}
|
||||
if (CSVParser_CharAt(*Parser) == SeparatorChar)
|
||||
{
|
||||
CSVParser_Advance(Parser);
|
||||
}
|
||||
}
|
||||
|
||||
return PointBeforeSeparator;
|
||||
}
|
||||
|
||||
internal gscsv_cell
|
||||
CSVCell_Init(gs_const_string File, u64 CellStart, u64 CellEnd)
|
||||
{
|
||||
gscsv_cell Result = {};
|
||||
Result.Value = Substring(File, CellStart, CellEnd);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal void
|
||||
CSVRow_PushCell(gscsv_row* Row, u64 CellIndex, u64 ColumnIndex)
|
||||
{
|
||||
Row->CellIndices[ColumnIndex] = CellIndex;
|
||||
}
|
||||
|
||||
internal gscsv_sheet
|
||||
CSV_Parse(gs_const_string File, gscsv_sheet_desc Desc, gs_memory_arena* Arena)
|
||||
{
|
||||
gscsv_sheet Result = {};
|
||||
|
||||
gscsv_parser Parser = {};
|
||||
Parser.Str = File;
|
||||
Parser.At = 0;
|
||||
Parser.Line = 0;
|
||||
|
||||
// Count Tabs in first line
|
||||
u64 Columns = 0;
|
||||
while (CSVParser_CanAdvance(Parser) && !IsNewline(CSVParser_CharAt(Parser)))
|
||||
{
|
||||
char At = CSVParser_CharAt(Parser);
|
||||
if (At == Desc.SeparatorChar) {
|
||||
Columns += 1;
|
||||
}
|
||||
CSVParser_Advance(&Parser);
|
||||
}
|
||||
// NOTE(PS): Add one on the end because the last column won't end in a SeparatorChar,
|
||||
// it ends in a newline
|
||||
Columns += 1;
|
||||
CSVParser_Reset(&Parser);
|
||||
|
||||
// Count New Lines
|
||||
u64 Rows = 0;
|
||||
while (CSVParser_CanAdvance(Parser))
|
||||
{
|
||||
char At = CSVParser_CharAt(Parser);
|
||||
if (IsNewline(At))
|
||||
{
|
||||
Rows++;
|
||||
while (CSVParser_CanAdvance(Parser) && IsNewline(CSVParser_CharAt(Parser)))
|
||||
{
|
||||
CSVParser_Advance(&Parser);
|
||||
}
|
||||
} else {
|
||||
CSVParser_Advance(&Parser);
|
||||
}
|
||||
}
|
||||
// NOTE(PS): Adding a row becuase the last row will just end in the EOF
|
||||
Rows += 1;
|
||||
CSVParser_Reset(&Parser);
|
||||
|
||||
// Allocate Result
|
||||
Result.SeparatorChar = Desc.SeparatorChar;
|
||||
Result.RowCount = Rows;
|
||||
Result.ColumnCount = Columns;
|
||||
Result.Cells = PushArray(Arena, gscsv_cell, Result.RowCount * Result.ColumnCount);
|
||||
Result.Rows = PushArray(Arena, gscsv_row, Result.RowCount);
|
||||
|
||||
// for rows, parse row
|
||||
// for cells parse cells
|
||||
for (u64 r = 0; r < Result.RowCount; r++)
|
||||
{
|
||||
u64 RowIndex = r;
|
||||
gscsv_row* Row = Result.Rows + RowIndex;
|
||||
Row->CellIndices = PushArray(Arena, u64, Result.ColumnCount);
|
||||
|
||||
for (u64 c = 0; c < Result.ColumnCount; c++)
|
||||
{
|
||||
u64 CellIndex = (r * Result.ColumnCount) + c;
|
||||
u64 CellStart = Parser.At;
|
||||
u64 CellEnd = CSVParser_AdvancePastSeparatorOrNewline(&Parser, Desc.SeparatorChar);
|
||||
|
||||
Result.Cells[CellIndex] = CSVCell_Init(Parser.Str, CellStart, CellEnd);
|
||||
CSVRow_PushCell(Row, CellIndex, c);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal gs_const_string
|
||||
CSVSheet_GetCell(gscsv_sheet Sheet, u64 Column, u64 Row)
|
||||
{
|
||||
gs_const_string Result = {};
|
||||
|
||||
if (Sheet.RowCount > Row && Sheet.ColumnCount > Column)
|
||||
{
|
||||
u64 CellIndex = (Row * Sheet.ColumnCount) + Column;
|
||||
Result = Sheet.Cells[CellIndex].Value;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
#endif //GS_CSV_H
|
|
@ -11,6 +11,7 @@
|
|||
#include "../gs_libs/gs_tests.h"
|
||||
|
||||
#include "../gs_libs/gs_path.h"
|
||||
#include "../gs_libs/gs_csv.h"
|
||||
|
||||
gs_memory_arena Scratch = {};
|
||||
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
|
||||
|
@ -29,6 +30,11 @@ bool PathTest (char* In, char* Out) {
|
|||
return StringsEqual(SanitizePath(ConstString(In), &Scratch), ConstString(Out));
|
||||
}
|
||||
|
||||
global char* SampleCSV = R"FOO(Flower Primary Hue (0-365) Secondary Hue (0-365) Tertiary Hue (0-365) Homonyms
|
||||
Flower A 55 32 128 foo, bar, blah, baz, whatever
|
||||
Flower B 123 344 32 foo, bar, blah, baz, whatever
|
||||
Flower C 55 32 128 foo, bar, blah, baz, whatever)FOO";
|
||||
|
||||
int main (int ArgCount, char** Args)
|
||||
{
|
||||
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch");
|
||||
|
@ -99,6 +105,24 @@ int main (int ArgCount, char** Args)
|
|||
TestResult(PathTest("C:\\hello\\world\\.\\test", "C:\\hello\\world\\test"));
|
||||
}
|
||||
|
||||
Test("gs_csv.h")
|
||||
{
|
||||
gs_const_string TestCSV = ConstString(SampleCSV);
|
||||
gscsv_sheet Sheet = CSV_Parse(TestCSV, { '\t' }, &Scratch);
|
||||
|
||||
gs_const_string Cell = CSVSheet_GetCell(Sheet, 0, 0);
|
||||
TestResult(StringsEqual(Cell, ConstString("Flower")));
|
||||
|
||||
Cell = CSVSheet_GetCell(Sheet, 1, 1);
|
||||
TestResult(StringsEqual(Cell, ConstString("55")));
|
||||
|
||||
Cell = CSVSheet_GetCell(Sheet, 4, 1);
|
||||
TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever")));
|
||||
|
||||
Cell = CSVSheet_GetCell(Sheet, 4, 3);
|
||||
TestResult(StringsEqual(Cell, ConstString("foo, bar, blah, baz, whatever")));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue