/**=============================================================================
"items" library - version 1.0.0, 20150102
=============================================================================**/
#include "items.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/*==============================================================================
Apre un file come stream testuale, alloca memoria dinamica nella quantita'
opportuna e legge il testo in essa. La stringa risultante e' terminata da '\0'.
Il chiamante deve liberare la memoria dinamica puntata dal valore di ritorno non
appena non e' piu' necessaria. Se la funzione non riesce ad aprire il file o ad
allocare memoria, il valore di ritorno e' NULL.
==============================================================================*/
char *LoadFile( const char *fileName ) {
char *auxPtr, *data = NULL;
long dataDim;
int c;
FILE *f;
if( fileName == NULL ) return data;
if( *fileName == '\0' ) return data;
f = fopen( fileName, "r" );
if( f == NULL ) return data;
for( dataDim=0; fgetc(f)!=EOF; ++dataDim );
data = malloc( dataDim+1 );
if( data != NULL ) {
rewind( f );
auxPtr = data;
while( (c=fgetc(f))!=EOF )
*auxPtr++ = c;
*auxPtr = '\0';
}
fclose( f );
return data;
}
/*==============================================================================
Alloca memoria dinamica e copia in essa una stringa. Il chiamante deve liberare
la memoria dinamica allocata appena non ne ha piu' necessita'.
==============================================================================*/
char *AllocateCopy( const char *s, long l ) {
long sl; // [s]tring [l]ength
char *copy = NULL;
if( s == NULL ) return copy;
sl = l<0 ? strlen(s) : l;
if( (copy=malloc(sl+1)) != NULL )
{ memcpy(copy,s,sl); copy[sl]='\0'; }
return copy;
}
/*==============================================================================
Restituisce la quantita' totale degli elementi contenuti nella stringa passata
tramite il parametro data. Gli elementi vengono riconosciuti contando le
ricorrenze del carattere passato tramite il parametro sep.
==============================================================================*/
long CountItemsInString( const char *data, int sep ) {
long n;
if( data == NULL ) return -1;
for( n=1; *data; ++data )
if( *data == sep ) ++n;
return n;
}
/*==============================================================================
Restituisce la quantita' totale degli elementi contenuti nel file il cui nome e'
passato tramite il parametro fileName. Gli elementi vengono riconosciuti
contando le ricorrenze del carattere passato tramite il parametro sep.
==============================================================================*/
long CountItemsInFile( const char *fileName, int sep ) {
FILE *f;
long n;
int c;
if( fileName == NULL ) return -1;
if( *fileName == '\0' ) return -1;
f = fopen( fileName, "r" );
if( f == NULL ) return -1;
for( n=1, c=fgetc(f); c!=EOF; c=fgetc(f) )
if( c == sep ) ++n;
fclose( f );
return n;
}
long TokeniseString( char *data, int sep, const char ***ptrs ) {
const char **auxPtr, **tap; /* [t]emporary [a]rray of [p]ointers */
const char *strtok_result;
long totItems;
char sp[2] = { sep, '\0' };
totItems = CountItemsInString( data, sep );
auxPtr = tap = calloc( totItems, sizeof(char*) );
if( tap == NULL ) return -1;
for( strtok_result = strtok(data,sp);
strtok_result != NULL;
*auxPtr++=strtok_result, strtok_result=strtok(NULL,sp));
*ptrs = tap;
return totItems;
}
/*==============================================================================
Carica tutti gli elementi dalla stringa passata tramite il parametro data,
copiandoli nella memoria dinamica e restituendo il loro indirizzo sotto forma di
un array di puntatori a char. Gli elementi vengono riconosciuti contando le
ricorrenze del carattere passato tramite il parametro sep.
==============================================================================*/
long GetAllItemsFromString( const char *data, int sep, const char ***ptrs ) {
long totItems = -1;
char *copy;
copy = AllocateCopy( data, -1 );
if( copy == NULL ) return -1;
totItems = TokeniseString( copy, sep, ptrs );
if( totItems == -1 ) free( copy );
return totItems;
}
/*==============================================================================
Carica tutti gli elementi contenuti nel file del quale viene passato il nome
tramite il parametro fileName, copiandoli nella memoria dinamica e restituendo
il loro indirizzo sotto forma di un array di puntatori a char. Gli elementi
vengono riconosciuti contando le ricorrenze del carattere passato tramite il
parametro sep.
==============================================================================*/
long GetAllItemsFromFile( const char *fileName, int sep, const char ***ptrs ) {
long totItems = 0;
char *data = NULL;
if( fileName == NULL ) return -1;
if( *fileName == '\0' ) return -1;
data = LoadFile( fileName );
if( data == NULL ) return -1;
totItems = TokeniseString( data, sep, ptrs );
if( totItems == -1 ) free( data );
return totItems;
}
/*==============================================================================
Carica dalla stringa data l'elemento alla posizione indicata dal parametro nItem
(zero based), copiandolo nell'area della memoria dinamica puntata dal puntatore
a char che viene restituito come valore di ritorno. Gli elementi vengono
riconosciuti contando le ricorrenze del carattere passato tramite il parametro
sep.
==============================================================================*/
char *GetItemFromString( const char *data, int sep, long nItem ) {
long ci; /* [c]urrent [i]tem */
char *strItem = NULL;
char sp[2] = { sep, '\0' };
if( data == NULL ) return strItem;
for( ci=0;
(ci<nItem)&&(data=strchr(data,sep));
++data, ++ci );
if( ci == nItem )
strItem = AllocateCopy( data, strcspn(data,sp) );
return strItem;
}
/*==============================================================================
Carica dal file che ha per nome la stringa passata tramite il parametro data
l'elemento alla posizione indicata dal parametro nItem (zero based), copiandolo
nell'area della memoria dinamica puntata dal puntatore a char che viene
restituito come valore di ritorno. Gli elementi vengono riconosciuti contando le
ricorrenze del carattere passato tramite il parametro sep.
==============================================================================*/
char *GetItemFromFile( const char *fileName, int sep, long nItem ) {
long i, start, length, c, ci; /* [c]urrent [i]tem */
char *strItem = NULL;
FILE *f;
if( fileName == NULL ) return strItem;
if( *fileName == '\0' ) return strItem;
f = fopen( fileName, "r" );
if( f == NULL ) return strItem;
for( ci=0, c=fgetc(f); ci!=nItem && c!=EOF; c=fgetc(f) )
if( c == sep ) ++ci;
if( ci == nItem ) {
start = ftell(f)-1;
for( c=fgetc(f); c!=sep&&c!=EOF; c=fgetc(f) );
length = ftell(f)-1-start;
if( (strItem=malloc(length+1)) != NULL ) {
fseek( f, start, SEEK_SET );
for( i=0; i<length; *(strItem+i)=fgetc(f), ++i );
*(strItem+i) = '\0';
}
}
fclose( f );
return strItem;
}
/*==============================================================================
Questa e' banale. Libera la memoria dinamica puntata dal contenuto del parametro
s e imposta il puntatore in s su NULL (in altre parole, quando la funzione
ritorna, il contenuto di s e' NULL).
==============================================================================*/
void FreeStringMemory( char **s ) {
if( *s!= NULL ) {
free( (void*)*s );
*s = NULL;
}
}
/*==============================================================================
Libera la memoria allocata nello spazio dinamico dalla funzione
GetItemsFromString() o dalla funzione GetItemsFromFile(). In uscita, il valore
del contenuto di ptrs e' NULL.
==============================================================================*/
void FreeStringsMemory( const char ***ptrs ) {
if( ptrs == NULL ) return;
if( *ptrs == NULL ) return;
if( **ptrs != NULL ) {
free( (void*)(**ptrs) );
**ptrs = NULL;
}
free( (void*)(*ptrs) );
(*ptrs) = NULL;
}