/** * 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 );