ConcatString.inl 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. /////////////////////// ConcatStringBase //////////////////////////
  13. template <typename ConcatStringType>
  14. inline const wchar_t* ConcatStringBase::GetSzImpl()
  15. {
  16. AssertCanHandleOutOfMemory();
  17. Assert(!this->IsFinalized());
  18. Assert(!this->IsFinalized());
  19. ScriptContext* scriptContext = this->GetScriptContext();
  20. charcount_t allocSize = SafeSzSize();
  21. Recycler* recycler = scriptContext->GetRecycler();
  22. wchar_t* target = RecyclerNewArrayLeaf(recycler, wchar_t, allocSize);
  23. Copy<ConcatStringType>(target, GetLength());
  24. target[GetLength()] = L'\0';
  25. SetBuffer(target);
  26. VirtualTableInfo<LiteralString>::SetVirtualTable(this);
  27. return JavascriptString::GetSz();
  28. }
  29. /////////////////////// ConcatStringN //////////////////////////
  30. template<int N>
  31. ConcatStringN<N>::ConcatStringN(StaticType* stringTypeStatic, bool doZeroSlotsAndLength) :
  32. ConcatStringBase(stringTypeStatic)
  33. {
  34. Assert(stringTypeStatic);
  35. if (doZeroSlotsAndLength)
  36. {
  37. memset(m_slots, 0, N * sizeof(JavascriptString*));
  38. this->SetLength(0); // Note: the length does not include null character.
  39. }
  40. }
  41. // static
  42. template<int N>
  43. ConcatStringN<N>* ConcatStringN<N>::New(ScriptContext* scriptContext)
  44. {
  45. Assert(scriptContext);
  46. return RecyclerNew(scriptContext->GetRecycler(), ConcatStringN<N>, scriptContext->GetLibrary()->GetStringTypeStatic());
  47. }
  48. // Set the slot at specified index to specified value.
  49. template<int N>
  50. void ConcatStringN<N>::SetItem(_In_range_(0, N - 1) int index, JavascriptString* value)
  51. {
  52. Assert(index >= 0 && index < N);
  53. // Note: value can be NULL. // TODO: should we just assert for non-zero?
  54. charcount_t oldItemLen = m_slots[index] ? m_slots[index]->GetLength() : 0;
  55. charcount_t newItemLen = value ? value->GetLength() : 0;
  56. if (value)
  57. {
  58. value = CompoundString::GetImmutableOrScriptUnreferencedString(value);
  59. }
  60. m_slots[index] = value;
  61. charcount_t newTotalLen = this->GetLength() - oldItemLen + newItemLen;
  62. this->SetLength(newTotalLen);
  63. }
  64. template<int N>
  65. inline const wchar_t * ConcatStringN<N>::GetSz()
  66. {
  67. const wchar_t * sz = GetSzImpl<ConcatStringN>();
  68. // Allow slots to be garbage collected if no more refs.
  69. memset(m_slots, 0, N * sizeof(JavascriptString*));
  70. return sz;
  71. }
  72. /////////////////////// ConcatStringWrapping //////////////////////////
  73. template<wchar_t L, wchar_t R>
  74. ConcatStringWrapping<L, R>::ConcatStringWrapping(JavascriptString* inner) :
  75. ConcatStringBase(inner->GetLibrary()->GetStringTypeStatic()),
  76. m_inner(CompoundString::GetImmutableOrScriptUnreferencedString(inner))
  77. {
  78. this->SetLength(inner->GetLength() + 2); // does not include null character
  79. }
  80. template<wchar_t L, wchar_t R>
  81. ConcatStringWrapping<L, R>* ConcatStringWrapping<L, R>::New(JavascriptString* inner)
  82. {
  83. Recycler* recycler = inner->GetRecycler();
  84. //return RecyclerNew(recycler, ConcatStringWrapping<L, R>, inner);
  85. // Expand the RecyclerNew macro as it breaks for more than one template arguments.
  86. #ifdef TRACK_ALLOC
  87. return new (recycler->TrackAllocInfo(TrackAllocData::CreateTrackAllocData(typeid(ConcatStringWrapping<L, R>), 0, (size_t)-1, __FILE__, __LINE__)),
  88. &Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
  89. #else
  90. return new (recycler, &Recycler::Alloc) ConcatStringWrapping<L, R>(inner);
  91. #endif
  92. }
  93. template<wchar_t L, wchar_t R>
  94. inline const wchar_t * ConcatStringWrapping<L, R>::GetSz()
  95. {
  96. const wchar_t * sz = GetSzImpl<ConcatStringWrapping>();
  97. m_inner = nullptr;
  98. memset(m_slots, 0, sizeof(m_slots));
  99. return sz;
  100. }
  101. template<wchar_t L, wchar_t R>
  102. inline JavascriptString* ConcatStringWrapping<L, R>::GetFirstItem() const
  103. {
  104. Assert(m_inner);
  105. wchar_t lBuf[2] = { L, '\0' };
  106. return this->GetLibrary()->CreateStringFromCppLiteral(lBuf);
  107. }
  108. template<wchar_t L, wchar_t R>
  109. inline JavascriptString* ConcatStringWrapping<L, R>::GetLastItem() const
  110. {
  111. Assert(m_inner);
  112. wchar_t rBuf[2] = { R, '\0' };
  113. return this->GetLibrary()->CreateStringFromCppLiteral(rBuf);
  114. }
  115. } // namespace Js.