ConcatString.inl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. // Note: this file is to work around linker unresolved externals WRT templatized types.
  7. // It's better than putting function bodies in .h file because bodies depend on other classes, such as ScriptContext,
  8. // for which normally only forward declarations would be available in .h file.
  9. // The reason why these are available in .inl is because .inl files are included in the very end in Runtime.h.
  10. namespace Js
  11. {
  12. template <typename StringType>
  13. inline LiteralStringWithPropertyStringPtr * LiteralStringWithPropertyStringPtr::ConvertString(StringType * originalString)
  14. {
  15. CompileAssert(sizeof(StringType) >= sizeof(LiteralStringWithPropertyStringPtr));
  16. VirtualTableInfo<LiteralStringWithPropertyStringPtr>::SetVirtualTable(originalString);
  17. LiteralStringWithPropertyStringPtr * convertedString = (LiteralStringWithPropertyStringPtr *)originalString;
  18. convertedString->SetPropertyString(nullptr);
  19. return convertedString;
  20. }
  21. /////////////////////// ConcatStringBase //////////////////////////
  22. template <typename ConcatStringType>
  23. inline const char16* ConcatStringBase::GetSzImpl()
  24. {
  25. AssertCanHandleOutOfMemory();
  26. Assert(!this->IsFinalized());
  27. Assert(!this->IsFinalized());
  28. ScriptContext* scriptContext = this->GetScriptContext();
  29. charcount_t allocSize = SafeSzSize();
  30. Recycler* recycler = scriptContext->GetRecycler();
  31. char16* target = RecyclerNewArrayLeaf(recycler, char16, allocSize);
  32. Copy<ConcatStringType>(target, GetLength());
  33. target[GetLength()] = _u('\0');
  34. SetBuffer(target);
  35. return JavascriptString::GetSz();
  36. }
  37. /////////////////////// ConcatStringN //////////////////////////
  38. template<int N>
  39. ConcatStringN<N>::ConcatStringN(StaticType* stringTypeStatic, bool doZeroSlotsAndLength) :
  40. ConcatStringBase(stringTypeStatic)
  41. {
  42. Assert(stringTypeStatic);
  43. if (doZeroSlotsAndLength)
  44. {
  45. ClearArray(m_slots, N);
  46. this->SetLength(0); // Note: the length does not include null character.
  47. }
  48. }
  49. // static
  50. template<int N>
  51. ConcatStringN<N>* ConcatStringN<N>::New(ScriptContext* scriptContext)
  52. {
  53. Assert(scriptContext);
  54. return RecyclerNew(scriptContext->GetRecycler(), ConcatStringN<N>, scriptContext->GetLibrary()->GetStringTypeStatic());
  55. }
  56. // Set the slot at specified index to specified value.
  57. template<int N>
  58. void ConcatStringN<N>::SetItem(_In_range_(0, N - 1) int index, JavascriptString* value)
  59. {
  60. Assert(index >= 0 && index < N);
  61. // Note: value can be NULL. // TODO: should we just assert for non-zero?
  62. charcount_t oldItemLen = m_slots[index] ? m_slots[index]->GetLength() : 0;
  63. charcount_t newItemLen = value ? value->GetLength() : 0;
  64. if (value)
  65. {
  66. value = CompoundString::GetImmutableOrScriptUnreferencedString(value);
  67. }
  68. m_slots[index] = value;
  69. charcount_t newTotalLen = this->GetLength() - oldItemLen + newItemLen;
  70. this->SetLength(newTotalLen);
  71. }
  72. template<int N>
  73. inline const char16 * ConcatStringN<N>::GetSz()
  74. {
  75. const char16 * sz = GetSzImpl<ConcatStringN>();
  76. // Allow slots to be garbage collected if no more refs.
  77. ClearArray(m_slots, N);
  78. LiteralStringWithPropertyStringPtr::ConvertString(this);
  79. return sz;
  80. }
  81. /////////////////////// ConcatStringWrapping //////////////////////////
  82. template<char16 L, char16 R>
  83. ConcatStringWrapping<L, R>::ConcatStringWrapping(JavascriptString* inner) :
  84. ConcatStringBase(inner->GetLibrary()->GetStringTypeStatic()),
  85. m_inner(CompoundString::GetImmutableOrScriptUnreferencedString(inner))
  86. {
  87. this->SetLength(inner->GetLength() + 2); // does not include null character
  88. }
  89. template<char16 L, char16 R>
  90. ConcatStringWrapping<L, R>* ConcatStringWrapping<L, R>::New(JavascriptString* inner)
  91. {
  92. Recycler* recycler = inner->GetRecycler();
  93. //return RecyclerNew(recycler, ConcatStringWrapping<L, R>, inner);
  94. // Expand the RecyclerNew macro as it breaks for more than one template arguments.
  95. #ifdef TRACK_ALLOC
  96. return new (recycler->TrackAllocInfo(TrackAllocData::CreateTrackAllocData(typeid(ConcatStringWrapping<L, R>), 0, (size_t)-1, __FILE__, __LINE__)),
  97. &Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
  98. #else
  99. return new (recycler, &Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
  100. #endif
  101. }
  102. template<char16 L, char16 R>
  103. inline const char16 * ConcatStringWrapping<L, R>::GetSz()
  104. {
  105. const char16 * sz = GetSzImpl<ConcatStringWrapping>();
  106. m_inner = nullptr;
  107. ClearArray(m_slots);
  108. LiteralStringWithPropertyStringPtr::ConvertString(this);
  109. return sz;
  110. }
  111. template<char16 L, char16 R>
  112. inline JavascriptString* ConcatStringWrapping<L, R>::GetFirstItem() const
  113. {
  114. Assert(m_inner);
  115. char16 lBuf[2] = { L, '\0' };
  116. return this->GetLibrary()->CreateStringFromCppLiteral(lBuf);
  117. }
  118. template<char16 L, char16 R>
  119. inline JavascriptString* ConcatStringWrapping<L, R>::GetLastItem() const
  120. {
  121. Assert(m_inner);
  122. char16 rBuf[2] = { R, '\0' };
  123. return this->GetLibrary()->CreateStringFromCppLiteral(rBuf);
  124. }
  125. } // namespace Js.