VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strformatnum.cpp@ 94272

最後變更 在這個檔案從94272是 94261,由 vboxsync 提交於 3 年 前

iprt/types.h,VMM,ValKit,IPRT: Dropped the bit counts in member prefixes in the RTFLOATxxU types and added a RTFLOAT32U. Added some fld [mem] tests. bugref:9898

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 14.0 KB
 
1/* $Id: strformatnum.cpp 94261 2022-03-16 01:34:29Z vboxsync $ */
2/** @file
3 * IPRT - String Formatter, Single Numbers.
4 */
5
6/*
7 * Copyright (C) 2010-2022 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/assert.h>
36#include <iprt/errcore.h>
37#include "internal/string.h"
38
39
40RTDECL(ssize_t) RTStrFormatU8(char *pszBuf, size_t cbBuf, uint8_t u8Value, unsigned int uiBase,
41 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
42{
43 fFlags &= ~RTSTR_F_BIT_MASK;
44 fFlags |= RTSTR_F_8BIT;
45
46 ssize_t cchRet;
47 if (cbBuf >= 64)
48 cchRet = RTStrFormatNumber(pszBuf, u8Value, uiBase, cchWidth, cchPrecision, fFlags);
49 else
50 {
51 char szTmp[64];
52 cchRet = RTStrFormatNumber(szTmp, u8Value, uiBase, cchWidth, cchPrecision, fFlags);
53 if ((size_t)cchRet < cbBuf)
54 memcpy(pszBuf, szTmp, cchRet + 1);
55 else
56 {
57 if (cbBuf)
58 {
59 memcpy(pszBuf, szTmp, cbBuf - 1);
60 pszBuf[cbBuf - 1] = '\0';
61 }
62 cchRet = VERR_BUFFER_OVERFLOW;
63 }
64 }
65 return cchRet;
66}
67
68
69RTDECL(ssize_t) RTStrFormatU16(char *pszBuf, size_t cbBuf, uint16_t u16Value, unsigned int uiBase,
70 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
71{
72 fFlags &= ~RTSTR_F_BIT_MASK;
73 fFlags |= RTSTR_F_16BIT;
74
75 ssize_t cchRet;
76 if (cbBuf >= 64)
77 cchRet = RTStrFormatNumber(pszBuf, u16Value, uiBase, cchWidth, cchPrecision, fFlags);
78 else
79 {
80 char szTmp[64];
81 cchRet = RTStrFormatNumber(szTmp, u16Value, uiBase, cchWidth, cchPrecision, fFlags);
82 if ((size_t)cchRet < cbBuf)
83 memcpy(pszBuf, szTmp, cchRet + 1);
84 else
85 {
86 if (cbBuf)
87 {
88 memcpy(pszBuf, szTmp, cbBuf - 1);
89 pszBuf[cbBuf - 1] = '\0';
90 }
91 cchRet = VERR_BUFFER_OVERFLOW;
92 }
93 }
94 return cchRet;
95}
96
97
98RTDECL(ssize_t) RTStrFormatU32(char *pszBuf, size_t cbBuf, uint32_t u32Value, unsigned int uiBase,
99 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
100{
101 fFlags &= ~RTSTR_F_BIT_MASK;
102 fFlags |= RTSTR_F_32BIT;
103
104 ssize_t cchRet;
105 if (cbBuf >= 64)
106 cchRet = RTStrFormatNumber(pszBuf, u32Value, uiBase, cchWidth, cchPrecision, fFlags);
107 else
108 {
109 char szTmp[64];
110 cchRet = RTStrFormatNumber(szTmp, u32Value, uiBase, cchWidth, cchPrecision, fFlags);
111 if ((size_t)cchRet < cbBuf)
112 memcpy(pszBuf, szTmp, cchRet + 1);
113 else
114 {
115 if (cbBuf)
116 {
117 memcpy(pszBuf, szTmp, cbBuf - 1);
118 pszBuf[cbBuf - 1] = '\0';
119 }
120 cchRet = VERR_BUFFER_OVERFLOW;
121 }
122 }
123 return cchRet;
124}
125
126
127RTDECL(ssize_t) RTStrFormatU64(char *pszBuf, size_t cbBuf, uint64_t u64Value, unsigned int uiBase,
128 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
129{
130 fFlags &= ~RTSTR_F_BIT_MASK;
131 fFlags |= RTSTR_F_64BIT;
132
133 ssize_t cchRet;
134 if (cbBuf >= 64)
135 cchRet = RTStrFormatNumber(pszBuf, u64Value, uiBase, cchWidth, cchPrecision, fFlags);
136 else
137 {
138 char szTmp[64];
139 cchRet = RTStrFormatNumber(szTmp, u64Value, uiBase, cchWidth, cchPrecision, fFlags);
140 if ((size_t)cchRet < cbBuf)
141 memcpy(pszBuf, szTmp, cchRet + 1);
142 else
143 {
144 if (cbBuf)
145 {
146 memcpy(pszBuf, szTmp, cbBuf - 1);
147 pszBuf[cbBuf - 1] = '\0';
148 }
149 cchRet = VERR_BUFFER_OVERFLOW;
150 }
151 }
152 return cchRet;
153}
154
155
156RTDECL(ssize_t) RTStrFormatU128(char *pszBuf, size_t cbBuf, PCRTUINT128U pu128, unsigned int uiBase,
157 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
158{
159 NOREF(cchWidth); NOREF(cchPrecision);
160 if (uiBase != 16)
161 fFlags |= RTSTR_F_SPECIAL;
162 fFlags &= ~RTSTR_F_BIT_MASK;
163
164 char szTmp[64+32+32+32];
165 char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
166 size_t cchResult = RTStrFormatNumber(pszTmp, pu128->QWords.qw1, 16, 0, 0, fFlags | RTSTR_F_64BIT);
167 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu128->QWords.qw0, 16, 8, 0,
168 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
169 if (pszTmp == pszBuf)
170 return cchResult;
171 int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
172 if (RT_SUCCESS(rc))
173 return cchResult;
174 return rc;
175}
176
177
178RTDECL(ssize_t) RTStrFormatU256(char *pszBuf, size_t cbBuf, PCRTUINT256U pu256, unsigned int uiBase,
179 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
180{
181 NOREF(cchWidth); NOREF(cchPrecision);
182 if (uiBase != 16)
183 fFlags |= RTSTR_F_SPECIAL;
184 fFlags &= ~RTSTR_F_BIT_MASK;
185
186 char szTmp[64+32+32+32];
187 char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
188 size_t cchResult = RTStrFormatNumber(pszTmp, pu256->QWords.qw3, 16, 0, 0, fFlags | RTSTR_F_64BIT);
189 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw2, 16, 8, 0,
190 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
191 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw1, 16, 8, 0,
192 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
193 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu256->QWords.qw0, 16, 8, 0,
194 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
195 if (pszTmp == pszBuf)
196 return cchResult;
197 int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
198 if (RT_SUCCESS(rc))
199 return cchResult;
200 return rc;
201}
202
203
204RTDECL(ssize_t) RTStrFormatU512(char *pszBuf, size_t cbBuf, PCRTUINT512U pu512, unsigned int uiBase,
205 signed int cchWidth, signed int cchPrecision, uint32_t fFlags)
206{
207 NOREF(cchWidth); NOREF(cchPrecision);
208 if (uiBase != 16)
209 fFlags |= RTSTR_F_SPECIAL;
210 fFlags &= ~RTSTR_F_BIT_MASK;
211
212 char szTmp[64+32+32+32 + 32+32+32+32];
213 char *pszTmp = cbBuf >= sizeof(szTmp) ? pszBuf : szTmp;
214 size_t cchResult = RTStrFormatNumber(pszTmp, pu512->QWords.qw7, 16, 0, 0, fFlags | RTSTR_F_64BIT);
215 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw6, 16, 8, 0,
216 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
217 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw5, 16, 8, 0,
218 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
219 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw4, 16, 8, 0,
220 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
221 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw3, 16, 8, 0,
222 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
223 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw2, 16, 8, 0,
224 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
225 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw1, 16, 8, 0,
226 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
227 cchResult += RTStrFormatNumber(&pszTmp[cchResult], pu512->QWords.qw0, 16, 8, 0,
228 (fFlags | RTSTR_F_64BIT | RTSTR_F_ZEROPAD) & ~RTSTR_F_SPECIAL);
229 if (pszTmp == pszBuf)
230 return cchResult;
231 int rc = RTStrCopy(pszBuf, cbBuf, pszTmp);
232 if (RT_SUCCESS(rc))
233 return cchResult;
234 return rc;
235}
236
237
238/**
239 * Helper for rtStrFormatR80Worker that copies out the resulting string.
240 */
241static ssize_t rtStrFormatR80CopyOutStr(char *pszBuf, size_t cbBuf, const char *pszSrc, size_t cchSrc)
242{
243 if (cchSrc < cbBuf)
244 {
245 memcpy(pszBuf, pszSrc, cchSrc);
246 pszBuf[cchSrc] = '\0';
247 return cchSrc;
248 }
249 if (cbBuf)
250 {
251 memcpy(pszBuf, pszSrc, cbBuf - 1);
252 pszBuf[cbBuf - 1] = '\0';
253 }
254 return VERR_BUFFER_OVERFLOW;
255}
256
257
258/**
259 * Common worker for RTStrFormatR80 and RTStrFormatR80u2.
260 */
261static ssize_t rtStrFormatR80Worker(char *pszBuf, size_t cbBuf, bool const fSign, bool const fInteger,
262 uint64_t const uFraction, uint16_t const uExponent, uint32_t fFlags)
263{
264 char szTmp[160];
265
266 /*
267 * Output sign first.
268 */
269 char *pszTmp = szTmp;
270 if (fSign)
271 *pszTmp++ = '-';
272 else
273 *pszTmp++ = '+';
274
275 /*
276 * Then check for special numbers (indicated by expontent).
277 */
278 bool fDenormal = false;
279 if (uExponent == 0)
280 {
281 /* Zero? */
282 if ( !uFraction
283 && !fInteger)
284 return fSign
285 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+0"))
286 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-0"));
287 fDenormal = true;
288 }
289 else if (uExponent == UINT16_C(0x7fff))
290 {
291 if (!fInteger)
292 {
293 if (!uFraction)
294 return fSign
295 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+PseudoInf"))
296 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-PseudoInf"));
297 if (!(fFlags & RTSTR_F_SPECIAL))
298 return fSign
299 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+PseudoNan"))
300 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-PseudoNan"));
301 pszTmp = (char *)memcpy(pszTmp, "PseudoNan[", 10) + 10;
302 }
303 else if (!(uFraction & RT_BIT_64(62)))
304 {
305 if (!(uFraction & (RT_BIT_64(62) - 1)))
306 return fSign
307 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+Inf"))
308 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-Inf"));
309 if (!(fFlags & RTSTR_F_SPECIAL))
310 return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("Nan"));
311 pszTmp = (char *)memcpy(pszTmp, "Nan[", 4) + 4;
312 }
313 else
314 {
315 if (!(uFraction & (RT_BIT_64(62) - 1)))
316 return fSign
317 ? rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+Ind"))
318 : rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("-Ind"));
319 if (!(fFlags & RTSTR_F_SPECIAL))
320 return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("QNan"));
321 pszTmp = (char *)memcpy(pszTmp, "QNan[", 5) + 5;
322 }
323 pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + 16, 0,
324 RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
325 *pszTmp++ = ']';
326 return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, szTmp, pszTmp - &szTmp[0]);
327 }
328
329 /*
330 * Format the mantissa and exponent.
331 */
332 *pszTmp++ = fInteger ? '1' : '0';
333 *pszTmp++ = 'm';
334 pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2+16, 0,
335 RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
336
337 *pszTmp++ = '^';
338 pszTmp += RTStrFormatNumber(pszTmp, (int32_t)uExponent - 16383, 10, 0, 0,
339 RTSTR_F_ZEROPAD | RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
340 if (fDenormal && (fFlags & RTSTR_F_SPECIAL))
341 {
342 if (fInteger)
343 pszTmp = (char *)memcpy(pszTmp, "[PDn]", 5) + 5;
344 else
345 pszTmp = (char *)memcpy(pszTmp, "[Den]", 5) + 5;
346 }
347 return rtStrFormatR80CopyOutStr(pszBuf, cbBuf, szTmp, pszTmp - &szTmp[0]);
348}
349
350
351RTDECL(ssize_t) RTStrFormatR80u2(char *pszBuf, size_t cbBuf, PCRTFLOAT80U2 pr80Value, signed int cchWidth,
352 signed int cchPrecision, uint32_t fFlags)
353{
354 RT_NOREF(cchWidth, cchPrecision);
355#ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
356 return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->sj64.fSign, pr80Value->sj64.fInteger,
357 pr80Value->sj64.uFraction, pr80Value->sj64.uExponent, fFlags);
358#else
359 return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->sj.fSign, pr80Value->sj.fInteger,
360 RT_MAKE_U64(pr80Value->sj.u32FractionLow, pr80Value->sj.u31FractionHigh),
361 pr80Value->sj.uExponent, fFlags);
362#endif
363}
364
365
366RTDECL(ssize_t) RTStrFormatR80(char *pszBuf, size_t cbBuf, PCRTFLOAT80U pr80Value, signed int cchWidth,
367 signed int cchPrecision, uint32_t fFlags)
368{
369 RT_NOREF(cchWidth, cchPrecision);
370 return rtStrFormatR80Worker(pszBuf, cbBuf, pr80Value->s.fSign, pr80Value->s.uMantissa >> 63,
371 pr80Value->s.uMantissa & (RT_BIT_64(63) - 1), pr80Value->s.uExponent, fFlags);
372}
373
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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