Dawn/src/file/csv.h
2021-09-18 23:13:05 -07:00

191 lines
5.7 KiB
C

/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "../libs.h"
#include "asset.h"
#include "../util/array.h"
/** Maximum characters that a cell can support */
#define CSV_BUFFER_SIZE 32
/** Maximum characters in any given cell */
#define CSV_CELL_SIZE_MAX 1024
/** Maximum number of columns/cells in a given row */
#define CSV_ROW_COLUMNS_MAX 16
/** Count of characters maximum that a row can support */
#define CSV_ROW_CHARACTERS_MAX CSV_CELL_SIZE_MAX * CSV_ROW_COLUMNS_MAX
/** Result of a CSV buffer operation. */
typedef struct {
/** How many rows within the CSV */
int32_t rowCount;
/** Count of columns in the CSV, this is the longest row in the CSV. */
int32_t columnCount;
/** How many cells within the CSV */
int32_t cellCount;
} csvbufferresult_t;
/** Callback to receive data for each cell in a CSV being buffered */
typedef bool csvbuffercallback_t(
assetbuffer_t *asset, void *user, int32_t row, int32_t column, char *data
);
/** Representation of a CSV Row's complete data. */
typedef struct {
/** Characters within the row */
char data[CSV_ROW_CHARACTERS_MAX];
/** Pointer to the start of each string within the row */
char *columns[CSV_ROW_COLUMNS_MAX];
/** How many columns within the row */
int32_t columnCount;
} csvrow_t;
/** Callback to receive buffer data for a CSV row */
typedef bool csvbufferrowcallback_t(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/** Callback to receive buffer data for a CSV row, but includes CSV headers. */
typedef bool csvbufferrowwitheaderscallback_t(
assetbuffer_t *asset, void *user, int32_t row,
csvrow_t *header, csvrow_t *current
);
/** Data used by the cell callback for when the row buffering is progressing */
typedef struct {
/** Which row the current buffer is on */
int32_t row;
/** Information about the current row being parsed */
csvrow_t rowCurrent;
/** Pointer to custom user data */
void *user;
/** Pointer to custom user callback */
csvbufferrowcallback_t *callback;
} csvbufferrowdata_t;
/** Data used by the row callback for when the header row is parsed */
typedef struct {
/** Information about the header row */
csvrow_t headerRow;
/** Pointer to custom user data */
void *user;
/** Pointer to custom user callback */
csvbufferrowwitheaderscallback_t *callback;
} csvbufferrowwithheadersdata_t;
/** Data used while searching a CSV */
typedef struct {
/** Row to store the data in */
csvrow_t *row;
/** Row's index */
int32_t rowIndex;
/** Column to check */
int32_t column;
/** Value to check row */
char *value;
} csvsearchdata_t;
/**
* Buffer each cell within a CSV Asset Buffer with a callback.
*
* @param asset Asset to buffer the CSV from.
* @param callback Callback to fire for each cell parsed.
* @param user Pointer to any custom user data.
* @return The result of the CSV Buffer Operation.
*/
csvbufferresult_t csvBuffer(
assetbuffer_t *asset, csvbuffercallback_t *callback, void *user
);
/** Callback for when the CSV Row Buffer is parsing a row */
bool _csvBufferRowParserCallback(
assetbuffer_t *asset, void *user, int32_t row, int32_t column, char *data
);
/**
* Buffer each row within a CSV Asset Buffer with a callback.
*
* @param asset Asset to buffer the CSV from.
* @param callback Callback to fire when a row is parsed.
* @param user Pointer to any custom user data.
* @return The result of the CSV Buffer Operation.
*/
csvbufferresult_t csvBufferRow(
assetbuffer_t *asset, csvbufferrowcallback_t *callback, void *user
);
/** Parser that the header parser buffer uses. */
bool _csvBufferRowWithHeadersCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/**
* Buffer each row within a CSV Asset Buffer with a callback. This will also
* provide the callback with the header row (The first row), already parsed.
*
* @param asset
* @param callback
* @param user
* @return csvbufferresult_t
*/
csvbufferresult_t csvBufferRowWithHeaders(
assetbuffer_t *asset, csvbufferrowwitheaderscallback_t *callback, void *user
);
/**
* Essentially a CSV Row Cloner, copies data from one CSV row to another and
* updates the char pointers for you.
*
* @param source The source CSV row to copy from.
* @param dest The destination CSV row to copy to.
*/
void csvRowPopulate(csvrow_t *source, csvrow_t *dest);
/** Callback used to parse and get the headers row */
bool _csvHeadersGetCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *current
);
/**
* Parses just the headers row from a CSV and stores the output into the
* provided buffers.
*
* @param asset Asset to get the headers from.
* @param row The CSV Row to store the headers data in.
* @return The result of the buffer operation.
*/
csvbufferresult_t csvHeadersGet(assetbuffer_t *asset, csvrow_t *row);
/**
* Gets the column index within the CSV Row for the specific key.
* @param row Row to get from.
* @param key Key to search for
* @return The column index for the key, or -1 if not found.
*/
int32_t csvColumnGetIndex(csvrow_t *row, char *key);
/** Callback to use while scanning the CSV to find the matching row */
bool _csvRowSearchCallback(
assetbuffer_t *asset, void *user, int32_t row, csvrow_t *csv
);
/**
* Search the CSV for a matching row. Will return data only if the given column
* matches the given value.
*
* @param asset Asset buffer to search.
* @param row Where the returned row will be stored.
* @param column Column to check.
* @param value Value to check in that column
* @return The row index that the result was found on, or -1 if not found.
*/
int32_t csvRowSearch(
assetbuffer_t *asset, csvrow_t *row, int32_t column, char *value
);