/*
 *      A string splitter to extract values expressed in a CSV-like format.
 *
 *      Copyright (c) 2004-2005 Naoaki Okazaki
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions (known as zlib license):
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 * Naoaki Okazaki <okazaki at chokkan dot org>
 *
 */

/* $Id: strsplit.h 2 2006-10-31 00:57:57Z naoaki $ */

/*
Template function 'strsplit' implements a parser for string values
deliminated by a input_separator which can be escaped by a quotation character.
In other words, this function can extract comma-separated values (CSV) or
tab-separated values (TSV) from a line expressed by a string class. The
parsed values will be stored into a object that is compatible to the
container adaptor such as std::vector and std::list. Both input_separator and 
quotation character are configurable with the third and forth arguments.
Two contiguous quotation characters in an escaped field are interpreted
as one quotation character. This implementation does not support a break
line escaped by a quotation mark and returns 1.

This code was comfirmed to be compiled with MCVC++ 2003 and gcc 3.3.
Define _BUILD_NCL_SAMPLE if you want to build a sample program.
    $ g++ -D_BUILD_NCL_SAMPLE -xc++ strsplit.h
*/

#ifndef __NCL_STRSPLIT_H__
#define __NCL_STRSPLIT_H__

#include <string>


#ifdef  USE_NCL_NAMESPACE
namespace ncl {
#endif/*USE_NCL_NAMESPACE*/


template <class _Cont, class _Elem>
static int strsplit(
    _Cont& values,
    const std::basic_string<_Elem>& line,
    const _Elem sep = (const _Elem)',',
    const _Elem quot = (const _Elem)'"'
    )
{
    int ret = 0;

    // Initialize the container.
    values.clear();
    typename std::basic_string<_Elem>::const_iterator it = line.begin();
    while (it != line.end()) {
        std::basic_string<_Elem> value;
        if (*it == quot) {
            for (++it;it != line.end();++it) {
                if (*it == quot) {
                    ++it;
                    if (it == line.end()) {
                        ret = 1;
                        break;
                    } else if (*it == sep) {
                        ++it;
                        break;
                    } else if (*it != quot) {
                        --it;
                    }
                }
                value += *it;
            }
        } else {
            for (;it != line.end();++it) {
                if (*it == sep) {
                    ++it;
                    break;
                }
                value += *it;
            }
        }
        values.push_back(value);
    }
    return ret;
}


#ifdef  USE_NCL_NAMESPACE
};
#endif/*USE_NCL_NAMESPACE*/






#ifdef  _BUILD_NCL_SAMPLE

#include <iostream>
#include <vector>

int main(int argc, char *argv[])
{
    std::vector<std::string> values;

    for (;;) {
        std::string line;
        std::getline(std::cin, line);
        strsplit(values, line, '\t');

        for (int i = 0;i < values.size();i++) {
            std::cout << values[i] << std::endl;
        }
        std::cout << std::endl;
    }
    return 0;
}

#endif/*_BUILD_NCL_SAMPLE*/

#endif/*__NCL_STRSPLIT_H__*/