1 martin 1.22 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.23 //
|
3 martin 1.22 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.23 //
|
10 martin 1.22 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.23 //
|
17 martin 1.22 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.23 //
|
20 martin 1.22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.23 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.23 //
|
28 martin 1.22 //////////////////////////////////////////////////////////////////////////
|
29 chuck 1.2 //
30 //%/////////////////////////////////////////////////////////////////////////////
|
31 lucier 1.7
|
32 chuck 1.2 #include <Pegasus/CQL/CQLUtilities.h>
|
33 lucier 1.7
34 // Query includes
35 #include <Pegasus/Query/QueryCommon/QueryException.h>
36
37 // Pegasus Common includes
38 #include <Pegasus/Common/Tracer.h>
|
39 ajay.rao 1.26 #include <Pegasus/Common/StringConversion.h>
|
40 lucier 1.7
41 // standard includes
|
42 chuck 1.3 #include <errno.h>
|
43 chuck 1.2
|
44 lucier 1.7 // symbol defines
|
45 chuck 1.2
|
46 lucier 1.7 // required for the windows compile
|
47 lucier 1.5 #ifndef _MSC_VER
48 #define _MSC_VER 0
49 #endif
50
|
51 chuck 1.2 PEGASUS_NAMESPACE_BEGIN
52
|
53 ajay.rao 1.26 const char CQLUtilities::KEY[] = "CQL.CQLUtilities.INVALID_STRING";
54 const char CQLUtilities::MSG[] = "Error converting string to $0. "
55 " String '$1' is invalid or causes an overflow ";
|
56 chuck 1.2
57 Uint64 CQLUtilities::stringToUint64(const String &stringNum)
58 {
|
59 karl 1.19 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToUint64()");
60 Uint64 x = 0;
|
61 ajay.rao 1.26 CString cstrNum = stringNum.getCString();
62 const char *p = (const char*)cstrNum;
63 const char *pstart = p;
64 Boolean isError = false;
65 Uint32 endStr = 0;
|
66 kumpf 1.24
|
67 ajay.rao 1.26 if (*p)
|
68 karl 1.19 {
|
69 ajay.rao 1.26 endStr = stringNum.size() - 1;
|
70 chuck 1.2 }
71
|
72 kumpf 1.24 // If the string is a real number, use stringToReal, then convert to
|
73 karl 1.19 // a Uint64
74 if (isReal(stringNum))
|
75 lucier 1.7 {
|
76 karl 1.19 // Note: the cast will rip off any non-whole number precision.
|
77 kumpf 1.24 // CQL spec is silent on whether to round up, round down, throw an
78 // error, or allow the platform to round as it sees fit.
|
79 karl 1.19 // We chose the latter for now.
80 return (Uint64) stringToReal64(stringNum);
|
81 lucier 1.7 }
|
82 chuck 1.2
|
83 ajay.rao 1.26 if (*p == '+')
|
84 chuck 1.2 {
|
85 ajay.rao 1.26 ++p;
|
86 chuck 1.2 }
87
|
88 ajay.rao 1.26 // There cannot be a negative '-' sign or empty string
89 if (*p == '-' || !*p)
90 {
91 isError = true;
92 }
93 else if (!((*p >= '0') && (*p <= '9')))
|
94 lucier 1.7 {
|
95 ajay.rao 1.26 isError = true;
|
96 karl 1.19 }
97 // if hexidecimal
|
98 ajay.rao 1.26 else if ( ((*p == '0') && ((p[1] == 'x') || (p[1] == 'X'))))
|
99 karl 1.19 {
|
100 ajay.rao 1.26 if (!StringConversion::hexStringToUint64(p,x,true))
101 {
102 isError = true;
103 }
104 }
105 else if (pstart[endStr] == 'b' || pstart[endStr] == 'B')
106 {
107 if (!StringConversion::binaryStringToUint64(p,x,true))
108 {
109 isError = true;
110 }
111 }
112 else if (!StringConversion::decimalStringToUint64(p,x,true))
|
113 karl 1.19 {
|
114 ajay.rao 1.26 isError = true;
|
115 lucier 1.7 }
|
116 ajay.rao 1.26 // return the value for the decimal string
117 if(isError)
|
118 karl 1.19 {
|
119 ajay.rao 1.26 MessageLoaderParms mload(
120 CQLUtilities::KEY,
121 CQLUtilities::MSG,
122 "Uint64",
123 stringNum);
124 throw CQLRuntimeException(mload);
|
125 lucier 1.7 }
|
126 ajay.rao 1.26 else
|
127 karl 1.19 {
|
128 ajay.rao 1.26 PEG_METHOD_EXIT();
129 return x;
|
130 karl 1.19 }
|
131 chuck 1.2 }
132
133 Sint64 CQLUtilities::stringToSint64(const String &stringNum)
134 {
|
135 karl 1.19 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToSint64()");
136 Sint64 x = 0;
|
137 ajay.rao 1.26 CString cstrNum = stringNum.getCString();
138 const char *p = (const char*)cstrNum;
139 const char* pstart = p;
140 Boolean isError = false;
141 Uint32 endStr = 0;
|
142 kumpf 1.24
|
143 ajay.rao 1.26 if (*p)
|
144 karl 1.19 {
|
145 ajay.rao 1.26 endStr = stringNum.size() - 1;
|
146 chuck 1.2 }
147
|
148 kumpf 1.24 // If the string is a real number, use stringToReal, then convert to
|
149 karl 1.19 // a Sint64
150 if (isReal(stringNum))
|
151 lucier 1.7 {
|
152 kumpf 1.24 // Note: the cast will rip off any non-whole number precision.
|
153 karl 1.19 // CQL spec is silent on whether to round up, round down, throw
|
154 kumpf 1.24 // an error, or allow the platform to round as it sees fit.
|
155 karl 1.19 // We chose the latter for now.
156 return (Sint64) stringToReal64(stringNum);
|
157 lucier 1.7 }
|
158 kumpf 1.24
|
159 karl 1.19 // skip over the sign if there is one
|
160 ajay.rao 1.26 if ((*p == '-')||(*p == '+'))
|
161 chuck 1.2 {
|
162 karl 1.19 p++;
|
163 chuck 1.2 }
|
164 kumpf 1.24
|
165 ajay.rao 1.26 if (!(*p >= '0') && (*p <= '9'))
|
166 karl 1.19 {
|
167 ajay.rao 1.26 isError = true;
|
168 karl 1.19 }
169
170 // ********************
171 // Build the Sint64 as a negative number, regardless of the
172 // eventual sign (negative numbers can be bigger than positive ones)
173 // ********************
|
174 kumpf 1.24
|
175 karl 1.19 // if hexidecimal
|
176 ajay.rao 1.26 else if ( (*p == '0') && (p[1] == 'x') || (p[1] == 'X'))
|
177 karl 1.19 {
178 // Convert a hexadecimal string
|
179 ajay.rao 1.26 if (!StringConversion::stringToSint64(
180 (const char *)(stringNum.getCString()),
181 StringConversion::hexStringToUint64,
182 x))
|
183 karl 1.19 {
|
184 ajay.rao 1.26 isError = true;
|
185 karl 1.19 }
186
|
187 ajay.rao 1.26 // return value from the hex string
|
188 kumpf 1.24
189 } // end if hexidecimal
|
190 karl 1.19
191 // if binary
|
192 ajay.rao 1.26
193 else if ( (pstart[endStr] == 'b') || (pstart[endStr] == 'B') )
|
194 karl 1.19 {
|
195 chuck 1.2 // Add on each digit, checking for overflow errors
|
196 ajay.rao 1.26 if (!StringConversion::stringToSint64(
197 (const char *)(stringNum.getCString()),
198 StringConversion::binaryStringToUint64,
199 x))
200 {
201 isError = true;
202 }
|
203 karl 1.19
|
204 ajay.rao 1.26 // return value from the binary string
|
205 karl 1.19
|
206 ajay.rao 1.26 } // end if binary
|
207 kumpf 1.24
|
208 ajay.rao 1.26 // Expect a positive decimal digit:
|
209 chuck 1.2
210
|
211 ajay.rao 1.26 else if (!StringConversion::stringToSint64(
212 (const char *)(stringNum.getCString()),
213 StringConversion::decimalStringToUint64,
214 x))
|
215 chuck 1.2 {
|
216 ajay.rao 1.26 isError = true;
|
217 chuck 1.2 }
|
218 ajay.rao 1.26 if(isError)
|
219 lucier 1.7 {
|
220 ajay.rao 1.26 MessageLoaderParms mload(
221 CQLUtilities::KEY,
222 CQLUtilities::MSG,
223 "Sint64",
224 stringNum);
225 throw CQLRuntimeException(mload);
|
226 karl 1.19
|
227 lucier 1.7 }
|
228 ajay.rao 1.26 else
|
229 lucier 1.7 {
|
230 ajay.rao 1.26 PEG_METHOD_EXIT();
231 return x;
|
232 lucier 1.7 }
|
233 chuck 1.2
234 }
235
236 Real64 CQLUtilities::stringToReal64(const String &stringNum)
237 {
|
238 karl 1.19 PEG_METHOD_ENTER(TRC_CQL,"CQLUtilities::stringToReal64()");
|
239 kumpf 1.24
|
240 karl 1.19 Real64 x = 0;
|
241 ajay.rao 1.26 CString cstrNum = stringNum.getCString();
242 const char *p = (const char*)cstrNum;
|
243 karl 1.19 Boolean neg = false;
|
244 kumpf 1.24
|
245 karl 1.19 if (*p == '-')
246 {
247 neg = true;
|
248 ajay.rao 1.26 }
249 if(!isReal(stringNum))
|
250 karl 1.19 {
|
251 ajay.rao 1.26 // Check if it it is a binary or hex integer
252 Uint32 endString = stringNum.size() - 1;
|
253 karl 1.19 if (neg)
254 x = stringToSint64(stringNum);
255 else
|
256 chuck 1.2
|
257 karl 1.19 // Check if the complier is MSVC 6, which does not support the conversion
|
258 kumpf 1.24 // operator from Uint64 to Real64
|
259 lucier 1.5 #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) && (_MSC_VER < 1300)
|
260 ajay.rao 1.26 {
261 Uint64 num = stringToUint64(stringNum);
262 Sint64 half = num / 2;
263 x = half;
264 x += half;
265 if (num % 2) // if odd, then add the lost remainder
266 x += 1;
267 }
|
268 lucier 1.5 #else
|
269 karl 1.19 x = stringToUint64(stringNum);
|
270 kumpf 1.24 #endif
|
271 karl 1.19 PEG_METHOD_EXIT();
272 return x;
|
273 kumpf 1.24 }
274
|
275 karl 1.19 //
276 // Do the conversion
277 //
|
278 ajay.rao 1.26 if (!StringConversion::stringToReal64(
279 (const char *)(stringNum.getCString()),
280 x))
281 {
282 MessageLoaderParms mload(
283 CQLUtilities::KEY,
284 CQLUtilities::MSG,
285 "Real64",
286 stringNum);
287 throw CQLRuntimeException(mload);
|
288 chuck 1.2 }
|
289 karl 1.19 PEG_METHOD_EXIT();
290 // printf("String %s = %.16e\n", (const char *)stringNum.getCString(), x);
291 return x;
|
292 chuck 1.2 }
293
|
294 lucier 1.11 String CQLUtilities::formatRealStringExponent(const String &realString)
295 {
|
296 karl 1.19 String newString(realString);
297 Uint32 expIndex = PEG_NOT_FOUND;
298 Uint32 index = newString.size() - 1;
|
299 kumpf 1.24
|
300 karl 1.19 expIndex = newString.find('E');
301 if (expIndex == PEG_NOT_FOUND)
302 expIndex = newString.find('e');
|
303 kumpf 1.24
|
304 karl 1.19 if (expIndex == PEG_NOT_FOUND)
305 return newString; // no exponent symbol, so just return
|
306 kumpf 1.24
|
307 karl 1.19 // format the exponent
308 index = expIndex + 1; // start index at next character
309 if (newString[index] == '+')
310 newString.remove(index, 1); // remove the '+' symbol
|
311 kumpf 1.24
|
312 karl 1.19 if (newString[index] == '-')
313 index++; // skip the '-' exponent sign
|
314 kumpf 1.24
|
315 karl 1.19 while (newString[index] == '0' && index < newString.size())
316 {
317 newString.remove(index, 1);
318 }
|
319 kumpf 1.24
|
320 karl 1.19 // If only an 'e' is left (only 0's behind it) then strip the 'e'
321 if (index >= newString.size())
322 newString.remove(expIndex, 1);
|
323 kumpf 1.24
|
324 karl 1.19 return newString;
|
325 lucier 1.11 }
326
|
327 humberto 1.12 Boolean CQLUtilities::isReal(const String &numString)
328 {
|
329 karl 1.19 // If there is a decimal point, we consider it to be a real.
330 if (numString.find('.') == PEG_NOT_FOUND)
331 return false;
332 return true;
|
333 humberto 1.12 }
334
|
335 chuck 1.2 PEGASUS_NAMESPACE_END
|