1 /*
2  Copyright (c) 2018, MIPI Alliance, Inc.
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions
7  are met:
8 
9  * Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in
14    the documentation and/or other materials provided with the
15    distribution.
16 
17  * Neither the name of the copyright holder nor the names of its
18    contributors may be used to endorse or promote products derived
19    from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /*
35  * Contributors:
36  * Norbert Schulz (Intel Corporation) - Initial API and implementation
37  */
38 #ifndef MIPI_SYST_COLLATERL_H_included
39 #define MIPI_SYST_COLLATERL_H_included
40 
41 #include <string>
42 #include <map>
43 #include <vector>
44 #include <cstdint>
45 #include <algorithm>
46 
47 #include "pugixml.hpp"
48 #include "mipi_syst_printer.h"
49 #include "mipi_syst_guid.h"
50 
51 MIPI_SYST_NAMESPACE_BEGIN
52 class guid;
53 
54 class collateral {
55 public:
getName()56 	const std::string& getName() const { return m_name;}
getFileName()57 	const std::string& getFileName() const { return m_file; }
58 
59 	/// Check if the given guid matches one of the catalog guid/mask pairs
60 	///
61 	/// @param guid to check catalog for
62 	/// @param build  client build number
63 	/// @return true if catalog matches, false otherwise
64 	///
65 	bool match(const guid & g, const uint64_t build) const;
66 
67 	static std::vector<collateral*> parseXml(const std::string& filename);
68 
69 	struct sourcepos {
sourcepossourcepos70 		sourcepos(uint32_t file, uint32_t line) :
71 			m_file(file), m_line(line) {};
72 
73 		uint32_t m_file = 0;
74 		uint32_t m_line = 0;
75 	};
76 
77 	/// Message entry for ID->MSG catalogs
78 	///
79 	template<typename T> struct catalogentry : public sourcepos {
80 		std::string msg;
81 		T mask;
82 
83 		catalogentry(std::string s ="",  T mask = (T)-1, uint32_t file = 0, uint32_t line=0)
sourceposcatalogentry84 			: sourcepos(file, line), msg(s)
85 		{}
86 
87 		bool operator!=(const catalogentry& other) {
88 			return msg != other.msg;
89 		}
90 	};
91 
92 	/// Container for (key:mask:value tuples
93 	///
94 	template<typename K, typename V> struct masked_item
95 	{
masked_itemmasked_item96 		masked_item() {}
masked_itemmasked_item97 		masked_item(const K& k, const K& m, const V& v) :
98 			m_key(k), m_mask(m), m_value(v) {}
99 
keymasked_item100 		K& key()   { return m_key; }
maskmasked_item101 		K& mask()  {return m_mask;}
valuemasked_item102 		V& value() {return m_value;}
103 
keymasked_item104 		const K& key()   const { return m_key; }
maskmasked_item105 		const K& mask()  const { return m_mask; }
valuemasked_item106 		const V& value() const { return m_value; }
107 
108 	private:
109 		K m_key;
110 		K m_mask;
111 		V m_value;
112 	};
113 
114 	template<typename K, typename V>
115 	class masked_vector : public std::vector<masked_item<K, V>>
116 	{
117 	public:
118 		typedef std::vector<masked_item<K, V>> base_type;
119 
120 		/// Find key in item vector using item mask when comparing (const)
121 		///
122 		/// @param k key to look for
123 		/// @return iterator to matching element or end() if not found
124 		///
125 		typename base_type::const_iterator
find(const K & k)126 		find(const K& k) const
127 		{
128 			return std::find_if(base_type::begin(), base_type::end(),
129 				[& k](const masked_item<K, V>& v)
130 				{
131 					return (v.key() & v.mask()) == (k & v.mask());
132 				}
133 			);
134 		}
135 
136 
137 		/// Find key in item vector using item mask when comparing
138 		///
139 		/// @param k key to look for
140 		///  @return iterator to matching element or end() if not found
141 		///
142 		typename base_type::iterator
find(const K & k)143 		find(const K& k)
144 		{
145 			return std::find_if(base_type::begin(), base_type::end(),
146 				[&k]( masked_item<K, V>& v)
147 			{
148 				return (v.key() & v.mask()) == (k & v.mask());
149 			}
150 			);
151 		}
152 	};
153 
154 	/// container for ID <-> value mapping sections in collateral
155 	///
156 	using guids      =  masked_vector<guid, std::string>;
157 	using builds     = masked_vector<uint64_t, std::string>;
158 	using srcfiles   = masked_vector<uint32_t, std::string>;
159 	using origins    = masked_vector<uint32_t, std::string>;
160 	using writetypes = masked_vector<uint8_t, std::string>;
161 	using catalog32  = masked_vector<uint32_t, catalogentry<uint32_t>>;
162 	using catalog64  = masked_vector<uint64_t, catalogentry<uint64_t>>;
163 
164 	template<typename T> const catalogentry<T> * getShortEntry(T id) const;
165 	template<typename T> const catalogentry<T> * getCatalogEntry(T id) const;
166 
167 	const std::string  * getSourceFile(uint32_t id) const;
168 	const std::string  * getWriteType(uint8_t id) const;
169 
170 
171 	/// Parse collateral from XML
172 	///
173 	collateral(pugi::xml_node& node, const std::string& file);
174 
175 	template<typename K, typename V>
176 	void parseMaskedItems(
177 		pugi::xml_node root,
178 		const char * tag,
179 		masked_vector<K, V>& dest);
180 private:
181 	std::string m_file;       /**< originating file name */
182 
183 	std::string m_name;       /**< catalog name */
184 	guids       m_guids;      /**< Guids where the collateral is valid    */
185 	builds      m_builds;     /**< builds where the collateral is valid   */
186 	catalog32   m_msgs32;     /**< message catalog with 32bit ID's        */
187 	catalog64   m_msgs64;     /**< message catalog with 64bit ID's        */
188 	catalog32   m_shorts32;   /**< short event id to message mapping      */
189 	catalog64   m_shorts64;   /**< short event id to message mapping      */
190 	writetypes  m_writeTypes; /**< write definitions                      */
191 	srcfiles    m_files;      /**< file catalog                           */
192 	origins     m_modules;    /**< module id to name mappings             */
193 
194 
195 private:
196 	/* no copy, assign */
197 	collateral() = delete;
198 	collateral(const collateral&) = delete;
199 	collateral& operator=(const collateral&) = delete;
200 };
201 
202 MIPI_SYST_NAMESPACE_END
203 
204 #endif // MIPI_SYST_COLLATERL_H_included
205