/*
 * Copyright (C) 2007 JasperSoft http://www.jaspersoft.com
 * 
 * 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 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed WITHOUT ANY WARRANTY; and without 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, see http://www.gnu.org/licenses/gpl.txt 
 * or write to:
 * 
 * Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330,
 * Boston, MA  USA  02111-1307
 */
 
#include "stringbuffer.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define INCREMENT_STRING_SIZE 256

/**
 * jasperserver_stringVSprintf:
 * 
 * (Function deriver by xmlTextWriterVSprintf from libxml2)
 * Utility function for formatted output
 *
 * \param format  see printf
 * \param argptr  pointer to the first member of the variable argument list.
 *
 * \return a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
 */
static  xmlChar * jasperserver_stringVSprintf(const char *format, va_list argptr);

/**
 * jasperserver_string_vformat:
 * 
 * (Function deriver by xmlTextWriterVSprintf from libxml2)
 * Utility function for formatted output
 *
 * \param format  see printf
 * \param argptr  pointer to the first member of the variable argument list.
 *
 * \return a new xmlChar buffer with the data or NULL on error. This buffer must be freed.
 */
int jasperserver_string_vformat(jasperserver_string_t *jsstr,const char *format, va_list argptr);


jasperserver_string_t *jasperserver_string_new()
{
       jasperserver_string_t *jsstr = (jasperserver_string_t *)malloc( sizeof(jasperserver_string_t));
       //jasperserver_init_string(jsstr);
       jsstr->buffer = xmlBufferCreate();
       return jsstr;
}

//void jasperserver_init_string(jasperserver_string_t *jsstr)
//{
//     jsstr->buffer = NULL;
//     jsstr->bufSize = 0;
//     jsstr->strLen = 0;
//}

void jasperserver_string_free(jasperserver_string_t *jsstr)
{
     if (!jsstr) return;
     if (jsstr->buffer)
     {
        xmlBufferFree(jsstr->buffer);
     }
}
/*
* Append a zero terminated C string to an XML buffer.
*/
void jasperserver_string_cappend(jasperserver_string_t *jsstr,const char *utf)
{
    if (!utf || !jsstr) 
    {
      return;
    }
    
    xmlBufferCCat(jsstr->buffer, utf);
}

/*
* Append a zero terminated string to an jasperserver_string.
*/
void jasperserver_string_append(jasperserver_string_t *jsstr,const xmlChar *utf)
{
    if (!utf || !jsstr) 
    {
      return;
    }
    
    xmlBufferCat(jsstr->buffer, utf);
} 
    
//    if (jsstr->buffer == NULL)
//    {
//       jsstr->buffer = (char *)malloc(INCREMENT_STRING_SIZE);
//       jsstr->bufSize = INCREMENT_STRING_SIZE;
//       sprintf(jsstr->buffer, "");
//       jsstr->strLen = 0;
//    }
//    
//    while (xmlUTF8Strsize(str)+1 > jsstr->bufSize - jsstr->strLen)
//    {
//        jsstr->buffer = (char *)realloc(jsstr->buffer, (jsstr->bufSize + INCREMENT_STRING_SIZE)* sizeof(char));
//        jsstr->bufSize += INCREMENT_STRING_SIZE;
//    }
//    strncat(jsstr->buffer,str,strlen(str));
//    jsstr->strLen += strlen(str);
    


//void jasperserver_replace_string(jasperserver_string_t *jsstr,const char *oldString, const char *newString)
//{
//     char *sPtr;
//     if (!oldString || !jsstr || !newString) 
//     {
//       return;
//     }
//     
//     sPtr = strstr(jsstr->buffer, oldString);
//     while (sPtr != NULL)
//     {
//           // Move the remaining string...
//           int pos = strlen(newString) - strlen(oldString);
//           
//           if (pos != 0)
//           {
//               // check in there is space available...
//               if (jsstr->strLen + 1 + pos > jsstr->bufSize)
//               {
//                  jsstr->buffer = (char *)realloc(jsstr->buffer, (jsstr->bufSize + INCREMENT_STRING_SIZE)* sizeof(char));
//                  jsstr->bufSize += INCREMENT_STRING_SIZE;
//               }
//               printf("Positions: %d",pos);
//               fflush(stdout);
//               memmove(sPtr + strlen(newString), sPtr + strlen(oldString), strlen(sPtr)+1);
//               jsstr->strLen += pos;
//           }
//           memcpy(sPtr, newString, strlen(newString));
//           
//           sPtr += strlen(newString);
//           sPtr = strstr(sPtr, oldString);
//     }
//     
//}


void jasperserver_string_set(jasperserver_string_t *jsstr,const xmlChar *str)
{
    if (!jsstr || !str) return;

    xmlBufferEmpty( jsstr->buffer );
    jasperserver_string_append(jsstr, str );
}

void jasperserver_string_cset(jasperserver_string_t *jsstr,const char *str)
{
    if (!jsstr || !str) return;
    
    xmlBufferEmpty( jsstr->buffer );
    jasperserver_string_cappend(jsstr, str );
}


int jasperserver_string_format(jasperserver_string_t *jsstr,const char *format, ...)
{
    int rc;
    xmlChar *buf;
    va_list ap;
    
    if (format == NULL) return -1;

    va_start(ap, format);

    rc = jasperserver_string_vformat(jsstr, format, ap);

    va_end(ap);
    return rc;
}


int jasperserver_string_vformat(jasperserver_string_t *jsstr,const char *format, va_list argptr)
{
    int rc;
    xmlChar *buf;

    buf = jasperserver_stringVSprintf(format, argptr);
    if (buf == 0) return 0;
    jasperserver_string_append(jsstr, buf);
    rc = strlen(buf);
    xmlFree(buf);
    return rc;
}


static xmlChar *
jasperserver_stringVSprintf(const char *format, va_list argptr)
{
    int size;
    int count;
    xmlChar *buf;

    size = 512;
    buf = (xmlChar *) xmlMalloc(size);
    if (buf == NULL) {
        return NULL;
    }

    while (((count = vsnprintf((char *) buf, size, format, argptr)) < 0)
           || (count == size - 1) || (count == size) || (count > size)) {
        xmlFree(buf);
        size += 512;
        buf = (xmlChar *) xmlMalloc(size);
        if (buf == NULL) {
            return NULL;
        }
    }

    return buf;
}
