VirtualBox

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

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

iprt: don't slurp <linux/module.h> here as the resulting other Linux headers conflict with our arch-specific headers

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

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