LCOV - code coverage report
Current view: top level - js/src/vm - StringBuffer.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 52 86 60.5 %
Date: 2017-07-14 16:53:18 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "vm/StringBuffer.h"
       8             : 
       9             : #include "mozilla/Range.h"
      10             : 
      11             : #include "jsobjinlines.h"
      12             : 
      13             : #include "vm/String-inl.h"
      14             : 
      15             : using namespace js;
      16             : 
      17             : template <typename CharT, class Buffer>
      18             : static CharT*
      19         538 : ExtractWellSized(JSContext* cx, Buffer& cb)
      20             : {
      21         538 :     size_t capacity = cb.capacity();
      22         538 :     size_t length = cb.length();
      23             : 
      24         538 :     CharT* buf = cb.extractOrCopyRawBuffer();
      25         538 :     if (!buf)
      26           0 :         return nullptr;
      27             : 
      28             :     /* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
      29         538 :     MOZ_ASSERT(capacity >= length);
      30         538 :     if (length > Buffer::sMaxInlineStorage && capacity - length > length / 4) {
      31          34 :         CharT* tmp = cx->zone()->pod_realloc<CharT>(buf, capacity, length + 1);
      32          34 :         if (!tmp) {
      33           0 :             js_free(buf);
      34           0 :             ReportOutOfMemory(cx);
      35           0 :             return nullptr;
      36             :         }
      37          34 :         buf = tmp;
      38             :     }
      39             : 
      40         538 :     return buf;
      41             : }
      42             : 
      43             : char16_t*
      44          11 : StringBuffer::stealChars()
      45             : {
      46          11 :     if (isLatin1() && !inflateChars())
      47           0 :         return nullptr;
      48             : 
      49          11 :     return ExtractWellSized<char16_t>(cx, twoByteChars());
      50             : }
      51             : 
      52             : bool
      53          17 : StringBuffer::inflateChars()
      54             : {
      55          17 :     MOZ_ASSERT(isLatin1());
      56             : 
      57          34 :     TwoByteCharBuffer twoByte(cx);
      58             : 
      59             :     /*
      60             :      * Note: we don't use Vector::capacity() because it always returns a
      61             :      * value >= sInlineCapacity. Since Latin1CharBuffer::sInlineCapacity >
      62             :      * TwoByteCharBuffer::sInlineCapacitychars, we'd always malloc here.
      63             :      */
      64          17 :     size_t capacity = Max(reserved_, latin1Chars().length());
      65          17 :     if (!twoByte.reserve(capacity))
      66           0 :         return false;
      67             : 
      68          17 :     twoByte.infallibleAppend(latin1Chars().begin(), latin1Chars().length());
      69             : 
      70          17 :     cb.destroy();
      71          17 :     cb.construct<TwoByteCharBuffer>(Move(twoByte));
      72          17 :     return true;
      73             : }
      74             : 
      75             : template <typename CharT, class Buffer>
      76             : static JSFlatString*
      77         527 : FinishStringFlat(JSContext* cx, StringBuffer& sb, Buffer& cb)
      78             : {
      79         527 :     size_t len = sb.length();
      80         527 :     if (!sb.append('\0'))
      81           0 :         return nullptr;
      82             : 
      83        1054 :     ScopedJSFreePtr<CharT> buf(ExtractWellSized<CharT>(cx, cb));
      84         527 :     if (!buf)
      85           0 :         return nullptr;
      86             : 
      87         527 :     JSFlatString* str = NewStringDontDeflate<CanGC>(cx, buf.get(), len);
      88         527 :     if (!str)
      89           0 :         return nullptr;
      90             : 
      91             :     /*
      92             :      * The allocation was made on a TempAllocPolicy, so account for the string
      93             :      * data on the string's zone.
      94             :      */
      95         527 :     str->zone()->updateMallocCounter(sizeof(CharT) * len);
      96             : 
      97         527 :     buf.forget();
      98         527 :     return str;
      99             : }
     100             : 
     101             : JSFlatString*
     102         846 : StringBuffer::finishString()
     103             : {
     104         846 :     size_t len = length();
     105         846 :     if (len == 0)
     106           0 :         return cx->names().empty;
     107             : 
     108         846 :     if (!JSString::validateLength(cx, len))
     109           0 :         return nullptr;
     110             : 
     111             :     JS_STATIC_ASSERT(JSFatInlineString::MAX_LENGTH_TWO_BYTE < TwoByteCharBuffer::InlineLength);
     112             :     JS_STATIC_ASSERT(JSFatInlineString::MAX_LENGTH_LATIN1 < Latin1CharBuffer::InlineLength);
     113             : 
     114         846 :     if (isLatin1()) {
     115         840 :         if (JSInlineString::lengthFits<Latin1Char>(len)) {
     116         319 :             mozilla::Range<const Latin1Char> range(latin1Chars().begin(), len);
     117         319 :             return NewInlineString<CanGC>(cx, range);
     118             :         }
     119             :     } else {
     120           6 :         if (JSInlineString::lengthFits<char16_t>(len)) {
     121           0 :             mozilla::Range<const char16_t> range(twoByteChars().begin(), len);
     122           0 :             return NewInlineString<CanGC>(cx, range);
     123             :         }
     124             :     }
     125             : 
     126         527 :     return isLatin1()
     127         533 :         ? FinishStringFlat<Latin1Char>(cx, *this, latin1Chars())
     128         533 :         : FinishStringFlat<char16_t>(cx, *this, twoByteChars());
     129             : }
     130             : 
     131             : JSAtom*
     132       17733 : StringBuffer::finishAtom()
     133             : {
     134       17733 :     size_t len = length();
     135       17733 :     if (len == 0)
     136           0 :         return cx->names().empty;
     137             : 
     138       17733 :     if (isLatin1()) {
     139       17733 :         JSAtom* atom = AtomizeChars(cx, latin1Chars().begin(), len);
     140       17733 :         latin1Chars().clear();
     141       17733 :         return atom;
     142             :     }
     143             : 
     144           0 :     JSAtom* atom = AtomizeChars(cx, twoByteChars().begin(), len);
     145           0 :     twoByteChars().clear();
     146           0 :     return atom;
     147             : }
     148             : 
     149             : bool
     150           0 : js::ValueToStringBufferSlow(JSContext* cx, const Value& arg, StringBuffer& sb)
     151             : {
     152           0 :     RootedValue v(cx, arg);
     153           0 :     if (!ToPrimitive(cx, JSTYPE_STRING, &v))
     154           0 :         return false;
     155             : 
     156           0 :     if (v.isString())
     157           0 :         return sb.append(v.toString());
     158           0 :     if (v.isNumber())
     159           0 :         return NumberValueToStringBuffer(cx, v, sb);
     160           0 :     if (v.isBoolean())
     161           0 :         return BooleanToStringBuffer(v.toBoolean(), sb);
     162           0 :     if (v.isNull())
     163           0 :         return sb.append(cx->names().null);
     164           0 :     if (v.isSymbol()) {
     165           0 :         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SYMBOL_TO_STRING);
     166           0 :         return false;
     167             :     }
     168           0 :     MOZ_ASSERT(v.isUndefined());
     169           0 :     return sb.append(cx->names().undefined);
     170             : }

Generated by: LCOV version 1.13