diff options
Diffstat (limited to 'printer/src/mipi_syst_collateral.cpp')
-rw-r--r-- | printer/src/mipi_syst_collateral.cpp | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/printer/src/mipi_syst_collateral.cpp b/printer/src/mipi_syst_collateral.cpp new file mode 100644 index 0000000..a421808 --- /dev/null +++ b/printer/src/mipi_syst_collateral.cpp @@ -0,0 +1,331 @@ +/* + Copyright (c) 2018, MIPI Alliance, Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Contributors: + * Norbert Schulz (Intel Corporation) - Initial API and implementation + */ + +#include <iomanip> +#include <sstream> +#include <iostream> +#include <type_traits> + +#include "mipi_syst_collateral.h" +#include "mipi_syst_guid.h" + +MIPI_SYST_NAMESPACE_BEGIN + +const char tagCollateral[] = "syst:Collateral"; +const char tagClient[] = "syst:Client"; +const char tagGuids[] = "syst:Guids"; +const char tagGuid[] = "syst:Guid"; +const char tagBuilds[] = "syst:Builds"; +const char tagBuild[] = "syst:Build"; +const char tagCatalog32[] = "syst:Catalog32"; +const char tagCatalog64[] = "syst:Catalog64"; +const char tagSourceFiles[] = "syst:SourceFiles"; +const char tagFile[] = "syst:File"; +const char tagShort32[] = "syst:Short32"; +const char tagShort64[] = "syst:Short64"; +const char tagWrite[] = "syst:Write"; +const char tagProtocol[] = "syst:Protocol"; +const char tagModules[] = "syst:Modules"; +const char tagModule[] = "syst:Module"; +const char tagID[] = "ID"; +const char tagMask[] = "Mask"; +const char tagFileAttr[] = "File"; +const char tagLine[] = "Line"; +const char tagFormat[] = "syst:Format"; + + +std::vector<collateral*> collateral::parseXml(const std::string& filename) +{ + pugi::xml_document doc; + pugi::xml_parse_result scan_result(doc.load_file(filename.c_str())); + std::stringstream sstr; + + if (!scan_result) { + sstr + << "XML parser error on file " + << filename + << " : " + << scan_result.description(); + + throw std::invalid_argument(sstr.str()); + } + + std::vector<collateral*> result; + + for(auto client(doc.child(tagCollateral).child(tagClient)); + client; + client = client.next_sibling(tagClient)) + { + result.push_back(new collateral(client, filename)); + } + return result; +} + + +collateral::collateral(pugi::xml_node& node, const std::string& file) : + m_file(file), + m_name(node.attribute("Name").as_string()) +{ + // Scan id <-> item mappings + // + parseMaskedItems(node.child(tagGuids), tagGuid, m_guids); + parseMaskedItems(node.child(tagBuilds), tagBuild, m_builds); + parseMaskedItems(node.child(tagSourceFiles), tagFile, m_files); + parseMaskedItems(node.child(tagModules), tagModule, m_modules); + parseMaskedItems(node.child(tagCatalog32), tagFormat, m_msgs32); + parseMaskedItems(node.child(tagCatalog64), tagFormat, m_msgs64); + parseMaskedItems(node.child(tagShort32), tagFormat, m_shorts32); + parseMaskedItems(node.child(tagShort64), tagFormat, m_shorts64); + parseMaskedItems(node.child(tagWrite), tagProtocol, m_writeTypes); +} + +bool collateral::match(const guid& g, uint64_t build) const +{ + for (auto& it : m_guids) { + if ((g & it.mask()) == (it.key() & it.mask())) + { + if (build != 0x0) { + // find collateral with matching build number + // + if (m_builds.find(build) != m_builds.end()) + { + return true; + } + } else { + return true; + } + } + } + + return false; +} + +template<> const collateral::catalogentry<uint32_t> * collateral::getCatalogEntry<>(uint32_t id) const +{ + auto hit = m_msgs32.find(id); + return (hit != m_msgs32.end()) ? &hit->value() : nullptr; +} + +template<> const collateral::catalogentry<uint64_t> * collateral::getCatalogEntry<>(uint64_t id) const +{ + auto hit = m_msgs64.find(id); + return (hit != m_msgs64.end()) ? &hit->value() : nullptr; +} +const std::string * collateral::getSourceFile(uint32_t id) const +{ + auto hit = m_files.find(id); + return (hit != m_files.end()) ? &hit->value() : nullptr; +} + +const std::string * collateral::getWriteType(uint8_t id) const +{ + auto hit(m_writeTypes.find(id)); + return (hit != m_writeTypes.end()) ? &hit->value() : nullptr; +} + +template<> const collateral::catalogentry<uint32_t> * collateral::getShortEntry<>(uint32_t id) const +{ + auto hit(m_shorts32.find(id)); + return (hit != m_shorts32.end()) ? &hit->value() : nullptr; +} +template<> const collateral::catalogentry<uint64_t> * collateral::getShortEntry<>(uint64_t id) const +{ + auto hit(m_shorts64.find(id)); + return (hit != m_shorts64.end()) ? &hit->value() : nullptr; +} + +template<typename K> bool parse(K& dest, const std::string& s) +{ + return stringToNum<K>(s, dest); +} + +template<> bool parse<guid>(guid& g, const std::string& s) +{ + return g.parse(s); +} + +template<typename K> K nomask() { return (K)-1; } +template<> guid nomask<guid>() { return guid("{ffffffff-ffff-ffff-ffff-ffffffffffff}"); } + +template<typename T> std::ostream & operator<<(std::ostream &os, const collateral::catalogentry<T>& p) +{ + return os << p.msg; +} + +template<typename K, typename V> +void collateral::parseMaskedItems( + pugi::xml_node root, const char * tag, masked_vector<K, V>& dest) +{ + for (pugi::xml_node item(root.child(tag)); + item; + item = item.next_sibling(tag)) + { + masked_item<K, V> data; + + std::string keyStr(item.attribute(tagID).as_string()); + std::string val(item.child_value()); + + if (!parse<K>(data.key(), keyStr)) { + std::stringstream what; + what << + "Malformed " << tag << "entry ID=\"" << keyStr << + "\" value =\"" << val << "\"" << + " for catalog " << m_name; + throw std::invalid_argument(what.str()); + } + + std::string maskStr(item.attribute(tagMask).as_string()); + if (!maskStr.empty()) { + if (!parse<K>(data.mask(), maskStr)) { + std::stringstream what; + what << + "Malformed " << tag << "entry Mask=\"" << maskStr << + "\" value =\"" << val << "\"" << + " for catalog " << m_name; + throw std::invalid_argument(what.str()); + } + } else { + data.mask() = nomask<K>(); + } + + data.value() = val; + + // scan option file/line data if value supports source positions + // + if (std::is_base_of<catalogentry<K>, V>::value) { + catalogentry<K> * entry((catalogentry<K>*)&data.value()); + entry->mask = data.mask(); + + std::string file(item.attribute(tagFileAttr).as_string()); + std::string line(item.attribute(tagLine).as_string()); + + if (!file.empty()) { + if (!parse(entry->m_file, file)) { + std::stringstream what; + what << + "Malformed File attribute " << file << + "in section " << tag << + " for catalog " << m_name; + throw std::invalid_argument(what.str()); + } + } + + if (!line.empty()) { + if (!parse(entry->m_line, line)) { + std::stringstream what; + what << + "Malformed Line attribute " << line << + "in section " << tag << + " for catalog " << m_name; + throw std::invalid_argument(what.str()); + } + } + } + + auto it = dest.find(data.key()); + if (it != dest.end() && it->value() != val) { + std::cerr << + "Overwriting ID" << data.key() << " -> " << val << + " old value: " << it->value() << std::endl; + *it = data; + } + else { + dest.push_back(data); + } + } +} + +/** Helper to parse a GUID "{...}" string into the binary representation. +* @param str GUID ascii string "{xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" +* @param guid resulting guid +* @return true if guid could be parserd +*/ +bool guid::parse(const std::string& str) +{ + if ( + (str.length() != sizeof("{00000000-0000-0000-0000-000000000000}")-1) || + str[0]!= '{' ||str[37] != '}' || + str[9] != '-' || str[14] != '-' || str[19] != '-' || str[24] != '-' + ) + { + return false; + } + + // parse the byte values; + // + const char * p(str.c_str()+1); + + for (int i(0); i < 16; ++i, p += 2) { + if (i == 4 || i == 6|| i == 8 || i == 10) { + p++; // skip "-" + } + std::stringstream sstr(std::string(p, 2)); + uint16_t temp; + + if (! (sstr >> std::hex >>temp)) { + return false; + } + u.b[i] = (uint8_t)(temp); + } + + return true; +} + +std::ostream& operator<<(std::ostream& os, const guid& g) +{ + auto flags(os.flags()); + + + os << '{'; + + for (int i(0); i < 16; ++i) { + os << std::setfill('0') << std::noshowbase << std::hex << std::setw(2) + << (uint16_t)g.u.b[i]; + + if (i == 3 || i == 5|| i == 7 || i == 9) { + os << '-'; + } + } + + os << '}'; + + os.flags(flags); + return os; +} + +MIPI_SYST_NAMESPACE_END
\ No newline at end of file |