Compare commits
28 Commits
1156c9debf
...
9ac6ee03e4
Author | SHA1 | Date | |
---|---|---|---|
9ac6ee03e4 | |||
9cdf20e7a7 | |||
924e47bacc | |||
b0e3062d59 | |||
959ffce49f | |||
27fdceb684 | |||
d6f0b0260e | |||
4b3c7bbb97 | |||
99995d7b0f | |||
638af0080d | |||
006cd346e9 | |||
679160e208 | |||
042667e538 | |||
0793a5a1c6 | |||
46ed839860 | |||
7ce936b8d1 | |||
cba239de98 | |||
c19760c62f | |||
1a0e8e5bcb | |||
4647b72551 | |||
61618b72bc | |||
3178e0eccf | |||
39059b3e49 | |||
3304163ab0 | |||
2fa4ca384c | |||
bb1e4aef4f | |||
769322ec6b | |||
d4b53ede9b |
@ -1,13 +1,73 @@
|
||||
#ifndef EASYCSV_H
|
||||
#define EASYCSV_H
|
||||
|
||||
#include "../src/_easycsv.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Public easycsv members */
|
||||
typedef struct easycsv {
|
||||
/*** Generic type definitions for internal use ***/
|
||||
|
||||
typedef uint32_t row_t; // max length of 2^32 - 1
|
||||
typedef uint32_t column_t;
|
||||
typedef char* rowstr; // non-const, to free it after usage
|
||||
|
||||
/*** Flags ***/
|
||||
|
||||
/** Flags to facilitate changing modes during file copying phases */
|
||||
typedef enum {
|
||||
EASYCSV_UNKNOWNMODE = 0,
|
||||
EASYCSV_R,
|
||||
EASYCSV_W
|
||||
} EASYCSV_MODE;
|
||||
|
||||
/** Flags to parameterise the easycsv_insertvalue */
|
||||
typedef enum {
|
||||
EASYCSV_REPLACE, ///< (default) replaces word
|
||||
EASYCSV_CONCAT, ///< concantates word at the end
|
||||
EASYCSV_RCONCAT, ///< concantates word from the start
|
||||
} EASYCSV_VALMODE;
|
||||
|
||||
/** Flags to parameterise sorting */
|
||||
typedef enum {
|
||||
EASYCSV_ALPHA, ///< sort alphabetically
|
||||
EASYCSV_RALPHA, ///< sort reverse alphabetically
|
||||
EASYCSV_NUMER, ///< sort numerically, from lowest value to highest
|
||||
EASYCSV_RNUMER ///< sort from highest value to lowest
|
||||
} EASYCSV_SORT;
|
||||
|
||||
/** Flags denoting cell type */
|
||||
typedef enum {
|
||||
EASYCSV_NONE,
|
||||
EASYCSV_STRING,
|
||||
EASYCSV_INT,
|
||||
EASYCSV_FLOAT,
|
||||
EASYCSV_UNKNOWNTYPE
|
||||
} _EASYCSV_TYPE;
|
||||
|
||||
/*** Structures ***/
|
||||
|
||||
/**
|
||||
* easycsv:
|
||||
*
|
||||
* A CSV file.
|
||||
*/
|
||||
typedef struct _easycsv easycsv;
|
||||
struct _easycsv {
|
||||
FILE *file; ///< original CSV file
|
||||
FILE *temp; ///< temporary CSV file for writing
|
||||
char fp[BUFSIZ];
|
||||
// char *tmpfp;
|
||||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
// EASYCSV_ERRORMSG error;
|
||||
EASYCSV_MODE mode;
|
||||
_easycsv *_priv;
|
||||
} easycsv;
|
||||
};
|
||||
|
||||
/*** Constructors ***/
|
||||
|
||||
@ -21,17 +81,17 @@ easycsv*
|
||||
easycsv_init(const char*,
|
||||
const EASYCSV_MODE);
|
||||
|
||||
/**
|
||||
* Initialise easycsv structure with a given error message mode
|
||||
* @param[in] relative path to CSV file
|
||||
* @param[in] easycsv mode
|
||||
* @param[in] easycsv error message mode
|
||||
* @return pointer to easycsv structure
|
||||
*/
|
||||
easycsv*
|
||||
easycsv_init_errormsg(const char*,
|
||||
const EASYCSV_MODE,
|
||||
const EASYCSV_ERRORMSG);
|
||||
/* /\** */
|
||||
/* * Initialise easycsv structure with a given error message mode */
|
||||
/* * @param[in] relative path to CSV file */
|
||||
/* * @param[in] easycsv mode */
|
||||
/* * @param[in] easycsv error message mode */
|
||||
/* * @return pointer to easycsv structure */
|
||||
/* *\/ */
|
||||
/* easycsv* */
|
||||
/* easycsv_init_errormsg(const char*, */
|
||||
/* const EASYCSV_MODE, */
|
||||
/* const EASYCSV_ERRORMSG); */
|
||||
|
||||
/**
|
||||
* Destroy easycsv structure
|
||||
@ -40,18 +100,27 @@ easycsv_init_errormsg(const char*,
|
||||
void
|
||||
easycsv_free(easycsv*);
|
||||
|
||||
/*** Error handling ***/
|
||||
|
||||
/**
|
||||
* Get error message
|
||||
* @return easycsv error message
|
||||
*/
|
||||
char*
|
||||
easycsv_get_error();
|
||||
|
||||
/*** Access, find ***/
|
||||
|
||||
/**
|
||||
* Find value and returns row and column
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @param[in] value to find
|
||||
* @param[out] row number
|
||||
* @param[out] column number
|
||||
* @return easycsv error code
|
||||
* @param[out] pointer to column number, unchanged if error
|
||||
* @param[out] pointer to row number, unchanged if error
|
||||
* @return 0 if success, -1 if error
|
||||
*/
|
||||
int
|
||||
easycsv_findvalue(const easycsv*,
|
||||
easycsv_find_value(const easycsv*,
|
||||
const char*,
|
||||
unsigned int*,
|
||||
unsigned int*);
|
||||
@ -60,55 +129,56 @@ easycsv_findvalue(const easycsv*,
|
||||
* Find number of instances of value
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @param[in] value to find
|
||||
* @return number of instances
|
||||
* @return positive integer if success, -1 if error
|
||||
*/
|
||||
int
|
||||
easycsv_findnumvalue(const easycsv*,
|
||||
easycsv_find_num_value(const easycsv*,
|
||||
const char*);
|
||||
|
||||
/*** Access, read ***/
|
||||
|
||||
/**
|
||||
* Read string in a specific cell
|
||||
* String is heap-allocated, it must be destroyed (free'd) manually
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @param[in] row number
|
||||
* @param[in] column number
|
||||
* @return string value of cell, NULL if empty cell
|
||||
* @return string value of cell, NULL if error
|
||||
*/
|
||||
char*
|
||||
easycsv_readvalue(const easycsv*,
|
||||
easycsv_read_value(const easycsv*,
|
||||
unsigned int,
|
||||
unsigned int);
|
||||
|
||||
/**
|
||||
* Read string in a specific cell with named column in row 1
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @param[in] row value
|
||||
* @param[in] column number
|
||||
* @return string value of cell, NULL if empty cell
|
||||
*/
|
||||
char*
|
||||
easycsv_readcolumnvalue(const easycsv*,
|
||||
const char*,
|
||||
unsigned int);
|
||||
/* /\** */
|
||||
/* * Read string in a specific cell with named column in row 1 */
|
||||
/* * @param[in] constant pointer to easycsv structure */
|
||||
/* * @param[in] row value */
|
||||
/* * @param[in] column number */
|
||||
/* * @return string value of cell, NULL if empty cell */
|
||||
/* *\/ */
|
||||
/* char* */
|
||||
/* easycsv_readcolumnvalue(const easycsv*, */
|
||||
/* const char*, */
|
||||
/* unsigned int); */
|
||||
|
||||
/*** Access, print ***/
|
||||
|
||||
/**
|
||||
* Return number of rows
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @return number of rows
|
||||
* @return number of rows, -1 if error
|
||||
*/
|
||||
int
|
||||
easycsv_printrows(const easycsv*);
|
||||
easycsv_print_rows(const easycsv*);
|
||||
|
||||
/**
|
||||
* Return number of columns
|
||||
* @param[in] constant pointer to easycsv structure
|
||||
* @return number of columns
|
||||
* @return number of columns, -1 if error
|
||||
*/
|
||||
int
|
||||
easycsv_printcolumns(const easycsv*);
|
||||
easycsv_print_columns(const easycsv*);
|
||||
|
||||
/*** Modifications, sort ***/
|
||||
|
||||
@ -138,25 +208,25 @@ easycsv_sortcolumn(easycsv*,
|
||||
|
||||
/*** Modifications, insert ***/
|
||||
|
||||
/**
|
||||
* Insert row into CSV file
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] cell value
|
||||
* @param[in] row number
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_insertrow(easycsv*,
|
||||
const char*,
|
||||
int);
|
||||
/* /\** */
|
||||
/* * Insert row into CSV file */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] cell value */
|
||||
/* * @param[in] row number */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_insertrow(easycsv*, */
|
||||
/* const char*, */
|
||||
/* int); */
|
||||
|
||||
/**
|
||||
* Insert string in a specific cell
|
||||
* Insert/replace string in a specific cell
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] cell value
|
||||
* @param[in] row number
|
||||
* @param[in] cell value (cell value will not be modified if there is an error)
|
||||
* @param[in] column number
|
||||
* @return easycsv error code
|
||||
* @param[in] row number
|
||||
* @return 0 if no error, -1 if error
|
||||
*/
|
||||
int
|
||||
easycsv_insertvalue(easycsv*,
|
||||
@ -164,75 +234,75 @@ easycsv_insertvalue(easycsv*,
|
||||
unsigned int,
|
||||
unsigned int);
|
||||
|
||||
/**
|
||||
* Insert string in a specific cell with specific mode
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] cell value
|
||||
* @param[in] row number
|
||||
* @param[in] column number
|
||||
* @param[in] easycsv value mode
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_insertvaluemode(easycsv*,
|
||||
const char*,
|
||||
unsigned int,
|
||||
unsigned int,
|
||||
EASYCSV_VALMODE);
|
||||
/* /\** */
|
||||
/* * Insert string in a specific cell with specific mode */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] cell value */
|
||||
/* * @param[in] row number */
|
||||
/* * @param[in] column number */
|
||||
/* * @param[in] easycsv value mode */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_insertvaluemode(easycsv*, */
|
||||
/* const char*, */
|
||||
/* unsigned int, */
|
||||
/* unsigned int, */
|
||||
/* EASYCSV_VALMODE); */
|
||||
|
||||
/**
|
||||
* Insert string in a specific cell with named column in a given row
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] cell value
|
||||
* @param[in] row number
|
||||
* @param[in] column value
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_insertcolumnvalue(easycsv*,
|
||||
const char*,
|
||||
unsigned int,
|
||||
const char*);
|
||||
/* /\** */
|
||||
/* * Insert string in a specific cell with named column in a given row */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] cell value */
|
||||
/* * @param[in] row number */
|
||||
/* * @param[in] column value */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_insertcolumnvalue(easycsv*, */
|
||||
/* const char*, */
|
||||
/* unsigned int, */
|
||||
/* const char*); */
|
||||
|
||||
/**
|
||||
* Insert string in a specific cell with named column in a given row with specific mode
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] cell value
|
||||
* @param[in] row number
|
||||
* @param[in] column value
|
||||
* @param[in] easycsv value mode
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_insertcolumnvaluemode(easycsv*,
|
||||
const char*,
|
||||
unsigned int,
|
||||
const char*,
|
||||
EASYCSV_VALMODE);
|
||||
/* /\** */
|
||||
/* * Insert string in a specific cell with named column in a given row with specific mode */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] cell value */
|
||||
/* * @param[in] row number */
|
||||
/* * @param[in] column value */
|
||||
/* * @param[in] easycsv value mode */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_insertcolumnvaluemode(easycsv*, */
|
||||
/* const char*, */
|
||||
/* unsigned int, */
|
||||
/* const char*, */
|
||||
/* EASYCSV_VALMODE); */
|
||||
|
||||
/*** Modifications, push ***/
|
||||
|
||||
/**
|
||||
* Create new column on the right-hand side of an existing one
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] column value
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_pushcolumn(easycsv*,
|
||||
const char*);
|
||||
/* /\** */
|
||||
/* * Create new column on the right-hand side of an existing one */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] column value */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_pushcolumn(easycsv*, */
|
||||
/* const char*); */
|
||||
|
||||
/**
|
||||
* Insert string in a vacant cell under a named column
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] column value
|
||||
* @param[in] cell value
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_pushcolumnvalue(easycsv*,
|
||||
const char*,
|
||||
const char*);
|
||||
/* /\** */
|
||||
/* * Insert string in a vacant cell under a named column */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] column value */
|
||||
/* * @param[in] cell value */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_pushcolumnvalue(easycsv*, */
|
||||
/* const char*, */
|
||||
/* const char*); */
|
||||
|
||||
/*** Modifications, delete ***/
|
||||
|
||||
@ -248,24 +318,24 @@ easycsv_deletevalue(easycsv*,
|
||||
unsigned int,
|
||||
unsigned int);
|
||||
|
||||
/**
|
||||
* Delete numbered column
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] column number
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_deletecolumnint(easycsv*,
|
||||
unsigned int);
|
||||
/* /\** */
|
||||
/* * Delete numbered column */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] column number */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_deletecolumnint(easycsv*, */
|
||||
/* unsigned int); */
|
||||
|
||||
/** Delete named column
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @param[in] column value
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_deletecolumnstr(easycsv*,
|
||||
const char*);
|
||||
/* /\** Delete named column */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @param[in] column value */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_deletecolumnstr(easycsv*, */
|
||||
/* const char*); */
|
||||
|
||||
/* Delete numered row */
|
||||
|
||||
@ -273,24 +343,24 @@ easycsv_deletecolumnstr(easycsv*,
|
||||
|
||||
/*** Modifications, append ***/
|
||||
|
||||
/**
|
||||
* Append two CSV files
|
||||
* @param[in] destination CSV file
|
||||
* @param[in] source CSV file
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_appendcsv(easycsv*,
|
||||
easycsv*);
|
||||
/* /\** */
|
||||
/* * Append two CSV files */
|
||||
/* * @param[in] destination CSV file */
|
||||
/* * @param[in] source CSV file */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_appendcsv(easycsv*, */
|
||||
/* easycsv*); */
|
||||
|
||||
/*** Modifications, miscellenaeous ***/
|
||||
|
||||
/**
|
||||
* Compress a CSV file
|
||||
* @param[in] pointer to easycsv structure
|
||||
* @return easycsv error code
|
||||
*/
|
||||
int
|
||||
easycsv_compress(easycsv*);
|
||||
/* /\** */
|
||||
/* * Compress a CSV file */
|
||||
/* * @param[in] pointer to easycsv structure */
|
||||
/* * @return easycsv error code */
|
||||
/* *\/ */
|
||||
/* int */
|
||||
/* easycsv_compress(easycsv*); */
|
||||
|
||||
#endif /* EASYCSV_H */
|
||||
|
@ -1,6 +1,12 @@
|
||||
lib_LTLIBRARIES = libeasycsv.la
|
||||
lib_LTLIBRARIES = libeasycsv.la libeasycsv_string.la
|
||||
libeasycsv_la_SOURCES = \
|
||||
_easycsv.c \
|
||||
_easycsv.h \
|
||||
easycsv.c
|
||||
easycsv.c \
|
||||
easycsv_error.h \
|
||||
easycsv_error.c \
|
||||
easycsv_p.h \
|
||||
easycsv_p.c
|
||||
libeasycsv_la_LIBADD = libeasycsv_string.la
|
||||
libeasycsv_string_la_SOURCES = \
|
||||
easycsv_string.h \
|
||||
easycsv_string.c
|
||||
include_HEADERS = ../include/easycsv.h
|
||||
|
506
src/_easycsv.c
506
src/_easycsv.c
@ -1,506 +0,0 @@
|
||||
#include "_easycsv.h"
|
||||
|
||||
/* (Constructor) Initialise _easycsv */
|
||||
_easycsv*
|
||||
_easycsv_priv_init(const char *fp,
|
||||
const EASYCSV_MODE mode,
|
||||
const EASYCSV_ERRORMSG error)
|
||||
{
|
||||
_easycsv *_priv = malloc(sizeof(_easycsv));
|
||||
|
||||
_priv->file = NULL;
|
||||
_priv->temp = NULL;
|
||||
_priv->fp = NULL;
|
||||
_priv->tmpfp = NULL;
|
||||
_priv->rows = 0;
|
||||
_priv->cols = 0;
|
||||
#ifdef EASYCSV_DEBUG
|
||||
_priv->start = 0;
|
||||
#endif
|
||||
|
||||
_priv->error = error;
|
||||
|
||||
/* Open file according to mode */
|
||||
switch (mode) {
|
||||
case EASYCSV_R: {
|
||||
_priv->file = fopen(fp, "r");
|
||||
break;
|
||||
}
|
||||
case EASYCSV_W: {
|
||||
_priv->file = fopen(fp, "w");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
_easycsv_printerror(_priv, EASYCSV_UNKNOWNIOMODE);
|
||||
_easycsv_priv_free(_priv);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_priv->file == NULL)
|
||||
{
|
||||
_easycsv_printerror(_priv, EASYCSV_OPENFAIL);
|
||||
_easycsv_priv_free(_priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t stfp = strlen(fp);
|
||||
|
||||
/* Allocate memory for char* */
|
||||
_priv->fp = malloc(stfp + 1); // + 1 for null
|
||||
|
||||
strcpy(_priv->fp, fp);
|
||||
|
||||
/* Calculate rows and cols if file exists */
|
||||
if (access(_priv->fp, F_OK) == 0) {
|
||||
_priv->rows = _easycsv_rows(_priv, mode);
|
||||
_priv->cols = _easycsv_columns(_priv, mode);
|
||||
}
|
||||
|
||||
if (mode == EASYCSV_W) {
|
||||
|
||||
/* csv->tmpfp = malloc(16 + stfp + 1); */
|
||||
/* strncpy(csv->tmpfp, prefix, 16); */
|
||||
|
||||
/* strncat(csv->tmpfp, fp, stfp); */
|
||||
|
||||
do {
|
||||
/* Write to temporary file */
|
||||
unsigned int i = 1;
|
||||
char buffer[21] = "/tmp/easycsv-"; // 13 char, 3 for digits, 4 for .csv, 1 for NULL
|
||||
|
||||
if (i < 100)
|
||||
strncat(buffer, "0", 1);
|
||||
|
||||
if (i < 10)
|
||||
strncat(buffer, "0", 1);
|
||||
|
||||
sprintf(buffer + strlen(buffer), "%i", i);
|
||||
strcat(buffer, ".csv");
|
||||
|
||||
if (access(buffer, F_OK) < 0) {
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
_priv->tmpfp = malloc(21);
|
||||
strncpy(_priv->tmpfp, buffer, 21);
|
||||
break;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
_priv->temp = fopen(_priv->tmpfp, "w");
|
||||
if (_priv->temp == NULL) {
|
||||
_easycsv_printerror(_priv, EASYCSV_OPENFAIL);
|
||||
_easycsv_priv_free(_priv);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
#ifdef EASYCSV_DEBUG
|
||||
printf("[%i] easycsv_debug: temp file %s opened\n", clock() - csv->start, csv->tmpfp);
|
||||
#endif*/
|
||||
/*
|
||||
|
||||
if (freopen(csv->fp, csv->mode, csv->file) == NULL) {
|
||||
fprintf(stderr, "easycsv: failed to set temporary file %s to %s mode\n", csv->tmpfp, csv->mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (freopen(csv->tmpfp, csv->mode, csv->temp) == NULL) {
|
||||
fprintf(stderr, "easycsv: failed to set temporary file %s to %s mode\n", csv->tmpfp, csv->mode);
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
return _priv;
|
||||
}
|
||||
|
||||
/* (Destructor) Free _easycsv memory */
|
||||
void
|
||||
_easycsv_priv_free(_easycsv *_priv)
|
||||
{
|
||||
/* ARGS CHECK */
|
||||
if (_priv == NULL)
|
||||
return;
|
||||
/* ARGS CHECK */
|
||||
if (_priv->file != NULL)
|
||||
fclose(_priv->file);
|
||||
if (_priv->temp != NULL)
|
||||
fclose(_priv->temp);
|
||||
if (_priv->fp != NULL)
|
||||
free(_priv->fp);
|
||||
if (_priv->tmpfp != NULL)
|
||||
free(_priv->tmpfp);
|
||||
free(_priv);
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_update(_easycsv *csv)
|
||||
{
|
||||
/* ARGS CHECK */
|
||||
if (csv == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_NULLCSV);
|
||||
return -1;
|
||||
}
|
||||
/* ARGS CHECK */
|
||||
|
||||
/* Set temp file to read binary */
|
||||
if (freopen(csv->tmpfp, "rb", csv->temp) == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_REOPENFAIL);
|
||||
easycsv_free(csv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set file to write binary */
|
||||
if (freopen(csv->fp, "wb", csv->file) == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_REOPENFAIL);
|
||||
easycsv_free(csv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy entire file */
|
||||
char buf[BUFSIZ];
|
||||
size_t size;
|
||||
while (size = fread(buf, 1, BUFSIZ, csv->temp)) {
|
||||
fwrite(buf, 1, size, csv->file);
|
||||
}
|
||||
|
||||
/* Set temp file back to write */
|
||||
if (freopen(csv->tmpfp, "w", csv->temp) == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_REOPENFAIL);
|
||||
easycsv_free(csv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set file back to read */
|
||||
if (freopen(csv->fp, "r", csv->file) == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_REOPENFAIL);
|
||||
easycsv_free(csv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_rows(_easycsv *_priv,
|
||||
const EASYCSV_MODE mode)
|
||||
{
|
||||
// no need to check _priv for NULL
|
||||
|
||||
if (_easycsv_rewind(_priv, mode) < 0)
|
||||
return -1;
|
||||
|
||||
int rows = 1;
|
||||
char c;
|
||||
|
||||
/* Go through each character in the file and count the number of \n
|
||||
in it */
|
||||
while ((c = fgetc(_priv->file)) != EOF) {
|
||||
if (c == '\n') rows++;
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_columns(_easycsv *_priv,
|
||||
const EASYCSV_MODE mode)
|
||||
{
|
||||
// no need to check _priv for NULL
|
||||
|
||||
/* Prepare it for reading */
|
||||
if (_easycsv_rewind(_priv, mode) < 0) return -1;
|
||||
|
||||
/*
|
||||
1. check if empty file
|
||||
2. check if only one column -> 0 commas
|
||||
3. if >1 column, n commas = n+1 columns
|
||||
*/
|
||||
|
||||
int col = 1;
|
||||
char c;
|
||||
|
||||
while ((c = fgetc(_priv->file)) != '\n') {
|
||||
if (c == ',') col++;
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
char*
|
||||
_easycsv_getrow(const _easycsv *csv,
|
||||
const unsigned int row)
|
||||
{
|
||||
/* ARGS CHECK */
|
||||
if (csv == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_NULLCSV);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (row > csv->rows) {
|
||||
_easycsv_printerror(csv, EASYCSV_OVERMAXROW);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (row == 0) {
|
||||
_easycsv_printerror(csv, EASYCSV_ZEROROW);
|
||||
return NULL;
|
||||
}
|
||||
/* END ARGS CHECK */
|
||||
|
||||
/* Allocate memory */
|
||||
char *str = malloc(BUFSIZ);
|
||||
|
||||
/* Set file pointer to start */
|
||||
rewind(csv->file);
|
||||
|
||||
for (int i = 1; i < row; i++)
|
||||
{
|
||||
/* skip until row is reached */
|
||||
fscanf(csv->file, "%*[^\n]\n", NULL);
|
||||
}
|
||||
|
||||
/* Grab the row and store it in str */
|
||||
fscanf(csv->file, "%s\n", str);
|
||||
|
||||
// printf("row: %s\n", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_rewind(_easycsv *_priv,
|
||||
const EASYCSV_MODE mode)
|
||||
{
|
||||
/* Check if empty file */
|
||||
if (fscanf(_priv->file, "\n") == EOF) {
|
||||
_easycsv_printerror(_priv, EASYCSV_EMPTYCSV);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if file is readable */
|
||||
if (mode != EASYCSV_R) {
|
||||
_easycsv_printerror(_priv, EASYCSV_UNREADABLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set file pointer to the start */
|
||||
rewind(_priv->file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_getcolumn(const _easycsv *csv,
|
||||
const char *col)
|
||||
{
|
||||
/* ARGS CHECK */
|
||||
if (_easycsv_checkcsvandstring_one(csv, col) < 0)
|
||||
return -1;
|
||||
/* ARGS CHECK */
|
||||
|
||||
/* Grab str of row 1 */
|
||||
char *firstrow = _easycsv_getrow(csv, 1);
|
||||
|
||||
if (firstrow == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_ROWNOTEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int commas = 0;
|
||||
|
||||
// printf("FIRST COLUMN: %s\n", firstrow);
|
||||
|
||||
/* Find first occurance of col in firstrow */
|
||||
char *str = strstr(firstrow, col);
|
||||
|
||||
if (str == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_COLNOTEXIST);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Count numbers of commas following str */
|
||||
char *c = strpbrk(str, ",");
|
||||
while (c != NULL) {
|
||||
commas++;
|
||||
c = strpbrk(c + 1, ",");
|
||||
}
|
||||
|
||||
/* no need to free c as it is already NULL at this point */
|
||||
// free((char*) str); apparently invalid pointer
|
||||
|
||||
// printf("ROW: %i\nCOL: %i\n", row, csv->cols - commas);
|
||||
/*
|
||||
#ifdef EASYCSV_DEBUG
|
||||
printf("[%i] rcv_commas: %i\n", clock() - csv->start, commas);
|
||||
#endif
|
||||
*/
|
||||
free(firstrow);
|
||||
|
||||
return csv->cols - commas;
|
||||
}
|
||||
|
||||
/*
|
||||
int _easycsv_checkifvalue(struct easycsv *csv, const int col, const int row)
|
||||
{
|
||||
const char *rowstr = _easycsv_getrow(csv, row);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
char*
|
||||
_easycsv_getvalueinrow(const _easycsv *_priv,
|
||||
const char *row,
|
||||
const unsigned int col)
|
||||
{
|
||||
size_t st;
|
||||
char *pch = NULL;
|
||||
|
||||
/* If not first column */
|
||||
if (col != 1) {
|
||||
|
||||
/* Get first occurance of comma in str,
|
||||
the first value is ommited but not the comma */
|
||||
char *pch = strpbrk(row, ",");
|
||||
|
||||
/* Repeat until desired col is found */
|
||||
for (int i = 2; i < col; i++) {
|
||||
pch = strpbrk(pch + 1, ",");
|
||||
}
|
||||
}
|
||||
|
||||
/* Get span from start of string to first occurence
|
||||
of comma */
|
||||
st = strcspn(pch + 1, ",");
|
||||
|
||||
/* If 0, no string exists! */
|
||||
if (st == 0) {
|
||||
_easycsv_printerror(_priv, EASYCSV_EMPTYVALUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *val = malloc(st + 1);
|
||||
strncpy(val, pch + 1, st);
|
||||
strncat(val, "\0", 1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
char*
|
||||
_easycsv_setcharptovalue(const _easycsv *_priv,
|
||||
const char *rowstr,
|
||||
const unsigned int col)
|
||||
{
|
||||
char *pch = rowstr;
|
||||
|
||||
for (unsigned int i = 1; i < col; i++) {
|
||||
pch = strchr(rowstr, ',');
|
||||
if (pch == NULL) {
|
||||
_easycsv_printerror(_priv, EASYCSV_NULLPTR);
|
||||
return NULL;
|
||||
}
|
||||
pch++;
|
||||
}
|
||||
|
||||
return pch;
|
||||
}
|
||||
|
||||
void
|
||||
_easycsv_printerror(const _easycsv *_priv,
|
||||
const EASYCSV_ERROR error)
|
||||
{
|
||||
switch (_priv->error) {
|
||||
case EASYCSV_ERROROFF: return;
|
||||
case EASYCSV_ERRORSTDOUT: _easycsv_geterror(_priv, error, stdout); break;
|
||||
case EASYCSV_ERRORSTDERR:
|
||||
default: _easycsv_geterror(_priv, error, stderr); return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_easycsv_geterror(const _easycsv *_priv,
|
||||
const EASYCSV_ERROR error,
|
||||
FILE *fs)
|
||||
{
|
||||
#ifdef EASYCSV_DEBUG
|
||||
fprintf(stderr, "[%i] ", clock() - _priv->start);
|
||||
#endif
|
||||
|
||||
fputs("easycsv: ", fs);
|
||||
|
||||
switch (error) {
|
||||
|
||||
/* Generic errors */
|
||||
case EASYCSV_NOERROR: fputs("no error", fs); break;
|
||||
case EASYCSV_NULLCSV: fputs("easycsv pointer is NULL", fs); break;
|
||||
case EASYCSV_NULLPTR: fputs("pointer is NULL", fs); break;
|
||||
case EASYCSV_EMPTYSTRING: fputs("string is empty", fs); break;
|
||||
case EASYCSV_EMPTYVALUE: fputs("value in CSV file is empty", fs); break;
|
||||
case EASYCSV_OVERMAXROW: fprintf(fs, "int exceeds row limit %i", _priv->rows); break;
|
||||
case EASYCSV_OVERMAXCOL: fprintf(fs, "int exceeds column limit %i", _priv->cols); break;
|
||||
case EASYCSV_ZEROROW: fputs("parameterised row number is zero", fs); break;
|
||||
case EASYCSV_ZEROCOL: fputs("parameterised column number is zero", fs); break;
|
||||
|
||||
/* File input/output errors */
|
||||
case EASYCSV_UNKNOWNIOMODE: fputs("unknown file IO mode", fs); break;
|
||||
case EASYCSV_OPENFAIL: fputs("failed to open file", fs); break;
|
||||
case EASYCSV_REOPENFAIL: fputs("failed to reopen file", fs); break;
|
||||
case EASYCSV_EMPTYCSV: fputs("CSV file is empty", fs); break;
|
||||
case EASYCSV_UNWRITABLE: fputs("CSV file is not in a writable mode", fs); break;
|
||||
case EASYCSV_UNREADABLE: fputs("CSV file is not in a readable mode", fs); break;
|
||||
case EASYCSV_UPDATEFAIL: fputs("CSV file has failed to update", fs); break;
|
||||
case EASYCSV_UPDATETEMPFAIL: fputs("failed to update temp CSV file", fs); break;
|
||||
case EASYCSV_FILEPTRFAIL: fputs("failed to move FILE pointer", fs); break;
|
||||
|
||||
/* Non-existant elements */
|
||||
case EASYCSV_ROWNOTEXIST: fputs("given row does not exist", fs); break;
|
||||
case EASYCSV_COLNOTEXIST: fputs("given column does not exist", fs); break;
|
||||
|
||||
/* User-facing failure */
|
||||
case EASYCSV_PUSHCOLFAIL: fputs("failed to push value under column", fs); break;
|
||||
case EASYCSV_COLNUMFAIL: fputs("failed to determine the column number of a value in the first row", fs); break;
|
||||
default: fputs("unknown error, easycsv* is possibly NULL", fs); break;
|
||||
}
|
||||
|
||||
if (_priv->fp != NULL)
|
||||
fprintf(fs, " in %s", _priv->fp);
|
||||
|
||||
fputc('\n', fs);
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_checkcsvandstring_one(const _easycsv *csv,
|
||||
const char *one)
|
||||
{
|
||||
if (csv == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_NULLCSV);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (one == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_EMPTYSTRING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_easycsv_checkcsvandstring_two(const _easycsv *csv,
|
||||
const char *one,
|
||||
const char *two)
|
||||
{
|
||||
if (_easycsv_checkcsvandstring_one(csv, one) < 0)
|
||||
return -1;
|
||||
|
||||
if (two == NULL) {
|
||||
_easycsv_printerror(csv, EASYCSV_EMPTYSTRING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
178
src/_easycsv.h
178
src/_easycsv.h
@ -1,178 +0,0 @@
|
||||
#ifndef _EASYCSV
|
||||
#define _EASYCSV
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "easycsv_error.h"
|
||||
|
||||
/* Generic type definitions for internal use */
|
||||
|
||||
typedef uint32_t row_t; // max length of 2^32 - 1
|
||||
typedef uint32_t column_t;
|
||||
typedef char* rowstr; // non-const, to free it after usage
|
||||
|
||||
/** Flags for error messages */
|
||||
typedef enum {
|
||||
EASYCSV_ERRORSTDERR = 0,
|
||||
EASYCSV_ERROROFF,
|
||||
EASYCSV_ERRORSTDOUT
|
||||
} EASYCSV_ERRORMSG;
|
||||
|
||||
/** Flags to facilitate changing modes during file copying phases */
|
||||
typedef enum {
|
||||
EASYCSV_UNKNOWNMODE = 0,
|
||||
EASYCSV_R,
|
||||
EASYCSV_W
|
||||
} EASYCSV_MODE;
|
||||
|
||||
/** Flags to parameterise the easycsv_insertvalue */
|
||||
typedef enum {
|
||||
EASYCSV_REPLACE, ///< (default) replaces word
|
||||
EASYCSV_CONCAT, ///< concantates word at the end
|
||||
EASYCSV_RCONCAT, ///< concantates word from the start
|
||||
} EASYCSV_VALMODE;
|
||||
|
||||
/** Flags to parameterise sorting */
|
||||
typedef enum {
|
||||
EASYCSV_ALPHA, ///< sort alphabetically
|
||||
EASYCSV_RALPHA, ///< sort reverse alphabetically
|
||||
EASYCSV_NUMER, ///< sort numerically, from lowest value to highest
|
||||
EASYCSV_RNUMER ///< sort from highest value to lowest
|
||||
} EASYCSV_SORT;
|
||||
|
||||
/* Flags denoting cell type */
|
||||
typedef enum {
|
||||
EASYCSV_NONE,
|
||||
EASYCSV_STRING,
|
||||
EASYCSV_INT,
|
||||
EASYCSV_FLOAT,
|
||||
EASYCSV_UNKNOWNTYPE
|
||||
} _EASYCSV_TYPE;
|
||||
|
||||
/* Private easycsv members */
|
||||
typedef struct _easycsv {
|
||||
FILE *file; // original CSV file
|
||||
FILE *temp; // temporary CSV file for writing
|
||||
char *fp;
|
||||
char *tmpfp;
|
||||
unsigned int rows;
|
||||
unsigned int cols;
|
||||
EASYCSV_ERRORMSG error;
|
||||
#ifdef EASYCSV_DEBUG
|
||||
clock_t start;
|
||||
#endif
|
||||
} _easycsv;
|
||||
|
||||
/* (Constructor) Initialise _easycsv */
|
||||
_easycsv*
|
||||
_easycsv_priv_init(const char*,
|
||||
const EASYCSV_MODE,
|
||||
const EASYCSV_ERRORMSG);
|
||||
|
||||
/* (Destructor) Free _easycsv memory */
|
||||
void
|
||||
_easycsv_priv_free(_easycsv*);
|
||||
|
||||
/* Verifies mode of file */
|
||||
// int _easycsv_checkmode(struct easycsv*, const char);
|
||||
|
||||
/* Copies data from temp FILE to file FILE */
|
||||
int
|
||||
_easycsv_update(_easycsv*);
|
||||
|
||||
/* Rewind easycsv, checks for readability */
|
||||
int
|
||||
_easycsv_rewind(_easycsv*,
|
||||
const EASYCSV_MODE);
|
||||
|
||||
/* Returns string of a specific row,
|
||||
includes the '\n' character as well! */
|
||||
char*
|
||||
_easycsv_getrow(const _easycsv*,
|
||||
const unsigned int);
|
||||
|
||||
/* Return column number of a named column */
|
||||
int
|
||||
_easycsv_getcolumn(const _easycsv*,
|
||||
const char*);
|
||||
|
||||
/* Verifies the type of the value (eg: string or int) */
|
||||
_EASYCSV_TYPE
|
||||
_easycsv_checktype(const _easycsv*,
|
||||
const int,
|
||||
const int);
|
||||
|
||||
/* Verifies if there is a value or not */
|
||||
int
|
||||
_easycsv_checkifvalue(const _easycsv*,
|
||||
const int,
|
||||
const int);
|
||||
|
||||
/* Grab const char* in row */
|
||||
char*
|
||||
_easycsv_getvalueinrow(const _easycsv*,
|
||||
const char*,
|
||||
const unsigned int);
|
||||
|
||||
/* Returns char pointer to start of value in rowstr */
|
||||
char*
|
||||
_easycsv_setcharptovalue(const _easycsv*,
|
||||
const char*,
|
||||
const unsigned int);
|
||||
|
||||
/* Insert value in row in specific column */
|
||||
char*
|
||||
_easycsv_insertvalueinrow(const _easycsv*,
|
||||
const char*,
|
||||
const char*,
|
||||
const unsigned int);
|
||||
|
||||
/* Calculate rows */
|
||||
int
|
||||
_easycsv_rows(_easycsv*,
|
||||
const EASYCSV_MODE);
|
||||
|
||||
/* Calculate columns*/
|
||||
int
|
||||
_easycsv_columns(_easycsv*,
|
||||
const EASYCSV_MODE);
|
||||
|
||||
void
|
||||
_easycsv_printerror(const _easycsv*,
|
||||
const EASYCSV_ERROR);
|
||||
|
||||
/* Print error from _easycsv struct in stderr */
|
||||
void
|
||||
_easycsv_geterror(const _easycsv*,
|
||||
const EASYCSV_ERROR,
|
||||
FILE*);
|
||||
|
||||
/* Check if easycsv* and const char* are NULL */
|
||||
int
|
||||
_easycsv_checkcsvandstring_one(const _easycsv*,
|
||||
const char*);
|
||||
|
||||
/* Check if easycsv* and two const char* are NULL*/
|
||||
int
|
||||
_easycsv_checkcsvandstring_two(const _easycsv*,
|
||||
const char*,
|
||||
const char*);
|
||||
|
||||
/* Verifies if the string is not NULL or empty, returns 0 on success and -1 on failure */
|
||||
// int _easycsv_checkstring(const char*);
|
||||
|
||||
/* Verifies if easycsv is not NULL or unallocated */
|
||||
// int _easycsv_checkeasycsv(const struct easycsv*);
|
||||
|
||||
/* Verifies if int is */
|
||||
// int _easycsv_checkunsigned(const int);
|
||||
|
||||
#endif
|
955
src/easycsv.c
955
src/easycsv.c
File diff suppressed because it is too large
Load Diff
60
src/easycsv_error.c
Normal file
60
src/easycsv_error.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "../include/easycsv.h"
|
||||
#include "easycsv_error.h"
|
||||
|
||||
/* void */
|
||||
/* _easycsv_printerror(const _easycsv *_priv, */
|
||||
/* const EASYCSV_ERROR error) */
|
||||
/* { */
|
||||
/* switch (_priv->error) { */
|
||||
/* case EASYCSV_ERROROFF: return; */
|
||||
/* case EASYCSV_ERRORSTDOUT: _easycsv_geterror(_priv, error, stdout); break; */
|
||||
/* case EASYCSV_ERRORSTDERR: */
|
||||
/* default: _easycsv_geterror(_priv, error, stderr); return; */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
static char s_error_msg[SCHAR_MAX];
|
||||
|
||||
void
|
||||
easycsv_error(EASYCSV_ERROR error,
|
||||
const char *error_msg)
|
||||
{
|
||||
switch (error) {
|
||||
case EASYCSV_NOERROR: sprintf(s_error_msg, "no error"); return;
|
||||
case EASYCSV_NULLCSV: sprintf(s_error_msg, "easycsv pointer is NULL"); return;
|
||||
case EASYCSV_NULLPTR: sprintf(s_error_msg, "pointer is NULL"); return;
|
||||
case EASYCSV_EMPTYSTRING: sprintf(s_error_msg, "string is empty"); return;
|
||||
case EASYCSV_EMPTYVALUE: sprintf(s_error_msg, "value in CSV file is empty"); return;
|
||||
case EASYCSV_OVERMAXROW: sprintf(s_error_msg, "int exceeds row limit of %s", error_msg); return;
|
||||
case EASYCSV_OVERMAXCOL: sprintf(s_error_msg, "int exceeds column limit of %s", error_msg); return;
|
||||
case EASYCSV_ZEROROW: sprintf(s_error_msg, "parameterised row number is zero"); return;
|
||||
case EASYCSV_ZEROCOL: sprintf(s_error_msg, "parameterised column number is zero"); return;
|
||||
case EASYCSV_MEMALLOC: sprintf(s_error_msg, "memory allocation failure"); return;
|
||||
|
||||
case EASYCSV_UNKNOWNIOMODE: sprintf(s_error_msg, "unknown file IO mode"); return;
|
||||
case EASYCSV_OPENFAIL: sprintf(s_error_msg, "failed to open file"); return;
|
||||
case EASYCSV_REOPENFAIL: sprintf(s_error_msg, "failed to reopen file"); return;
|
||||
case EASYCSV_EMPTYCSV: sprintf(s_error_msg, "CSV file is empty"); return;
|
||||
case EASYCSV_UNWRITABLE: sprintf(s_error_msg, "CSV file is not in a writable mode"); return;
|
||||
case EASYCSV_UNREADABLE: sprintf(s_error_msg, "CSV file is not in a readable mode"); return;
|
||||
case EASYCSV_UPDATEFAIL: sprintf(s_error_msg, "CSV file has failed to update"); return;
|
||||
case EASYCSV_UPDATETEMPFAIL: sprintf(s_error_msg, "failed to update temp CSV file"); return;
|
||||
case EASYCSV_FILEPTRFAIL: sprintf(s_error_msg, "failed to move FILE pointer"); return;
|
||||
|
||||
case EASYCSV_ROWNOTEXIST: sprintf(s_error_msg, "given row does not exist"); return;
|
||||
case EASYCSV_COLNOTEXIST: sprintf(s_error_msg, "given column does not exist"); return;
|
||||
|
||||
case EASYCSV_PUSHCOLFAIL: sprintf(s_error_msg, "failed to push value under column"); return;
|
||||
case EASYCSV_COLNUMFAIL: sprintf(s_error_msg, "failed to determine the column number of a value in the first row"); return;
|
||||
case EASYCSV_FINDVALUEFAIL: sprintf(s_error_msg, "cannot find the value %s", error_msg); return;
|
||||
default: sprintf(s_error_msg, "unknown error"); return;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
easycsv_get_error()
|
||||
{
|
||||
return s_error_msg;
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
#ifndef EASYCSV_ERROR
|
||||
#define EASYCSV_ERROR
|
||||
#ifndef EASYCSV_ERROR_H
|
||||
#define EASYCSV_ERROR_H
|
||||
|
||||
/* Error flags */
|
||||
typedef enum {
|
||||
|
||||
typedef enum EASYCSV_ERROR {
|
||||
/* Generic errors */
|
||||
EASYCSV_NOERROR, // no error
|
||||
EASYCSV_NULLCSV, // easycsv* is NULL
|
||||
@ -14,6 +13,7 @@ typedef enum {
|
||||
EASYCSV_OVERMAXCOL, // int exceeds col limit
|
||||
EASYCSV_ZEROROW,
|
||||
EASYCSV_ZEROCOL,
|
||||
EASYCSV_MEMALLOC, ///< memory allocation failure
|
||||
|
||||
/* File input/output errors */
|
||||
EASYCSV_UNKNOWNIOMODE, // unknown file IO mode
|
||||
@ -34,6 +34,11 @@ typedef enum {
|
||||
EASYCSV_PUSHCOLFAIL, // push column value fail
|
||||
EASYCSV_COLNUMFAIL, // column number retrieval fail
|
||||
EASYCSV_READVALUEFAIL, // read value fail
|
||||
EASYCSV_FINDVALUEFAIL, // find value fail
|
||||
} EASYCSV_ERROR;
|
||||
|
||||
void
|
||||
easycsv_error(EASYCSV_ERROR,
|
||||
const char*);
|
||||
|
||||
#endif
|
||||
|
270
src/easycsv_p.c
Normal file
270
src/easycsv_p.c
Normal file
@ -0,0 +1,270 @@
|
||||
#include "easycsv_p.h"
|
||||
#include "easycsv_error.h"
|
||||
|
||||
/* int */
|
||||
/* _easycsv_update(_easycsv *csv) */
|
||||
/* { */
|
||||
/* /\* ARGS CHECK *\/ */
|
||||
/* if (csv == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_NULLCSV); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
/* /\* ARGS CHECK *\/ */
|
||||
|
||||
/* /\* Set temp file to read binary *\/ */
|
||||
/* if (freopen(csv->tmpfp, "rb", csv->temp) == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_REOPENFAIL); */
|
||||
/* easycsv_free(csv); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* /\* Set file to write binary *\/ */
|
||||
/* if (freopen(csv->fp, "wb", csv->file) == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_REOPENFAIL); */
|
||||
/* easycsv_free(csv); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* /\* Copy entire file *\/ */
|
||||
/* char buf[BUFSIZ]; */
|
||||
/* size_t size; */
|
||||
/* while (size = fread(buf, 1, BUFSIZ, csv->temp)) { */
|
||||
/* fwrite(buf, 1, size, csv->file); */
|
||||
/* } */
|
||||
|
||||
/* /\* Set temp file back to write *\/ */
|
||||
/* if (freopen(csv->tmpfp, "w", csv->temp) == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_REOPENFAIL); */
|
||||
/* easycsv_free(csv); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* /\* Set file back to read *\/ */
|
||||
/* if (freopen(csv->fp, "r", csv->file) == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_REOPENFAIL); */
|
||||
/* easycsv_free(csv); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
/*** Accès ***/
|
||||
|
||||
int
|
||||
easycsv_rows(const easycsv *csv)
|
||||
{
|
||||
if (easycsv_rewind(csv) < 0) return -1;
|
||||
|
||||
int rows = 1;
|
||||
char c;
|
||||
|
||||
/* Go through each character in the file and count the number of new lines */
|
||||
while ((c = fgetc(csv->file)) != EOF) {
|
||||
if (c == '\n') rows++;
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
int
|
||||
easycsv_columns(const easycsv *csv)
|
||||
{
|
||||
if (easycsv_rewind(csv) < 0) return -1;
|
||||
|
||||
/*
|
||||
1. check if empty file
|
||||
2. check if only one column -> 0 commas
|
||||
3. if >1 column, n commas = n+1 columns
|
||||
*/
|
||||
|
||||
int col = 1;
|
||||
char c;
|
||||
|
||||
while ((c = fgetc(csv->file)) != '\n') {
|
||||
if (c == ',') col++;
|
||||
}
|
||||
|
||||
return col;
|
||||
}
|
||||
|
||||
char*
|
||||
easycsv_get_row(const easycsv *csv,
|
||||
unsigned int row)
|
||||
{
|
||||
char *str = malloc(BUFSIZ);
|
||||
easycsv_rewind(csv);
|
||||
|
||||
for (int i = 1; i < row; i++) {
|
||||
fscanf(csv->file, "%*[^\n]\n", NULL);
|
||||
}
|
||||
|
||||
fscanf(csv->file, "%s\n", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
easycsv_rewind(const easycsv *csv)
|
||||
{
|
||||
/* Check if empty file */
|
||||
if (fscanf(csv->file, "\n") == EOF) {
|
||||
easycsv_error(EASYCSV_EMPTYCSV, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if file is readable */
|
||||
if (csv->mode != EASYCSV_R) {
|
||||
easycsv_error(EASYCSV_UNREADABLE, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set file pointer to the start */
|
||||
rewind(csv->file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* int */
|
||||
/* _easycsv_getcolumn(const _easycsv *csv, */
|
||||
/* const char *col) */
|
||||
/* { */
|
||||
/* /\* ARGS CHECK *\/ */
|
||||
/* if (_easycsv_checkcsvandstring_one(csv, col) < 0) */
|
||||
/* return -1; */
|
||||
/* /\* ARGS CHECK *\/ */
|
||||
|
||||
/* /\* Grab str of row 1 *\/ */
|
||||
/* char *firstrow = _easycsv_getrow(csv, 1); */
|
||||
|
||||
/* if (firstrow == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_ROWNOTEXIST); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* unsigned int commas = 0; */
|
||||
|
||||
/* // printf("FIRST COLUMN: %s\n", firstrow); */
|
||||
|
||||
/* /\* Find first occurance of col in firstrow *\/ */
|
||||
/* char *str = strstr(firstrow, col); */
|
||||
|
||||
/* if (str == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_COLNOTEXIST); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* /\* Count numbers of commas following str *\/ */
|
||||
/* char *c = strpbrk(str, ","); */
|
||||
/* while (c != NULL) { */
|
||||
/* commas++; */
|
||||
/* c = strpbrk(c + 1, ","); */
|
||||
/* } */
|
||||
|
||||
/* /\* no need to free c as it is already NULL at this point *\/ */
|
||||
/* // free((char*) str); apparently invalid pointer */
|
||||
|
||||
/* // printf("ROW: %i\nCOL: %i\n", row, csv->cols - commas); */
|
||||
/* /\* */
|
||||
/* #ifdef EASYCSV_DEBUG */
|
||||
/* printf("[%i] rcv_commas: %i\n", clock() - csv->start, commas); */
|
||||
/* #endif */
|
||||
/* *\/ */
|
||||
/* free(firstrow); */
|
||||
|
||||
/* return csv->cols - commas; */
|
||||
/* } */
|
||||
|
||||
/*
|
||||
int _easycsv_checkifvalue(struct easycsv *csv, const int col, const int row)
|
||||
{
|
||||
const char *rowstr = _easycsv_getrow(csv, row);
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* char* */
|
||||
/* _easycsv_getvalueinrow(const _easycsv *_priv, */
|
||||
/* const char *row, */
|
||||
/* const unsigned int col) */
|
||||
/* { */
|
||||
/* size_t st; */
|
||||
/* char *pch = NULL; */
|
||||
|
||||
/* /\* If not first column *\/ */
|
||||
/* if (col != 1) { */
|
||||
|
||||
/* /\* Get first occurance of comma in str, */
|
||||
/* the first value is ommited but not the comma *\/ */
|
||||
/* char *pch = strpbrk(row, ","); */
|
||||
|
||||
/* /\* Repeat until desired col is found *\/ */
|
||||
/* for (int i = 2; i < col; i++) { */
|
||||
/* pch = strpbrk(pch + 1, ","); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
/* /\* Get span from start of string to first occurence */
|
||||
/* of comma *\/ */
|
||||
/* st = strcspn(pch + 1, ","); */
|
||||
|
||||
/* /\* If 0, no string exists! *\/ */
|
||||
/* if (st == 0) { */
|
||||
/* _easycsv_printerror(_priv, EASYCSV_EMPTYVALUE); */
|
||||
/* return NULL; */
|
||||
/* } */
|
||||
|
||||
/* char *val = malloc(st + 1); */
|
||||
/* strncpy(val, pch + 1, st); */
|
||||
/* strncat(val, "\0", 1); */
|
||||
|
||||
/* return val; */
|
||||
/* } */
|
||||
|
||||
char*
|
||||
easycsv_set_charp_to_value(const char *rowstr,
|
||||
unsigned int col)
|
||||
{
|
||||
/* Get first occurance of comma in str, the first value is ommited but not the comma */
|
||||
char *pch = (char*) rowstr;
|
||||
/* Repeat until desired col is found */
|
||||
for (unsigned int i = 1; i < col; i++) {
|
||||
pch = strpbrk(pch + 1, ",");
|
||||
}
|
||||
|
||||
return pch;
|
||||
}
|
||||
|
||||
/* int */
|
||||
/* _easycsv_checkcsvandstring_one(const _easycsv *csv, */
|
||||
/* const char *one) */
|
||||
/* { */
|
||||
/* if (csv == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_NULLCSV); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* if (one == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_EMPTYSTRING); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
/* int */
|
||||
/* _easycsv_checkcsvandstring_two(const _easycsv *csv, */
|
||||
/* const char *one, */
|
||||
/* const char *two) */
|
||||
/* { */
|
||||
/* if (_easycsv_checkcsvandstring_one(csv, one) < 0) */
|
||||
/* return -1; */
|
||||
|
||||
/* if (two == NULL) { */
|
||||
/* _easycsv_printerror(csv, EASYCSV_EMPTYSTRING); */
|
||||
/* return -1; */
|
||||
/* } */
|
||||
|
||||
/* return 0; */
|
||||
/* } */
|
113
src/easycsv_p.h
Normal file
113
src/easycsv_p.h
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef EASYCSV_P_H
|
||||
#define EASYCSV_P_H
|
||||
|
||||
#include "../include/easycsv.h"
|
||||
|
||||
/*** Accès ***/
|
||||
|
||||
/**
|
||||
* Returns string of a specific row, including '\n' character
|
||||
* This function does not check parameters!
|
||||
* This function does not produce errors!
|
||||
* @param[in] const pointer to easycsv structure
|
||||
* @param[in] row number
|
||||
* @return string of row (heap-allocated)
|
||||
*/
|
||||
char*
|
||||
easycsv_get_row(const easycsv*,
|
||||
unsigned int);
|
||||
|
||||
/* /\** */
|
||||
/* * Returns column number of a named column *\/ */
|
||||
/* int */
|
||||
/* _easycsv_getcolumn(const _easycsv*, */
|
||||
/* const char*); */
|
||||
|
||||
/* /\* Verifies the type of the value (eg: string or int) *\/ */
|
||||
/* _EASYCSV_TYPE */
|
||||
/* _easycsv_checktype(const _easycsv*, */
|
||||
/* const int, */
|
||||
/* const int); */
|
||||
|
||||
/* /\* Verifies if there is a value or not *\/ */
|
||||
/* int */
|
||||
/* _easycsv_checkifvalue(const _easycsv*, */
|
||||
/* const int, */
|
||||
/* const int); */
|
||||
|
||||
/* /\* Grab const char* in row *\/ */
|
||||
/* char* */
|
||||
/* _easycsv_getvalueinrow(const _easycsv*, */
|
||||
/* const char*, */
|
||||
/* const unsigned int); */
|
||||
|
||||
/**
|
||||
* Returns char pointer towards the n-th occurence of ',' in a given string
|
||||
* This function does not check parameters!
|
||||
* This function does not produce errors!
|
||||
* @param[in] string of row (string with multiple occurences of ',')
|
||||
* @param[in] n-th occurence to place the char pointer
|
||||
* @return char pointer towards the n-th occurence of ',' in a given string
|
||||
*/
|
||||
char*
|
||||
easycsv_set_charp_to_value(const char*,
|
||||
unsigned int);
|
||||
|
||||
/* /\* Insert value in row in specific column *\/ */
|
||||
/* char* */
|
||||
/* _easycsv_insertvalueinrow(const _easycsv*, */
|
||||
/* const char*, */
|
||||
/* const char*, */
|
||||
/* const unsigned int); */
|
||||
|
||||
/**
|
||||
* Calculate rows of easycsv
|
||||
* @param[in] const pointer to easycsv structure
|
||||
* @return number of rows in easycsv
|
||||
*/
|
||||
int
|
||||
easycsv_rows(const easycsv*);
|
||||
|
||||
/**
|
||||
* Calculate columns of easycsv
|
||||
* @param[in] const pointer to easycsv structure
|
||||
* @return number of columns in easycsv
|
||||
*/
|
||||
int
|
||||
easycsv_columns(const easycsv*);
|
||||
|
||||
/**
|
||||
* Rewind easycsv FILE pointer
|
||||
* @param[in] const pointer to easycsv structure
|
||||
* @return 0 if no error, -1 if fail
|
||||
*/
|
||||
int
|
||||
easycsv_rewind(const easycsv*);
|
||||
|
||||
/* /\* Check if easycsv* and const char* are NULL *\/ */
|
||||
/* int */
|
||||
/* _easycsv_checkcsvandstring_one(const _easycsv*, */
|
||||
/* const char*); */
|
||||
|
||||
/* /\* Check if easycsv* and two const char* are NULL*\/ */
|
||||
/* int */
|
||||
/* _easycsv_checkcsvandstring_two(const _easycsv*, */
|
||||
/* const char*, */
|
||||
/* const char*); */
|
||||
|
||||
/* Verifies if the string is not NULL or empty, returns 0 on success and -1 on failure */
|
||||
// int _easycsv_checkstring(const char*);
|
||||
|
||||
/* Verifies if easycsv is not NULL or unallocated */
|
||||
// int _easycsv_checkeasycsv(const struct easycsv*);
|
||||
|
||||
/* Verifies if int is */
|
||||
// int _easycsv_checkunsigned(const int);
|
||||
|
||||
/*** Modifications ***/
|
||||
|
||||
/* Copies data from temp FILE to file FILE */
|
||||
/* int */
|
||||
/* _easycsv_update(_easycsv*); */
|
||||
|
||||
#endif
|
67
src/easycsv_string.c
Normal file
67
src/easycsv_string.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "string.h"
|
||||
|
||||
char*
|
||||
easycsv_set_charp_to_value(const char *rowstr,
|
||||
unsigned int col)
|
||||
{
|
||||
/* Get first occurance of comma in str, the first value is ommited but not the comma */
|
||||
char *pch = (char*) rowstr;
|
||||
/* Repeat until desired col is found */
|
||||
for (unsigned int i = 1; i < col; i++) {
|
||||
pch = strpbrk(pch + 1, ",");
|
||||
}
|
||||
|
||||
return pch;
|
||||
}
|
||||
|
||||
char*
|
||||
easycsv_insert_string_row(const char* val,
|
||||
const char* rowstr,
|
||||
unsigned int col,
|
||||
unsigned int col_max)
|
||||
{
|
||||
size_t rowstrst = strlen(rowstr);
|
||||
size_t st = 0;
|
||||
size_t commas = 0;
|
||||
char *pch = NULL;
|
||||
char *newstr = NULL;
|
||||
|
||||
/* column is within limit */
|
||||
if (1 <= col && col <= col_max) {
|
||||
|
||||
/* Set pch to start of value in rowstr */
|
||||
pch = easycsv_set_charp_to_value(rowstr, col);
|
||||
|
||||
/* Calculate size of existing value */
|
||||
st = strcspn(pch, ",");
|
||||
|
||||
newstr = malloc(rowstrst - st + strlen(val) + 1);
|
||||
|
||||
/* Copy char to newstr before value (pch) */
|
||||
strncpy(newstr, rowstr, pch - rowstr);
|
||||
|
||||
strcat(newstr, val);
|
||||
|
||||
/* Set pch to after value */
|
||||
pch = strchr(rowstr, ',');
|
||||
|
||||
/* Calculate length of rest of string */
|
||||
st = strlen(pch);
|
||||
|
||||
/* Concentate rest of string including NULL char */
|
||||
strcat(newstr, pch);
|
||||
}
|
||||
else {
|
||||
commas = col - col_max;
|
||||
// csv->cols = col;
|
||||
newstr = malloc(rowstrst + commas + strlen(val) + 1);
|
||||
strncpy(newstr, rowstr, rowstrst);
|
||||
for (size_t i = 0; i < commas; i++)
|
||||
strncat(newstr, ",", 1);
|
||||
strcat(newstr, val); // append \0
|
||||
}
|
||||
return newstr;
|
||||
}
|
32
src/easycsv_string.h
Normal file
32
src/easycsv_string.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef EASYCSV_STRING_P_H
|
||||
#define EASYCSV_STRING_P_H
|
||||
|
||||
/**
|
||||
* Returns char pointer towards the n-th occurence of ',' in a given string
|
||||
* This function does not check parameters!
|
||||
* This function does not produce errors!
|
||||
* @param[in] string of row (string with multiple occurences of ',')
|
||||
* @param[in] n-th occurence to place the char pointer
|
||||
* @return char pointer towards the n-th occurence of ',' in a given string
|
||||
*/
|
||||
char*
|
||||
easycsv_set_charp_to_value(const char*,
|
||||
unsigned int);
|
||||
|
||||
/**
|
||||
* Insert a string in a comma-separated string of sub-strings in a specified position (by comma)
|
||||
* @param[in] string to be inserted
|
||||
* @param[in] comma-separated string
|
||||
* @param[in] specified position of string
|
||||
* @param[in] total number of sub-strings BEFORE manipulation
|
||||
* @return heap-allocated string
|
||||
*/
|
||||
char*
|
||||
easycsv_insert_string_row(const char*,
|
||||
const char*,
|
||||
unsigned int,
|
||||
unsigned int);
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -1,11 +1,19 @@
|
||||
TESTS = \
|
||||
check_easycsv
|
||||
check_easycsv \
|
||||
check_easycsv_string
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
check_easycsv
|
||||
check_easycsv \
|
||||
check_easycsv_string
|
||||
|
||||
check_easycsv_SOURCES = \
|
||||
check_easycsv.c
|
||||
check_easycsv_CFLAGS = $(CHECK_CFLAGS)
|
||||
check_easycsv_LDFLAGS = $(CHECK_LIBS)
|
||||
check_easycsv_LDADD = $(top_builddir)/src/libeasycsv.la
|
||||
|
||||
check_easycsv_string_SOURCES = \
|
||||
check_easycsv_string.c
|
||||
check_easycsv_string_CFLAGS = $(CHECK_CFLAGS)
|
||||
check_easycsv_string_LDFLAGS = $(CHECK_LIBS)
|
||||
check_easycsv_string_LDADD = $(top_builddir)/src/libeasycsv_string.la
|
||||
|
@ -34,6 +34,7 @@ START_TEST(test_easycsv_init_write_2)
|
||||
csv = easycsv_init(SAMPLE2_PATH, EASYCSV_W);
|
||||
ck_assert_ptr_nonnull(csv);
|
||||
easycsv_free(csv);
|
||||
remove(SAMPLE2_PATH);
|
||||
}
|
||||
|
||||
Suite*
|
||||
@ -52,48 +53,136 @@ easycsv_constructor_suite(void)
|
||||
tcase_add_test(tc_write, test_easycsv_init_write_2);
|
||||
|
||||
suite_add_tcase(s, tc_read);
|
||||
//suite_add_tcase(s, tc_write);
|
||||
suite_add_tcase(s, tc_write);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
START_TEST(test_easycsv_printcolumns)
|
||||
START_TEST(test_easycsv_print_columns)
|
||||
{
|
||||
easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R);
|
||||
ck_assert_int_eq(easycsv_printcolumns(csv), 3);
|
||||
ck_assert_int_eq(easycsv_print_columns(csv), 3);
|
||||
easycsv_free(csv);
|
||||
|
||||
ck_assert_int_eq(easycsv_print_columns(NULL), -1);
|
||||
}
|
||||
|
||||
START_TEST(test_easycsv_print_rows)
|
||||
{
|
||||
easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R);
|
||||
ck_assert_int_eq(easycsv_print_rows(csv), 4);
|
||||
easycsv_free(csv);
|
||||
|
||||
ck_assert_int_eq(easycsv_print_rows(NULL), -1);
|
||||
}
|
||||
|
||||
START_TEST(test_easycsv_read_value)
|
||||
{
|
||||
easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R);
|
||||
char* str;
|
||||
|
||||
str = easycsv_read_value(csv, 1, 1);
|
||||
ck_assert_str_eq(str, "FILEPATHA1");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 2, 1);
|
||||
ck_assert_str_eq(str, "FILEPATHB1");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 1, 2);
|
||||
ck_assert_str_eq(str, "FILEPATHA2");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 1, 3);
|
||||
ck_assert_str_eq(str, "");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 1, 4);
|
||||
ck_assert_str_eq(str, "");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 3, 4);
|
||||
ck_assert_str_eq(str, "");
|
||||
free(str);
|
||||
|
||||
str = easycsv_read_value(csv, 0, 0);
|
||||
ck_assert_ptr_null(str);
|
||||
|
||||
str = easycsv_read_value(csv, 4, 1);
|
||||
ck_assert_ptr_null(str);
|
||||
|
||||
str = easycsv_read_value(csv, 3, 5);
|
||||
ck_assert_ptr_null(str);
|
||||
|
||||
easycsv_free(csv);
|
||||
}
|
||||
|
||||
START_TEST(test_easycsv_printrows)
|
||||
START_TEST(test_easycsv_find_value)
|
||||
{
|
||||
easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R);
|
||||
ck_assert_int_eq(easycsv_printrows(csv), 5);
|
||||
unsigned int col = 0, row = 0;
|
||||
|
||||
easycsv_find_value(csv, "FILEPATHA1", &col, &row);
|
||||
ck_assert_int_eq(col, 1);
|
||||
ck_assert_int_eq(row, 1);
|
||||
|
||||
easycsv_find_value(csv, "FILEPATHB1", &col, &row);
|
||||
ck_assert_int_eq(col, 2);
|
||||
ck_assert_int_eq(row, 1);
|
||||
|
||||
easycsv_find_value(csv, "FILEPATHA2", &col, &row);
|
||||
ck_assert_int_eq(col, 1);
|
||||
ck_assert_int_eq(row, 2);
|
||||
|
||||
easycsv_find_value(csv, "", &col, &row);
|
||||
ck_assert_int_eq(col, 1);
|
||||
ck_assert_int_eq(row, 3);
|
||||
|
||||
easycsv_free(csv);
|
||||
}
|
||||
|
||||
START_TEST(test_easycsv_readcolumnvalue)
|
||||
START_TEST(test_easycsv_find_num_value)
|
||||
{
|
||||
easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R);
|
||||
ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 1), "FILEPATHA1");
|
||||
ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 2), "FILEPATHB1");
|
||||
ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 3), NULL);
|
||||
ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST2", 1), "FILEPATHA2");
|
||||
|
||||
ck_assert_int_eq(easycsv_find_num_value(csv, "FILEPATHA1"), 1);
|
||||
ck_assert_int_eq(easycsv_find_num_value(csv, "FILEPATHB1"), 1);
|
||||
ck_assert_int_eq(easycsv_find_num_value(csv, "FILEPATHA2"), 1);
|
||||
ck_assert_int_eq(easycsv_find_num_value(csv, ""), 3);
|
||||
ck_assert_int_eq(easycsv_find_num_value(csv, "NOVALUE"), 0);
|
||||
|
||||
easycsv_free(csv);
|
||||
}
|
||||
|
||||
/* START_TEST(test_easycsv_readcolumnvalue) */
|
||||
/* { */
|
||||
/* easycsv *csv = easycsv_init(SAMPLE1_PATH, EASYCSV_R); */
|
||||
/* ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 1), "FILEPATHA1"); */
|
||||
/* ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 2), "FILEPATHB1"); */
|
||||
/* ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST1", 3), NULL); */
|
||||
/* ck_assert_str_eq(easycsv_readcolumnvalue(csv, "TEST2", 1), "FILEPATHA2"); */
|
||||
/* easycsv_free(csv); */
|
||||
/* } */
|
||||
|
||||
Suite*
|
||||
easycsv_access_suite(void)
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc_find, *tc_read, *tc_print;
|
||||
s = suite_create ("access");
|
||||
tc_find = tcase_create ("find");
|
||||
tcase_add_test(tc_find, test_easycsv_find_value);
|
||||
tcase_add_test(tc_find, test_easycsv_find_num_value);
|
||||
|
||||
tc_read = tcase_create ("read");
|
||||
tcase_add_test(tc_read, test_easycsv_readcolumnvalue);
|
||||
tcase_add_test(tc_read, test_easycsv_read_value);
|
||||
/* tcase_add_test(tc_read, test_easycsv_readcolumnvalue); */
|
||||
|
||||
tc_print = tcase_create ("print");
|
||||
tcase_add_test(tc_print, test_easycsv_printcolumns);
|
||||
tcase_add_test(tc_print, test_easycsv_printrows);
|
||||
tcase_add_test(tc_print, test_easycsv_print_columns);
|
||||
tcase_add_test(tc_print, test_easycsv_print_rows);
|
||||
|
||||
suite_add_tcase(s, tc_find);
|
||||
suite_add_tcase(s, tc_read);
|
||||
suite_add_tcase(s, tc_print);
|
||||
|
||||
|
35
tests/check_easycsv_string.c
Normal file
35
tests/check_easycsv_string.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <check.h>
|
||||
#include "../src/easycsv_string.h"
|
||||
|
||||
START_TEST(test_easycsv_set_charp_to_value)
|
||||
{
|
||||
const char* str1 = "test,test,test,test";
|
||||
char* c;
|
||||
c = easycsv_set_charp_to_value(str1, 1);
|
||||
ck_assert_ptr_eq(c, &str1[0]);
|
||||
c = easycsv_set_charp_to_value(str1, 2);
|
||||
ck_assert_ptr_eq(c, &str1[5]);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int number_failed;
|
||||
SRunner *sr;
|
||||
Suite *s;
|
||||
|
||||
TCase *tc_string;
|
||||
s = suite_create("string manipulation");
|
||||
tc_string = tcase_create("string");
|
||||
tcase_add_test(tc_string, test_easycsv_set_charp_to_value);
|
||||
|
||||
suite_add_tcase(s, tc_string);
|
||||
|
||||
sr = srunner_create(s);
|
||||
|
||||
srunner_run_all(sr, CK_VERBOSE);
|
||||
number_failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return number_failed;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
TEST1,TEST2,TEST3
|
||||
FILEPATHA1,FILEPATHA2,FILEPATHA3
|
||||
FILEPATHB1,FILEPATHB2,FILEPATHB3
|
||||
,FILEPATHC2,FILEPATHC3
|
||||
,FILEPATHD2,
|
||||
FILEPATHA1,FILEPATHB1,FILEPATHC1
|
||||
FILEPATHA2,FILEPATHB2,FILEPATHC2
|
||||
,FILEPATHB3,FILEPATHC3
|
||||
,FILEPATHB4,
|
|
Loading…
Reference in New Issue
Block a user