1 //
2 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 //   Free Software Foundation, Inc
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 
19 #ifndef GNASH_OBJECTURI_H
20 #define GNASH_OBJECTURI_H
21 
22 #ifdef HAVE_CONFIG_H
23 #include "gnashconfig.h" // GNASH_STATS_OBJECT_URI_NOCASE
24 #endif
25 
26 #include "string_table.h"
27 #include "namedStrings.h"
28 
29 #include <string>
30 #include <sstream>
31 
32 //#define GNASH_STATS_OBJECT_URI_NOCASE 1
33 
34 #ifdef GNASH_STATS_OBJECT_URI_NOCASE
35 # include "Stats.h"
36 #endif
37 
38 namespace gnash {
39 
40 /// A URI for describing as_objects.
41 //
42 /// This is used as a unique identifier for any object member, especially
43 /// prototypes, class, constructors.
44 struct ObjectURI
45 {
46 
47     /// Comparison taking case into account (or not).
48     class CaseLessThan;
49 
50     /// Simple, case-sensitive less-than comparison for containers.
51     class LessThan;
52 
53     /// Case-sensitive equality
54     class CaseEquals;
55 
56     /// Log strings.
57     class Logger;
58 
59     /// Default constructor.
60     //
61     /// This must be equivalent to an empty string.
ObjectURIObjectURI62     ObjectURI()
63         :
64         name(0),
65         nameNoCase(0)
66     {}
67 
68     /// Construct an ObjectURI from name
ObjectURIObjectURI69     ObjectURI(NSV::NamedStrings name)
70         :
71         name(name),
72         nameNoCase(0)
73     {}
74 
75 
emptyObjectURI76     bool empty() const {
77         return (name == 0);
78     }
79 
toStringObjectURI80     const std::string& toString(string_table& st) const {
81         return st.value(name);
82     }
83 
noCaseObjectURI84     string_table::key noCase(string_table& st) const {
85 
86         if (!name) return 0;
87 
88         if (!nameNoCase) {
89             nameNoCase = st.noCase(name);
90 #ifdef GNASH_STATS_OBJECT_URI_NOCASE
91             static stats::KeyLookup statNonSkip("ObjectURI::noCase non-skips",
92                     st, 0, 0, 0);
93             statNonSkip.check(name);
94 #endif
95         }
96 #ifdef GNASH_STATS_OBJECT_URI_NOCASE
97         else {
98             static stats::KeyLookup stat("ObjectURI::noCase skips",
99                     st, 0, 0, 0);
100             stat.check(name);
101         }
102 #endif
103 
104         return nameNoCase;
105     }
106 
107     string_table::key name;
108 
109 private:
110 
111     mutable string_table::key nameNoCase;
112 };
113 
114 /// Get the name element of an ObjectURI
115 inline string_table::key
getName(const ObjectURI & o)116 getName(const ObjectURI& o)
117 {
118     return o.name;
119 }
120 
121 class ObjectURI::LessThan
122 {
123 public:
operator()124     bool operator()(const ObjectURI& a, const ObjectURI& b) const {
125         return a.name < b.name;
126     }
127 };
128 
129 class ObjectURI::CaseLessThan
130 {
131 public:
132     CaseLessThan(string_table& st, bool caseless = false)
133         :
_st(st)134         _st(st),
135         _caseless(caseless)
136     {}
operator()137     bool operator()(const ObjectURI& a, const ObjectURI& b) const {
138         if (_caseless) return a.noCase(_st) < b.noCase(_st);
139         return a.name < b.name;
140     }
141 private:
142     string_table& _st;
143     const bool _caseless;
144 };
145 
146 class ObjectURI::CaseEquals
147 {
148 public:
149     CaseEquals(string_table& st, bool caseless = false)
150         :
_st(st)151         _st(st),
152         _caseless(caseless)
153     {}
operator()154     bool operator()(const ObjectURI& a, const ObjectURI& b) const {
155         if (_caseless) return a.noCase(_st) == b.noCase(_st);
156         return a.name == b.name;
157     }
158 private:
159     string_table& _st;
160     const bool _caseless;
161 };
162 
163 class ObjectURI::Logger
164 {
165 public:
Logger(string_table & st)166     Logger(string_table& st) : _st(st) {}
167 
operator()168     std::string operator()(const ObjectURI& uri) const {
169         const string_table::key name = getName(uri);
170         return _st.value(name);
171     }
172 
debug(const ObjectURI & uri)173     std::string debug(const ObjectURI& uri) const {
174         std::stringstream ss;
175         const string_table::key name = getName(uri);
176         const string_table::key nameNoCase = uri.noCase(_st);
177         ss << _st.value(name)
178            << "(" << name << ")/"
179            << _st.value(nameNoCase)
180            << "(" << nameNoCase << ")";
181         return ss.str();
182     }
183 
184 private:
185     string_table& _st;
186 };
187 
188 } // namespace gnash
189 #endif
190