/* $ 17:59 4.10.2008
 *
 * Tiny ConfigFile Parser (TCPF) 0.0.1 PRE ALPHA
 *
 * Author: Tiiffi
 *
 * Contact: http://tiiffi.ath.cx
 *          tiiffi @ Quakenet
 *          tiiffi -> gmail.com 
 *
 *
 * file:        tcfp_parser.c
 * description: tcfp parser sources.        
 *
 * =============================================================================
 *
 * This file is part of Tiny ConfigFile Parser (TCPF).
 *
 * Tiny ConfigFile Parser (TCPF) 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 3 of the License, or
 * (at your option) any later version.
 *
 * Tiny ConfigFile Parser (TCPF) 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 Tiny ConfigFile Parser (TCPF).  If not, see <http://www.gnu.org/licenses/>.
 *
 * =============================================================================
 */



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>

#include "tcfp_parser.h"


_TCFP_config_value_t *TCFP_get_value(const char *config_data, const char *key, const char delimiter)
{   
    char *keyValue;

    int setlen = strlen(key);
    int valLen = 0;
 
    char *ptr = strstr(config_data, key);  
    if(ptr == NULL)
    #if TCFP_ERROR_STRINGS
        /* return TCFP_NOT_FOUND; */
    #else
        return NULL;
    #endif  

    ptr += setlen;
    if((ptr[0] != '=') && (ptr[0] != ' '))
    #if TCFP_ERROR_STRINGS
        /* return TCFP_NOT_FOUND; */
    #else
        return NULL;
    #endif

    
    
    setlen = 0;
    while(ptr[valLen] != '\r' && ptr[valLen] != '\n')
    {
        if(ptr[valLen] == delimiter)
        {
            setlen = 1;
            break;
        }
        valLen++;
    }     
    if(setlen < 1) 
    #if TCFP_ERROR_STRINGS
        /* return TCFP_NO_DELIMITER; */
    #else
        return NULL;
    #endif    

   
    /* I think this needs some rechecking */
    ptr = strchr(ptr, delimiter);
    if(ptr == NULL)
    #if TCFP_ERROR_STRINGS
        /* return TCFP_UNKNOWN_ERROR; */
    #else
        return NULL;
    #endif
    ptr++;


    valLen = 0;
    setlen = 0;
    while(ptr[valLen] != '\r' && ptr[valLen] != '\n')
    {
        if(ptr[valLen] == '#') break; /* comment line */

        if(ptr[valLen] == ' ' && setlen == 0) ptr++;
        else
        {
            if(ptr[valLen] == ' ' && ptr[valLen+1] == ' ') break;
            else
            {
                if(setlen == 0) setlen = 1;
                valLen++;
            }
        }
    }
    if(valLen < 1)
    #if TCFP_ERROR_STRINGS
        /* return TCFP_CFG_EMPTY; */
    #else
        return NULL;
    #endif


    keyValue = malloc ( valLen * sizeof(keyValue) + 1);
    if(keyValue == NULL)
    #if TCFP_ERROR_STRINGS
        /* return TCFP_ALLOC_FAILURE; */
    #else
        return NULL;
    #endif

    memcpy(keyValue, ptr, valLen);
    keyValue[valLen] = 0;

    return keyValue;
    /* return TCFP_OK; */
}

void TCFP_free_config_value(_TCFP_config_value_t *keyValue)
{
    if(keyValue) free(keyValue);
}


_TCFP_config_data_t *TCFP_load_config(char *cFilename)
{
    _TCFP_config_data_t *config_data;
    FILE *cFile;
    long int fsize;

    cFile = fopen(cFilename, "rb");
    if(cFile == NULL) return NULL; /* File reading failed */

    if(fseek(cFile, 0, SEEK_END) != 0) return NULL; /* fseek failed */
    
    fsize = ftell(cFile);
    if(fsize < 0) return NULL; /* ftell failed */
    rewind(cFile);

    config_data = (char*) malloc((size_t)fsize * sizeof(char) + 1);
    if(config_data == NULL) return NULL; /* Memory allocating failed */
    
    fread(config_data, (size_t)fsize, sizeof(char), cFile);
    if(ferror(cFile))
    {
        if(config_data) free(config_data);
        fclose(cFile);
        return NULL; /* fread failed */  
    }
    config_data[fsize] = '\0';
  
    if((fclose(cFile)) == EOF)
    {
        if(config_data) free(config_data);
        return NULL; /* fclose failed */
    }

    return config_data;
}

void TCFP_free_config_data(_TCFP_config_data_t *config_data)
{
    if(config_data) free( config_data );
}


#if TCFP_ERROR_STRINGS
char *TCFP_error_string(int error)
{
    switch(error)
    {
        /* global errors */
        case TCFP_NO_ERROR:      return "TCFP: No error.";
        case TCFP_ERROR:         return "TCFP: Error occured.";
        case TCFP_UNKNOWN_ERROR: return "TCFP: Ceiling cat is watching you masturbate.";

        /* getConfig errors */
        case TCFP_NOT_FOUND:     return "TCFP: key not found.";
        case TCFP_NO_DELIMITER:  return "TCFP: Delimiter not found.";
        case TCFP_CFG_EMPTY:     return "TCFP: Key value empty.";        
        case TCFP_ALLOC_FAILURE: return "TCFP: Data allocation failed.";

        default:    return "Blackhole!";
    }
}
#endif



/* EOF */