Skip to content

Instantly share code, notes, and snippets.

@rocarvaj
Created October 4, 2012 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rocarvaj/3834623 to your computer and use it in GitHub Desktop.
Save rocarvaj/3834623 to your computer and use it in GitHub Desktop.
Read file and parse strings

Read file and parse

Las funciones importantes est'an en parse.c. Adjunto tambi'en el archivo macros.h, que tiene algunas funciones macro que se llaman en parse.c, pero se llaman s'olo para cosas como testear para ver si hay alguna condici'on de lleve a error.

/* OFP - Open Forest Planner
*
* Copyright (C) 2008 - Rodolfo Carvajal, Miguel Constantino, Marcos Goycoolea,
* Juan Pablo Vielma and Andrés Weintraub
* (Names in alphabetical order)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**
* @file macros_ofp.hpp
* @brief Contains macros used in OFP.
* @date 2008-07-27
*/
/*******************************************************************************/
/** MEMORY MACROS */
/*******************************************************************************/
/* ========================================================================= */
/** @name Code Location Utility:
* this are utility macros to print information about where we are.
* @note For some reason __func__ don't work correctly for sun's cc in inline
* functions, so we don't use in SUN architecture */
/* @{ */
#define __EG_PRINTLOCF__(F) fprintf(((F==0)?stderr:F),", in %s (%s:%d)\n",__func__,__FILE__,__LINE__)
#define __EG_PRINTLOC__ __EG_PRINTLOCF__(stderr)
#define __EG_PRINTLOC2F__(F) fprintf(((F==0)?stderr:F),"in %s (%s:%d)\n",__func__,__FILE__,__LINE__)
#define __EG_PRINTLOC2__ __EG_PRINTLOC2F__(stderr)
/* @} */
/* ========================================================================= */
/** @brief From EGlib (eg_mem.h)
* This macro is to print error messages and exit the program with
* code one from the current function, it also print the file and line where
* this happend */
#define EXIT(A,...) ({if(A){\
fprintf(stderr,"EXIT: ");\
fprintf(stderr,__VA_ARGS__);\
__EG_PRINTLOC__;\
exit(1);}})
/* ========================================================================= */
/** @brief From EGlib (eg_mem.h)
* This macro print messages to the screen when the condition A is
* true. */
#define WARNING(A,...) ({if(A){\
fprintf(stderr,"WARNING: ");\
fprintf(stderr,__VA_ARGS__);\
__EG_PRINTLOC__;}})
/* ========================================================================= */
/** @brief From EGlib (eg_mem.h)
* This function replace free, the idea of this is to HOPEFULLY later
* develop a memory leack checker that tell us who and where asked for memory
* and didn't free it, in hte meantime they do nothing.
* @param A pointer to the piece of memory to be freed, if debuging is enabled,
* the function will test for freing NULL pointers, for suspicios address
* freing and so on. note that the given pointer will point to NULL after this
* call, thus reducing the posibility of freeing multiple times the same piece
* of memory, or of allocating it after freeing it. */
// #define MEMfree(A) ({\ EXIT(((A) && !(((size_t)(A))>>19)),"Trying to free pointer "#A\ " with value %zd\nThis is probably an error",(size_t)(A));\ if(A) free(A);})
#define MEMfree(A) free(A)
/* ========================================================================= */
/** @brief From EGlib (eg_mem.h)
* This function replace malloc, check if the memory is not zero, if
* it is, it exit from the program, and display who called it and how much
* memory it tryed to alloc.
* @param A number of bytes to allocate.
* @return a void* pointer to the newly allocated memory, note that if the
* function returns at all, it will return with the amount of memory required,
* so no NULL checking is ever necesary after an MEMmalloc call.
* */
#define MEMmalloc(A) ({\
size_t const _EGmp_sz_ = (A);\
void * _EGmp_res_ = 0;\
/*WARNINGL(0,!_EGmp_sz_,"Allocating 0 bytes");*/\
if(_EGmp_sz_)\
{\
_EGmp_res_ = calloc((size_t)1,_EGmp_sz_);\
EXIT(!_EGmp_res_,"Not enough memory while allocating %zd bytes",_EGmp_sz_);\
}\
_EGmp_res_;})
/* ========================================================================= */
/** @brief From EGlib (eg_mem.h)
* This function allocate 'count' elements of type 'type' and returns
* a pointer of type 'type*'. If the memory is not available the program will
* exit indicating where it was trying to get memory and how much, it will also
* check some common errors like allocating zero bytes.
* @param type type of the element required.
* @param count number of contiguous elements of the given type required.
* @return pointer to the beggining of the allocated array of the apropiate
* type (so no casting is needed). Note that if this function returns at all,
* then the memory has been allocated and thus no NULL checking return is
* necesary. */
#define MEMsmalloc(type,count) (type*)MEMmalloc(sizeof(type)*(count))
/* ========================================================================= */
/** @brief Realloc a given pointer to the new size, and check that we find
* enough memory to return. If we don't, we exit the execution.
* @param __ptr pointer to reallocate.
* @param __sz new number of bytes to reallocate.
* @return pointer to the new block of memory */
#define MEMrealloc(__ptr,__sz) ({\
const size_t ____sz = (size_t)(__sz);\
(__ptr) = realloc((__ptr),____sz);\
EXIT(!(__ptr)&&(____sz),"not enough memory while reallocating %zd",____sz);\
(__ptr);})
/*******************************************************************************/
/** DEBUG MACROS */
/*******************************************************************************/
#define UNUSED_ARG(x) (void)x
#define DBG_LEVEL_OFF 0
#define DBG_LEVEL_LOW 1
#define DBG_LEVEL_MEDIUM 100
#define DBG_LEVEL_HIGH 1000
#define DIS_LEVEL_OFF 0
#define DIS_LEVEL_LOW 1
#define DIS_LEVEL_MEDIUM 10
#define DIS_LEVEL_HIGH 100
#define __DBG_PRINT_LOC__(F) fprintf(((F==0)?stderr:F), " in %s (%s:%d)\n", __func__, __FILE__, __LINE__)
#define DBG_EXIT(A,REST...) {\
fprintf(stderr, ##REST); \
__DBG_PRINT_LOC__(stderr); \
exit(A); }
#define DBG_RETURN(A,REST...) {\
fprintf(stderr, ##REST); \
__DBG_PRINT_LOC__(stderr); \
return (A);}
#define DBG_GOTO(A,REST...) {\
fprintf(stderr, ##REST); \
__DBG_PRINT_LOC__(stderr); \
goto A;}
#define DBG_IF_EXIT(A,B,REST...) {\
if(A) DBG_EXIT(B,##REST) }
#define DBG_IF_RETURN(A,B,REST...) {\
if(A) DBG_RETURN(B,##REST) }
#define DBG_IF_GOTO(A,B,REST...) {\
if(A) DBG_GOTO(B,##REST) }
#define DBG_MESSAGE(A, REST...) {\
if(A) {\
fprintf(stderr, ##REST); \
__DBG_PRINT_LOC__(stderr); \
}}
#define DBG_IF_MESSAGE(A, REST...) {\
if(A) {\
fprintf(stderr, ##REST); \
__DBG_PRINT_LOC__(stderr); \
}}
/* ========================================================================= */
/** @brief this macro test if a value is non zero, if it is it print where is
* it and return 1. The idea is to use it to check return values of functions
* */
#define CHECKRVAL(A) ({\
if(A){\
__EG_PRINTLOC2__;\
return A;}})
/* ========================================================================= */
/** @brief this function, if the input is non zero, print a message of
* function, file and line and then goto the second parameter */
#define CHECKRVALG(A,B) ({\
if(A){\
__EG_PRINTLOC2__;\
goto B;}})
/* ========================================================================= */
/** @brief This macro is to print error messages and to return with value one
* from the current function, it also print the file and line where this
* happend */
#define TESTG(A,B,...) ({\
if(A){\
fprintf(stderr,__VA_ARGS__);\
__EG_PRINTLOC__;\
goto B;}})
/* ========================================================================= */
/** @brief This macro is to print error messages and to return with value one
* from the current function, it also print the file and line where this
* happend */
#define TEST(A,...) ({\
if(A){\
fprintf(stderr,__VA_ARGS__);\
__EG_PRINTLOC__;\
return 1;}})
/*******************************************************************************/
/** I/O MACROS AND FUNCTIONS */
/*******************************************************************************/
/** @brief safe open function, it test that we can open the given file with the
* given mode, if an error occurs, display it on screen and exit, otherwise,
* return the open file stream.
* @param __file file name to open (is a const char*)
* @param __mode to use to open the file (is a const char*)
* @return FILE* stream
* This function is part of OMPlib*/
#define OFPfopen(__file,__mode) ({\
const char*__EGsfile = (__file);\
const char*__EGsmode = (__mode);\
FILE*__EGsFILE = fopen(__EGsfile,__EGsmode);\
if(!__EGsFILE)\
{\
const int __EGserrno = errno;\
fprintf(stderr,"fopen() failed with error code %d, error\n%s",__EGserrno,strerror(__EGserrno));\
fprintf(stderr,"fopen() bad file = %s\n", __file); \
DBG_MESSAGE(0,"Could not open %s with mode %s", __EGsfile, __EGsmode);\
exit(__EGserrno);\
}\
__EGsFILE;})
#define OFPindexof(i, t, nperiods) ((nperiods+1)*(i)+(t))
/* given two *pointers 'next' and 'current' and a constant set
* of strings (parse delimiters), it stores in 'next' the next
* meaningfull string, and in current the rest of the secuence,
* the idea is to iterate over 'next' while it is not true;
* you have to store the original pointer to the string stream
* elsewere; also, we assume that the original stream is
* terminated with '\0'; also, it will discard any sub-string
* that start with #, that is inteded for discard comments.
* NOTE: this function WILL change the original string!!!!!
* There is no guarantee on how it will be changed.
* This function is part of OMPlib*/
void OFPparse (
char **next,
char **current,
const char *delim,
const char *comment)
{
/* local variables */
int i;
char *ctmp;
char *curchar = *current;
/* if the current line is NULL we stop */
if (*current == 0)
{
*next = 0;
return;
}
/* first try to find a meaningful caracter
* Values 0 to 127 are ASCII, but the first 32 are non-printing */
while ((((*curchar < 32) || (*curchar > 126))) && (*curchar != '\0'))
curchar++;
/* we check for sequences of delimiters */
while (index (delim, *curchar) && (*curchar != '\0'))
curchar++;
/* if we are at the end, we stop */
if ((*curchar) == '\0')
{
*next = *current = 0;
return;
}
/* now we see if it is a comment, and if it is we discard everything */
if (index (comment, *curchar))
{
*next = *current = 0;
return;
}
/* now we know that we have a meaningful token, we only need to find
* the next delimiter */
*next = curchar;
/* we look at the end of this stream */
*current = index (curchar, 0);
i = strlen (delim);
while (i)
{
i--;
ctmp = index (curchar, delim[i]);
if (ctmp && (ctmp < *current) && (ctmp > *next))
*current = ctmp;
}
/* now we assume that all non-printable characters are also delimiters */
i = 32;
while (i)
{
i--;
ctmp = index (curchar, i);
if (ctmp && (ctmp < *current) && (ctmp > *next))
*current = ctmp;
}
/* at this stage *current point to the next delimiter or \0 */
if (index (curchar, 0) == *current)
{
*current = 0;
return;
}
/* otherwise there is going to be a non null current and we have to
* add the \0 to the end of next */
**current = 0;
(*current)++;
/* ending */
return;
}
/* Given a string 'input' this function uses EGioParse to separate
* up to N words in it, we assume that argv (output) is an array of pointers to strings
* of size N, and note that the input array will be changed.
* This function is part of OMPlib*/
void OFPnparse (
char *input,
int max_argc,
const char *delim,
const char *comment,
int *argc,
char **argv)
{
char *next;
for ((*argc) = 0, next = input; ((*argc) < max_argc) && next; (*argc)++)
{
OFPparse (&next, &input, delim, comment);
if (next == 0)
break;
argv[(*argc)] = next;
}
return;
}
/*================================================================*/
/* Reads a line of the file, up to max_len characters */
int OFPread_line (
char * str,
const size_t max_len,
FILE * file)
{
char c = 0;
size_t len = max_len;
while (((c = getc (file)) != EOF) && (c != '\n') && --len)
{
str[max_len - 1 - len] = c;
}
str[max_len - len] = '\0';
TEST ((max_len - len) == 0 && c != '\n', "Nothing to be read");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment