VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strformatrt.cpp@ 39903

Last change on this file since 39903 was 38546, checked in by vboxsync, 13 years ago

warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 52.4 KB
Line 
1/* $Id: strformatrt.cpp 38546 2011-08-26 12:38:46Z vboxsync $ */
2/** @file
3 * IPRT - IPRT String Formatter Extensions.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_STRING
32#include <iprt/string.h>
33#ifndef RT_NO_EXPORT_SYMBOL
34# define RT_NO_EXPORT_SYMBOL /* don't slurp <linux/module.h> which then again
35 slurps arch-specific headers defining symbols */
36#endif
37#include "internal/iprt.h"
38
39#include <iprt/log.h>
40#include <iprt/assert.h>
41#include <iprt/string.h>
42#include <iprt/stdarg.h>
43#ifdef IN_RING3
44# include <iprt/thread.h>
45# include <iprt/err.h>
46#endif
47#include <iprt/ctype.h>
48#include <iprt/time.h>
49#include <iprt/net.h>
50#include <iprt/path.h>
51#define STRFORMAT_WITH_X86
52#ifdef STRFORMAT_WITH_X86
53# include <iprt/x86.h>
54#endif
55#include "internal/string.h"
56
57
58
59/**
60 * Callback to format iprt formatting extentions.
61 * See @ref pg_rt_str_format for a reference on the format types.
62 *
63 * @returns The number of bytes formatted.
64 * @param pfnOutput Pointer to output function.
65 * @param pvArgOutput Argument for the output function.
66 * @param ppszFormat Pointer to the format string pointer. Advance this till the char
67 * after the format specifier.
68 * @param pArgs Pointer to the argument list. Use this to fetch the arguments.
69 * @param cchWidth Format Width. -1 if not specified.
70 * @param cchPrecision Format Precision. -1 if not specified.
71 * @param fFlags Flags (RTSTR_NTFS_*).
72 * @param chArgSize The argument size specifier, 'l' or 'L'.
73 */
74DECLHIDDEN(size_t) rtstrFormatRt(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat, va_list *pArgs,
75 int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize)
76{
77 const char *pszFormatOrg = *ppszFormat;
78 char ch = *(*ppszFormat)++;
79 size_t cch;
80 char szBuf[80];
81
82 if (ch == 'R')
83 {
84 ch = *(*ppszFormat)++;
85 switch (ch)
86 {
87 /*
88 * Groups 1 and 2.
89 */
90 case 'T':
91 case 'G':
92 case 'H':
93 case 'R':
94 case 'C':
95 case 'I':
96 case 'X':
97 case 'U':
98 {
99 /*
100 * Interpret the type.
101 */
102 typedef enum
103 {
104 RTSF_INT,
105 RTSF_INTW,
106 RTSF_BOOL,
107 RTSF_FP16,
108 RTSF_FP32,
109 RTSF_FP64,
110 RTSF_IPV4,
111 RTSF_IPV6,
112 RTSF_MAC,
113 RTSF_NETADDR,
114 RTSF_UUID
115 } RTSF;
116 static const struct
117 {
118 uint8_t cch; /**< the length of the string. */
119 char sz[10]; /**< the part following 'R'. */
120 uint8_t cb; /**< the size of the type. */
121 uint8_t u8Base; /**< the size of the type. */
122 RTSF enmFormat; /**< The way to format it. */
123 uint16_t fFlags; /**< additional RTSTR_F_* flags. */
124 }
125 /** Sorted array of types, looked up using binary search! */
126 s_aTypes[] =
127 {
128#define STRMEM(str) sizeof(str) - 1, str
129 { STRMEM("Ci"), sizeof(RTINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
130 { STRMEM("Cp"), sizeof(RTCCPHYS), 16, RTSF_INTW, 0 },
131 { STRMEM("Cr"), sizeof(RTCCUINTREG), 16, RTSF_INTW, 0 },
132 { STRMEM("Cu"), sizeof(RTUINT), 10, RTSF_INT, 0 },
133 { STRMEM("Cv"), sizeof(void *), 16, RTSF_INTW, 0 },
134 { STRMEM("Cx"), sizeof(RTUINT), 16, RTSF_INT, 0 },
135 { STRMEM("Gi"), sizeof(RTGCINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
136 { STRMEM("Gp"), sizeof(RTGCPHYS), 16, RTSF_INTW, 0 },
137 { STRMEM("Gr"), sizeof(RTGCUINTREG), 16, RTSF_INTW, 0 },
138 { STRMEM("Gu"), sizeof(RTGCUINT), 10, RTSF_INT, 0 },
139 { STRMEM("Gv"), sizeof(RTGCPTR), 16, RTSF_INTW, 0 },
140 { STRMEM("Gx"), sizeof(RTGCUINT), 16, RTSF_INT, 0 },
141 { STRMEM("Hi"), sizeof(RTHCINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
142 { STRMEM("Hp"), sizeof(RTHCPHYS), 16, RTSF_INTW, 0 },
143 { STRMEM("Hr"), sizeof(RTGCUINTREG), 16, RTSF_INTW, 0 },
144 { STRMEM("Hu"), sizeof(RTHCUINT), 10, RTSF_INT, 0 },
145 { STRMEM("Hv"), sizeof(RTHCPTR), 16, RTSF_INTW, 0 },
146 { STRMEM("Hx"), sizeof(RTHCUINT), 16, RTSF_INT, 0 },
147 { STRMEM("I16"), sizeof(int16_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
148 { STRMEM("I32"), sizeof(int32_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
149 { STRMEM("I64"), sizeof(int64_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
150 { STRMEM("I8"), sizeof(int8_t), 10, RTSF_INT, RTSTR_F_VALSIGNED },
151 { STRMEM("Rv"), sizeof(RTRCPTR), 16, RTSF_INTW, 0 },
152 { STRMEM("Tbool"), sizeof(bool), 10, RTSF_BOOL, 0 },
153 { STRMEM("Tfile"), sizeof(RTFILE), 10, RTSF_INT, 0 },
154 { STRMEM("Tfmode"), sizeof(RTFMODE), 16, RTSF_INTW, 0 },
155 { STRMEM("Tfoff"), sizeof(RTFOFF), 10, RTSF_INT, RTSTR_F_VALSIGNED },
156 { STRMEM("Tfp16"), sizeof(RTFAR16), 16, RTSF_FP16, RTSTR_F_ZEROPAD },
157 { STRMEM("Tfp32"), sizeof(RTFAR32), 16, RTSF_FP32, RTSTR_F_ZEROPAD },
158 { STRMEM("Tfp64"), sizeof(RTFAR64), 16, RTSF_FP64, RTSTR_F_ZEROPAD },
159 { STRMEM("Tgid"), sizeof(RTGID), 10, RTSF_INT, RTSTR_F_VALSIGNED },
160 { STRMEM("Tino"), sizeof(RTINODE), 16, RTSF_INTW, 0 },
161 { STRMEM("Tint"), sizeof(RTINT), 10, RTSF_INT, RTSTR_F_VALSIGNED },
162 { STRMEM("Tiop"), sizeof(RTIOPORT), 16, RTSF_INTW, 0 },
163 { STRMEM("Tldrm"), sizeof(RTLDRMOD), 16, RTSF_INTW, 0 },
164 { STRMEM("Tmac"), sizeof(PCRTMAC), 16, RTSF_MAC, 0 },
165 { STRMEM("Tnaddr"), sizeof(PCRTNETADDR), 10, RTSF_NETADDR,0 },
166 { STRMEM("Tnaipv4"), sizeof(RTNETADDRIPV4), 10, RTSF_IPV4, 0 },
167 { STRMEM("Tnaipv6"), sizeof(PCRTNETADDRIPV6),16, RTSF_IPV6, 0 },
168 { STRMEM("Tnthrd"), sizeof(RTNATIVETHREAD), 16, RTSF_INTW, 0 },
169 { STRMEM("Tproc"), sizeof(RTPROCESS), 16, RTSF_INTW, 0 },
170 { STRMEM("Tptr"), sizeof(RTUINTPTR), 16, RTSF_INTW, 0 },
171 { STRMEM("Treg"), sizeof(RTCCUINTREG), 16, RTSF_INTW, 0 },
172 { STRMEM("Tsel"), sizeof(RTSEL), 16, RTSF_INTW, 0 },
173 { STRMEM("Tsem"), sizeof(RTSEMEVENT), 16, RTSF_INTW, 0 },
174 { STRMEM("Tsock"), sizeof(RTSOCKET), 10, RTSF_INT, 0 },
175 { STRMEM("Tthrd"), sizeof(RTTHREAD), 16, RTSF_INTW, 0 },
176 { STRMEM("Tuid"), sizeof(RTUID), 10, RTSF_INT, RTSTR_F_VALSIGNED },
177 { STRMEM("Tuint"), sizeof(RTUINT), 10, RTSF_INT, 0 },
178 { STRMEM("Tunicp"), sizeof(RTUNICP), 16, RTSF_INTW, RTSTR_F_ZEROPAD },
179 { STRMEM("Tutf16"), sizeof(RTUTF16), 16, RTSF_INTW, RTSTR_F_ZEROPAD },
180 { STRMEM("Tuuid"), sizeof(PCRTUUID), 16, RTSF_UUID, 0 },
181 { STRMEM("Txint"), sizeof(RTUINT), 16, RTSF_INT, 0 },
182 { STRMEM("U16"), sizeof(uint16_t), 10, RTSF_INT, 0 },
183 { STRMEM("U32"), sizeof(uint32_t), 10, RTSF_INT, 0 },
184 { STRMEM("U64"), sizeof(uint64_t), 10, RTSF_INT, 0 },
185 { STRMEM("U8"), sizeof(uint8_t), 10, RTSF_INT, 0 },
186 { STRMEM("X16"), sizeof(uint16_t), 16, RTSF_INT, 0 },
187 { STRMEM("X32"), sizeof(uint32_t), 16, RTSF_INT, 0 },
188 { STRMEM("X64"), sizeof(uint64_t), 16, RTSF_INT, 0 },
189 { STRMEM("X8"), sizeof(uint8_t), 16, RTSF_INT, 0 },
190#undef STRMEM
191 };
192 static const char s_szNull[] = "<NULL>";
193
194 const char *pszType = *ppszFormat - 1;
195 int iStart = 0;
196 int iEnd = RT_ELEMENTS(s_aTypes) - 1;
197 int i = RT_ELEMENTS(s_aTypes) / 2;
198
199 union
200 {
201 uint8_t u8;
202 uint16_t u16;
203 uint32_t u32;
204 uint64_t u64;
205 int8_t i8;
206 int16_t i16;
207 int32_t i32;
208 int64_t i64;
209 RTFAR16 fp16;
210 RTFAR32 fp32;
211 RTFAR64 fp64;
212 bool fBool;
213 PCRTMAC pMac;
214 RTNETADDRIPV4 Ipv4Addr;
215 PCRTNETADDRIPV6 pIpv6Addr;
216 PCRTNETADDR pNetAddr;
217 PCRTUUID pUuid;
218 } u;
219
220 AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
221
222 /*
223 * Lookup the type - binary search.
224 */
225 for (;;)
226 {
227 int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
228 if (!iDiff)
229 break;
230 if (iEnd == iStart)
231 {
232 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
233 return 0;
234 }
235 if (iDiff < 0)
236 iEnd = i - 1;
237 else
238 iStart = i + 1;
239 if (iEnd < iStart)
240 {
241 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
242 return 0;
243 }
244 i = iStart + (iEnd - iStart) / 2;
245 }
246
247 /*
248 * Advance the format string and merge flags.
249 */
250 *ppszFormat += s_aTypes[i].cch - 1;
251 fFlags |= s_aTypes[i].fFlags;
252
253 /*
254 * Fetch the argument.
255 * It's important that a signed value gets sign-extended up to 64-bit.
256 */
257 RT_ZERO(u);
258 if (fFlags & RTSTR_F_VALSIGNED)
259 {
260 switch (s_aTypes[i].cb)
261 {
262 case sizeof(int8_t):
263 u.i64 = va_arg(*pArgs, /*int8_t*/int);
264 fFlags |= RTSTR_F_8BIT;
265 break;
266 case sizeof(int16_t):
267 u.i64 = va_arg(*pArgs, /*int16_t*/int);
268 fFlags |= RTSTR_F_16BIT;
269 break;
270 case sizeof(int32_t):
271 u.i64 = va_arg(*pArgs, int32_t);
272 fFlags |= RTSTR_F_32BIT;
273 break;
274 case sizeof(int64_t):
275 u.i64 = va_arg(*pArgs, int64_t);
276 fFlags |= RTSTR_F_64BIT;
277 break;
278 default:
279 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
280 break;
281 }
282 }
283 else
284 {
285 switch (s_aTypes[i].cb)
286 {
287 case sizeof(uint8_t):
288 u.u8 = va_arg(*pArgs, /*uint8_t*/unsigned);
289 fFlags |= RTSTR_F_8BIT;
290 break;
291 case sizeof(uint16_t):
292 u.u16 = va_arg(*pArgs, /*uint16_t*/unsigned);
293 fFlags |= RTSTR_F_16BIT;
294 break;
295 case sizeof(uint32_t):
296 u.u32 = va_arg(*pArgs, uint32_t);
297 fFlags |= RTSTR_F_32BIT;
298 break;
299 case sizeof(uint64_t):
300 u.u64 = va_arg(*pArgs, uint64_t);
301 fFlags |= RTSTR_F_64BIT;
302 break;
303 case sizeof(RTFAR32):
304 u.fp32 = va_arg(*pArgs, RTFAR32);
305 break;
306 case sizeof(RTFAR64):
307 u.fp64 = va_arg(*pArgs, RTFAR64);
308 break;
309 default:
310 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
311 break;
312 }
313 }
314
315 /*
316 * Format the output.
317 */
318 switch (s_aTypes[i].enmFormat)
319 {
320 case RTSF_INT:
321 {
322 cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
323 break;
324 }
325
326 /* hex which defaults to max width. */
327 case RTSF_INTW:
328 {
329 Assert(s_aTypes[i].u8Base == 16);
330 if (cchWidth < 0)
331 {
332 cchWidth = s_aTypes[i].cb * 2 + (fFlags & RTSTR_F_SPECIAL ? 2 : 0);
333 fFlags |= RTSTR_F_ZEROPAD;
334 }
335 cch = RTStrFormatNumber(szBuf, u.u64, s_aTypes[i].u8Base, cchWidth, cchPrecision, fFlags);
336 break;
337 }
338
339 case RTSF_BOOL:
340 {
341 static const char s_szTrue[] = "true ";
342 static const char s_szFalse[] = "false";
343 if (u.u64 == 1)
344 return pfnOutput(pvArgOutput, s_szTrue, sizeof(s_szTrue) - 1);
345 if (u.u64 == 0)
346 return pfnOutput(pvArgOutput, s_szFalse, sizeof(s_szFalse) - 1);
347 /* invalid boolean value */
348 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "!%lld!", u.u64);
349 }
350
351 case RTSF_FP16:
352 {
353 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
354 cch = RTStrFormatNumber(&szBuf[0], u.fp16.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
355 Assert(cch == 4);
356 szBuf[4] = ':';
357 cch = RTStrFormatNumber(&szBuf[5], u.fp16.off, 16, 4, -1, fFlags | RTSTR_F_16BIT);
358 Assert(cch == 4);
359 cch = 4 + 1 + 4;
360 break;
361 }
362 case RTSF_FP32:
363 {
364 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
365 cch = RTStrFormatNumber(&szBuf[0], u.fp32.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
366 Assert(cch == 4);
367 szBuf[4] = ':';
368 cch = RTStrFormatNumber(&szBuf[5], u.fp32.off, 16, 8, -1, fFlags | RTSTR_F_32BIT);
369 Assert(cch == 8);
370 cch = 4 + 1 + 8;
371 break;
372 }
373 case RTSF_FP64:
374 {
375 fFlags &= ~(RTSTR_F_VALSIGNED | RTSTR_F_BIT_MASK | RTSTR_F_WIDTH | RTSTR_F_PRECISION | RTSTR_F_THOUSAND_SEP);
376 cch = RTStrFormatNumber(&szBuf[0], u.fp64.sel, 16, 4, -1, fFlags | RTSTR_F_16BIT);
377 Assert(cch == 4);
378 szBuf[4] = ':';
379 cch = RTStrFormatNumber(&szBuf[5], u.fp64.off, 16, 16, -1, fFlags | RTSTR_F_64BIT);
380 Assert(cch == 16);
381 cch = 4 + 1 + 16;
382 break;
383 }
384
385 case RTSF_IPV4:
386 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
387 "%u.%u.%u.%u",
388 u.Ipv4Addr.au8[0],
389 u.Ipv4Addr.au8[1],
390 u.Ipv4Addr.au8[2],
391 u.Ipv4Addr.au8[3]);
392
393 case RTSF_IPV6:
394 {
395 if (VALID_PTR(u.pIpv6Addr))
396 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
397 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
398 u.pIpv6Addr->au8[0],
399 u.pIpv6Addr->au8[1],
400 u.pIpv6Addr->au8[2],
401 u.pIpv6Addr->au8[3],
402 u.pIpv6Addr->au8[4],
403 u.pIpv6Addr->au8[5],
404 u.pIpv6Addr->au8[6],
405 u.pIpv6Addr->au8[7],
406 u.pIpv6Addr->au8[8],
407 u.pIpv6Addr->au8[9],
408 u.pIpv6Addr->au8[10],
409 u.pIpv6Addr->au8[11],
410 u.pIpv6Addr->au8[12],
411 u.pIpv6Addr->au8[13],
412 u.pIpv6Addr->au8[14],
413 u.pIpv6Addr->au8[15]);
414 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
415 }
416
417 case RTSF_MAC:
418 {
419 if (VALID_PTR(u.pMac))
420 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
421 "%02x:%02x:%02x:%02x:%02x:%02x",
422 u.pMac->au8[0],
423 u.pMac->au8[1],
424 u.pMac->au8[2],
425 u.pMac->au8[3],
426 u.pMac->au8[4],
427 u.pMac->au8[5]);
428 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
429 }
430
431 case RTSF_NETADDR:
432 {
433 if (VALID_PTR(u.pNetAddr))
434 {
435 switch (u.pNetAddr->enmType)
436 {
437 case RTNETADDRTYPE_IPV4:
438 if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
439 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
440 "%u.%u.%u.%u",
441 u.pNetAddr->uAddr.IPv4.au8[0],
442 u.pNetAddr->uAddr.IPv4.au8[1],
443 u.pNetAddr->uAddr.IPv4.au8[2],
444 u.pNetAddr->uAddr.IPv4.au8[3]);
445 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
446 "%u.%u.%u.%u:%u",
447 u.pNetAddr->uAddr.IPv4.au8[0],
448 u.pNetAddr->uAddr.IPv4.au8[1],
449 u.pNetAddr->uAddr.IPv4.au8[2],
450 u.pNetAddr->uAddr.IPv4.au8[3],
451 u.pNetAddr->uPort);
452
453 case RTNETADDRTYPE_IPV6:
454 if (u.pNetAddr->uPort == RTNETADDR_PORT_NA)
455 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
456 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
457 u.pNetAddr->uAddr.IPv6.au8[0],
458 u.pNetAddr->uAddr.IPv6.au8[1],
459 u.pNetAddr->uAddr.IPv6.au8[2],
460 u.pNetAddr->uAddr.IPv6.au8[3],
461 u.pNetAddr->uAddr.IPv6.au8[4],
462 u.pNetAddr->uAddr.IPv6.au8[5],
463 u.pNetAddr->uAddr.IPv6.au8[6],
464 u.pNetAddr->uAddr.IPv6.au8[7],
465 u.pNetAddr->uAddr.IPv6.au8[8],
466 u.pNetAddr->uAddr.IPv6.au8[9],
467 u.pNetAddr->uAddr.IPv6.au8[10],
468 u.pNetAddr->uAddr.IPv6.au8[11],
469 u.pNetAddr->uAddr.IPv6.au8[12],
470 u.pNetAddr->uAddr.IPv6.au8[13],
471 u.pNetAddr->uAddr.IPv6.au8[14],
472 u.pNetAddr->uAddr.IPv6.au8[15]);
473 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
474 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x %u",
475 u.pNetAddr->uAddr.IPv6.au8[0],
476 u.pNetAddr->uAddr.IPv6.au8[1],
477 u.pNetAddr->uAddr.IPv6.au8[2],
478 u.pNetAddr->uAddr.IPv6.au8[3],
479 u.pNetAddr->uAddr.IPv6.au8[4],
480 u.pNetAddr->uAddr.IPv6.au8[5],
481 u.pNetAddr->uAddr.IPv6.au8[6],
482 u.pNetAddr->uAddr.IPv6.au8[7],
483 u.pNetAddr->uAddr.IPv6.au8[8],
484 u.pNetAddr->uAddr.IPv6.au8[9],
485 u.pNetAddr->uAddr.IPv6.au8[10],
486 u.pNetAddr->uAddr.IPv6.au8[11],
487 u.pNetAddr->uAddr.IPv6.au8[12],
488 u.pNetAddr->uAddr.IPv6.au8[13],
489 u.pNetAddr->uAddr.IPv6.au8[14],
490 u.pNetAddr->uAddr.IPv6.au8[15],
491 u.pNetAddr->uPort);
492
493 case RTNETADDRTYPE_MAC:
494 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
495 "%02x:%02x:%02x:%02x:%02x:%02x",
496 u.pNetAddr->uAddr.Mac.au8[0],
497 u.pNetAddr->uAddr.Mac.au8[1],
498 u.pNetAddr->uAddr.Mac.au8[2],
499 u.pNetAddr->uAddr.Mac.au8[3],
500 u.pNetAddr->uAddr.Mac.au8[4],
501 u.pNetAddr->uAddr.Mac.au8[5]);
502
503 default:
504 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
505 "unsupported-netaddr-type=%u", u.pNetAddr->enmType);
506
507 }
508 }
509 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
510 }
511
512 case RTSF_UUID:
513 {
514 if (VALID_PTR(u.pUuid))
515 {
516 /* cannot call RTUuidToStr because of GC/R0. */
517 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
518 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
519 u.pUuid->Gen.u32TimeLow,
520 u.pUuid->Gen.u16TimeMid,
521 u.pUuid->Gen.u16TimeHiAndVersion,
522 u.pUuid->Gen.u8ClockSeqHiAndReserved,
523 u.pUuid->Gen.u8ClockSeqLow,
524 u.pUuid->Gen.au8Node[0],
525 u.pUuid->Gen.au8Node[1],
526 u.pUuid->Gen.au8Node[2],
527 u.pUuid->Gen.au8Node[3],
528 u.pUuid->Gen.au8Node[4],
529 u.pUuid->Gen.au8Node[5]);
530 }
531 return pfnOutput(pvArgOutput, s_szNull, sizeof(s_szNull) - 1);
532 }
533
534 default:
535 AssertMsgFailed(("Internal error %d\n", s_aTypes[i].enmFormat));
536 return 0;
537 }
538
539 /*
540 * Finally, output the formatted string and return.
541 */
542 return pfnOutput(pvArgOutput, szBuf, cch);
543 }
544
545
546 /* Group 3 */
547
548 /*
549 * Base name printing.
550 */
551 case 'b':
552 {
553 switch (*(*ppszFormat)++)
554 {
555 case 'n':
556 {
557 const char *pszLastSep;
558 const char *psz = pszLastSep = va_arg(*pArgs, const char *);
559 if (!VALID_PTR(psz))
560 return pfnOutput(pvArgOutput, "<null>", sizeof("<null>") - 1);
561
562 while ((ch = *psz) != '\0')
563 {
564 if (RTPATH_IS_SEP(ch))
565 {
566 do
567 psz++;
568 while ((ch = *psz) != '\0' && RTPATH_IS_SEP(ch));
569 if (!ch)
570 break;
571 pszLastSep = psz;
572 }
573 psz++;
574 }
575
576 return pfnOutput(pvArgOutput, pszLastSep, psz - pszLastSep);
577 }
578
579 default:
580 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
581 break;
582 }
583 break;
584 }
585
586
587 /*
588 * Pretty function / method name printing.
589 */
590 case 'f':
591 {
592 switch (*(*ppszFormat)++)
593 {
594 /*
595 * Pretty function / method name printing.
596 * This isn't 100% right (see classic signal prototype) and it assumes
597 * standardized names, but it'll do for today.
598 */
599 case 'n':
600 {
601 const char *pszStart;
602 const char *psz = pszStart = va_arg(*pArgs, const char *);
603 if (!VALID_PTR(psz))
604 return pfnOutput(pvArgOutput, "<null>", sizeof("<null>") - 1);
605
606 while ((ch = *psz) != '\0' && ch != '(')
607 {
608 if (RT_C_IS_BLANK(ch))
609 {
610 psz++;
611 while ((ch = *psz) != '\0' && (RT_C_IS_BLANK(ch) || ch == '('))
612 psz++;
613 if (ch)
614 pszStart = psz;
615 }
616 else if (ch == '(')
617 break;
618 else
619 psz++;
620 }
621
622 return pfnOutput(pvArgOutput, pszStart, psz - pszStart);
623 }
624
625 default:
626 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
627 break;
628 }
629 break;
630 }
631
632
633 /*
634 * hex dumping and COM/XPCOM.
635 */
636 case 'h':
637 {
638 switch (*(*ppszFormat)++)
639 {
640 /*
641 * Hex stuff.
642 */
643 case 'x':
644 {
645 uint8_t *pu8 = va_arg(*pArgs, uint8_t *);
646 if (cchPrecision <= 0)
647 cchPrecision = 16;
648 if (pu8)
649 {
650 switch (*(*ppszFormat)++)
651 {
652 /*
653 * Regular hex dump.
654 */
655 case 'd':
656 {
657 int off = 0;
658 cch = 0;
659
660 if (cchWidth <= 0)
661 cchWidth = 16;
662
663 while (off < cchPrecision)
664 {
665 int i;
666 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s%0*x %04x:", off ? "\n" : "", sizeof(pu8) * 2, (uintptr_t)pu8, off);
667 for (i = 0; i < cchWidth && off + i < cchPrecision ; i++)
668 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0,
669 off + i < cchPrecision ? !(i & 7) && i ? "-%02x" : " %02x" : " ", pu8[i]);
670 while (i++ < cchWidth)
671 cch += pfnOutput(pvArgOutput, " ", 3);
672
673 cch += pfnOutput(pvArgOutput, " ", 1);
674
675 for (i = 0; i < cchWidth && off + i < cchPrecision; i++)
676 {
677 uint8_t u8 = pu8[i];
678 cch += pfnOutput(pvArgOutput, u8 < 127 && u8 >= 32 ? (const char *)&u8 : ".", 1);
679 }
680
681 /* next */
682 pu8 += cchWidth;
683 off += cchWidth;
684 }
685 return cch;
686 }
687
688 /*
689 * Hex string.
690 */
691 case 's':
692 {
693 if (cchPrecision-- > 0)
694 {
695 cch = RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%02x", *pu8++);
696 for (; cchPrecision > 0; cchPrecision--, pu8++)
697 cch += RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, " %02x", *pu8);
698 return cch;
699 }
700 break;
701 }
702
703 default:
704 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
705 break;
706 }
707 }
708 else
709 return pfnOutput(pvArgOutput, "<null>", sizeof("<null>") - 1);
710 break;
711 }
712
713
714#ifdef IN_RING3
715 /*
716 * XPCOM / COM status code: %Rhrc, %Rhrf, %Rhra
717 * ASSUMES: If Windows Then COM else XPCOM.
718 */
719 case 'r':
720 {
721 uint32_t hrc = va_arg(*pArgs, uint32_t);
722 PCRTCOMERRMSG pMsg = RTErrCOMGet(hrc);
723 switch (*(*ppszFormat)++)
724 {
725 case 'c':
726 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
727 case 'f':
728 return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
729 case 'a':
730 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, hrc, pMsg->pszMsgFull);
731 default:
732 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
733 return 0;
734 }
735 break;
736 }
737#endif /* IN_RING3 */
738
739 default:
740 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
741 return 0;
742
743 }
744 break;
745 }
746
747 /*
748 * iprt status code: %Rrc, %Rrs, %Rrf, %Rra.
749 */
750 case 'r':
751 {
752 int rc = va_arg(*pArgs, int);
753#ifdef IN_RING3 /* we don't want this anywhere else yet. */
754 PCRTSTATUSMSG pMsg = RTErrGet(rc);
755 switch (*(*ppszFormat)++)
756 {
757 case 'c':
758 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
759 case 's':
760 return pfnOutput(pvArgOutput, pMsg->pszMsgShort, strlen(pMsg->pszMsgShort));
761 case 'f':
762 return pfnOutput(pvArgOutput, pMsg->pszMsgFull, strlen(pMsg->pszMsgFull));
763 case 'a':
764 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (%d) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
765 default:
766 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
767 return 0;
768 }
769#else /* !IN_RING3 */
770 switch (*(*ppszFormat)++)
771 {
772 case 'c':
773 case 's':
774 case 'f':
775 case 'a':
776 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%d", rc);
777 default:
778 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
779 return 0;
780 }
781#endif /* !IN_RING3 */
782 break;
783 }
784
785#if defined(IN_RING3)
786 /*
787 * Windows status code: %Rwc, %Rwf, %Rwa
788 */
789 case 'w':
790 {
791 long rc = va_arg(*pArgs, long);
792# if defined(RT_OS_WINDOWS)
793 PCRTWINERRMSG pMsg = RTErrWinGet(rc);
794# endif
795 switch (*(*ppszFormat)++)
796 {
797# if defined(RT_OS_WINDOWS)
798 case 'c':
799 return pfnOutput(pvArgOutput, pMsg->pszDefine, strlen(pMsg->pszDefine));
800 case 'f':
801 return pfnOutput(pvArgOutput, pMsg->pszMsgFull,strlen(pMsg->pszMsgFull));
802 case 'a':
803 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "%s (0x%08X) - %s", pMsg->pszDefine, rc, pMsg->pszMsgFull);
804# else
805 case 'c':
806 case 'f':
807 case 'a':
808 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "0x%08X", rc);
809# endif
810 default:
811 AssertMsgFailed(("Invalid status code format type '%.10s'!\n", pszFormatOrg));
812 return 0;
813 }
814 break;
815 }
816#endif /* IN_RING3 */
817
818 /*
819 * Group 4, structure dumpers.
820 */
821 case 'D':
822 {
823 /*
824 * Interpret the type.
825 */
826 typedef enum
827 {
828 RTST_TIMESPEC
829 } RTST;
830/** Set if it's a pointer */
831#define RTST_FLAGS_POINTER RT_BIT(0)
832 static const struct
833 {
834 uint8_t cch; /**< the length of the string. */
835 char sz[16-2]; /**< the part following 'R'. */
836 uint8_t cb; /**< the size of the argument. */
837 uint8_t fFlags; /**< RTST_FLAGS_* */
838 RTST enmType; /**< The structure type. */
839 }
840 /** Sorted array of types, looked up using binary search! */
841 s_aTypes[] =
842 {
843#define STRMEM(str) sizeof(str) - 1, str
844 { STRMEM("Dtimespec"), sizeof(PCRTTIMESPEC), RTST_FLAGS_POINTER, RTST_TIMESPEC},
845#undef STRMEM
846 };
847 const char *pszType = *ppszFormat - 1;
848 int iStart = 0;
849 int iEnd = RT_ELEMENTS(s_aTypes) - 1;
850 int i = RT_ELEMENTS(s_aTypes) / 2;
851
852 union
853 {
854 const void *pv;
855 uint64_t u64;
856 PCRTTIMESPEC pTimeSpec;
857 } u;
858
859 AssertMsg(!chArgSize, ("Not argument size '%c' for RT types! '%.10s'\n", chArgSize, pszFormatOrg));
860
861 /*
862 * Lookup the type - binary search.
863 */
864 for (;;)
865 {
866 int iDiff = strncmp(pszType, s_aTypes[i].sz, s_aTypes[i].cch);
867 if (!iDiff)
868 break;
869 if (iEnd == iStart)
870 {
871 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
872 return 0;
873 }
874 if (iDiff < 0)
875 iEnd = i - 1;
876 else
877 iStart = i + 1;
878 if (iEnd < iStart)
879 {
880 AssertMsgFailed(("Invalid format type '%.10s'!\n", pszFormatOrg));
881 return 0;
882 }
883 i = iStart + (iEnd - iStart) / 2;
884 }
885 *ppszFormat += s_aTypes[i].cch - 1;
886
887 /*
888 * Fetch the argument.
889 */
890 u.u64 = 0;
891 switch (s_aTypes[i].cb)
892 {
893 case sizeof(const void *):
894 u.pv = va_arg(*pArgs, const void *);
895 break;
896 default:
897 AssertMsgFailed(("Invalid format error, size %d'!\n", s_aTypes[i].cb));
898 break;
899 }
900
901 /*
902 * If it's a pointer, we'll check if it's valid before going on.
903 */
904 if ((s_aTypes[i].fFlags & RTST_FLAGS_POINTER) && !VALID_PTR(u.pv))
905 return pfnOutput(pvArgOutput, "<null>", sizeof("<null>") - 1);
906
907 /*
908 * Format the output.
909 */
910 switch (s_aTypes[i].enmType)
911 {
912 case RTST_TIMESPEC:
913 return RTStrFormat(pfnOutput, pvArgOutput, NULL, NULL, "%'lld ns", RTTimeSpecGetNano(u.pTimeSpec));
914
915 default:
916 AssertMsgFailed(("Invalid/unhandled enmType=%d\n", s_aTypes[i].enmType));
917 break;
918 }
919 break;
920 }
921
922#ifdef IN_RING3
923 /*
924 * Group 5, XML / HTML escapers.
925 */
926 case 'M':
927 {
928 char chWhat = (*ppszFormat)[0];
929 bool fAttr = chWhat == 'a';
930 char chType = (*ppszFormat)[1];
931 AssertMsgBreak(chWhat == 'a' || chWhat == 'e', ("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
932 *ppszFormat += 2;
933 switch (chType)
934 {
935 case 's':
936 {
937 static const char s_szElemEscape[] = "<>&\"'";
938 static const char s_szAttrEscape[] = "<>&\"\n\r"; /* more? */
939 const char * const pszEscape = fAttr ? s_szAttrEscape : s_szElemEscape;
940 size_t const cchEscape = (fAttr ? RT_ELEMENTS(s_szAttrEscape) : RT_ELEMENTS(s_szElemEscape)) - 1;
941 size_t cchOutput = 0;
942 const char *pszStr = va_arg(*pArgs, char *);
943 ssize_t cchStr;
944 ssize_t offCur;
945 ssize_t offLast;
946
947 if (!VALID_PTR(pszStr))
948 pszStr = "<NULL>";
949 cchStr = RTStrNLen(pszStr, (unsigned)cchPrecision);
950
951 if (fAttr)
952 cchOutput += pfnOutput(pvArgOutput, "\"", 1);
953 if (!(fFlags & RTSTR_F_LEFT))
954 while (--cchWidth >= cchStr)
955 cchOutput += pfnOutput(pvArgOutput, " ", 1);
956
957 offLast = offCur = 0;
958 while (offCur < cchStr)
959 {
960 if (memchr(pszEscape, pszStr[offCur], cchEscape))
961 {
962 if (offLast < offCur)
963 cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
964 switch (pszStr[offCur])
965 {
966 case '<': cchOutput += pfnOutput(pvArgOutput, "&lt;", 4); break;
967 case '>': cchOutput += pfnOutput(pvArgOutput, "&gt;", 4); break;
968 case '&': cchOutput += pfnOutput(pvArgOutput, "&amp;", 5); break;
969 case '\'': cchOutput += pfnOutput(pvArgOutput, "&apos;", 6); break;
970 case '"': cchOutput += pfnOutput(pvArgOutput, "&quot;", 6); break;
971 case '\n': cchOutput += pfnOutput(pvArgOutput, "&#xA;", 5); break;
972 case '\r': cchOutput += pfnOutput(pvArgOutput, "&#xD;", 5); break;
973 default:
974 AssertFailed();
975 }
976 offLast = offCur + 1;
977 }
978 offCur++;
979 }
980 if (offLast < offCur)
981 cchOutput += pfnOutput(pvArgOutput, &pszStr[offLast], offCur - offLast);
982
983 while (--cchWidth >= cchStr)
984 cchOutput += pfnOutput(pvArgOutput, " ", 1);
985 if (fAttr)
986 cchOutput += pfnOutput(pvArgOutput, "\"", 1);
987 return cchOutput;
988 }
989
990 default:
991 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
992 }
993 break;
994 }
995#endif /* IN_RING3 */
996
997
998 /*
999 * Groups 6 - CPU Architecture Register Formatters.
1000 * "%RAarch[reg]"
1001 */
1002 case 'A':
1003 {
1004 char const * const pszArch = *ppszFormat;
1005 const char *pszReg = pszArch;
1006 size_t cchOutput = 0;
1007 int cPrinted = 0;
1008 size_t cchReg;
1009
1010 /* Parse out the */
1011 while ((ch = *pszReg++) && ch != '[')
1012 { /* nothing */ }
1013 AssertMsgBreak(ch == '[', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
1014
1015 cchReg = 0;
1016 while ((ch = pszReg[cchReg]) && ch != ']')
1017 cchReg++;
1018 AssertMsgBreak(ch == ']', ("Malformed IPRT architecture register format type '%.10s'!\n", pszFormatOrg));
1019
1020 *ppszFormat = &pszReg[cchReg + 1];
1021
1022
1023#define REG_EQUALS(a_szReg) (sizeof(a_szReg) - 1 == cchReg && !strncmp(a_szReg, pszReg, sizeof(a_szReg) - 1))
1024#define REG_OUT_BIT(a_uVal, a_fBitMask, a_szName) \
1025 do { \
1026 if ((a_uVal) & (a_fBitMask)) \
1027 { \
1028 if (!cPrinted++) \
1029 cchOutput += pfnOutput(pvArgOutput, "{" a_szName, sizeof(a_szName)); \
1030 else \
1031 cchOutput += pfnOutput(pvArgOutput, "," a_szName, sizeof(a_szName)); \
1032 (a_uVal) &= ~(a_fBitMask); \
1033 } \
1034 } while (0)
1035#define REG_OUT_CLOSE(a_uVal) \
1036 do { \
1037 if ((a_uVal)) \
1038 { \
1039 cchOutput += pfnOutput(pvArgOutput, !cPrinted ? "{unkn=" : ",unkn=", 6); \
1040 cch = RTStrFormatNumber(&szBuf[0], (a_uVal), 16, 1, -1, fFlags); \
1041 cchOutput += pfnOutput(pvArgOutput, szBuf, cch); \
1042 cPrinted++; \
1043 } \
1044 if (cPrinted) \
1045 cchOutput += pfnOutput(pvArgOutput, "}", 1); \
1046 } while (0)
1047
1048
1049 if (0)
1050 { /* dummy */ }
1051#ifdef STRFORMAT_WITH_X86
1052 /*
1053 * X86 & AMD64.
1054 */
1055 else if ( pszReg - pszArch == 3 + 1
1056 && pszArch[0] == 'x'
1057 && pszArch[1] == '8'
1058 && pszArch[2] == '6')
1059 {
1060 if (REG_EQUALS("cr0"))
1061 {
1062 uint64_t cr0 = va_arg(*pArgs, uint64_t);
1063 fFlags |= RTSTR_F_64BIT;
1064 cch = RTStrFormatNumber(&szBuf[0], cr0, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
1065 cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
1066 REG_OUT_BIT(cr0, X86_CR0_PE, "PE");
1067 REG_OUT_BIT(cr0, X86_CR0_MP, "MP");
1068 REG_OUT_BIT(cr0, X86_CR0_EM, "EM");
1069 REG_OUT_BIT(cr0, X86_CR0_TS, "DE");
1070 REG_OUT_BIT(cr0, X86_CR0_ET, "ET");
1071 REG_OUT_BIT(cr0, X86_CR0_NE, "NE");
1072 REG_OUT_BIT(cr0, X86_CR0_WP, "WP");
1073 REG_OUT_BIT(cr0, X86_CR0_AM, "AM");
1074 REG_OUT_BIT(cr0, X86_CR0_NW, "NW");
1075 REG_OUT_BIT(cr0, X86_CR0_CD, "CD");
1076 REG_OUT_BIT(cr0, X86_CR0_PG, "PG");
1077 REG_OUT_CLOSE(cr0);
1078 }
1079 else if (REG_EQUALS("cr4"))
1080 {
1081 uint64_t cr4 = va_arg(*pArgs, uint64_t);
1082 fFlags |= RTSTR_F_64BIT;
1083 cch = RTStrFormatNumber(&szBuf[0], cr4, 16, 8, -1, fFlags | RTSTR_F_ZEROPAD);
1084 cchOutput += pfnOutput(pvArgOutput, szBuf, cch);
1085 REG_OUT_BIT(cr4, X86_CR4_VME, "VME");
1086 REG_OUT_BIT(cr4, X86_CR4_PVI, "PVI");
1087 REG_OUT_BIT(cr4, X86_CR4_TSD, "TSD");
1088 REG_OUT_BIT(cr4, X86_CR4_DE, "DE");
1089 REG_OUT_BIT(cr4, X86_CR4_PSE, "PSE");
1090 REG_OUT_BIT(cr4, X86_CR4_PAE, "PAE");
1091 REG_OUT_BIT(cr4, X86_CR4_MCE, "MCE");
1092 REG_OUT_BIT(cr4, X86_CR4_PGE, "PGE");
1093 REG_OUT_BIT(cr4, X86_CR4_PCE, "PCE");
1094 REG_OUT_BIT(cr4, X86_CR4_OSFSXR, "OSFSXR");
1095 REG_OUT_BIT(cr4, X86_CR4_OSXMMEEXCPT, "OSXMMEEXCPT");
1096 REG_OUT_BIT(cr4, X86_CR4_VMXE, "VMXE");
1097 REG_OUT_BIT(cr4, X86_CR4_SMXE, "SMXE");
1098 REG_OUT_BIT(cr4, X86_CR4_PCIDE, "PCIDE");
1099 REG_OUT_BIT(cr4, X86_CR4_OSXSAVE, "OSXSAVE");
1100 REG_OUT_BIT(cr4, X86_CR4_SMEP, "SMPE");
1101 REG_OUT_CLOSE(cr4);
1102 }
1103 else
1104 AssertMsgFailed(("Unknown x86 register specified in '%.10s'!\n", pszFormatOrg));
1105 }
1106#endif
1107 else
1108 AssertMsgFailed(("Unknown architecture specified in '%.10s'!\n", pszFormatOrg));
1109#undef REG_OUT_BIT
1110#undef REG_OUT_CLOSE
1111#undef REG_EQUALS
1112 return cchOutput;
1113 }
1114
1115 /*
1116 * Invalid/Unknown. Bitch about it.
1117 */
1118 default:
1119 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1120 break;
1121 }
1122 }
1123 else
1124 AssertMsgFailed(("Invalid IPRT format type '%.10s'!\n", pszFormatOrg));
1125
1126 NOREF(pszFormatOrg);
1127 return 0;
1128}
1129
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette