| /* -*- 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); |
| } |