Esempio n. 1
0
byteArrayOop HCodeBuffer::bytes() {
  BlockScavenge bs;
  align();
  Klass* klass = Universe::byteArrayKlassObj()->klass_part();
  byteArrayOop result = byteArrayOop(klass->allocateObjectSize(byteLength()));

  for (int index = 0; index < byteLength(); index++)
    result->byte_at_put(index + 1, (unsigned char) _bytes->at(index));
  
  return result;
}
Esempio n. 2
0
char *genStr(char *filename, int len) {
    int fh;
    unsigned char *data;

    if ((fh = open(filename, O_RDONLY)) == -1) FILE_ERR(filename, "open");

    struct stat finfo;
    fstat(fh, &finfo);

    if ((data = mmap(0, finfo.st_size, PROT_READ, MAP_SHARED, fh, 0))
            == MAP_FAILED) FILE_ERR(filename, "mmap");
    if (close(fh) == -1) FILE_ERR(filename, "close");

    int dataIdx = 0, alphabetSize = 1;
    for (; data[dataIdx]; dataIdx += byteLength(data[dataIdx]), ++alphabetSize);
    ++dataIdx;  // we're on the null byte, want to be where data actually starts
    if (alphabetSize*alphabetSize*(8+4*alphabetSize) != finfo.st_size - dataIdx) {
        return "!!! CORRUPT DATA FILE !!!";
    }

    char *str = malloc((len+1) * 4*sizeof *str);
    int a = alphabetSize - 1, b = alphabetSize - 1;
    int strpos = 0;
    for (int i = 0; i < len; ++i) {
        unsigned char *dataPtr = DATA(a, b);
        unsigned long long n = longRand(getLong(dataPtr));
        dataPtr += 8;
        int nextCharPos = 0;
        for (; nextCharPos < alphabetSize; ++nextCharPos) {
            unsigned int m = getInt(dataPtr);
            if (m > n) break;
            n -= m;
            dataPtr += 4;
        }
        a = b;
        b = nextCharPos;
        int alphabetIdx = 0;
        for (; nextCharPos; --nextCharPos) {
            alphabetIdx += byteLength(ALPHABET[alphabetIdx]);
        }
        int nextCharLen = byteLength(ALPHABET[alphabetIdx]);
        for (int i = nextCharLen; i >= 0; --i) {
            str[strpos + i] = ALPHABET[alphabetIdx + i];
        }
        strpos += nextCharLen;
    }
    str[strpos] = '\0';
    //for (int i = 0; i < len*2; ++i) printf("str[%d]: %c\n", i, str[i]);

    if (munmap(data, finfo.st_size) == -1) FILE_ERR(filename, "munmap");

    return str;
}
Esempio n. 3
0
void ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset, ExceptionCode& ec)
{
    if (byteOffset > byteLength() ||
        byteOffset + array->byteLength() > byteLength() ||
        byteOffset + array->byteLength() < byteOffset) {
        // Out of range offset or overflow
        ec = INDEX_SIZE_ERR;
        return;
    }

    char* base = static_cast<char*>(baseAddress());
    memmove(base + byteOffset, array->baseAddress(), array->byteLength());
}
Esempio n. 4
0
bool SymbolCell::operator==(const SymbolCell &other) const
{
	if (isGlobalConstant() && other.isGlobalConstant())
	{
		// Constant folding guarantees this works
		return this == &other;
	}

	if (byteLength() != other.byteLength())
	{
		return false;
	}

	if (dataIsInline())
	{
		auto thisInlineSymbol = static_cast<const InlineSymbolCell*>(this);
		auto otherInlineSymbol = static_cast<const InlineSymbolCell*>(&other);

		return memcmp(
				thisInlineSymbol->inlineData(),
				otherInlineSymbol->inlineData(),
				thisInlineSymbol->inlineByteLength()) == 0;
	}
	else
	{
		auto thisHeapSymbol = static_cast<const HeapSymbolCell*>(this);

		auto thisByteArray = thisHeapSymbol->heapByteArray();
		auto otherByteArray = static_cast<const HeapSymbolCell*>(&other)->heapByteArray();

		return thisByteArray->isEqual(otherByteArray, thisHeapSymbol->heapByteLength());
	}
}
bool
TCPSocketParent::RecvData(const SendableData& aData,
                          const uint32_t& aTrackingNumber)
{
  ErrorResult rv;
  switch (aData.type()) {
    case SendableData::TArrayOfuint8_t: {
      AutoSafeJSContext autoCx;
      JS::Rooted<JS::Value> val(autoCx);
      const nsTArray<uint8_t>& buffer = aData.get_ArrayOfuint8_t();
      bool ok = IPC::DeserializeArrayBuffer(autoCx, buffer, &val);
      NS_ENSURE_TRUE(ok, true);
      RootedTypedArray<ArrayBuffer> data(autoCx);
      data.Init(&val.toObject());
      Optional<uint32_t> byteLength(buffer.Length());
      mSocket->SendWithTrackingNumber(autoCx, data, 0, byteLength, aTrackingNumber, rv);
      break;
    }

    case SendableData::TnsCString: {
      const nsCString& strData = aData.get_nsCString();
      mSocket->SendWithTrackingNumber(strData, aTrackingNumber, rv);
      break;
    }

    default:
      MOZ_CRASH("unexpected SendableData type");
  }
  NS_ENSURE_FALSE(rv.Failed(), true);
  return true;
}
Esempio n. 6
0
BytevectorCell* StringCell::toUtf8Bytevector(World &world, SliceIndexType start, SliceIndexType end)
{
	CharRange range = charRange(start, end);

	if (range.isNull())
	{
		return nullptr;
	}

	ByteLengthType newLength = range.endPointer - range.startPointer;
	SharedByteArray *byteArray;

	if ((newLength == byteLength()) && !dataIsInline())
	{
		// Reuse our existing byte array
		byteArray = static_cast<HeapStringCell*>(this)->heapByteArray()->ref();
	}
	else
	{
		// Create a new byte array and initialize it
		byteArray = SharedByteArray::createInstance(newLength);
		memcpy(byteArray->data(), range.startPointer, newLength);
	}

	return BytevectorCell::withByteArray(world, byteArray, newLength);
}
Esempio n. 7
0
v8::Handle<v8::Object> DOMArrayBuffer::wrap(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    // It's possible that no one except for the new wrapper owns this object at
    // this moment, so we have to prevent GC to collect this object until the
    // object gets associated with the wrapper.
    RefPtr<DOMArrayBuffer> protect(this);

    ASSERT(!DOMDataStore::containsWrapper(this, isolate));
    v8::EscapableHandleScope handleScope(isolate);
    v8::Handle<v8::Context> context = isolate->GetCurrentContext();
    if (context == node::g_context) {
      context = nodeToDOMContext(context);
    }
    v8::Context::Scope context_scope(context);

    const WrapperTypeInfo* wrapperTypeInfo = this->wrapperTypeInfo();
    v8::Local<v8::Object> wrapper = v8::ArrayBuffer::New(isolate, data(), byteLength());

    // Only when we create a new wrapper, let V8 know that we allocated and
    // associated a new memory block with the wrapper. Note that
    // setDeallocationObserver implicitly calls
    // DOMArrayBufferDeallocationObserver::blinkAllocatedMemory.
    buffer()->setDeallocationObserver(DOMArrayBufferDeallocationObserver::instance());

    // FIXME: escape
    associateWithWrapper(isolate, wrapperTypeInfo, wrapper);
    return handleScope.Escape(wrapper);
}
QString QHexSpinBox::textFromValue (int value) const
{
    QString str = QString("%1").arg(QSpinBox::textFromValue(value), byteLength() * 2, QChar('0'));
    if (upperCase())
        str = str.toUpper();
    return str;
}
Esempio n. 9
0
int StringCell::compare(const StringCell *other, UnicodeChar (*converter)(UnicodeChar)) const
{
	const std::uint8_t *ourScanPtr = const_cast<StringCell*>(this)->utf8Data();
	const std::uint8_t *ourEndPtr = &constUtf8Data()[byteLength()];

	const std::uint8_t *theirScanPtr = const_cast<StringCell*>(other)->utf8Data();
	const std::uint8_t *theirEndPtr = &other->constUtf8Data()[other->byteLength()];

	while(true)
	{
		int ourEnd = ourScanPtr == ourEndPtr;
		int theirEnd = theirScanPtr == theirEndPtr;

		if (ourEnd || theirEnd)
		{
			// One of the strings ended
			return theirEnd - ourEnd;
		}

		const UnicodeChar ourChar = utf8::decodeChar(&ourScanPtr);
		const UnicodeChar theirChar = utf8::decodeChar(&theirScanPtr);

		int charCompare = ourChar.compare(theirChar, converter);

		if (charCompare != 0)
		{
			return charCompare;
		}
	}

	return 0;
}
Esempio n. 10
0
int StringCell::compare(const StringCell *other) const
{
	ByteLengthType compareBytes = std::min(byteLength(), other->byteLength());

	// Bytewise comparisons in UTF-8 sort Unicode code points correctly
	int result = memcmp(constUtf8Data(), other->constUtf8Data(), compareBytes);

	if (result != 0)
	{
		return result;
	}
	else
	{
		return byteLength() - other->byteLength();
	}
}
Esempio n. 11
0
bool StringCell::operator==(const StringCell &other) const
{
	if (byteLength() != other.byteLength())
	{
		return false;
	}

	if (dataIsInline())
	{
		auto thisInlineString = static_cast<const InlineStringCell*>(this);
		auto otherInlineString = static_cast<const InlineStringCell*>(&other);

		return memcmp(
				thisInlineString->inlineData(),
				otherInlineString->inlineData(),
				thisInlineString->inlineByteLength()) == 0;
	}
	else
	{
		auto thisHeapString = static_cast<const HeapStringCell*>(this);

		auto thisByteArray = thisHeapString->heapByteArray();
		auto otherByteArray = static_cast<const HeapStringCell*>(&other)->heapByteArray();

		return thisByteArray->isEqual(otherByteArray, thisHeapString->heapByteLength());
	}
}
Esempio n. 12
0
StringCell* StringCell::copy(alloc::Heap &heap)
{
	void *cellPlacement = heap.allocate();

	if (dataIsInline())
	{
		auto inlineCopy = new (cellPlacement) InlineStringCell(byteLength(), charLength());
		memcpy(inlineCopy->utf8Data(), utf8Data(), byteLength());

		return inlineCopy;
	}
	else
	{
		auto heapThis = static_cast<HeapStringCell*>(this);
		return new (cellPlacement) HeapStringCell(heapThis->heapByteArray()->ref(), byteLength(), charLength());
	}
}
Esempio n. 13
0
const std::uint8_t* StringCell::charPointer(CharLengthType charOffset, const std::uint8_t *startFrom, ByteLengthType startOffset)
{
	// Is the rest of the string ASCII?
	// We can determine this by verifying the number remaining bytes in the string are equal to the number of remaining
	// characters.
	const auto bytesLeft = &utf8Data()[byteLength()] - startFrom;
	const auto charsLeft = charLength() - startOffset;

	if (bytesLeft == charsLeft)
	{
		return startFrom + (charOffset - startOffset);
	}

	const std::uint8_t *scanPtr;

	// Should we do a forward scan or backwards scan?
	// Prefer forwards slightly as it probably plays better with hardware memory prefetch
	if ((charOffset - startOffset) > (charsLeft / 2))
	{
		scanPtr = &utf8Data()[byteLength()];

		auto endOffset = charLength();
		while(endOffset > charOffset)
		{
			if (!utf8::isContinuationByte(*(--scanPtr)))
			{
				endOffset--;
			}
		}
	}
	else
	{
		scanPtr = startFrom;
		while(startOffset < charOffset)
		{
			if (!utf8::isContinuationByte(*(++scanPtr)))
			{
				startOffset++;
			}
		}
	}

	return scanPtr;
}
Esempio n. 14
0
JSArrayBufferView* DataView::wrap(ExecState* exec, JSGlobalObject* globalObject)
{
#if 0
    return JSDataView::create(
        exec, globalObject->typedArrayStructure(TypeDataView), buffer(), byteOffset(),
        byteLength());
#else
    return 0;
#endif
}
Esempio n. 15
0
std::size_t StringCell::byteCapacity() const
{
	if (dataIsInline())
	{
		return inlineDataSize();
	}
	else
	{
		return static_cast<const HeapStringCell*>(this)->heapByteArray()->capacity(byteLength());
	}
}
Esempio n. 16
0
		//----------
		void Skeleton::newFrameArrived(astra::frame & frame) {
			auto pointFrame = frame.get<astra::pointframe>();
			if (pointFrame.is_valid()) {
				this->pointFrameLock.lock();
				{
					this->pointFrame.recreate(pointFrame.resolutionX(), pointFrame.resolutionY());
					memcpy(this->pointFrame.data(), pointFrame.data(), pointFrame.byteLength());
					this->pointFrameNew = true;
				}
				this->pointFrameLock.unlock();
			}
		}
