1 /*------------------------------------------------------------------------------ 2 * 3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved. 4 * The YADIFA TM software product is provided under the BSD 3-clause license: 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * * Neither the name of EURid nor the names of its contributors may be 16 * used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 *------------------------------------------------------------------------------ 32 * 33 */ 34 35 /** @defgroup format C-string formatting 36 * @ingroup dnscore 37 * @brief 38 * 39 * @{ 40 * 41 *----------------------------------------------------------------------------*/ 42 43 #pragma once 44 45 #include <stdio.h> 46 #include <stdarg.h> 47 48 #include <dnscore/sys_types.h> 49 #include <dnscore/output_stream.h> 50 #include <dnscore/dnscore.h> 51 52 #define OSPRINT_DUMP_LAYOUT_GROUP_MASK 0x0000ff00U 53 #define OSPRINT_DUMP_LAYOUT_GROUP_SHIFT 0x00000008U 54 #define OSPRINT_DUMP_LAYOUT_SEPARATOR_MASK 0x000000ffU 55 #define OSPRINT_DUMP_LAYOUT_SEPARATOR_SHIFT 0x00000000U 56 #define OSPRINT_DUMP_OFFSET 0x80000000U 57 #define OSPRINT_DUMP_ADDRESS 0x40000000U 58 #define OSPRINT_DUMP_HEX 0x20000000U 59 #define OSPRINT_DUMP_TEXT 0x10000000U 60 #define OSPRINT_DUMP_SQUEEZE_ZEROES 0x08000000U 61 62 // predefined layouts 63 #define OSPRINT_DUMP_LAYOUT_DENSE 0x0000ffffU 64 #define OSPRINT_DUMP_LAYOUT_ERIC 0x000003ffU 65 #define OSPRINT_DUMP_LAYOUT_GERY 0x00000003U 66 67 #define OSPRINT_DUMP_ALL (OSPRINT_DUMP_ADDRESS|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) 68 #define OSPRINT_DUMP_BUFFER (OSPRINT_DUMP_OFFSET|OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) 69 #define OSPRINT_DUMP_HEXTEXT (OSPRINT_DUMP_HEX|OSPRINT_DUMP_TEXT) 70 #define OSPRINT_DUMP_BASE16 (OSPRINT_DUMP_LAYOUT_DENSE|OSPRINT_DUMP_HEX) 71 72 /** 73 * 74 * Formats: 75 * 76 * modifier : restrict : 77 * : to : 78 * - : : change justification 79 * 123456789 : : padding space 80 * 0 : : use '0' char for padding 81 * .12345789 : f : for float types, precision to use 82 * hh : iudXxo : half half : 8 bits 83 * h : iudXxo : half : 16 bits 84 * l : iudXxo : long : 32 bits 85 * ll : iudXxo : long long : 64 bits 86 * L : f : long double 87 * 88 * formats : 89 * : 90 * %t : integer, prints the number of tabs on the output 91 * %S : integer, prints the number of spaces on the output 92 * %T : integer, prints the 32/64 bits UTC time on the output 93 * %T : 32 bits = YYYY-MM-DD HH:mm:SS 94 * %lT : 64 bits = YYYY-MM-DD HH:mm:SS 95 * %llT : 64 bits = YYYY-MM-DD HH:mm:SS.NNNNNN 96 * %i : integer, prints the signed 8/16/32/64 bits integer in base 10 on the output 97 * %r : integer, prints the ya_result registered message on the output or the hexadecimal code 98 * %u : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output 99 * %d : integer, prints the unsigned 8/16/32/64 bits integer in base 10 on the output 100 * %X : integer, prints the unsigned 8/16/32/64 bits integer in base 16 uppercase on the output 101 * %x : integer, prints the unsigned 8/16/32/64 bits integer in base 16 lowercase on the output 102 * %o : integer, prints the unsigned 8/16/32/64 bits integer in base 8 on the output 103 * %p : void* , prints the pointer in hexadecimal on the output 104 * %P : void* , prints the name of the pointer if possible, else the hexadecimal on the output 105 * %f : double , prints the long double/double/float on the output 106 * %s : char* , prints the ASCIIZ string on the output 107 * %c : char , prints the 8-bits char on the output 108 * %w : format_writer, calls the format_writer callback to print on the output 109 * 110 * Format extension mechanism: 111 * 112 * "%{registeredformatname}" : void*, prints the pointed value on the output 113 * : use ya_result format_registerclass(format_handler_descriptor* fhd) for registration 114 */ 115 116 /* void* value, output_stream*, s32 padding, char pad_char, bool left_justified, void* reserved */ 117 118 typedef void format_handler_method(const void*, output_stream*, s32, char, bool, void* reserved_for_method_parameters); 119 120 typedef struct format_handler_descriptor format_handler_descriptor; 121 122 // About the %w format: 123 // 124 // a pointer to this can be given as a 'w' parameter ie: "%w" 125 // the writer callback get's called with 126 // void* value as first parameter, what to print 127 // output_stream *os as second parameter, where to write the chars to 128 // s32 padding the number of chars it's supposed to take on the output (minimum) 129 // char padchar the character to use for padding 130 // bool left_justified where to justify the text 131 // void* don't use that one 132 // 133 // ex: 134 // 135 // format_writer temp_fw_0 = {my_complex_or_rare_type_printer_callback, &my_complex_or_rare_type}; 136 // 137 // format("So the value is : '%w'\n", &temp_fw_0); 138 // 139 140 struct format_writer 141 { 142 format_handler_method *callback; 143 const void * value; 144 }; 145 146 typedef struct format_writer format_writer; 147 148 struct format_handler_descriptor 149 { 150 const char* name; 151 int name_len; /* Needed in order to quicken the matching */ 152 format_handler_method* format_handler; 153 }; 154 155 void format_class_init(); 156 157 ya_result format_registerclass(const format_handler_descriptor* fhd); 158 159 /** 160 * %% -> % 161 * %-09lli right-justified 0-padded "long long integer" (s64) 162 * %-9llu right-justified "long long unsigned integer" (u64) 163 * %-20{class} right-justified "class" (class has to be registered) 164 * %-20{class(a,b,c,d)} right-justified "class" called with 4 arguments (class has to be registered) 165 * 166 * %[-][0| ]([hh|h|l|ll]u|i|x)|([L]f)|c|s|{} 167 * 168 * --- 169 * 170 * hh 8 bits 171 * h 16 bits 172 * l 32 bits (The default if no length is given is 32 bits) 173 * ll 64 bits 174 * 175 * i signed integer 176 * u unsigned integer 177 * d unsigned integer 178 * x hexadecimal lo 179 * X hexadecimal hi 180 * b binary (not in yet) 181 * 182 * --- 183 * 184 * L long 185 * 186 * f double 187 * 188 * --- 189 * 190 * c char 191 * 192 * --- 193 * 194 * s asciiz string 195 * 196 * --- 197 * 198 * {class name} pointer to something that will be interpreted by the handler 199 * 200 */ 201 202 ya_result vosformat(output_stream* os_, const char* fmt, va_list args); 203 ya_result osprint(output_stream* stream,const char* text); 204 ya_result osprintln(output_stream* stream,const char* text); 205 ya_result osformat(output_stream* stream,const char* fmt,...); 206 ya_result osformatln(output_stream* stream,const char* fmt,...); 207 ya_result print(const char* text); 208 ya_result println(const char* text); 209 ya_result format(const char* fmt,...); 210 ya_result formatln(const char* fmt,...); 211 212 // prefixes time | pid | pthread_self 213 ya_result debug_osformatln(output_stream* stream, const char* fmt, ...); 214 ya_result debug_println(const char* text); 215 216 int vsnformat(char* out_, size_t out_size, const char* fmt, va_list args); 217 int snformat(char* out, size_t out_size, const char* fmt, ...); 218 219 /** 220 * This formatter will return an allocated (malloc) string as a result of the format 221 * 222 * @param outp 223 * @param out_size 224 * @param fmt 225 * @param args 226 * @return 227 */ 228 229 int vasnformat(char** outp, size_t out_size, const char* fmt, va_list args); 230 231 /** 232 * This formatter will return an allocated (malloc) string as a result of the format 233 * 234 * @param outp 235 * @param out_size 236 * @param fmt 237 * @param ... 238 * @return 239 */ 240 241 int asnformat(char** outp, size_t out_size, const char* fmt, ...); 242 243 /** 244 * This formatter will return an allocated (malloc) string as a result of the format 245 * 246 * @param outp 247 * @param fmt 248 * @param ... 249 * @return 250 */ 251 252 int asformat(char** outp, const char* fmt, ...); 253 254 /* Used by extensions */ 255 256 void format_dec_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 257 void format_dec_s64(s64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 258 void format_hex_u64_lo(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 259 void format_hex_u64_hi(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 260 void format_oct_u64(u64 val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 261 void format_asciiz(const char* val, output_stream* stream, s32 padding, char pad_char, bool left_justified); 262 263 /**/ 264 265 int osprint_base16(output_stream* os, const u8* rdata, u32 rdata_size); 266 int osprint_base64(output_stream* os, const u8* rdata, u32 rdata_size); 267 268 void osprint_u32(output_stream* os, u32 value); 269 void osprint_u16(output_stream* os, u16 value); 270 void osprint_u32_hex(output_stream* os, u32 value); 271 272 void print_char(char value); 273 274 void osprint_char(output_stream *os, char value); 275 void osprint_char_times(output_stream *os, char value, int times); 276 void osprint_dump_with_base(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags, const void* base_pointer_); 277 void osprint_dump(output_stream *os, const void* data_pointer_, size_t size_, size_t line_size, u32 flags); 278 279 ya_result osprint_type_bitmap(output_stream *os, const u8 *rdata_pointer, u16 rdata_size); 280 ya_result osprint_rdata(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size); 281 ya_result osprint_rdata_escaped(output_stream *os, u16 type, const u8 *rdata_pointer, u16 rdata_size); 282 ya_result print_rdata(u16 type, u8 *rdata, u16 rdata_size); 283 284 void osprint_question(output_stream *os, u8 *qname, u16 qclass, u16 qtype); 285 void print_question(u8 *qname, u16 qclass, u16 qtype); 286 287 #if 0 /* fix */ 288 #else 289 #define FORMAT_BREAK_ON_INVALID(address__, len__) 290 #endif 291 292 /* 293 * This is just a tool function used to test vsnformat. 294 * It is not meant for the logger. 295 * It has an output length limitation of 4096 bytes. 296 * 297 * Please use the other functions if possible. 298 */ 299 300 int fformat(FILE *out, const char *fmt, ...); 301 302 /** 303 * This tool struct is used so the RDATA part of a record can be printed/formatted 304 * 305 * we would have: 306 * 307 * rdata_desc myrdata={TYPE_SOA, rdata_len, rdata}; 308 * format("bla bla bla %{rdatadesc}", &myrdata); 309 * 310 * 311 */ 312 313 struct rdata_desc_s 314 { 315 u16 type; 316 u16 len; 317 const u8 * rdata; 318 }; 319 320 typedef struct rdata_desc_s rdata_desc; 321 322