Index: src/shared/Dictionary.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/shared/Dictionary.cpp |
@@ -0,0 +1,90 @@ |
+#include <fstream> |
+#include <stdexcept> |
+#include <Windows.h> |
+ |
+#include "Dictionary.h" |
+#include "Utils.h" |
+ |
+Dictionary* Dictionary::instance = 0; |
+ |
+const std::wstring baseLocale = L"en"; |
+ |
+Dictionary::Dictionary(const std::wstring& locale) |
+{ |
+ std::wstring basePath = GetDllDir() + L"locales\\"; |
+ |
+ // Always load base locale first - that's our fallback |
+ ReadDictionary(basePath, baseLocale); |
+ |
+ // Now try to load by full locale code |
+ if (locale != baseLocale && !ReadDictionary(basePath, locale)) |
Felix Dahlke
2013/06/11 12:31:14
It looks like if this or the other ReadDictionary
Wladimir Palant
2013/06/12 13:46:07
Yes, it is intended - even incomplete localization
Felix Dahlke
2013/06/13 18:07:37
Okay, just wasn't sure if it was intended.
|
+ { |
+ // Fall back to short locale name |
+ size_t pos = locale.find(L'-'); |
+ if (pos != std::wstring::npos && locale.compare(0, pos, baseLocale) != 0) |
+ ReadDictionary(basePath, locale.substr(0, pos)); |
+ } |
+} |
+ |
+void Dictionary::Create(const std::wstring& locale) |
+{ |
+ if (!instance) |
+ instance = new Dictionary(locale); |
+} |
+ |
+Dictionary* Dictionary::GetInstance() |
+{ |
+ if (!instance) |
+ throw std::runtime_error("Attempt to access dictionary before creating"); |
+ |
+ return instance; |
+} |
+ |
+bool Dictionary::ReadDictionary(const std::wstring& basePath, const std::wstring& locale) |
+{ |
+ std::ifstream stream(basePath + locale + L".ini"); |
Oleksandr
2013/06/18 07:41:09
I think it wouldn't hurt to use "filebuf::sh_read
Wladimir Palant
2013/06/18 08:17:48
Good point even though this is non-standard, will
Wladimir Palant
2013/11/05 11:30:25
After looking into this I am less convinced that t
Eric
2013/11/05 13:56:06
The full constructor is declared thus:
explic
Wladimir Palant
2013/11/06 08:51:46
Not really. If you look at http://msdn.microsoft.c
Eric
2013/11/06 17:49:53
After realizing that I hadn't remembered what was
Felix Dahlke
2013/11/06 23:09:50
This seems a bit like premature optimisation to me
Wladimir Palant
2013/11/07 06:53:57
According to http://msdn.microsoft.com/en-us/libra
|
+ if (stream.fail()) |
+ return false; |
+ |
+ std::string section; |
+ while (!stream.eof()) |
Felix Dahlke
2013/06/11 12:31:14
I think the following would suffice, it'd be a bit
Wladimir Palant
2013/06/12 13:46:07
IMHO that will get us into an endless loop - std::
Felix Dahlke
2013/06/13 18:07:37
No, it wouldn't be an endless loop, this is the ca
|
+ { |
+ std::string line; |
+ std::getline(stream, line); |
+ if (stream.fail()) |
+ return false; |
+ |
+ line = ::TrimString(line); |
+ if (line.size() >= 2 && line[0] == '[' && line[line.size() - 1] == ']') |
+ { |
+ // Section header |
+ section = line.substr(1, line.size() - 2); |
+ } |
+ else if (line.size() >= 1 && line[0] == '#') |
Felix Dahlke
2013/06/11 12:31:14
This won't allow for comments preceeded by whitesp
Wladimir Palant
2013/06/12 13:46:07
We call TrimLine earlier so whitespace is allowed.
Felix Dahlke
2013/06/13 18:07:37
Hm. One benefit of this is that the translated str
|
+ { |
+ // Comment |
+ continue; |
+ } |
+ else |
+ { |
+ // Value |
+ size_t pos = line.find('='); |
+ if (pos != std::string::npos) |
+ { |
+ std::string key = ::TrimString(line.substr(0, pos)); |
+ std::string value = ::TrimString(line.substr(pos + 1)); |
+ data[KeyType(section, key)] = ToUtf16String(value); |
+ } |
+ } |
+ } |
+ return true; |
+} |
+ |
+std::wstring Dictionary::Lookup(const std::string& section, const std::string& key) const |
+{ |
+ DataType::const_iterator it = data.find(KeyType(section, key)); |
+ if (it == data.end()) |
+ return L"### MISSING STRING [" + ToUtf16String(section) + L", " + ToUtf16String(key) + L"] ###"; |
+ |
+ return it->second; |
+} |