/******************************************************************************
 *    strqsep.cpp
 *
 *    This file is part of Object Script Library
 *    Copyright (C) 2005-2009 Tom N Harris <telliamed@whoopdedo.org>
 *
 *    Permission is hereby granted, free of charge, to any person obtaining
 *    a copy of this software and associated documentation files (the 
 *    "Software"), to deal in the Software without restriction, including 
 *    without limitation the rights to use, copy, modify, merge, publish, 
 *    distribute, sublicense, and/or sell copies of the Software, and to 
 *    permit persons to whom the Software is furnished to do so.
 *    
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
 *    INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 *    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 
 *    AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 
 *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 *    THE SOFTWARE.
 *
 *****************************************************************************/

#include <string.h>

/* Seperate a string on any of delim characters while preserving 
 * substrings surrounded by an equal pair of any of quotes characters.
 * str is the address of a pointer to the string to be seperated.
 * The pointer to the next token in the string, or NULL, is copied to 
 * the address and the the value that was passed in *str is returned.
 * delim and quotes cannot be NULL.
 * Empty tokens will be returned.
 * Like strtok and strsep, the string data will be modified.
 * str, of course, must be an lvalue.
 */
char* strqsep(char** str, const char* delim, const char* quotes)
{
	char dtable[256];
	char qtable[256];
	register char* p = *str;
	if (!p) return NULL;
	memset(dtable,0,sizeof(dtable));
	memset(qtable,0,sizeof(dtable));
	{
		register const unsigned char* d = reinterpret_cast<const unsigned char*>(delim);
		while (*d)
			dtable[*d++] = -1;
	}
	{
		register const unsigned char* q = reinterpret_cast<const unsigned char*>(quotes);
		while (*q)
			qtable[*q++] = -1;
	}
	while (*p)
	{
		if (qtable[*reinterpret_cast<unsigned char*>(p)])
		{
			register char* t = p;
			do
			{
				t = strchr(t+1, *p);
				if (!t)
				{
					p = *str;
					*str = NULL;
					return p;
				}
			}
			while (*(t-1) == '\\');
			p = t;
		}
		else if (dtable[*reinterpret_cast<unsigned char*>(p)])
		{
			register char* t = *str;
			*p++ = '\0';
			*str = p;
			return t;
		}
		++p;
	}
	p = *str;
	*str = NULL;
	return p;
}
