blob: 5b451fe4f2a3a7882e6dc87c299f35b6b29a7f90 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLibraryPch.h"
namespace Js
{
char16* BufferStringBuilder::WritableString::SafeCopyAndAdvancePtr(__out_ecount(cchDst) char16* dst, charcount_t& cchDst, __in_ecount(cch) const char16* ptr, charcount_t cch)
{
Assert( IsValidCharCount(cch) );
Assert( dst != nullptr);
Assert( ptr != nullptr);
if( cchDst < cch )
{
Throw::FatalInternalError();
}
wmemcpy_s(dst, cchDst, ptr, cch);
cchDst -= cch;
return dst + cch;
}
void BufferStringBuilder::WritableString::SetContent(
const char16* prefix, charcount_t cchPrefix,
const char16* content, charcount_t cchContent,
const char16* suffix, charcount_t cchSuffix)
{
char16* dst = GetWritableBuffer();
charcount_t cchRemain = GetLength();
dst = SafeCopyAndAdvancePtr(dst, cchRemain, prefix, cchPrefix);
dst = SafeCopyAndAdvancePtr(dst, cchRemain, content, cchContent);
(void)SafeCopyAndAdvancePtr(dst, cchRemain, suffix, cchSuffix);
}
BufferStringBuilder::WritableString* BufferStringBuilder::WritableString::New(charcount_t length, ScriptContext* scriptContext)
{
Recycler* recycler = scriptContext->GetRecycler();
// Allocate recycler memory to store the string plus a terminating NUL
charcount_t allocSize = JavascriptString::SafeSzSize(length);
char16* buffer = RecyclerNewArrayLeaf(recycler, char16, allocSize);
#if DBG
// Fill with a debug pattern (including the space for the NUL terminator)
wmemset( buffer, k_dbgFill, allocSize );
#endif
WritableString* newInstance = RecyclerNew(recycler, WritableString, scriptContext->GetLibrary()->GetStringTypeStatic(), length, buffer);
return newInstance;
}
JavascriptString* BufferStringBuilder::ToString()
{
DbgAssertNotFrozen();
char16* buffer = DangerousGetWritableBuffer();
charcount_t length = this->m_string->GetLength();
#if DBG
// Can't do this check easily when user use the debug filled character
#if 0
for( charcount_t i = 0; i != length; ++i )
{
// This could be tripped if the buffer actually contains a char
// with the debug fill value. In that case, this assert may
// need to be downgraded to a warning.
AssertMsg( buffer[i] != k_dbgFill, "BufferString was not completely filled before ToString" );
}
#endif
AssertMsg( buffer[length] == k_dbgFill, "BufferString sentinel was overwritten." );
#endif
// NUL terminate
buffer[length] = _u('\0');
JavascriptString* result = this->m_string;
#ifdef PROFILE_STRINGS
StringProfiler::RecordNewString( this->m_string->GetScriptContext(), buffer, length );
#endif
// Prevent further calls to ToString, SetContent etc.
this->m_string = nullptr;
return result;
}
} // namespace Js