/*
* iErrVal will be GF_SUCCESS
* cpRv will be the address of the space just before "the" in cpLine
* iLenField will be 4
*/
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.
*/
/******************************************************************************
getLocationMB()
Whereas the getField() class of functions are designed to copy data from
a delimited buffer into another buffer defined by the caller, the
getLocation() class of functions are designed to find the beginning of
a particular position in the delimited buffer.
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
ipLenField - o:length of the extract field if location is detected
ipErrVal - o:where errors are placed, is always filled with a GF_xxxx
Returns:
addr: location of required field
NULL: field not found or error, check *ipErrVal
****/
char *
getLocationMB(char *cpLine, int iLenLine, char *cpDelim, int iLenDelim,
int iDesiredFld, int *ipLenField, int *ipErrVal)
{
int iCurField;
int iValidBytes;
int iByteCounter;
char *cpField;
char *cpStartOfField; // points to first byte of data in field
char *cpEndOfField; // points to one past last byte of data in field
for(;;) /* enables single exit point */
{
/**********
check parms
**********/
if (ipErrVal == NULL)
break; // can't set anything...
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
// and it still hasn't been found yet
if (iLenLine - iByteCounter < iLenDelim)
{
*ipErrVal = GF_FIELD_NOT_FOUND;
break;
}
if (iLenDelim == 1)
{
// this saves on a call to memcmp if the length of
// delimiters is 1... it's not truly multi-byte.
if (*(cpLine+iByteCounter) == *cpDelim)
{
// delimiter found, locate first byte of field
cpField = cpLine + iByteCounter + iLenDelim;
iCurField++; // note new field was found
iByteCounter += iLenDelim; // jump past delimiter
}
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; // jump past delimiter
}
else
{
iByteCounter++;
}
}
}
}
if (*ipErrVal != GF_SUCCESS)
break;
cpStartOfField = cpField;
// At this point:
//
// 1. The start of the proper field is being pointed to by cpStartOfField
// 2. iByteCounter is equal to exactly the number of bytes already examined
// 3. (iLenLine - iByteCounter) is equal to the number of bytes left to process
//
/************************
find end of desired field
************************/
// not endless because SOMETHING below will eventually match
for (iValidBytes = 0;; cpField++, iValidBytes++, iByteCounter++)
{
if (iLenDelim < iLenLine - iByteCounter + 1)
{
if (iLenDelim == 1)
{
// this will be slightly faster than the memcmp below...
if (*cpField == *cpDelim)
{
// next delimiter encountered; end of field
break;
}
}
else
{
if (memcmp(cpField, cpDelim, iLenDelim) == 0)
{
// next delimiter encountered; end of field
break;
}
}
}
// 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
break;
}
}
// end of field is defined to be the first byte which doesn't
// count towards the number of valid bytes.