Home | History | Annotate | Download | only in runtime
      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