blob: c4e86dbad28a6d88861469009f9d2eb9158f75e1 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "vm/StringBuffer.h"
#include "jsobjinlines.h"
#include "vm/String-inl.h"
using namespace js;
jschar *
StringBuffer::extractWellSized()
{
size_t capacity = cb.capacity();
size_t length = cb.length();
jschar *buf = cb.extractRawBuffer();
if (!buf)
return NULL;
/* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
JS_ASSERT(capacity >= length);
if (length > CharBuffer::sMaxInlineStorage && capacity - length > length / 4) {
size_t bytes = sizeof(jschar) * (length + 1);
JSContext *cx = context();
jschar *tmp = (jschar *)cx->realloc_(buf, bytes);
if (!tmp) {
js_free(buf);
return NULL;
}
buf = tmp;
}
return buf;
}
JSFlatString *
StringBuffer::finishString()
{
JSContext *cx = context();
if (cb.empty())
return cx->names().empty;
size_t length = cb.length();
if (!JSString::validateLength(cx, length))
return NULL;
JS_STATIC_ASSERT(JSShortString::MAX_SHORT_LENGTH < CharBuffer::InlineLength);
if (JSShortString::lengthFits(length))
return NewShortString<CanGC>(cx, TwoByteChars(cb.begin(), length));
if (!cb.append('\0'))
return NULL;
jschar *buf = extractWellSized();
if (!buf)
return NULL;
JSFlatString *str = js_NewString<CanGC>(cx, buf, length);
if (!str)
js_free(buf);
return str;
}
JSAtom *
StringBuffer::finishAtom()
{
JSContext *cx = context();
size_t length = cb.length();
if (length == 0)
return cx->names().empty;
JSAtom *atom = AtomizeChars<CanGC>(cx, cb.begin(), length);
cb.clear();
return atom;
}
bool
js::ValueToStringBufferSlow(JSContext *cx, const Value &arg, StringBuffer &sb)
{
RootedValue v(cx, arg);
if (!ToPrimitive(cx, JSTYPE_STRING, &v))
return false;
if (v.isString())
return sb.append(v.toString());
if (v.isNumber())
return NumberValueToStringBuffer(cx, v, sb);
if (v.isBoolean())
return BooleanToStringBuffer(cx, v.toBoolean(), sb);
if (v.isNull())
return sb.append(cx->names().null);
JS_ASSERT(v.isUndefined());
return sb.append(cx->names().undefined);
}