/*
 * Copyright (C) Tildeslash Ltd. All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 *
 * You must obey the GNU Affero General Public License in all respects
 * for all of the code used other than OpenSSL.  
 */

#include "Config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>

#include "StringBuffer.h"


/**
 * Implementation of the StringBuffer interface. 
 *
 * @see http://www.mmonit.com/
 * @file
 */


/* ------------------------------------------------------------ Definitions */


#define T StringBuffer_T
struct T {
        int used;
        int length;
	uchar_t *buffer;
};


/* ---------------------------------------------------------------- Private */


static inline void append(T S, const char *s, va_list ap) {
        va_list ap_copy;
        while (true) {
                va_copy(ap_copy, ap);
                int n = vsnprintf((char*)(S->buffer + S->used), S->length - S->used, s, ap_copy);
                va_end(ap_copy);
                if ((S->used + n) < S->length) {
                        S->used += n;
                        break;
                }
                S->length += STRLEN + n;
                RESIZE(S->buffer, S->length);
        }
}


static inline T ctor(int hint) {
        T S;
        NEW(S);
        S->used = 0;
        S->length = hint;
        S->buffer = ALLOC(hint);
        *S->buffer = 0;
        return S;
}


/* ----------------------------------------------------------------- Public */


T StringBuffer_new(const char *s) {
        return StringBuffer_append(ctor(STRLEN), "%s", s);
}


T StringBuffer_create(int hint) {
        if (hint <= 0)
                THROW(AssertException, "Illegal hint value");
        return ctor(hint);
}


void StringBuffer_free(T *S) {
        assert(S && *S);
        FREE((*S)->buffer);
        FREE(*S);
}


T StringBuffer_append(T S, const char *s, ...) {
        assert(S);
        if (s && *s) {
                va_list ap;
                va_start(ap, s);
                append(S, s, ap);
                va_end(ap);
        }
        return S;
}


T StringBuffer_vappend(T S, const char *s, va_list ap) {
        assert(S);
        if (s && *s) {
                va_list ap_copy;
                va_copy(ap_copy, ap);
                append(S, s, ap_copy);
                va_end(ap_copy);
        }
        return S;
}


char StringBuffer_charAt(T S, int index) {
        assert(S);
        if (index < 0 || index > S->used)
                THROW(AssertException, "Index out of bounds");
        return S->buffer[index];
}


void StringBuffer_setCharAt(T S, int index, char c) {
        assert(S);
        if (index < 0 || index > S->used)
                THROW(AssertException, "Index out of bounds");
        S->buffer[index] = c;
}


int StringBuffer_replace(T S, const char *a, const char *b) {
        int n = 0;
        assert(S);
        if (a && b && *a) {
                register int i, j;
                for (i = 0; S->buffer[i]; i++) {
                        if (S->buffer[i] == *a) {
                                j = 0;
                                do
                                        if (! a[++j]) {n++; break;}
                                while (S->buffer[i + j] == a[j]);
                        }
                }
                if (n) {
                        int m = n;
                        size_t bl = strlen(b);
                        size_t diff = bl - strlen(a);
                        if (diff > 0) {
                                size_t required = (diff * n) + S->used + 1;
                                if (required >= S->length) {
                                        S->length = (int)required;
                                        RESIZE(S->buffer, S->length);
                                }
                        }
                        for (i = 0; m; i++) {
                                if (S->buffer[i] == *a) {
                                        j = 0;
                                        do
                                                if (! a[++j]) {
                                                        memmove(S->buffer + i + bl, S->buffer + i + j, (S->used - (i + j)));
                                                        memcpy(S->buffer + i, b, bl); 
                                                        S->used += diff;
                                                        i += bl - 1;
                                                        m--;
                                                        break;
                                                }
                                        while (S->buffer[i + j] == a[j]);
                                }
                        }
                        S->buffer[S->used] = 0;
                }
        }
        return n;
}


T StringBuffer_trim(T S) {
        assert(S);
        // Right trim
        while (S->used && isspace(S->buffer[S->used - 1])) 
                S->buffer[--S->used] = 0;
        // Left trim
        if (isspace(*S->buffer)) {
                int i;
                for (i = 0; isspace(S->buffer[i]); i++) ;
                memmove(S->buffer, S->buffer + i, S->used - i);
                S->used -= i;
                S->buffer[S->used] = 0;
        }
        return S;
}


T StringBuffer_delete(T S, int index) {
        assert(S);
        if (index < 0 || index > S->used)
                THROW(AssertException, "Index out of bounds");
        S->used = index;
        S->buffer[S->used] = 0;
        return S;
}


int StringBuffer_indexOf(T S, const char *s) {
        assert(S);
        if (s && *s) {
                register int i, j;
                for (i = 0; i <= S->used; i++) {
                        if (S->buffer[i] == *s) {
                                j = 0;
                                do
                                        if (! s[++j])
                                                return i;
                                while (S->buffer[i + j] == s[j]);
                        }
                }
        }
        return -1;
}


int StringBuffer_lastIndexOf(T S, const char *s) {
        assert(S);
        if (s && *s) {
                register int i, j;
                for (i = S->used; i >= 0; i--) {
                        if (S->buffer[i] == *s) {
                                j = 0;
                                do
                                        if (! s[++j])
                                                return i;
                                while (S->buffer[i + j] == s[j]);
                        }
                }
        }
        return -1;
}


const char *StringBuffer_substring(T S, int index) {
        assert(S);
        if (index < 0 || index > S->used)
                THROW(AssertException, "Index out of bounds");
        return (const char*)(S->buffer + index);
}


int StringBuffer_length(T S) {
        assert(S);
        return S->used;
}


T StringBuffer_clear(T S) {
        assert(S);
        S->used = 0;
        *S->buffer = 0;
        return S;
}


const char *StringBuffer_toString(T S) {
        assert(S);
        return (const char*)S->buffer;
}

