blob: cfd6c3638131ad87e193c13188a021e3c16b1456 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
// Note: this file is to work around linker unresolved externals WRT templatized types.
// It's better than putting function bodies in .h file because bodies depend on other classes, such as ScriptContext,
// for which normally only forward declarations would be available in .h file.
// The reason why these are available in .inl is because .inl files are included in the very end in Runtime.h.
namespace Js
{
template <typename StringType>
inline LiteralStringWithPropertyStringPtr * LiteralStringWithPropertyStringPtr::ConvertString(StringType * originalString)
{
CompileAssert(sizeof(StringType) >= sizeof(LiteralStringWithPropertyStringPtr));
VirtualTableInfo<LiteralStringWithPropertyStringPtr>::SetVirtualTable(originalString);
LiteralStringWithPropertyStringPtr * convertedString = (LiteralStringWithPropertyStringPtr *)originalString;
convertedString->SetPropertyString(nullptr);
return convertedString;
}
/////////////////////// ConcatStringBase //////////////////////////
template <typename ConcatStringType>
inline const char16* ConcatStringBase::GetSzImpl()
{
AssertCanHandleOutOfMemory();
Assert(!this->IsFinalized());
Assert(!this->IsFinalized());
ScriptContext* scriptContext = this->GetScriptContext();
charcount_t allocSize = SafeSzSize();
Recycler* recycler = scriptContext->GetRecycler();
char16* target = RecyclerNewArrayLeaf(recycler, char16, allocSize);
Copy<ConcatStringType>(target, GetLength());
target[GetLength()] = _u('\0');
SetBuffer(target);
return JavascriptString::GetSz();
}
/////////////////////// ConcatStringN //////////////////////////
template<int N>
ConcatStringN<N>::ConcatStringN(StaticType* stringTypeStatic, bool doZeroSlotsAndLength) :
ConcatStringBase(stringTypeStatic)
{
Assert(stringTypeStatic);
if (doZeroSlotsAndLength)
{
ClearArray(m_slots, N);
this->SetLength(0); // Note: the length does not include null character.
}
}
// static
template<int N>
ConcatStringN<N>* ConcatStringN<N>::New(ScriptContext* scriptContext)
{
Assert(scriptContext);
return RecyclerNew(scriptContext->GetRecycler(), ConcatStringN<N>, scriptContext->GetLibrary()->GetStringTypeStatic());
}
// Set the slot at specified index to specified value.
template<int N>
void ConcatStringN<N>::SetItem(_In_range_(0, N - 1) int index, JavascriptString* value)
{
Assert(index >= 0 && index < N);
// Note: value can be NULL. // TODO: should we just assert for non-zero?
charcount_t oldItemLen = m_slots[index] ? m_slots[index]->GetLength() : 0;
charcount_t newItemLen = value ? value->GetLength() : 0;
if (value)
{
value = CompoundString::GetImmutableOrScriptUnreferencedString(value);
}
m_slots[index] = value;
charcount_t newTotalLen = this->GetLength() - oldItemLen + newItemLen;
this->SetLength(newTotalLen);
}
template<int N>
inline const char16 * ConcatStringN<N>::GetSz()
{
const char16 * sz = GetSzImpl<ConcatStringN>();
// Allow slots to be garbage collected if no more refs.
ClearArray(m_slots, N);
LiteralStringWithPropertyStringPtr::ConvertString(this);
return sz;
}
/////////////////////// ConcatStringWrapping //////////////////////////
template<char16 L, char16 R>
ConcatStringWrapping<L, R>::ConcatStringWrapping(JavascriptString* inner) :
ConcatStringBase(inner->GetLibrary()->GetStringTypeStatic()),
m_inner(CompoundString::GetImmutableOrScriptUnreferencedString(inner))
{
this->SetLength(inner->GetLength() + 2); // does not include null character
}
template<char16 L, char16 R>
ConcatStringWrapping<L, R>* ConcatStringWrapping<L, R>::New(JavascriptString* inner)
{
Recycler* recycler = inner->GetRecycler();
//return RecyclerNew(recycler, ConcatStringWrapping<L, R>, inner);
// Expand the RecyclerNew macro as it breaks for more than one template arguments.
#ifdef TRACK_ALLOC
return new (recycler->TrackAllocInfo(TrackAllocData::CreateTrackAllocData(typeid(ConcatStringWrapping<L, R>), 0, (size_t)-1, __FILE__, __LINE__)),
&Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
#else
return new (recycler, &Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
#endif
}
template<char16 L, char16 R>
inline const char16 * ConcatStringWrapping<L, R>::GetSz()
{
const char16 * sz = GetSzImpl<ConcatStringWrapping>();
m_inner = nullptr;
ClearArray(m_slots);
LiteralStringWithPropertyStringPtr::ConvertString(this);
return sz;
}
template<char16 L, char16 R>
inline JavascriptString* ConcatStringWrapping<L, R>::GetFirstItem() const
{
Assert(m_inner);
char16 lBuf[2] = { L, '\0' };
return this->GetLibrary()->CreateStringFromCppLiteral(lBuf);
}
template<char16 L, char16 R>
inline JavascriptString* ConcatStringWrapping<L, R>::GetLastItem() const
{
Assert(m_inner);
char16 rBuf[2] = { R, '\0' };
return this->GetLibrary()->CreateStringFromCppLiteral(rBuf);
}
} // namespace Js.