1 /* 2 * Copyright (C) 2003, 2006, 2007, 2008, 2009 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 #ifndef Identifier_h 22 #define Identifier_h 23 24 #include "JSGlobalData.h" 25 #include "ThreadSpecific.h" 26 #include "UString.h" 27 28 namespace JSC { 29 30 class ExecState; 31 32 class Identifier { 33 friend class Structure; 34 public: 35 Identifier() { } 36 37 Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals. 38 Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { } 39 Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { } 40 Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { } 41 42 Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals. 43 Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { } 44 Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { } 45 Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { } 46 47 // Special constructor for cases where we overwrite an object in place. 48 Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { } 49 50 const UString& ustring() const { return _ustring; } 51 52 const UChar* data() const { return _ustring.data(); } 53 int size() const { return _ustring.size(); } 54 55 const char* ascii() const { return _ustring.ascii(); } 56 57 static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); } 58 static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); } 59 static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); } 60 61 bool isNull() const { return _ustring.isNull(); } 62 bool isEmpty() const { return _ustring.isEmpty(); } 63 64 uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); } 65 uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); }; 66 uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); } 67 unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); } 68 double toDouble() const { return _ustring.toDouble(); } 69 70 friend bool operator==(const Identifier&, const Identifier&); 71 friend bool operator!=(const Identifier&, const Identifier&); 72 73 friend bool operator==(const Identifier&, const char*); 74 friend bool operator!=(const Identifier&, const char*); 75 76 static void remove(UString::Rep*); 77 78 static bool equal(const UString::Rep*, const char*); 79 static bool equal(const UString::Rep*, const UChar*, int length); 80 static bool equal(const UString::Rep* a, const UString::Rep* b) { return JSC::equal(a, b); } 81 82 static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals. 83 static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals. 84 85 private: 86 UString _ustring; 87 88 static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); } 89 static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); } 90 91 static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length); 92 static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length); 93 94 static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r) 95 { 96 if (r->isIdentifier()) { 97 #ifndef NDEBUG 98 checkSameIdentifierTable(exec, r); 99 #endif 100 return r; 101 } 102 return addSlowCase(exec, r); 103 } 104 static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r) 105 { 106 if (r->isIdentifier()) { 107 #ifndef NDEBUG 108 checkSameIdentifierTable(globalData, r); 109 #endif 110 return r; 111 } 112 return addSlowCase(globalData, r); 113 } 114 115 static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r); 116 static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r); 117 118 static void checkSameIdentifierTable(ExecState*, UString::Rep*); 119 static void checkSameIdentifierTable(JSGlobalData*, UString::Rep*); 120 }; 121 122 inline bool operator==(const Identifier& a, const Identifier& b) 123 { 124 return Identifier::equal(a, b); 125 } 126 127 inline bool operator!=(const Identifier& a, const Identifier& b) 128 { 129 return !Identifier::equal(a, b); 130 } 131 132 inline bool operator==(const Identifier& a, const char* b) 133 { 134 return Identifier::equal(a, b); 135 } 136 137 inline bool operator!=(const Identifier& a, const char* b) 138 { 139 return !Identifier::equal(a, b); 140 } 141 142 IdentifierTable* createIdentifierTable(); 143 void deleteIdentifierTable(IdentifierTable*); 144 145 struct ThreadIdentifierTableData { 146 ThreadIdentifierTableData() 147 : defaultIdentifierTable(0) 148 , currentIdentifierTable(0) 149 { 150 } 151 152 IdentifierTable* defaultIdentifierTable; 153 IdentifierTable* currentIdentifierTable; 154 }; 155 156 extern WTF::ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific; 157 void createIdentifierTableSpecific(); 158 159 inline IdentifierTable* defaultIdentifierTable() 160 { 161 if (!g_identifierTableSpecific) 162 createIdentifierTableSpecific(); 163 ThreadIdentifierTableData& data = **g_identifierTableSpecific; 164 165 return data.defaultIdentifierTable; 166 } 167 168 inline void setDefaultIdentifierTable(IdentifierTable* identifierTable) 169 { 170 if (!g_identifierTableSpecific) 171 createIdentifierTableSpecific(); 172 ThreadIdentifierTableData& data = **g_identifierTableSpecific; 173 174 data.defaultIdentifierTable = identifierTable; 175 } 176 177 inline IdentifierTable* currentIdentifierTable() 178 { 179 if (!g_identifierTableSpecific) 180 createIdentifierTableSpecific(); 181 ThreadIdentifierTableData& data = **g_identifierTableSpecific; 182 183 return data.currentIdentifierTable; 184 } 185 186 inline IdentifierTable* setCurrentIdentifierTable(IdentifierTable* identifierTable) 187 { 188 if (!g_identifierTableSpecific) 189 createIdentifierTableSpecific(); 190 ThreadIdentifierTableData& data = **g_identifierTableSpecific; 191 192 IdentifierTable* oldIdentifierTable = data.currentIdentifierTable; 193 data.currentIdentifierTable = identifierTable; 194 return oldIdentifierTable; 195 } 196 197 inline void resetCurrentIdentifierTable() 198 { 199 if (!g_identifierTableSpecific) 200 createIdentifierTableSpecific(); 201 ThreadIdentifierTableData& data = **g_identifierTableSpecific; 202 203 data.currentIdentifierTable = data.defaultIdentifierTable; 204 } 205 206 } // namespace JSC 207 208 #endif // Identifier_h 209