CharacterBuffer.h 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. namespace JsUtil
  7. {
  8. static const charcount_t MAX_FAST_HASH_LENGTH = 256;
  9. // A buffer of characters, may have embedded null.
  10. template <typename T>
  11. class CharacterBuffer
  12. {
  13. public:
  14. CharacterBuffer() : string(nullptr), len((charcount_t)-1) {}
  15. CharacterBuffer(T const * string, charcount_t len) : string(string), len(len) {}
  16. CharacterBuffer(const CharacterBuffer& other) : string(other.string), len(other.len) {}
  17. bool operator==(CharacterBuffer const& other) const
  18. {
  19. Assert(string != nullptr);
  20. if (this->len != other.len)
  21. {
  22. return false;
  23. }
  24. return this->string == other.string || StaticEquals(string, other.string, this->len);
  25. }
  26. operator hash_t() const
  27. {
  28. Assert(string != nullptr);
  29. return StaticGetHashCode(string, len);
  30. }
  31. int FastHash() const
  32. {
  33. Assert(string != nullptr);
  34. return InternalGetHashCode<true>(string, len);
  35. }
  36. CharacterBuffer& operator=(T const * s)
  37. {
  38. Assert(s == nullptr);
  39. string = nullptr;
  40. len = (charcount_t)-1;
  41. return *this;
  42. }
  43. static bool StaticEquals(__in_z T const * s1, __in_z T const* s2, __in charcount_t length);
  44. static int StaticGetHashCode(__in_z T const * s, __in charcount_t length)
  45. {
  46. return InternalGetHashCode<false>(s, length);
  47. }
  48. // This must be identical to Trident's getHash function in fastDOMCompiler.pl
  49. template <bool fastHash>
  50. static int InternalGetHashCode(__in_z T const * s, __in charcount_t length)
  51. {
  52. // TODO: This hash performs poorly on small strings, consider finding a better hash function
  53. // now that some type handlers hash by string instead of PropertyId.
  54. int hash = 0;
  55. charcount_t hashLength = length;
  56. if (fastHash)
  57. {
  58. hashLength = min(length, MAX_FAST_HASH_LENGTH);
  59. }
  60. for (charcount_t i = 0; i < hashLength; i++)
  61. {
  62. hash = _rotl(hash, 7);
  63. hash ^= s[i];
  64. }
  65. return hash;
  66. }
  67. T const * GetBuffer() const { return string; }
  68. charcount_t GetLength() const { return len; }
  69. private:
  70. Field(T const *) string;
  71. Field(charcount_t) len;
  72. };
  73. template<>
  74. inline bool
  75. CharacterBuffer<WCHAR>::StaticEquals(__in_z WCHAR const * s1, __in_z WCHAR const * s2, __in charcount_t length)
  76. {
  77. return wmemcmp(s1, s2, length) == 0;
  78. }
  79. template<>
  80. inline bool
  81. CharacterBuffer<unsigned char>::StaticEquals(__in_z unsigned char const * s1, __in_z unsigned char const *s2, __in charcount_t length)
  82. {
  83. return memcmp(s1, s2, length) == 0;
  84. }
  85. }