source: trunk/dll/commafmt.c@ 1036

Last change on this file since 1036 was 907, checked in by Steven Levine, 18 years ago

Avoid out of memory traps in Compare Directories
Rework Compare Directories progress display for 2 second update rate
Start refactoring to reduce dependence on fm3dll.h
Add timer services (IsITimerExpired etc.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.2 KB
Line 
1
2/***********************************************************************
3
4 $Id: commafmt.c 907 2008-01-06 07:26:17Z stevenhl $
5
6 Command formatting tools
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2004, 2005 Steven H. Levine
10
11 06 Jan 04 SHL Disable hundfmt, clean commafmt
12 25 May 05 SHL Drop hundfmt
13 25 May 05 SHL Add CommaFmtULL, CommaFmtUL
14 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
15 05 Nov 07 GKY Use commafmtULL to display file sizes for large file support
16 10 Nov 07 GKY Get thousands separator from country info for file sizes.
17
18***********************************************************************/
19
20/*
21 * COMMAFMT.C
22 * Adapted from public domain code by Bob Stout
23 *
24 * 2. By making the numeric argument a long and prototyping it before
25 * use, passed numeric arguments will be implicitly cast to longs
26 * thereby avoiding int overflow.
27 * 3. Use the thousands grouping and thousands separator from the
28 * ANSI locale to make this more robust.
29 */
30
31#include <string.h>
32
33#include "fm3dll.h"
34
35size_t commafmt(char *pszBuf, // Output buffer
36 UINT cBufSize, // Buffer size, including nul
37 long lNumber) // Number to convert
38{
39 UINT cChars = 1; // Number of characters generated (excluding nul)
40 UINT cDigits = 1; // For commas
41 INT sign = 1;
42
43 char *pch = pszBuf + cBufSize - 1;
44
45 if (cBufSize < 2)
46 goto ABORT;
47
48 *pch-- = 0; // Stuff terminator
49 --cBufSize;
50 if (lNumber < 0) {
51 sign = -1;
52 lNumber = -lNumber;
53 }
54
55 for (; cChars <= cBufSize; ++cChars, ++cDigits) {
56 *pch-- = (CHAR)(lNumber % 10 + '0');
57 lNumber /= 10;
58 if (!lNumber)
59 break;
60 if (cDigits % 3 == 0) {
61 *pch-- = *ThousandsSeparator;
62 ++cChars;
63 }
64 if (cChars >= cBufSize)
65 goto ABORT;
66 } // for
67
68 if (sign < 0) {
69 if (cBufSize == 0)
70 goto ABORT;
71 *pch-- = '-';
72 ++cChars;
73 }
74
75 strcpy(pszBuf, ++pch); // Left align
76
77 return cChars;
78
79ABORT:
80 *pszBuf = 0;
81 return 0;
82}
83
84/**
85 * Format long long number with commas and SI unit suffix
86 * @param pszBuf Points to output buffer
87 * @param cBufSize Buffer size including space for terminating nul
88 * @param ullNumber Number to convert
89 * @param chPreferred Preferred suffix, blank, K, M
90 * @return size of formatting string excluding terminating nul
91 */
92
93size_t CommaFmtULL(char *pszBuf, // Output buffer
94 UINT cBufSize, // Buffer size, including nul
95 ULONGLONG ullNumber, // Number to convert
96 CHAR chPreferred) // Preferred suffix, blank, K, M, G
97{
98 CHAR chSuffix = ' ';
99 size_t c;
100
101 if (ullNumber >= 1ULL << 31 || (chPreferred != ' ' && ullNumber >= 1024)) {
102 ullNumber = (ullNumber + 1023) >> 10;
103 chSuffix = 'K';
104 if (ullNumber >= 1ULL << 31 || (chPreferred == 'M' && ullNumber >= 1024) ||
105 (chPreferred == 'G' && ullNumber >= 1024)) {
106 ullNumber = (ullNumber + 1023) >> 10;
107 chSuffix = 'M';
108 if (ullNumber >= 1ULL << 31 || (chPreferred == 'G' && ullNumber >= 1024)) {
109 ullNumber = (ullNumber + 1023) >> 10;
110 chSuffix = 'G';
111 }
112 }
113 }
114
115 c = commafmt(pszBuf, cBufSize, (LONG)ullNumber);
116
117 if (chSuffix != ' ') {
118 if (c + 4 > cBufSize) {
119 *pszBuf = 0;
120 c = 0;
121 }
122 else {
123 pszBuf += c;
124 *pszBuf++ = chSuffix;
125 *pszBuf++ = 'i';
126 *pszBuf++ = 'B';
127 c += 3;
128 *pszBuf = 0;
129 }
130 }
131 return c;
132}
133
134//=== CommaFmtUL: format unsigned long number with commas and SI unit suffix ===
135
136size_t CommaFmtUL(char *pszBuf, // Output buffer
137 UINT cBufSize, // Buffer size, including nul
138 ULONG ulNumber, // Number to convert
139 CHAR chPreferred) // Preferred suffix, blank, K, M
140{
141 CHAR chSuffix = ' ';
142 size_t c;
143
144 if (ulNumber >= 1ULL << 31 || (chPreferred != ' ' && ulNumber >= 1024)) {
145 ulNumber = (ulNumber + 1023) >> 10;
146 chSuffix = 'K';
147 if (ulNumber >= 1ULL << 31 || (chPreferred == 'M' && ulNumber >= 1024)) {
148 ulNumber = (ulNumber + 1023) >> 10;
149 chSuffix = 'M';
150 }
151 }
152
153 c = commafmt(pszBuf, cBufSize, ulNumber);
154
155 if (chSuffix != ' ') {
156 if (c + 4 > cBufSize) {
157 *pszBuf = 0;
158 c = 0;
159 }
160 else {
161 pszBuf += c;
162 *pszBuf++ = chSuffix;
163 *pszBuf++ = 'i';
164 *pszBuf++ = 'B';
165 c += 3;
166 *pszBuf = 0;
167 }
168 }
169 return c;
170}
171
172#pragma alloc_text(MISC8,commafmt,CommaFmtU64)
Note: See TracBrowser for help on using the repository browser.