/************************************************************************/ /* Shared library routine for parsing .csv files */ /* Scott Auge sauge@amduus.com scott_auge@yahoo.com */ /************************************************************************/ char *RCS = "$Header: /home/sauge/code/C/importer/prsimport.c,v 1.7 2004/11/20 10:46:35 sauge Exp sauge $"; /* Comment out to turn off or use -DDEBUG in compiler invocation */ /* This should be compiled with -shared on gcc or what ever */ /* creates a shared memory executable on your operating system. */ /* #define DEBUG */ #include #include "prsimport.h" #ifdef DEBUG #include #endif /************************************************************************/ /* Given a line from a .csv file, determine how many entries there are. */ /* Strings are contained in " and " */ /* Quotes are double quoted as in """" is for a string " */ /* Numbers are contained without " and " */ /* Warning: If the data size in the column for the given Line is */ /* greater than the space allocated in Junk, this routine will */ /* wash out! */ /************************************************************************/ int NumColumns (char *Line, char *Junk) { int iNumColumns = 0; /* Loop GetColumn incrementing column number till it complains */ while(1) { if (GetColumn(Line, iNumColumns, Junk) == 0) iNumColumns++; else break; } return iNumColumns; } /* int NumColumns () */ /************************************************************************/ /* Given a line and column number, return the text in that line. Fun- */ /* ction returns the error or no error. */ /* You must allocate the space for Value yourself. */ /************************************************************************/ int GetColumn (char *cpLine, int iColumn, char *cpValue) { typedef enum {FALSE = 0, TRUE = 1} bool; int iCurColumn = 0, iCurLinePos = 0, iCurValuePos = 0; char cCurChar; bool InString = FALSE; int iLineLen = strlen(cpLine); #ifdef DEBUG printf("1:iLineLen=%i\n", iLineLen); #endif /* Find the column we want */ while (1) { /* If we are on the column we want, bail outta here */ if (iCurColumn == iColumn) break; /* Ran out of string - return impossible column number error */ if (iCurLinePos > iLineLen) return -1; /* Grab a character from line and move forward for the next one */ cCurChar = *(cpLine + iCurLinePos); iCurLinePos++; #ifdef DEBUG printf("2:cCurChar = %c, iCurLinePos=%i\n", cCurChar, iCurLinePos); #endif /* If we got a ", we need to know if we are in a string, or if */ /* we are working a "" which is a " in the string. */ /* If we are working a "" then skip over it. If not, then we */ /* are in a string delimiter. Toggle the InString flag. */ if (cCurChar == '"' && *(cpLine + iCurLinePos) == '"') iCurLinePos++; else if (cCurChar == '"') { InString = InString == FALSE ? TRUE : FALSE; continue; } /* If we got a comma and we ain't in a string, then we found */ /* a new column! */ if (cCurChar == ',' && InString == FALSE) iCurColumn++; } /* while () */ /* Start pulling out the data we want */ while (1) { /* Ran out of string - return impossible column number error */ if (iCurLinePos >= iLineLen) return 0; /* Grab a character from line and move forward for the next one */ cCurChar = *(cpLine + iCurLinePos); iCurLinePos++; #ifdef DEBUG printf("2:cCurChar = %c, iCurLinePos=%i\n", cCurChar, iCurLinePos); #endif /* If we got a ", we need to know if we are in a string, or if */ /* we are working a "" which is a " in the string. */ /* If we are working a "" then skip over it. If not, then we */ /* are in a string delimiter. Toggle the InString flag. */ if (cCurChar == '"' && *(cpLine + iCurLinePos) == '"') iCurLinePos++; else if (cCurChar == '"') { InString = InString == FALSE ? TRUE : FALSE; continue; } /* If we got a comma and we ain't in a string, then we found */ /* a new column! We are done! */ if (cCurChar == ',' && InString == FALSE) break; *(cpValue + iCurValuePos) = cCurChar; iCurValuePos++; } /* while () */ return 0; } /* GetColumn () */ /************************************************************************/ /* Progress doesn't provide much to clean up memory once it has been */ /* used. Even unallocating and re-allocating doesn't work to clean */ /* char strings. Run the memptr's through this to clean em out. */ /************************************************************************/ int ClearMem (char *M, int Size) { memset((char *)M, '\0', Size); } /* ClearMem */