Fennel: /home/pub/open/dev/fennel/common/ResourceBundle.cpp Source File (original) (raw)

00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 #include "fennel/common/CommonPreamble.h" 00024 #include "fennel/common/ResourceBundle.h" 00025 00026 #include 00027 #include 00028 #include 00029 #include 00030 #include 00031 #include 00032 #include 00033 00034 #include <boost/lexical_cast.hpp> 00035 00036 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/common/ResourceBundle.cpp#14 $"); 00037 00038 using namespace std; 00039 using namespace boost; 00040 00041 static string globalResourceLocation(""); 00042 00043 RecursiveMutex ResourceBundle::mutex; 00044 00045 RecursiveMutex &ResourceBundle::getMutex() 00046 { 00047 return mutex; 00048 } 00049 00050 void ResourceBundle::setGlobalResourceFileLocation(const string &location) 00051 { 00052 globalResourceLocation = location; 00053 } 00054 00055 ResourceBundle::ResourceBundle( 00056 const string &baseName, 00057 const Locale &locale, 00058 const string &location) 00059 : _baseName(baseName), 00060 _locale(locale), 00061 _location(location), 00062 _parent(NULL) 00063 { 00064 loadMessages(); 00065 } 00066 00067 ResourceBundle::~ResourceBundle() 00068 { 00069 } 00070 00071 void ResourceBundle::setParent(ResourceBundle *bundle) 00072 { 00073 _parent = bundle; 00074 } 00075 00076 const set ResourceBundle::getKeys() const 00077 { 00078 set keys; 00079 00080 map<string, string>::const_iterator iter = _messages.begin(), 00081 end = _messages.end(); 00082 00083 while (iter != end) { 00084 keys.insert((*iter).first); 00085 iter++; 00086 } 00087 00088 if (_parent) { 00089 set parentKeys = _parent->getKeys(); 00090 00091 keys.insert(parentKeys.begin(), parentKeys.end()); 00092 } 00093 00094 return keys; 00095 } 00096 00097 static string MISSING_KEY("[[unknown key]]"); 00098 00099 const string &ResourceBundle::getMessage(const string &key) const 00100 { 00101 map<string, string>::const_iterator iter; 00102 iter = _messages.find(key); 00103 if (iter == _messages.end()) { 00104 if (_parent) { 00105 return parent->getMessage(key); 00106 } 00107 00108 return MISSING_KEY; 00109 } 00110 00111 return (*iter).second; 00112 } 00113 00114 00115 bool ResourceBundle::hasMessage(const string &key) const 00116 { 00117 return 00118 _messages.find(key) != _messages.end() 00119 || (_parent && _parent->hasMessage(key)); 00120 } 00121 00122 const Locale &ResourceBundle::getLocale() const 00123 { 00124 return _locale; 00125 } 00126 00127 00128 const string &ResourceBundle::getBaseName() const 00129 { 00130 return _baseName; 00131 } 00132 00133 00134 static const char APOS = '''; 00135 static const char LEFT_BRACE = '{'; 00136 static const char RIGHT_BRACE = '}'; 00137 static const char COMMA = ','; 00138 00139 static string convertPropertyToBoost(string &message) 00140 { 00141 stringstream ss; 00142 00143 bool quoted = false; 00144 char ch; 00145 char nextCh; 00146 00147 for (int i = 0, n = message.length(); i < n; i++) { 00148 ch = message[i]; 00149 nextCh = (i + 1 < n) ? message[i + 1] : 0; 00150 00151 if (ch == APOS) { 00152 if (nextCh != APOS) { 00153
00154 quoted = !quoted; 00155 continue; 00156 } 00157 00158
00159
00160 ss << APOS; 00161 i++; 00162 continue; 00163 } 00164 00165 if (quoted || ch != LEFT_BRACE) { 00166 ss << ch; 00167 continue; 00168 } 00169 00170
00171 string::size_type commaPos = message.find(COMMA, i); 00172 string::size_type bracketPos = message.find(RIGHT_BRACE, i); 00173 if (bracketPos == string::npos) { 00174
00175 return message; 00176 } 00177 00178 int argEndIndex = (commaPos == string::npos 00179 ? bracketPos 00180 : min(commaPos, bracketPos)); 00181 00182 int argIndex = boost::lexical_cast( 00183 message.substr(i + 1, argEndIndex - (i + 1))); 00184 00185
00186 ss << '%' << (argIndex + 1) << '%'; 00187 00188
00189 bool quotedPattern = false; 00190 int bracketDepth = 0; 00191 i = argEndIndex; 00192 00193 bool done = false; 00194 while (!done && i < n) { 00195 ch = message[i]; 00196 00197 switch (ch) { 00198 default: 00199 i++; 00200 break; 00201 00202 case APOS: 00203 quotedPattern = !quotedPattern; 00204 i++; 00205 break; 00206 00207 case LEFT_BRACE: 00208 if (!quotedPattern) { 00209 bracketDepth++; 00210 } 00211 i++; 00212 break; 00213 00214 case RIGHT_BRACE: 00215 if (!quotedPattern) { 00216 if (bracketDepth > 0) { 00217 bracketDepth--; 00218 } else { 00219
00220 done = true; 00221 break; 00222 } 00223 } 00224 i++; 00225 break; 00226 } 00227 } 00228 00229 if (i == n) { 00230
00231 return message; 00232 } 00233 } 00234 00235 return ss.str(); 00236 } 00237 00238 00239 00240 00241 00242 00243 00244 00245 void ResourceBundle::loadMessages() 00246 { 00247 fstream in; 00248 00249
00250 string fileName; 00251 00252 if (_locale == Locale("")) { 00253 fileName.assign(_baseName 00254 + ".properties"); 00255 } else { 00256 fileName.assign(_baseName 00257 + "
" 00258 + _locale.getDisplayName() 00259 + ".properties"); 00260 } 00261 00262
00263 bool tryGlobalLocation = true; 00264 if (_location.empty()) { 00265 string path = _location + "/" + fileName; 00266 in.open(path.c_str(), ios::in); 00267 if (in.good()) { 00268 tryGlobalLocation = false; 00269 } 00270 } 00271 00272
00273 if (tryGlobalLocation) { 00274 bool tryEnvVar = true; 00275 00276
00277
00278 if (globalResourceLocation.empty()) { 00279 string path = globalResourceLocation + "/" + fileName; 00280 in.open(path.c_str(), ios::in); 00281 if (in.good()) { 00282 tryEnvVar = false; 00283 } 00284 } 00285 00286 if (tryEnvVar) { 00287 const char *fennelHome = getenv("FENNEL_HOME"); 00288 if (fennelHome == NULL) { 00289 return; 00290 } 00291 00292 string path = string(fennelHome) + "/common/" + fileName; 00293 in.open(path.c_str(), ios::in); 00294 if (!in.good()) { 00295 return; 00296 } 00297 } 00298 } 00299 00300 string line, key, message; 00301 while (in.good()) { 00302 getline(in, line); 00303 00304 if (line.length() == 0 || line[0] == '#') { 00305
00306 continue; 00307 } 00308 00309 string::size_type pos = line.find('='); 00310 if (pos == string::npos) { 00311
00312 continue; 00313 } 00314 00315 key = line.substr(0, pos); 00316 message = line.substr(pos + 1); 00317 00318 _messages[key] = convertPropertyToBoost(message); 00319 } 00320 00321 in.close(); 00322 } 00323 00324 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/common/ResourceBundle.cpp#14 $"); 00325 00326