CharacterBuffer.h 3.1 KB

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