1/*
2 * Copyright (C) 2015 Yusuke Suzuki <[email protected]>.
3 * Copyright (C) 2019 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <limits>
30#include <wtf/Vector.h>
31#include <wtf/text/StringHash.h>
32#include <wtf/text/WTFString.h>
33
34namespace JSC {
35
36class TemplateObjectDescriptorTable;
37
38class TemplateObjectDescriptor : public RefCounted<TemplateObjectDescriptor> {
39public:
40 typedef Vector<String, 4> StringVector;
41 typedef Vector<Optional<String>, 4> OptionalStringVector;
42
43 enum DeletedValueTag { DeletedValue };
44 TemplateObjectDescriptor(DeletedValueTag);
45 enum EmptyValueTag { EmptyValue };
46 TemplateObjectDescriptor(EmptyValueTag);
47
48 bool isDeletedValue() const { return m_rawStrings.isEmpty() && m_hash == std::numeric_limits<unsigned>::max(); }
49
50 bool isEmptyValue() const { return m_rawStrings.isEmpty() && !m_hash; }
51
52 unsigned hash() const { return m_hash; }
53
54 const StringVector& rawStrings() const { return m_rawStrings; }
55 const OptionalStringVector& cookedStrings() const { return m_cookedStrings; }
56
57 bool operator==(const TemplateObjectDescriptor& other) const { return m_hash == other.m_hash && m_rawStrings == other.m_rawStrings; }
58 bool operator!=(const TemplateObjectDescriptor& other) const { return m_hash != other.m_hash || m_rawStrings != other.m_rawStrings; }
59
60 struct Hasher {
61 static unsigned hash(const TemplateObjectDescriptor& key) { return key.hash(); }
62 static bool equal(const TemplateObjectDescriptor& a, const TemplateObjectDescriptor& b) { return a == b; }
63 static constexpr bool safeToCompareToEmptyOrDeleted = false;
64 };
65
66 static unsigned calculateHash(const StringVector& rawStrings);
67 ~TemplateObjectDescriptor();
68
69 static Ref<TemplateObjectDescriptor> create(StringVector&& rawStrings, OptionalStringVector&& cookedStrings)
70 {
71 return adoptRef(*new TemplateObjectDescriptor(WTFMove(rawStrings), WTFMove(cookedStrings)));
72 }
73
74private:
75 TemplateObjectDescriptor(StringVector&& rawStrings, OptionalStringVector&& cookedStrings);
76
77 StringVector m_rawStrings;
78 OptionalStringVector m_cookedStrings;
79 unsigned m_hash { 0 };
80};
81
82inline TemplateObjectDescriptor::TemplateObjectDescriptor(StringVector&& rawStrings, OptionalStringVector&& cookedStrings)
83 : m_rawStrings(WTFMove(rawStrings))
84 , m_cookedStrings(WTFMove(cookedStrings))
85 , m_hash(calculateHash(m_rawStrings))
86{
87}
88
89inline TemplateObjectDescriptor::TemplateObjectDescriptor(DeletedValueTag)
90 : m_hash(std::numeric_limits<unsigned>::max())
91{
92}
93
94inline TemplateObjectDescriptor::TemplateObjectDescriptor(EmptyValueTag)
95 : m_hash(0)
96{
97}
98
99inline unsigned TemplateObjectDescriptor::calculateHash(const StringVector& rawStrings)
100{
101 StringHasher hasher;
102 for (const String& string : rawStrings) {
103 if (string.is8Bit())
104 hasher.addCharacters(string.characters8(), string.length());
105 else
106 hasher.addCharacters(string.characters16(), string.length());
107 }
108 return hasher.hash();
109}
110
111} // namespace JSC
112
113namespace WTF {
114template<typename T> struct DefaultHash;
115
116template<> struct DefaultHash<JSC::TemplateObjectDescriptor> {
117 typedef JSC::TemplateObjectDescriptor::Hasher Hash;
118};
119
120template<> struct HashTraits<JSC::TemplateObjectDescriptor> : CustomHashTraits<JSC::TemplateObjectDescriptor> {
121};
122
123} // namespace WTF
124