/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/* Headers */
#include <stdio.h>
#ifdef VX
#include <string.h>
#endif
#include "js-utils.h"
#include "js-stringbuffer.h"

/* Procedures */
void
JSStringBuffer::ensureCapacity(int minimumCapacity)
{
    int maxCapacity = valueLength;

    if (minimumCapacity > maxCapacity) {
        int newCapacity = (maxCapacity + 1) * 2;

        if (minimumCapacity > newCapacity) {
            newCapacity = minimumCapacity;
        }

        jsChar_t *newValue
		= (jsChar_t *) JS_NewZoneObj(cx, sizeof (*newValue)
						* newCapacity);
	if (value != NULL) {
	    memcpy(newValue, value, sizeof (*newValue) * count);
	    JS_DeleteZoneObj(cx, value);
	}
	valueLength = newCapacity;
	value = newValue;
    }
}    

void
JSStringBuffer::append(jsString_t string, int offset, int len)
{
    ensureCapacity(count + len);
    memcpy(value + count, string + offset, sizeof (*value) * len);
    count += len;
}
void
JSStringBuffer::append(jsString_t string)
{
    int len = strlen(string);

    ensureCapacity(count + len);
    memcpy(value + count, string, sizeof (*value) * len);
    count += len;
}
void
JSStringBuffer::append(jsChar_t c)
{
    ensureCapacity(count + 1);
    value[count++] = c;
}
void
JSStringBuffer::append(int i)
{
    append((int64_t) i);
}
void
JSStringBuffer::append(int64_t l)
{
    jsChar_t buf[32];

#if __x86_64
    sprintf(buf, "%ld", l);
#else
    sprintf(buf, "%lld", l);
#endif

    int len = strlen(buf);

    ensureCapacity(count + len);
    memcpy(value + count, buf, sizeof (*value) * len);
    count += len;
}
int
JSStringBuffer::length()
{
    return count;
}
#ifdef DTOA
jsChar_t
JSStringBuffer::charAt(int index)
{
    return value[index];
}
void
JSStringBuffer::setLength(int newLength)
{
    ensureCapacity(newLength);
    if (count < newLength) {
	memcpy(value + count, 0, sizeof (*value) * (newLength - count));
    }
    count = newLength;
}
JSStringBuffer *
JSStringBuffer::insert(int offset, jsChar_t c)
{
    ensureCapacity(count + 1);
    memmove(value + offset + 1, value + offset,
	sizeof (*value) * (count - offset));
    value[offset] = c;
    count += 1;
    return this;
}
JSStringBuffer *
JSStringBuffer::reverse()
{
    int n = count - 1;

    for (int j = (n - 1) >> 1; j >= 0; --j) {
        jsChar_t temp;

	temp = value[j];
        value[j] = value[n - j];
        value[n - j] = temp;
    }
    return this;
}
#endif /* DTOA */
jsString_t
JSStringBuffer::toString()
{
    ensureCapacity(count + 1);
    value[count] = '\0';
    return value;
}
jsString_t
JSStringBuffer::offString()
{
    jsString_t result = toString();

    valueLength = 0;
    value = NULL;
    count = 0;

    return result;
}

JSStringBuffer::JSStringBuffer(JSContext *cx, int length)
{
    this->cx = cx;
    valueLength = length;
    if (valueLength > 0) {
	value = (jsChar_t *) JS_NewZoneObj(cx, sizeof (*value) * valueLength);
    } else {
	value = NULL;
    }
    count = 0;
}
JSStringBuffer::JSStringBuffer(JSContext *cx, jsString_t string)
{
    this->cx = cx;

    valueLength = 0;
    value = NULL;
    count = 0;

    append(string);
}
JSStringBuffer::~JSStringBuffer()
{
    if (value != NULL) {
	JS_DeleteZoneObj(cx, value);
    }
}

