/* Copyright David Abrahams 2004. Distributed under the Boost */
/* Software License, Version 1.0. (See accompanying */
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */

#include "jam.h"
#include "strings.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>


#ifndef NDEBUG
# define JAM_STRING_MAGIC ((char)0xcf)
# define JAM_STRING_MAGIC_SIZE 4
static void assert_invariants( string* self )
{
    int i;

    if ( self->value == 0 )
    {
        assert( self->size == 0 );
        assert( self->capacity == 0 );
        assert( self->opt[0] == 0 );
        return;
    }

    assert( self->size < self->capacity );
    assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
    assert( strlen( self->value ) == self->size );

    for (i = 0; i < 4; ++i)
    {
        assert( self->magic[i] == JAM_STRING_MAGIC );
        assert( self->value[self->capacity + i] == JAM_STRING_MAGIC );
    }
}
#else
# define JAM_STRING_MAGIC_SIZE 0
# define assert_invariants(x) do {} while (0)
#endif

void string_new( string* s )
{
    s->value = s->opt;
    s->size = 0;
    s->capacity = sizeof(s->opt);
    s->opt[0] = 0;
#ifndef NDEBUG
    memset(s->magic, JAM_STRING_MAGIC, sizeof(s->magic));
#endif
    assert_invariants( s );
}

void string_free( string* s )
{
    assert_invariants( s );
    if ( s->value != s->opt )
        BJAM_FREE( s->value );
    string_new( s );
}

static void string_reserve_internal( string* self, size_t capacity )
{
    if ( self->value == self->opt )
    {
        self->value = (char*)BJAM_MALLOC_ATOMIC( capacity + JAM_STRING_MAGIC_SIZE );
        self->value[0] = 0;
        strncat( self->value, self->opt, sizeof(self->opt) );
        assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
    }
    else
    {
        self->value = (char*)BJAM_REALLOC( self->value, capacity + JAM_STRING_MAGIC_SIZE );
    }
#ifndef NDEBUG
    memcpy( self->value + capacity, self->magic, JAM_STRING_MAGIC_SIZE );
#endif
    self->capacity = capacity;
}

void string_reserve( string* self, size_t capacity )
{
    assert_invariants( self );
    if ( capacity <= self->capacity )
        return;
    string_reserve_internal( self, capacity );
    assert_invariants( self );
}

static void extend_full( string* self, char const* start, char const* finish )
{
    size_t new_size = self->capacity + ( finish - start );
    size_t new_capacity = self->capacity;
    size_t old_size = self->capacity;
    while ( new_capacity < new_size + 1)
        new_capacity <<= 1;
    string_reserve_internal( self, new_capacity );
    memcpy( self->value + old_size, start, new_size - old_size );
    self->value[new_size] = 0;
    self->size = new_size;
}

void string_append( string* self, char const* rhs )
{
    char* p = self->value + self->size;
    char* end = self->value + self->capacity;
    assert_invariants( self );

    while ( *rhs && p != end)
        *p++ = *rhs++;

    if ( p != end )
    {
        *p = 0;
        self->size = p - self->value;
    }
    else
    {
        extend_full( self, rhs, rhs + strlen(rhs) );
    }
    assert_invariants( self );
}

void string_append_range( string* self, char const* start, char const* finish )
{
    char* p = self->value + self->size;
    char* end = self->value + self->capacity;
    assert_invariants( self );

    while ( p != end && start != finish )
        *p++ = *start++;

    if ( p != end )
    {
        *p = 0;
        self->size = p - self->value;
    }
    else
    {
        extend_full( self, start, finish );
    }
    assert_invariants( self );
}

void string_copy( string* s, char const* rhs )
{
    string_new( s );
    string_append( s, rhs );
}

void string_truncate( string* self, size_t n )
{
    assert_invariants( self );
    assert( n <= self->capacity );
    self->value[self->size = n] = 0;
    assert_invariants( self );
}

void string_pop_back( string* self )
{
    string_truncate( self, self->size - 1 );
}

void string_push_back( string* self, char x )
{
    string_append_range( self, &x, &x + 1 );
}

char string_back( string* self )
{
    assert_invariants( self );
    return self->value[self->size - 1];
}

#ifndef NDEBUG
void string_unit_test()
{
    string s[1];
    int i;
    char buffer[sizeof(s->opt) * 2 + 2];
    int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);

    string_new(s);

    for (i = 0; i < limit; ++i)
    {
        string_push_back( s, (char)(i + 1) );
    };

    for (i = 0; i < limit; ++i)
    {
        assert( i < s->size );
        assert( s->value[i] == (char)(i + 1));
    }

    string_free(s);

}
#endif

