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("Setting Working Directory\n");
|
||||||
OutputDebugStringA(WorkingDirectory.Str);
|
OutputDebugStringA(WorkingDirectory.Str);
|
||||||
|
OutputDebugStringA("\n");
|
||||||
Result = SetCurrentDirectory(WorkingDirectory.Str);
|
Result = SetCurrentDirectory(WorkingDirectory.Str);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
{
|
{
|
||||||
|
@ -525,6 +525,8 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
||||||
|
|
||||||
#include "../../gs_libs/gs_path.h"
|
#include "../../gs_libs/gs_path.h"
|
||||||
|
|
||||||
|
#include "../../gs_libs/gs_csv.h"
|
||||||
|
|
||||||
int WINAPI
|
int WINAPI
|
||||||
WinMain (
|
WinMain (
|
||||||
HINSTANCE HInstance,
|
HINSTANCE HInstance,
|
||||||
|
@ -541,13 +543,29 @@ WinMain (
|
||||||
|
|
||||||
ThreadContext.Allocator.Debug = &AllocDebug;
|
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;
|
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);
|
MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
|
||||||
Win32UpdateWindowDimension(&MainWindow);
|
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_tests.h"
|
||||||
|
|
||||||
#include "../gs_libs/gs_path.h"
|
#include "../gs_libs/gs_path.h"
|
||||||
|
#include "../gs_libs/gs_csv.h"
|
||||||
|
|
||||||
gs_memory_arena Scratch = {};
|
gs_memory_arena Scratch = {};
|
||||||
void* Alloc(u64 Size, u64* ResultSize) { *ResultSize = Size; return malloc(Size); }
|
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));
|
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)
|
int main (int ArgCount, char** Args)
|
||||||
{
|
{
|
||||||
Scratch = CreateMemoryArena(CreateAllocator(Alloc, Free), "Scratch");
|
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"));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue