/***************************************************************************
  
  gbc_project.c
  
  (c) Benoît Minisini <benoit.minisini@gambas-basic.org>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2, or (at your option)
  any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  MA 02110-1301, USA.
  
***************************************************************************/

#define __GBC_PROJECT_C

#include "gb_common.h"
#include "gb_common_buffer.h"
#include "gb_buffer.h"
#include "gb_str.h"
#include "gbc_project.h"

#include <ctype.h>

static char *_buffer = NULL;
static int _buffer_pos;

bool PROJECT_load(const char *path)
{
	if (!_buffer)
		BUFFER_create(&_buffer);
	return BUFFER_load_file(&_buffer, path);
}

static bool read_line(const char **line, int *len)
{
	int l;
	char c;
	
	if (_buffer_pos >= BUFFER_length(_buffer))
		return TRUE;
	
	*line = &_buffer[_buffer_pos];
	l = 0;
	
	while (_buffer_pos < BUFFER_length(_buffer))
	{
		c = _buffer[_buffer_pos++];
		if (c == '\n')
			break;
		l++;
	}
	
	*len = l;
	return FALSE;
}

void PROJECT_browse(PROJECT_BROWSE_FUNC func)
{
	const char *p2;
	const char *line;
	int len;
	int len_key;
	
	_buffer_pos = 0;
	
	while (!read_line(&line, &len))
	{
		if (!isalpha(*line))
			continue;
		p2 = memchr(line, '=', len);
		if (!p2)
			continue;
		len_key = p2 - line;
		if ((*func)(line, len_key, p2 + 1, len - len_key - 1))
			break;
	}
}

static int read_hex_digit(unsigned char c)
{
	if (c >= '0' && c <= '9')
		return (c - '0');
	else if (c >= 'A' && c <= 'F')
		return (c - 'A' + 10);
	else if (c >= 'a' && c <= 'f')
		return (c - 'a' + 10);
	else
		return 0;
}

void PROJECT_browse_string_list(const char *value, int len, PROJECT_BROWSE_VALUE func)
{
	int i;
	int l;
	char c;
	
	l = 0;
	
	i = 0;
	while (i < len)
	{
		c = value[i++];
		if (c != '"')
			break;
		
		while (i < len)
		{
			c = value[i++];
			if (c == '"')
			{
				func(COMMON_buffer, l);
				break;
			}
			
			if (c == '\\')
			{
				if (i >= len)
					break;
				c = value[i++];

				if (c == 'n')
					c = '\n';
				else if (c == 't')
					c = '\t';
				else if (c == 'r')
					c = '\r';
				else if (c == 'x')
				{
					if (i >= (len - 2))
						break;

					c = (read_hex_digit(value[i]) << 4) + read_hex_digit(value[i + 1]);
					i += 2;
				}
			}
			
			COMMON_buffer[l++] = c;
		}
		
		if (i >= len)
			break;
		
		c = value[i++];
		if (c != ',')
			break;
	}
}

void PROJECT_exit()
{
	BUFFER_delete(&_buffer);
}
