KHtml

AtomicString.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB. If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20 
21 #ifdef AVOID_STATIC_CONSTRUCTORS
22 #define ATOMICSTRING_HIDE_GLOBALS 1
23 #endif
24 
25 #include "AtomicString.h"
26 
27 //#include "StaticConstructors.h"
28 #include "StringHash.h"
29 //#include <kjs/identifier.h>
30 #include <wtf/HashSet.h>
31 
32 //using KJS::Identifier;
33 //using KJS::UString;
34 
35 namespace khtml
36 {
37 
38 static HashSet<DOMStringImpl *> *stringTable;
39 
40 struct CStringTranslator {
41  static unsigned hash(const char *c)
42  {
43  return DOMStringImpl::computeHash(c);
44  }
45 
46  static bool equal(DOMStringImpl *r, const char *s)
47  {
48  int length = r->length();
49  const QChar *d = r->unicode();
50  for (int i = 0; i != length; ++i) {
51  unsigned char c = s[i];
52  if (d[i] != c) {
53  return false;
54  }
55  }
56  return s[length] == 0;
57  }
58 
59  static void translate(DOMStringImpl *&location, const char *const &c, unsigned hash)
60  {
61  location = new DOMStringImpl(c, strlen(c), hash);
62  }
63 };
64 
65 bool operator==(const AtomicString &a, const char *b)
66 {
67  DOMStringImpl *impl = a.impl();
68  if ((!impl || !impl->unicode()) && !b) {
69  return true;
70  }
71  if ((!impl || !impl->unicode()) || !b) {
72  return false;
73  }
74  return CStringTranslator::equal(impl, b);
75 }
76 
77 DOMStringImpl *AtomicString::add(const char *c)
78 {
79  if (!c) {
80  return nullptr;
81  }
82  if (!*c) {
83  return DOMStringImpl::empty();
84  }
85  init();
86  std::pair<HashSet<DOMStringImpl *>::iterator, bool> addResult = stringTable->add<const char *, CStringTranslator>(c);
87  if (!addResult.second) {
88  return *addResult.first;
89  }
90  return *addResult.first;
91 }
92 
93 struct UCharBuffer {
94  const QChar *s;
95  unsigned length;
96 };
97 
98 static inline bool equal(DOMStringImpl *string, const QChar *characters, unsigned length)
99 {
100  if (string->length() != length) {
101  return false;
102  }
103 
104  /* Do it 4-bytes-at-a-time on architectures where it's safe */
105 
106  const uint32_t *stringCharacters = reinterpret_cast<const uint32_t *>(string->unicode());
107  const uint32_t *bufferCharacters = reinterpret_cast<const uint32_t *>(characters);
108 
109  unsigned halfLength = length >> 1;
110  for (unsigned i = 0; i != halfLength; ++i) {
111  if (*stringCharacters++ != *bufferCharacters++) {
112  return false;
113  }
114  }
115 
116  if (length & 1 && *reinterpret_cast<const uint16_t *>(stringCharacters) != *reinterpret_cast<const uint16_t *>(bufferCharacters)) {
117  return false;
118  }
119 
120  return true;
121 }
122 
123 struct UCharBufferTranslator {
124  static unsigned hash(const UCharBuffer &buf)
125  {
126  return DOMStringImpl::computeHash(buf.s, buf.length);
127  }
128 
129  static bool equal(DOMStringImpl *const &str, const UCharBuffer &buf)
130  {
131  return khtml::equal(str, buf.s, buf.length);
132  }
133 
134  static void translate(DOMStringImpl *&location, const UCharBuffer &buf, unsigned hash)
135  {
136  location = new DOMStringImpl(buf.s, buf.length, hash);
137  }
138 };
139 
140 struct HashAndCharacters {
141  unsigned hash;
142  const QChar *characters;
143  unsigned length;
144 };
145 
146 struct HashAndCharactersTranslator {
147  static unsigned hash(const HashAndCharacters &buffer)
148  {
149  ASSERT(buffer.hash == DOMStringImpl::computeHash(buffer.characters, buffer.length));
150  return buffer.hash;
151  }
152 
153  static bool equal(DOMStringImpl *const &string, const HashAndCharacters &buffer)
154  {
155  return khtml::equal(string, buffer.characters, buffer.length);
156  }
157 
158  static void translate(DOMStringImpl *&location, const HashAndCharacters &buffer, unsigned hash)
159  {
160  location = new DOMStringImpl(buffer.characters, buffer.length, hash);
161  }
162 };
163 
164 DOMStringImpl *AtomicString::add(const QChar *s, int length)
165 {
166  if (!s) {
167  return nullptr;
168  }
169 
170  if (length == 0) {
171  return DOMStringImpl::empty();
172  }
173 
174  init();
175  UCharBuffer buf = { s, static_cast<uint>(length) };
176  std::pair<HashSet<DOMStringImpl *>::iterator, bool> addResult = stringTable->add<UCharBuffer, UCharBufferTranslator>(buf);
177  if (!addResult.second) {
178  return *addResult.first;
179  }
180  return *addResult.first;
181 }
182 
183 DOMStringImpl *AtomicString::add(const QChar *s)
184 {
185  if (!s) {
186  return nullptr;
187  }
188 
189  int length = 0;
190  while (s[length] != QChar(0)) {
191  length++;
192  }
193 
194  if (length == 0) {
195  return DOMStringImpl::empty();
196  }
197 
198  init();
199  UCharBuffer buf = {s, static_cast<uint>(length)};
200  std::pair<HashSet<DOMStringImpl *>::iterator, bool> addResult = stringTable->add<UCharBuffer, UCharBufferTranslator>(buf);
201  if (!addResult.second) {
202  return *addResult.first;
203  }
204  return *addResult.first;
205 }
206 
207 DOMStringImpl *AtomicString::add(DOMStringImpl *r)
208 {
209  if (!r || r->m_inTable) {
210  return r;
211  }
212 
213  if (r->length() == 0) {
214  return DOMStringImpl::empty();
215  }
216 
217  init();
218  DOMStringImpl *result = *stringTable->add(r).first;
219  if (result == r) {
220  r->m_inTable = true;
221  }
222  return result;
223 }
224 
225 void AtomicString::remove(DOMStringImpl *r)
226 {
227  stringTable->remove(r);
228 }
229 
230 /*DOMStringImpl* AtomicString::add(const KJS::Identifier& identifier)
231 {
232  if (identifier.isNull())
233  return 0;
234 
235  UString::Rep* string = identifier.ustring().rep();
236  unsigned length = string->size();
237  if (!length)
238  return StringImpl::empty();
239 
240  HashAndCharacters buffer = { string->computedHash(), string->data(), length };
241  pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
242  if (!addResult.second)
243  return *addResult.first;
244  return adoptRef(*addResult.first);
245 }
246 
247 PassRefPtr<StringImpl> AtomicString::add(const KJS::UString& ustring)
248 {
249  if (ustring.isNull())
250  return 0;
251 
252  UString::Rep* string = ustring.rep();
253  unsigned length = string->size();
254  if (!length)
255  return StringImpl::empty();
256 
257  HashAndCharacters buffer = { string->hash(), string->data(), length };
258  pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable->add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
259  if (!addResult.second)
260  return *addResult.first;
261  return adoptRef(*addResult.first);
262 }
263 
264 AtomicStringImpl* AtomicString::find(const KJS::Identifier& identifier)
265 {
266  if (identifier.isNull())
267  return 0;
268 
269  UString::Rep* string = identifier.ustring().rep();
270  unsigned length = string->size();
271  if (!length)
272  return static_cast<AtomicStringImpl*>(StringImpl::empty());
273 
274  HashAndCharacters buffer = { string->computedHash(), string->data(), length };
275  HashSet<StringImpl*>::iterator iterator = stringTable->find<HashAndCharacters, HashAndCharactersTranslator>(buffer);
276  if (iterator == stringTable->end())
277  return 0;
278  return static_cast<AtomicStringImpl*>(*iterator);
279 }
280 
281 AtomicString::operator UString() const
282 {
283  return m_string;
284 }*/
285 
286 #define DEFINE_GLOBAL(type, name, ...) \
287  const type name;
288 
289 DEFINE_GLOBAL(AtomicString, nullAtom)
290 DEFINE_GLOBAL(AtomicString, emptyAtom, "")
291 DEFINE_GLOBAL(AtomicString, textAtom, "#text")
292 DEFINE_GLOBAL(AtomicString, commentAtom, "#comment")
293 DEFINE_GLOBAL(AtomicString, starAtom, "*")
294 
295 void AtomicString::init()
296 {
297  static bool initialized;
298  if (!initialized) {
299  stringTable = new HashSet<DOMStringImpl *>;
300 
301  // Use placement new to initialize the globals.
302  /*new ((void*)&nullAtom) AtomicString;
303  new ((void*)&emptyAtom) AtomicString("");
304  new ((void*)&textAtom) AtomicString("#text");
305  new ((void*)&commentAtom) AtomicString("#comment");
306  new ((void*)&starAtom) AtomicString("*");*/
307 
308  initialized = true;
309  }
310 }
311 
312 }
This file is part of the HTML rendering engine for KDE.
bool operator==(const Qt3DRender::QGraphicsApiFilter &reference, const Qt3DRender::QGraphicsApiFilter &sample)
QCA_EXPORT void init()
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:47:58 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.