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_PRINTF_H_included 40 #define MIPI_SYST_PRINTF_H_included 41 42 #include <string> 43 #include <stdint.h> 44 #include <vector> 45 46 #include "mipi_syst_printer.h" 47 48 MIPI_SYST_NAMESPACE_BEGIN 49 50 /// Finite state machine parser to parse printf format strings used in catalog 51 /// and printf messages. It detects if we got a string embedded with formats like 52 /// this: 53 /// %[flags][width][.precision][length]specifier 54 /// 55 /// flags: - + (space) # 0 56 /// width: (number) * 57 /// precision: .(number) .* 58 /// length: hh h l ll j z t L 59 /// specifier: d i u o x X f F e E g G a A c s p n 60 /// 61 /// details: http://www.cplusplus.com/reference/cstdio/printf/ 62 /// 63 class fmtscanner 64 { 65 public: fmtscanner(bool is32Bit)66 fmtscanner(bool is32Bit) : 67 SIZEOF_PTR(is32Bit ? 4 : 8), 68 SIZEOF_INT(4), 69 SIZEOF_LONG(is32Bit ? 4 : 8), 70 SIZEOF_SIZEOF(is32Bit ? 4 : 8), 71 SIZEOF_LONGLONG(8) 72 {} 73 ~fmtscanner()74 ~fmtscanner() {} 75 76 /// argument variants 77 // 78 enum ArgType { 79 INTEGER, ///< 32/64 bit integer 80 POINTER, ///< 32/64 bit pointer 81 DOUBLE, ///< floating point number 82 TEXT, ///< text portion in format 83 STRING, ///< pointer to string %s 84 PERCENT_N, ///< the odd %n format 85 STAR, ///< an int from a %* arg 86 UNKNOWN ///< invalid format 87 }; 88 89 enum Result { 90 OK = 0, 91 UNKNOWN_FORMAT = (1 << 1), 92 INCOMPLETE_FORMAT = (1 << 2) 93 }; 94 95 /// Helper class to store information for one printf format fragment 96 /// 97 class ArgFragment { 98 public: 99 ArgFragment(ArgType type, size_t size, const std::string& text); 100 type()101 ArgType type() const { return _type; } size()102 size_t size() const { return _size; } text()103 const std::string& text() const { return _text; } 104 105 private: 106 ArgType _type; ///< arg type 107 size_t _size; ///< arg buffer space usage 108 std::string _text; ///< argument string fragment 109 }; 110 111 typedef std::vector<ArgFragment> Args; 112 113 protected: 114 115 /// Finite state machine states of the argument parser 116 /// 117 enum FmtScanState { 118 START, 119 PLAINTEXT, 120 PERCENT, 121 FLAGS, 122 WIDTH, WIDTH_NUMBER, 123 PRECISION_DOT, PRECISION_VAL, PRECISION_NUMBER, 124 MODIFIER, 125 MODIFIER_HALF, 126 MODIFIER_LONG, 127 SPECIFIER 128 }; 129 130 /// Format modifier types 131 /// 132 enum Modifier { 133 MOD_NONE, MOD_HH, MOD_H, MOD_L, MOD_LL, MOD_J, MOD_Z, MOD_T, MOD_LD 134 }; 135 136 public: 137 /// Parse a printf argument string into a vector of argument fragments 138 /// @eturn OK if no error, or bitmask of errors from Result enumeration. 139 /// 140 uint32_t parse(const std::string& fmt, Args& args); 141 142 const uint32_t SIZEOF_PTR; 143 const uint32_t SIZEOF_INT; 144 const uint32_t SIZEOF_LONG; 145 const uint32_t SIZEOF_SIZEOF; 146 const uint32_t SIZEOF_LONGLONG; 147 }; 148 149 150 /// Printf style formatter for events 151 /// 152 /// This class does printf style formatting using a format string 153 /// and memory buffer for the printf arguments. The code assumes 154 /// that all arguments are stored in the buffer without any padding 155 /// bytes. Strings are embedded as byte sequences into the buffer, 156 /// including their terminating null byte. 157 /// 158 /// Here is an example of how the buffer is expected 159 /// to be setup for the given printf call: 160 /// 161 /// printf("the %s jumped over the %s, %d times", "cow", "moon", 2); 162 /// 163 /// Argument buffer layout, following the format string: 164 /// 165 /// +-----------------------------------------------------------------+ 166 /// | 'c' | 'o' | 'w' | 0 | 'm' | 'o' | 'o' | 'n' | 0 | 2 | 0 | 0 | 0 | 167 /// +-----------------------------------------------------------------+ 168 /// |<--- P1 --->| |<--- P2 -->| |<--- P3 -->| 169 /// 170 /// It will print "the cow jumped over the moon, 2 times". 171 /// 172 class msgprintf 173 { 174 public: msgprintf(bool is32bit)175 msgprintf(bool is32bit) : 176 _scanner(is32bit) 177 {} 178 179 /// Initialize a printf formatter based on fmt and argument buffer 180 /// 181 /// @param fmt a C99 language compliant printf format string 182 /// @param args the argument buffer 183 /// @param size number of bytes in argument buffer 184 /// @param result ougoing string result or error message 185 /// 186 /// @ return true if formatting succeeded, false if not. 187 /// 188 bool format(const std::string& fmt, 189 const void * args, uint32_t size, 190 std::string& result); 191 192 private: 193 194 fmtscanner _scanner; 195 fmtscanner::Args _args; 196 197 msgprintf(const msgprintf&) = delete; 198 msgprintf operator=(const msgprintf&) = delete; 199 }; 200 201 MIPI_SYST_NAMESPACE_END 202 203 #endif // MIPI_SYST_PRINTER_H_included 204