DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (27a812186ff4)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
/* -*- 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 nullptr;

    /* 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);
        ExclusiveContext* cx = context();
        jschar* tmp = (jschar*)cx->realloc_(buf, bytes);
        if (!tmp) {
            js_free(buf);
            return nullptr;
        }
        buf = tmp;
    }

    return buf;
}

JSFlatString*
StringBuffer::finishString()
{
    ExclusiveContext* cx = context();
    if (cb.empty())
        return cx->names().empty;

    size_t length = cb.length();
    if (!JSString::validateLength(cx, length))
        return nullptr;

    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 nullptr;

    jschar* buf = extractWellSized();
    if (!buf)
        return nullptr;

    JSFlatString* str = js_NewString<CanGC>(cx, buf, length);
    if (!str)
        js_free(buf);
    return str;
}

JSAtom*
StringBuffer::finishAtom()
{
    ExclusiveContext* cx = context();

    size_t length = cb.length();
    if (length == 0)
        return cx->names().empty;

    JSAtom* atom = AtomizeChars(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(v.toBoolean(), sb);
    if (v.isNull())
        return sb.append(cx->names().null);
    JS_ASSERT(v.isUndefined());
    return sb.append(cx->names().undefined);
}