/src/mozilla-central/xpcom/string/nsTextFormatter.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | /* |
8 | | * This code was copied from xpcom/ds/nsTextFormatter r1.3 |
9 | | * Memory model and Frozen linkage changes only. |
10 | | * -- Prasad <prasad@medhas.org> |
11 | | */ |
12 | | |
13 | | #ifndef nsTextFormatter_h___ |
14 | | #define nsTextFormatter_h___ |
15 | | |
16 | | /* |
17 | | ** API for PR printf like routines. Supports the following formats |
18 | | ** %d - decimal |
19 | | ** %u - unsigned decimal |
20 | | ** %x - unsigned hex |
21 | | ** %X - unsigned uppercase hex |
22 | | ** %o - unsigned octal |
23 | | ** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above |
24 | | ** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above |
25 | | ** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above |
26 | | ** %s - utf8 string |
27 | | ** %S - char16_t string |
28 | | ** %c - character |
29 | | ** %p - pointer (deals with machine dependent pointer size) |
30 | | ** %f - float |
31 | | ** %g - float |
32 | | */ |
33 | | #include <stdio.h> |
34 | | #include <stdarg.h> |
35 | | #include "nscore.h" |
36 | | #include "nsString.h" |
37 | | #include "mozilla/Span.h" |
38 | | #include "mozilla/TypeTraits.h" |
39 | | |
40 | | #ifdef XPCOM_GLUE |
41 | | #error "nsTextFormatter is not available in the standalone glue due to NSPR dependencies." |
42 | | #endif |
43 | | |
44 | | class nsTextFormatter |
45 | | { |
46 | | public: |
47 | | |
48 | | /* |
49 | | * sprintf into a fixed size buffer. Guarantees that the buffer is null |
50 | | * terminated. Returns the length of the written output, NOT including the |
51 | | * null terminator, or (uint32_t)-1 if an error occurs. |
52 | | */ |
53 | | template<typename ...T> |
54 | | static uint32_t snprintf(char16_t* aOut, uint32_t aOutLen, const char16_t* aFmt, T... aArgs) { |
55 | | BoxedValue values[] = { BoxedValue(aArgs)... }; |
56 | | return vsnprintf(aOut, aOutLen, aFmt, mozilla::MakeSpan(values, sizeof...(aArgs))); |
57 | | } |
58 | | |
59 | | /* |
60 | | * sprintf into an existing nsAString, overwriting any contents it already |
61 | | * has. Infallible. |
62 | | */ |
63 | | template<typename ...T> |
64 | | static void ssprintf(nsAString& aOut, const char16_t* aFmt, T... aArgs) { |
65 | | BoxedValue values[] = { BoxedValue(aArgs)... }; |
66 | | vssprintf(aOut, aFmt, mozilla::MakeSpan(values, sizeof...(aArgs))); |
67 | | } |
68 | | |
69 | | private: |
70 | | |
71 | | enum ArgumentKind { |
72 | | INT, |
73 | | UINT, |
74 | | POINTER, |
75 | | DOUBLE, |
76 | | STRING, |
77 | | STRING16, |
78 | | INTPOINTER, |
79 | | }; |
80 | | |
81 | | union ValueUnion { |
82 | | int64_t mInt; |
83 | | uint64_t mUInt; |
84 | | void const* mPtr; |
85 | | double mDouble; |
86 | | char const* mString; |
87 | | char16_t const* mString16; |
88 | | int* mIntPtr; |
89 | | }; |
90 | | |
91 | | struct BoxedValue { |
92 | | ArgumentKind mKind; |
93 | | ValueUnion mValue; |
94 | | |
95 | | explicit BoxedValue(int aArg) |
96 | | : mKind(INT) |
97 | | { |
98 | | mValue.mInt = aArg; |
99 | | } |
100 | | |
101 | | explicit BoxedValue(unsigned int aArg) |
102 | | : mKind(UINT) |
103 | | { |
104 | | mValue.mUInt = aArg; |
105 | | } |
106 | | |
107 | | explicit BoxedValue(long aArg) |
108 | | : mKind(INT) |
109 | | { |
110 | | mValue.mInt = aArg; |
111 | | } |
112 | | |
113 | | explicit BoxedValue(unsigned long aArg) |
114 | | : mKind(UINT) |
115 | | { |
116 | | mValue.mUInt = aArg; |
117 | | } |
118 | | |
119 | | explicit BoxedValue(long long aArg) |
120 | | : mKind(INT) |
121 | 0 | { |
122 | 0 | mValue.mInt = aArg; |
123 | 0 | } |
124 | | |
125 | | explicit BoxedValue(unsigned long long aArg) |
126 | | : mKind(UINT) |
127 | 0 | { |
128 | 0 | mValue.mUInt = aArg; |
129 | 0 | } |
130 | | |
131 | | explicit BoxedValue(const void* aArg) |
132 | | : mKind(POINTER) |
133 | 0 | { |
134 | 0 | mValue.mPtr = aArg; |
135 | 0 | } |
136 | | |
137 | | explicit BoxedValue(double aArg) |
138 | | : mKind(DOUBLE) |
139 | | { |
140 | | mValue.mDouble = aArg; |
141 | | } |
142 | | |
143 | | explicit BoxedValue(const char* aArg) |
144 | | : mKind(STRING) |
145 | | { |
146 | | mValue.mString = aArg; |
147 | | } |
148 | | |
149 | | explicit BoxedValue(const char16_t* aArg) |
150 | | : mKind(STRING16) |
151 | 3 | { |
152 | 3 | mValue.mString16 = aArg; |
153 | 3 | } |
154 | | |
155 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
156 | | explicit BoxedValue(const char16ptr_t aArg) |
157 | | : mKind(STRING16) |
158 | | { |
159 | | mValue.mString16 = aArg; |
160 | | } |
161 | | |
162 | | #endif |
163 | | |
164 | | explicit BoxedValue(int* aArg) |
165 | | : mKind(INTPOINTER) |
166 | 0 | { |
167 | 0 | mValue.mIntPtr = aArg; |
168 | 0 | } |
169 | | |
170 | 0 | bool IntCompatible() const { |
171 | 0 | return mKind == INT || mKind == UINT; |
172 | 0 | } |
173 | | |
174 | 0 | bool PointerCompatible() const { |
175 | 0 | return mKind == POINTER || mKind == STRING || mKind == STRING16 || mKind == INTPOINTER; |
176 | 0 | } |
177 | | }; |
178 | | |
179 | | struct SprintfStateStr; |
180 | | |
181 | | static int fill2(SprintfStateStr* aState, const char16_t* aSrc, int aSrcLen, int aWidth, |
182 | | int aFlags); |
183 | | static int fill_n(SprintfStateStr* aState, const char16_t* aSrc, int aSrcLen, int aWidth, |
184 | | int aPrec, int aFlags); |
185 | | static int cvt_ll(SprintfStateStr* aState, uint64_t aNum, int aWidth, int aPrec, int aRadix, |
186 | | int aFlags, const char16_t* aHexStr); |
187 | | static int cvt_f(SprintfStateStr* aState, double aDouble, int aWidth, int aPrec, |
188 | | const char16_t aType, int aFlags); |
189 | | static int cvt_S(SprintfStateStr* aState, const char16_t* aStr, int aWidth, int aPrec, |
190 | | int aFlags); |
191 | | static int cvt_s(SprintfStateStr* aState, const char* aStr, int aWidth, int aPrec, |
192 | | int aFlags); |
193 | | static int dosprintf(SprintfStateStr* aState, const char16_t* aFmt, |
194 | | mozilla::Span<BoxedValue> aValues); |
195 | | static int StringStuff(SprintfStateStr* aState, const char16_t* aStr, uint32_t aLen); |
196 | | static int LimitStuff(SprintfStateStr* aState, const char16_t* aStr, uint32_t aLen); |
197 | | static uint32_t vsnprintf(char16_t* aOut, uint32_t aOutLen, const char16_t* aFmt, |
198 | | mozilla::Span<BoxedValue> aValues); |
199 | | static void vssprintf(nsAString& aOut, const char16_t* aFmt, |
200 | | mozilla::Span<BoxedValue> aValues); |
201 | | }; |
202 | | |
203 | | #endif /* nsTextFormatter_h___ */ |