#ifndef CSV_PARSER_H #define CSV_PARSER_H #include #include #include /* Forward declarations */ typedef struct csv_parser csv_parser_t; typedef struct csv_field csv_field_t; typedef struct csv_record csv_record_t; typedef struct csv_document csv_document_t; /* Error codes */ typedef enum { CSV_SUCCESS = 0, CSV_ERROR_MEMORY = -1, CSV_ERROR_PARSE = -2, CSV_ERROR_INVALID_PARAM = -3, CSV_ERROR_IO = -4 } csv_error_t; /* Error information structure */ typedef struct { const char *message; /* Error message (valid until next parse operation) */ int line; /* Line number where error occurred (1-based, 0 if unknown) */ int column; /* Column number where error occurred (1-based, 0 if unknown) */ bool has_location; /* Whether line/column information is available */ } csv_error_info_t; /* CSV field structure - represents a single cell value in the CSV */ struct csv_field { char *value; /* Field value (null-terminated string) */ struct csv_field *next; /* Next field in the record */ }; /* CSV record structure - represents a single row in the CSV */ struct csv_record { csv_field_t *fields; /* Linked list of field values */ size_t field_count; /* Number of fields in this record */ struct csv_record *next; /* Next record in the document */ }; /* CSV document structure - represents the complete parsed CSV */ struct csv_document { csv_record_t *records; /* Linked list of data records (excluding header) */ size_t record_count; /* Number of data records (excluding header) */ csv_record_t *header; /* Optional header record (can be NULL) */ }; /* Parser context (opaque, stateful - maintains error state between operations) */ struct csv_parser; /** * Create a new CSV parser context * @return Parser context or NULL on error * @note Parser maintains error state; create separate parsers for concurrent use */ csv_parser_t *csv_parser_create(void); /** * Destroy a CSV parser context and free all associated memory * @param parser Parser context to destroy (NULL is safe to pass) */ void csv_parser_destroy(csv_parser_t *parser); /** * Parse CSV data from a string * @param parser Parser context (must not be NULL) * @param input Input CSV string (null-terminated, must not be NULL) * @param document Pointer to store the parsed document (must not be NULL) * @return CSV_SUCCESS on success, error code on failure * @note The parser will set *document to NULL on failure */ csv_error_t csv_parser_parse_string(csv_parser_t *parser, const char *input, csv_document_t **document); /** * Parse CSV data from a file pointer * @param parser Parser context (must not be NULL) * @param file Open file pointer (must not be NULL and readable) * @param document Pointer to store the parsed document (must not be NULL) * @return CSV_SUCCESS on success, error code on failure * @note The parser will set *document to NULL on failure * @note File position will be advanced to end of parsed content */ csv_error_t csv_parser_parse_file(csv_parser_t *parser, FILE *file, csv_document_t **document); /** * Get detailed error information from the parser * @param parser Parser context (must not be NULL) * @return Error information structure * @note The returned message pointer is valid until the next parse operation */ csv_error_info_t csv_parser_get_error_info(csv_parser_t *parser); /** * Free a CSV document and all associated memory * @param document Document to free (NULL is safe to pass) */ void csv_document_free(csv_document_t *document); /** * Convert error code to human-readable string * @param error Error code * @return Error description string */ const char *csv_error_string(csv_error_t error); /* Data access helper functions */ /** * Check if document has a header record * @param document CSV document (must not be NULL) * @return true if header exists, false if not */ bool csv_document_has_header(const csv_document_t *document); /** * Get the first data record from document (skipping header if present) * @param document CSV document (must not be NULL) * @return First data record or NULL if empty */ csv_record_t *csv_document_get_first_record(const csv_document_t *document); /** * Get the next record in sequence * @param record Current record (must not be NULL) * @return Next record or NULL if at end */ csv_record_t *csv_record_get_next(const csv_record_t *record); /** * Get the first field from a record * @param record CSV record (must not be NULL) * @return First field or NULL if record is empty */ csv_field_t *csv_record_get_first_field(const csv_record_t *record); /** * Get the next field in sequence * @param field Current field (must not be NULL) * @return Next field or NULL if at end */ csv_field_t *csv_field_get_next(const csv_field_t *field); /** * Get field value as string * @param field CSV field (must not be NULL) * @return Field value string or NULL on error * @note Returns the parsed string value from a CSV cell */ const char *csv_field_get_value(const csv_field_t *field); /** * Set the first record as the header (moves it from records to header) * @param document CSV document (must not be NULL and have at least one record) * @return CSV_SUCCESS on success, error code on failure * @note This operation modifies the document structure by promoting the first data record */ csv_error_t csv_document_set_first_record_as_header(csv_document_t *document); #endif /* CSV_PARSER_H */