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
39 #ifndef MIPI_SYST_PRINTER_H_included
40 #define MIPI_SYST_PRINTER_H_included
41
42 #include <cstdint>
43 #include <string>
44 #include <sstream>
45 #include <iomanip>
46
47
48 // Is Host Big Endian ?
49 //
50 #if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
51 #define MIPI_SYST_BIG_ENDIAN
52 #endif
53
54 #define MIPI_SYST_NAMESPACE ::mipi::syst
55 #define MIPI_SYST_NAMESPACE_BEGIN namespace mipi { namespace syst {
56 #define MIPI_SYST_NAMESPACE_END }}
57
58 #define MIPI_SYST_NAMESPACE_USE using namespace MIPI_SYST_NAMESPACE
59
60 MIPI_SYST_NAMESPACE_BEGIN
61
62 /// This function template attempts to convert a string into a numeric value.
63 ///
64 /// Hexadecimal and decimal numbers are supported.
65 /// Hexadecimal values are expected to be prefixed with "0x"; without
66 /// this prefix the string is interpreted as a decimal value.
67 /// @param num_str the string to convert to a number
68 /// @param num the converted number will be stored in here
69 /// @return true if the conversion was successful, false otherwise
70 ///
71 template<class Type>
stringToNum(const std::string & num_str,Type & num)72 bool stringToNum(const std::string& num_str, Type& num)
73 {
74 const std::string terminator("@");
75 std::string tail;
76 std::stringstream sstr;
77
78 sstr << num_str << terminator;
79 auto base(num_str.find("0x") ? std::dec : std::hex);
80
81 if (sizeof(Type) == 1) {
82 // workaround for byte type assignment to use numbers not characters
83 //
84 uint32_t temp;
85 sstr >> base >> temp >> tail;
86 num = (Type)temp;
87 } else {
88 sstr >> base >> num >> tail;
89 }
90 if (tail != terminator)
91 {
92 return false;
93 }
94 return !sstr.fail();
95 }
96
toHexValue(T val)97 template<class T> std::string toHexValue(T val)
98 {
99 std::stringstream sstr;
100
101 sstr << "0x"
102 << std::hex << std::uppercase
103 << std::setfill('0') << std::setw(sizeof(T) * 2)
104 << val;
105
106 return sstr.str();
107 }
108
109 /// Helper to extract little endian values of sizeof(T) from a byte array
110 ///
bytes2ValLE(const void * p)111 template<class T> T bytes2ValLE(const void * p)
112 {
113 const uint8_t* data((const uint8_t*)p);
114 T result(0);
115
116 for (size_t i(0); i < sizeof(T); ++i) {
117 result |= (T)(*data++) << (i * 8);
118 }
119 return result;
120 }
121
122 /// Call the host libc printf for the formatting of one argument
123 /// to ensure compliance with C99 printf format rules.
124 /// The function needs to support 3 different call types.
125 /// One argument may use up to 2 star '*' format options
126 /// to dynamically change width and precisions.
127 ///
hostPrintf(std::stringstream & dest,const std::string & format,T value,const std::vector<int> & starArgs)128 template<class T> bool hostPrintf(
129 std::stringstream& dest,
130 const std::string& format, T value, const std::vector<int>& starArgs)
131 {
132 int result(0);
133 char buf[64 * 1024];
134
135 // Map to native printf API on host system.
136 // The "_set_printf_count_output() is a Windows special. Without it
137 // a call the msvcrt runtime throws a SEH exception on %n usage as
138 // part of security enhancements. We can safely allow %n
139 // as the message printf treats it as a nop.
140 //
141 #if defined(_WIN32)
142 int(*nativeSprintf)(char * data, size_t buffer, const char * format, ...) = _snprintf;
143 int saved_flag(_set_printf_count_output(1));
144 #else
145 int(*nativeSprintf)(char * data, size_t buffer, const char * format, ...) = snprintf;
146 #endif
147
148 switch (starArgs.size()) {
149 case 0:
150 result = nativeSprintf(buf, sizeof(buf), format.c_str(), value);
151 break;
152 case 1:
153 result = nativeSprintf(buf, sizeof(buf), format.c_str(), starArgs[0], value);
154 break;
155 case 2:
156 result = nativeSprintf(buf, sizeof(buf), format.c_str(), starArgs[0], starArgs[1], value);
157 break;
158 default:
159 result = -1; // format error, too many stars seen in argument format
160 break;
161 }
162
163 #if defined(_WIN32)
164 _set_printf_count_output(saved_flag);
165 #endif
166
167 if (result < 0) {
168 dest << " - invalid format '" << format << "' in printf";
169 }
170 else if (result >= sizeof(buf)) {
171 dest << " - printf result using format '" << format << "' is too large";
172 }
173 else {
174 dest << buf;
175 return true;
176 }
177
178 return false;
179 }
180
181 MIPI_SYST_NAMESPACE_END
182
183 #endif // MIPI_SYST_PRINTER_H_included
184