Professional Software Consulting

getFieldMB()

The getFieldMB function.

Example Usage
int iRv;
char caBuf[255+1];
char *cpLine = "11111111|||22222222|||&33333333|||";
char *cpDelim = "|||";

memset(caBuf, 0, sizeof(caBuf));
iRv = getFieldMB(cpLine, strlen(cpLine), cpDelim, strlen(cpDelim), 2, caBuf, sizeof(caBuf)-1);

/*
* 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 ((cpLine == NULL) || (cpOutBuf == NULL) || (cpDelim == NULL))
        {
            iRv = GF_NULL_PARAM;
            break;
        }

        if (iSizBuf < 1)
        {
            iRv = GF_SIZE_TOO_SMALL;
            break;
        }

        if ((iLenDelim) < 1 || (iLenLine < 1) || (iDesiredFld < 1))
        {
            iRv = GF_INVALID_PARMS;
            break;
        }


        /**************************
        find start of desired field
        **************************/

        cpField = cpLine;
        iRv = GF_SUCCESS;
        iByteCounter = 0;
        iCurField = 1;

        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.


        /* initialize output */
        memset(cpOutBuf, 0, iSizBuf);


        /************
        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" */


    return(iRv);
}    // end getFieldMB()

     Contact Us     

Something wrong with this page or this site? Let the webmaster know by clicking HERE
This website designed, implemented, and maintained by Corey Dulecki
© 2009-2012, Corey's Consulting LLC