VirtualBox

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

最後變更 在這個檔案從37966是 37966,由 vboxsync 提交於 14 年 前

testcase+fixes

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

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