/*
* Returns GF_SUCCESS
* caBuf set to "22222222"
*/
Source Code
/**
* Copyright (c) 2008, Corey's Consulting LLC. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/******************************************************************************
getFieldMB()
This function gets a field from a buffer using multi-byte delimiters.
THIS IS NOT A STRING FUNCTION!!!!! While it will set the output
buffer to nulls prior to filling it, it does not intentionally null
terminate the resulting buffer, nor will it use any string functions
to perform its operations; it is designed to extract data from a binary
buffer of a known size that has delimiters that are 1 or more bytes in
length. Its most common application is to parse a file with \r\n line
delimiters. The delimiter may be of any length.
Example:
if delim="ab":
++---------++------------++++-------- multi-byte delimiters
|| || ||||
|| || |||| +--- NOT part of a delimiter
|| || |||| |
vv vv vvvv v
lineabfewjkdwjkabjfi4eo2cfjdkababfdvda
^^^^ ^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^
|||| ||||||||| |||||||||||| |||||
|||| ||||||||| |||||||||||| +++++--- fifth field
|||| ||||||||| |||||||||||| fourth field is empty
|||| ||||||||| ++++++++++++------------ third field
|||| +++++++++-------------------------- second field
++++------------------------------------- first field
Parameters:
cpLine - i:line containing fields, needn't be null terminated
iLenLine - i:length of cpLine
cpDelim - i:field delimiter to use
iLenDelim - i:length of cpDelim
iDesiredFld - i:field number to get, starting at 1
cpOutBuf - o:output buffer, where field will go, will be null terminated
iSizBuf - i:size of output buffer, to prevent overruns
Returns:
GF_xxx
****/
int
getFieldMB(char *cpLine, int iLenLine, char *cpDelim, int iLenDelim,
int iDesiredFld, char *cpOutBuf,int iSizBuf)
{
int iRv;
int iCurField;
int iBytesCopied;
int iByteCounter;
char *cpField;
for(;;) /* enables single exit point */
{
/**********
check parms
**********/
if (iDesiredFld != 1) /* first field starts at offset 0 */
{
while (iCurField < iDesiredFld)
{
// break if we're so close to the end there can't be a delim
if (iLenLine - iByteCounter < iLenDelim)
{
iRv = GF_FIELD_NOT_FOUND;
break;
}
if (iLenDelim == 1)
{
// this increases the speed when delimiter length is 1
if (*(cpLine+iByteCounter) == *cpDelim)
{
// delimiter found, locate first byte of field
cpField = cpLine + iByteCounter + iLenDelim;
iCurField++; // note new field was found
iByteCounter += iLenDelim;
}
else
{
iByteCounter++;
}
}
else
{
if (memcmp(cpLine+iByteCounter, cpDelim, iLenDelim) == 0)
{
// delimiter found, locate first byte of field
cpField = cpLine + iByteCounter + iLenDelim;
iCurField++; // note new field was found
iByteCounter += iLenDelim;
}
else
{
iByteCounter++;
}
}
}
}
if (iRv != GF_SUCCESS)
break;
// at this point, the start of the proper field is being pointed to by
// cpField, iByteCounter is equal to exactly the number of bytes
// already examined, and (iLenLine - iByteCounter) is equal to the
// number of bytes left to process.
/************
extract field
************/
// not endless because SOMETHING below will eventually match
for (iBytesCopied = 0;; cpField++, iBytesCopied++, iByteCounter++)
{
if (iLenDelim < iLenLine - iByteCounter + 1)
{
// this increases the speed when delimiter length is 1
if (iLenDelim == 1)
{
if (*cpField == *cpDelim)
{
// next delimiter encountered; end of field
iRv = GF_SUCCESS;
break;
}
}
else
{
if (memcmp(cpField, cpDelim, iLenDelim) == 0)
{
// next delimiter encountered; end of field
iRv = GF_SUCCESS;
break;
}
}
}
// bail if we are about to run out of room and overwrite
if (iBytesCopied+1 >= iSizBuf)
{
iRv = GF_SIZE_TOO_SMALL;
}
// bail if we run out of input data
if (iByteCounter >= iLenLine)
{
// iByteCounter must be one past end of buffer, must have
// just finished copying the last field
iRv = GF_SUCCESS;
break;
}
cpOutBuf[iBytesCopied] = *cpField;
}
if (1==1)
break;
} /* end single exit point "for" */