Esempio n. 17
0
const UT_UTF8String & UT_UTF8String::lowerCase ()
{
	if(!byteLength())
		return *this;
	
	UT_UTF8Stringbuf * n = pimpl->lowerCase ();
	if(n)
	{
		delete pimpl;
		pimpl = n;
	}
	
	return *this;
}
Esempio n. 18
0
bool
TCPSocketParent::RecvData(const SendableData& aData,
                          const uint32_t& aTrackingNumber)
{
  ErrorResult rv;

  if (mFilter) {
    mozilla::net::NetAddr addr; // dummy value
    bool allowed;
    MOZ_ASSERT(aData.type() == SendableData::TArrayOfuint8_t,
               "Unsupported data type for filtering");
    const InfallibleTArray<uint8_t>& data(aData.get_ArrayOfuint8_t());
    nsresult nsrv = mFilter->FilterPacket(&addr, data.Elements(),
                                          data.Length(),
                                          nsISocketFilter::SF_OUTGOING,
                                          &allowed);

    // Reject sending of unallowed data
    if (NS_WARN_IF(NS_FAILED(nsrv)) || !allowed) {
      TCPSOCKET_LOG(("%s: Dropping outgoing TCP packet", __FUNCTION__));
      return false;
    }
  }

  switch (aData.type()) {
    case SendableData::TArrayOfuint8_t: {
      AutoSafeJSContext autoCx;
      JS::Rooted<JS::Value> val(autoCx);
      const nsTArray<uint8_t>& buffer = aData.get_ArrayOfuint8_t();
      bool ok = IPC::DeserializeArrayBuffer(autoCx, buffer, &val);
      NS_ENSURE_TRUE(ok, true);
      RootedTypedArray<ArrayBuffer> data(autoCx);
      data.Init(&val.toObject());
      Optional<uint32_t> byteLength(buffer.Length());
      mSocket->SendWithTrackingNumber(autoCx, data, 0, byteLength, aTrackingNumber, rv);
      break;
    }

    case SendableData::TnsCString: {
      const nsCString& strData = aData.get_nsCString();
      mSocket->SendWithTrackingNumber(strData, aTrackingNumber, rv);
      break;
    }

    default:
      MOZ_CRASH("unexpected SendableData type");
  }
  NS_ENSURE_SUCCESS(rv.StealNSResult(), true);
  return true;
}
Esempio n. 19
0
void typeStr(WINDOW *win, char *str) {
    mvwprintw(win, 1, 1, str);
    wrefresh(win);

    int pos = 0;

    uchar input[4];
    while (1) {
        input[0] = getch();
        int inputBytes = byteLength(input[0]);
        int i = 1;
        for (uchar *p = input + 1; i < inputBytes; ++i) {
            *p = getch();
        }

        int fail = 0;
        if (byteLength(*str) == inputBytes) {
            for (i = 0; i < inputBytes; ++i) {
                if ((uchar)str[i] != input[i]) {
                    fail = 1;
                    break;
                }
            }
        } else fail = 1;

        if (fail) wattron(win, COLOR_PAIR(FAIL));
        mvwprintw(win, 2, pos+1, "%.*s", inputBytes, input);
        wrefresh(win);
        wattroff(win, COLOR_PAIR(FAIL));
        if (!fail) {
            ++pos;
            str += inputBytes;
        }

        if (input[0] == '\x03') break;
    }
}
Esempio n. 20
0
StringCell *StringCell::toConvertedString(World &world, UnicodeChar (*converter)(UnicodeChar))
{
	const std::uint8_t *scanPtr = utf8Data();
	const std::uint8_t *endPtr = &constUtf8Data()[byteLength()];

	StringCellBuilder builder(charLength());

	while(scanPtr != endPtr)
	{
		const UnicodeChar originalChar = utf8::decodeChar(&scanPtr);
		const UnicodeChar convertedChar = (*converter)(originalChar);

		builder << convertedChar;
	}

	return builder.result(world);
}
Esempio n. 21
0
v8::Handle<v8::Object> DOMArrayBuffer::wrap(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
{
    // It's possible that no one except for the new wrapper owns this object at
    // this moment, so we have to prevent GC to collect this object until the
    // object gets associated with the wrapper.
    RefPtr<DOMArrayBuffer> protect(this);

    ASSERT(!DOMDataStore::containsWrapperNonTemplate(this, isolate));

    const WrapperTypeInfo* wrapperTypeInfo = this->wrapperTypeInfo();
    v8::Handle<v8::Object> wrapper = v8::ArrayBuffer::New(isolate, data(), byteLength());

    // Only when we create a new wrapper, let V8 know that we allocated and
    // associated a new memory block with the wrapper. Note that
    // setDeallocationObserver implicitly calls
    // DOMArrayBufferDeallocationObserver::blinkAllocatedMemory.
    buffer()->setDeallocationObserver(DOMArrayBufferDeallocationObserver::instance());

    return associateWithWrapper(wrapperTypeInfo, wrapper, isolate);
}
Esempio n. 22
0
void UT_UTF8Stringbuf::decodeURL()
{
	if(!m_psz || !*m_psz)
		return;

	char * buff = (char*)g_try_malloc(byteLength() + 1);
	UT_return_if_fail( buff );
	buff[0] = 0;

	UTF8Iterator J(this);
	const char * ptr = J.current();
	UT_UCS4Char c = charCode(J.current());

	char utf8cache[7]; utf8cache[6] = 0;
	UT_uint32 iCachePos = 0;
	UT_uint32 iCacheNeeded = 0;
	

	while (c != 0)
	{
		if(c == '%')
		{
			J.advance();
			UT_UCS4Char b1 = charCode(J.current());
			J.advance();
			UT_UCS4Char b2 = charCode(J.current());
			J.advance();

			if(isalnum(b1) && isalnum(b2))
			{
				b1 = s_charCode_to_hexval(b1);
				b2 = s_charCode_to_hexval(b2);
					
				UT_UCS4Char code = ((b1 << 4)& 0xf0) | (b2 & 0x0f);

				if(iCacheNeeded == 0)
				{
					// we start new utf8 sequence in the cache
					if ((code & 0x80) == 0)         iCacheNeeded = 1;
					else if ((code & 0xe0) == 0xc0) iCacheNeeded = 2;
					else if ((code & 0xf0) == 0xe0) iCacheNeeded = 3;
					else if ((code & 0xf8) == 0xf0) iCacheNeeded = 4;
					else if ((code & 0xfc) == 0xf8) iCacheNeeded = 5;
					else if ((code & 0xfe) == 0xfc) iCacheNeeded = 6;

					utf8cache[0] = (char) code;
					utf8cache[iCacheNeeded] = 0; // make sure the sequence will be terminated
					iCachePos++;
				}
				else
				{
					// append to our cache
					utf8cache[iCachePos++] = (char) code;
				}

				if(iCacheNeeded == 0 && (code >= 0x7f && code <= 0xff))
				{
					// the present character is not a valid start of utf8 sequence --
					// this is almost certainly a character from the extended ASCII set
					// which was encoded directly according to the RFC 1738 scheme, we
					// just append it
					
					size_t iLenBuff = strlen(buff);
					size_t iLenLeft = byteLength() - iLenBuff;
					
					char * p = buff + iLenBuff;
					UT_Unicode::UCS4_to_UTF8(p, iLenLeft, code);
 
					// we need to null-terminate
					*p = 0;
				}
				
				if(iCacheNeeded && iCacheNeeded <= iCachePos)
				{
					UT_ASSERT_HARMLESS( iCacheNeeded == iCachePos );
					
					// append the cache to our buffer
					UT_uint32 iLenBuff = strlen(buff);
					char * p = buff + iLenBuff;
					strcat(p, utf8cache);

					iCacheNeeded = iCachePos = 0;
				}
			}
			else
			{
				// this should not happen in encoded url and so we will ignore this token;
				// if we are in the middle of utf8 sequence; we will reset it
				iCacheNeeded = iCachePos = 0;
			}
		}
		else
		{
			J.advance(); // advance here, for the sake of the else clause below
			
			if(iCacheNeeded > iCachePos)
			{
				// we are processing a utf sequence, so just append this byte to our cache
				utf8cache[iCachePos++] = (char) c;
			}
			else
			{
				const char * p = J.current();
				UT_uint32 iLen = p ? p - ptr : strlen(ptr);
				strncat(buff, ptr, iLen);
			}
		}

		ptr = J.current();
		c = charCode(J.current());
	}
	
	assign(buff);
	g_free(buff);
}
Esempio n. 23
0
JSArrayBufferView* DataView::wrap(ExecState* exec, JSGlobalObject* globalObject)
{
    return JSDataView::create(
        exec, globalObject->typedArrayStructure(TypeDataView), possiblySharedBuffer(), byteOffset(),
        byteLength());
}
Esempio n. 24
0
RefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const
{
    return sliceImpl(clampIndex(begin), byteLength());
}
Esempio n. 25
0
Ref<IDBKey> IDBKey::createBinary(JSC::JSArrayBufferView& arrayBufferView)
{
    auto bufferView = arrayBufferView.possiblySharedImpl();
    return adoptRef(*new IDBKey(ThreadSafeDataBuffer::copyData(bufferView->data(), bufferView->byteLength())));
}
Esempio n. 26
0
bool StringCell::replaceBytes(const CharRange &range, const std::uint8_t *pattern, unsigned int patternBytes, unsigned int count)
{
	assert(!isGlobalConstant());

	const unsigned int requiredBytes = patternBytes * count;
	const unsigned int replacedBytes = range.byteCount();
	
	// If we have exclusive access to our data and we're not resizing the string we can use the fast path
	if ((dataIsInline() || static_cast<HeapStringCell*>(this)->heapByteArray()->isExclusive()) &&
	    (requiredBytes == replacedBytes))
	{
		std::uint8_t *copyDest = const_cast<std::uint8_t*>(range.startPointer);
		while(count--)
		{
			memmove(copyDest, pattern, patternBytes);
			copyDest += patternBytes;
		}
	}
	else
	{
		// Create a new string from pieces of the old string
		const std::uint64_t newByteLength = byteLength() + requiredBytes - replacedBytes;
		const auto newCharLength = charLength();

		if (newByteLength > maximumByteLength())
		{
			return false;
		}

		const ByteLengthType initialBytes = range.startPointer - utf8Data();
		const ByteLengthType finalBytes = newByteLength - initialBytes - requiredBytes;

		const bool wasInline = dataIsInline();
		const bool nowInline = newByteLength <= inlineDataSize();

		SharedByteArray *oldByteArray = nullptr;
		SharedByteArray *newByteArray = nullptr;

		// Does this require a COW due to sharing our byte array?
		const bool needsCow = (!wasInline && !nowInline) &&
			                   !static_cast<HeapStringCell*>(this)->heapByteArray()->isExclusive();

		// Determine if we exceeded our current capacity or if we're using less than half of our allocated space
		// This will trigger a reallocation of our heap space
		const auto currentCapacity = byteCapacity();
		const bool needHeapRealloc = (newByteLength > currentCapacity) ||
			                         ((newByteLength < (currentCapacity / 2)) && !nowInline) ||
			                         needsCow;

		std::uint8_t* destString;
		const std::uint8_t* copySource;

		if (!wasInline && nowInline)
		{
			// We're converting to an inline string
			destString = static_cast<InlineStringCell*>(this)->inlineData();
			copySource = pattern;

			// Store our old byte array so we can unref it later
			// The code below will overwrite it with our new inline string
			oldByteArray = static_cast<HeapStringCell*>(this)->heapByteArray();

			// Fill the initial chunk of the string
			memcpy(destString, utf8Data(), initialBytes);
		}
		else if (needHeapRealloc)
		{
			size_t byteArraySize = newByteLength;

			newByteArray = SharedByteArray::createInstance(byteArraySize);
			destString = newByteArray->data();
			copySource = pattern;

			// Fill the initial chunk of the string
			memcpy(destString, utf8Data(), initialBytes);

			if (!wasInline)
			{
				// Store our old byte array so we can unref it later
				oldByteArray = static_cast<HeapStringCell*>(this)->heapByteArray();
			}
		}
		else
		{
			destString = utf8Data();

			// The initial chunk is already correct

			// Are our pattern bytes in the range we're about to overwrite?
			// We only need to check the end of the pattern because the pattern should only be completely inside our
			// completely outside our string
			if (((pattern + patternBytes) > (utf8Data() + initialBytes)) &&
				((pattern + patternBytes) <= (utf8Data() + byteLength())))
			{
				// Create a temporary copy to work with
				copySource = new std::uint8_t[patternBytes];
				memcpy(const_cast<std::uint8_t*>(copySource), pattern, patternBytes);
			}
			else
			{
				copySource = pattern;
			}
		}

		// Move the unchanged chunk at the end
		// We need to do this now because if the pattern bytes are longer than the byte we're replacing then we might
		// overwrite the beginning of the unchanged chunk
		memmove(destString + initialBytes + requiredBytes, range.startPointer + replacedBytes, finalBytes);
		
		std::uint8_t* copyDest = destString + initialBytes;

		while(count--)
		{
			memcpy(copyDest, copySource, patternBytes);
			copyDest += patternBytes;
		}

		if (copySource != pattern)
		{
			delete[] copySource;
		}

		// Update ourselves with our new string
		setLengths(newByteLength, newCharLength);

		if (newByteArray)
		{
			static_cast<HeapStringCell*>(this)->setHeapByteArray(newByteArray);
		}

		if (oldByteArray != nullptr)
		{
			// We can unref this now
			oldByteArray->unref();
		}
	}
	
	return true;
}