From 54b6cfa9a9e5b861a9930af873580d6dc20f773c Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 21 Oct 2008 07:00:00 -0700 Subject: Initial Contribution --- tools/localize/ValuesFile.cpp | 266 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 tools/localize/ValuesFile.cpp (limited to 'tools/localize/ValuesFile.cpp') diff --git a/tools/localize/ValuesFile.cpp b/tools/localize/ValuesFile.cpp new file mode 100644 index 000000000000..bd6f494d74e5 --- /dev/null +++ b/tools/localize/ValuesFile.cpp @@ -0,0 +1,266 @@ +#include "ValuesFile.h" + +#include "XMLHandler.h" + +#include +#include +#include +#include +#include + +using namespace std; + +const char* const ANDROID_XMLNS = "http://schemas.android.com/apk/res/android"; +const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2"; + +const char *const NS_MAP[] = { + "android", ANDROID_XMLNS, + "xliff", XLIFF_XMLNS, + NULL, NULL +}; + +const XMLNamespaceMap ANDROID_NAMESPACES(NS_MAP); + + +// ===================================================================================== +class ArrayHandler : public XMLHandler +{ +public: + ArrayHandler(ValuesFile* vf, int version, const string& versionString, const string& id); + + virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name, + const vector& attrs, XMLHandler** next); + virtual int OnText(const SourcePos& pos, const string& text); + virtual int OnComment(const SourcePos& pos, const string& text); + +private: + ValuesFile* m_vf; + int m_version; + int m_index; + string m_versionString; + string m_id; + string m_comment; +}; + +ArrayHandler::ArrayHandler(ValuesFile* vf, int version, const string& versionString, + const string& id) + :m_vf(vf), + m_version(version), + m_index(0), + m_versionString(versionString), + m_id(id) +{ +} + +int +ArrayHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name, + const vector& attrs, XMLHandler** next) +{ + if (ns == "" && name == "item") { + XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT); + m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(), + m_id, m_index, node, m_version, m_versionString, + trim_string(m_comment))); + *next = new NodeHandler(node, XMLNode::EXACT); + m_index++; + m_comment = ""; + return 0; + } else { + pos.Error("invalid <%s> element inside \n", name.c_str()); + return 1; + } +} + +int +ArrayHandler::OnText(const SourcePos& pos, const string& text) +{ + return 0; +} + +int +ArrayHandler::OnComment(const SourcePos& pos, const string& text) +{ + m_comment += text; + return 0; +} + +// ===================================================================================== +class ValuesHandler : public XMLHandler +{ +public: + ValuesHandler(ValuesFile* vf, int version, const string& versionString); + + virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name, + const vector& attrs, XMLHandler** next); + virtual int OnText(const SourcePos& pos, const string& text); + virtual int OnComment(const SourcePos& pos, const string& text); + +private: + ValuesFile* m_vf; + int m_version; + string m_versionString; + string m_comment; +}; + +ValuesHandler::ValuesHandler(ValuesFile* vf, int version, const string& versionString) + :m_vf(vf), + m_version(version), + m_versionString(versionString) +{ +} + +int +ValuesHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name, + const vector& attrs, XMLHandler** next) +{ + if (ns == "" && name == "string") { + string id = XMLAttribute::Find(attrs, "", "name", ""); + XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT); + m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(), + id, -1, node, m_version, m_versionString, + trim_string(m_comment))); + *next = new NodeHandler(node, XMLNode::EXACT); + } + else if (ns == "" && name == "array") { + string id = XMLAttribute::Find(attrs, "", "name", ""); + *next = new ArrayHandler(m_vf, m_version, m_versionString, id); + } + m_comment = ""; + return 0; +} + +int +ValuesHandler::OnText(const SourcePos& pos, const string& text) +{ + return 0; +} + +int +ValuesHandler::OnComment(const SourcePos& pos, const string& text) +{ + m_comment += text; + return 0; +} + +// ===================================================================================== +ValuesFile::ValuesFile(const Configuration& config) + :m_config(config), + m_strings(), + m_arrays() +{ +} + +ValuesFile::~ValuesFile() +{ +} + +ValuesFile* +ValuesFile::ParseFile(const string& filename, const Configuration& config, + int version, const string& versionString) +{ + ValuesFile* result = new ValuesFile(config); + + TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString)); + XMLHandler::ParseFile(filename, &top); + + return result; +} + +ValuesFile* +ValuesFile::ParseString(const string& filename, const string& text, const Configuration& config, + int version, const string& versionString) +{ + ValuesFile* result = new ValuesFile(config); + + TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString)); + XMLHandler::ParseString(filename, text, &top); + + return result; +} + +const Configuration& +ValuesFile::GetConfiguration() const +{ + return m_config; +} + +void +ValuesFile::AddString(const StringResource& str) +{ + if (str.index < 0) { + m_strings.insert(str); + } else { + m_arrays[str.id].insert(str); + } +} + +set +ValuesFile::GetStrings() const +{ + set result = m_strings; + + for (map >::const_iterator it = m_arrays.begin(); + it != m_arrays.end(); it++) { + result.insert(it->second.begin(), it->second.end()); + } + + return result; +} + +XMLNode* +ValuesFile::ToXMLNode() const +{ + XMLNode* root; + + // + { + vector attrs; + ANDROID_NAMESPACES.AddToAttributes(&attrs); + root = XMLNode::NewElement(GENERATED_POS, "", "resources", attrs, XMLNode::PRETTY); + } + + // + for (map >::const_iterator it = m_arrays.begin(); + it != m_arrays.end(); it++) { + vector arrayAttrs; + arrayAttrs.push_back(XMLAttribute("", "name", it->first)); + const set& items = it->second; + XMLNode* arrayNode = XMLNode::NewElement(items.begin()->pos, "", "array", arrayAttrs, + XMLNode::PRETTY); + root->EditChildren().push_back(arrayNode); + + // + for (set::const_iterator item = items.begin(); + item != items.end(); item++) { + XMLNode* itemNode = item->value->Clone(); + itemNode->SetName("", "item"); + itemNode->EditAttributes().clear(); + arrayNode->EditChildren().push_back(itemNode); + } + } + + // + for (set::const_iterator it=m_strings.begin(); it!=m_strings.end(); it++) { + const StringResource& str = *it; + vector attrs; + XMLNode* strNode = str.value->Clone(); + strNode->SetName("", "string"); + strNode->EditAttributes().clear(); + strNode->EditAttributes().push_back(XMLAttribute("", "name", str.id)); + root->EditChildren().push_back(strNode); + } + + return root; +} + +string +ValuesFile::ToString() const +{ + XMLNode* xml = ToXMLNode(); + string s = "\n"; + s += xml->ToString(ANDROID_NAMESPACES); + delete xml; + s += '\n'; + return s; +} + -- cgit v1.2.3-59-g8ed1b