BufferStringBuilder.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. #include "RuntimeLibraryPch.h"
  6. namespace Js
  7. {
  8. char16* BufferStringBuilder::WritableString::SafeCopyAndAdvancePtr(__out_ecount(cchDst) char16* dst, charcount_t& cchDst, __in_ecount(cch) const char16* ptr, charcount_t cch)
  9. {
  10. Assert( IsValidCharCount(cch) );
  11. Assert( dst != nullptr);
  12. Assert( ptr != nullptr);
  13. js_wmemcpy_s(dst, cchDst, ptr, cch);
  14. cchDst -= cch;
  15. return dst + cch;
  16. }
  17. void BufferStringBuilder::WritableString::SetContent(
  18. const char16* prefix, charcount_t cchPrefix,
  19. const char16* content, charcount_t cchContent,
  20. const char16* suffix, charcount_t cchSuffix)
  21. {
  22. char16* dst = GetWritableBuffer();
  23. charcount_t cchRemain = GetLength();
  24. dst = SafeCopyAndAdvancePtr(dst, cchRemain, prefix, cchPrefix);
  25. dst = SafeCopyAndAdvancePtr(dst, cchRemain, content, cchContent);
  26. (void)SafeCopyAndAdvancePtr(dst, cchRemain, suffix, cchSuffix);
  27. }
  28. BufferStringBuilder::WritableString* BufferStringBuilder::WritableString::New(charcount_t length, ScriptContext* scriptContext)
  29. {
  30. Recycler* recycler = scriptContext->GetRecycler();
  31. // Allocate recycler memory to store the string plus a terminating NUL
  32. charcount_t allocSize = JavascriptString::SafeSzSize(length);
  33. char16* buffer = RecyclerNewArrayLeaf(recycler, char16, allocSize);
  34. #if DBG
  35. // Fill with a debug pattern (including the space for the NUL terminator)
  36. wmemset( buffer, k_dbgFill, allocSize );
  37. #endif
  38. WritableString* newInstance = RecyclerNew(recycler, WritableString, scriptContext->GetLibrary()->GetStringTypeStatic(), length, buffer);
  39. return newInstance;
  40. }
  41. JavascriptString* BufferStringBuilder::ToString()
  42. {
  43. DbgAssertNotFrozen();
  44. char16* buffer = DangerousGetWritableBuffer();
  45. charcount_t length = this->m_string->GetLength();
  46. #if DBG
  47. // Can't do this check easily when user use the debug filled character
  48. #if 0
  49. for( charcount_t i = 0; i != length; ++i )
  50. {
  51. // This could be tripped if the buffer actually contains a char
  52. // with the debug fill value. In that case, this assert may
  53. // need to be downgraded to a warning.
  54. AssertMsg( buffer[i] != k_dbgFill, "BufferString was not completely filled before ToString" );
  55. }
  56. #endif
  57. AssertMsg( buffer[length] == k_dbgFill, "BufferString sentinel was overwritten." );
  58. #endif
  59. // NUL terminate
  60. buffer[length] = _u('\0');
  61. JavascriptString* result = this->m_string;
  62. #ifdef PROFILE_STRINGS
  63. StringProfiler::RecordNewString( this->m_string->GetScriptContext(), buffer, length );
  64. #endif
  65. // Prevent further calls to ToString, SetContent etc.
  66. this->m_string = nullptr;
  67. return result;
  68. }
  69. } // namespace Js