Skip to content

Commit 134558f

Browse files
committed
double-conversion floating-point conversions
- using double-conversion library for floating-point numeric/string conversions - added string replace[InPlace], remove[InPlace] - reverted overwritten FileChannel purge age and count features - file size value checks in SMTPClient
1 parent 9dd1482 commit 134558f

13 files changed

Lines changed: 370 additions & 291 deletions

File tree

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ CPackSourceConfig.cmake
4343

4444
# Logs and databases #
4545
######################
46-
*.log
46+
*.log*
4747
*.sqlite
4848
*.db
4949
test*.txt
50+
XML/testsuite/rss.xml
5051

5152
# OS generated files #
5253
######################

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
This is the changelog file for the POCO C++ Libraries.
22

3+
Release 1.5.0 (2012-12-17)
4+
==========================
5+
- using double-conversion library for floating-point numeric/string conversions
36

47
Release 1.5.0 (2012-10-14)
58
==========================

Foundation/include/Poco/Config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@
139139

140140
// Windows CE has no locale support
141141
#if defined(_WIN32_WCE)
142-
#define POCO_NO_LOCALE
142+
#define POCO_NO_LOCALE
143143
#endif
144144

145145

Foundation/include/Poco/FileChannel.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ class Foundation_API FileChannel: public Channel
161161
/// * <n> weeks: the maximum age is <n> weeks.
162162
/// * <n> months: the maximum age is <n> months, where a month has 30 days.
163163
///
164-
/// The purgeCount property has an integer value that
165-
/// specifies the maximum number of archived log files.
166-
/// If the number is exceeded, archived log files are
167-
/// deleted, starting with the oldest.
164+
/// The purgeCount property has an integer value that specifies the maximum number
165+
/// of archived log files. If the number is exceeded, archived log files are
166+
/// deleted, starting with the oldest. When "none" or empty string are
167+
/// supplied, they reset purgeCount to none (no purging).
168168
///
169169
/// The flush property specifies whether each log message is flushed
170170
/// immediately to the log file (which may hurt application performance,

Foundation/include/Poco/NumericString.h

Lines changed: 29 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,12 @@
5555
#include <locale>
5656
#endif
5757

58-
// TODO:
59-
// POCO version is fast but simplistic, hence less accurate, undef this for
60-
// double-conversion library use in string => float/double conversions (T.B.D.)
61-
// (double-conversion library is always used for float/double => string)
62-
#define POCO_STR_TO_FLOAT_FAST
6358

6459
#define POCO_MAX_INT_STRING_LEN 65
6560
#define POCO_MAX_FLT_STRING_LEN 128
61+
#define POCO_FLT_INF "inf"
62+
#define POCO_FLT_NAN "nan"
63+
#define POCO_FLT_EXP 'e'
6664

6765

6866
namespace Poco {
@@ -210,173 +208,6 @@ bool strToInt(const std::string& str, I& result, short base, char thSep = ',')
210208
{
211209
return strToInt(str.c_str(), result, base, thSep);
212210
}
213-
214-
215-
namespace Impl {
216-
217-
static char DUMMY_EXP_UNDERFLOW; // dummy default val
218-
219-
}
220-
221-
222-
template <typename F>
223-
bool strToFloat (const char* pStr, F& result, char& eu = Impl::DUMMY_EXP_UNDERFLOW, char decSep = '.', char thSep = ',')
224-
/// Converts zero-terminated array to floating-point number;
225-
/// Returns true if succesful. Exponent underflow (i.e. loss of precision due to exponent value)
226-
/// is signalled in eu. Thousand separators are recognized for the locale
227-
/// and silently skipped but not verified for correct positioning.
228-
///
229-
/// If parsing was unsuccesful, the return value is false with
230-
/// result and eu values undetermined.
231-
/// This function will perform fast but significant rounding errors may occur after
232-
/// the platform precision is exceeded.
233-
/// For better precision conversion, use double-conversion wrappers (strToFloatDC and strToDoubleDC).
234-
{
235-
#ifndef POCO_STR_TO_FLOAT_FAST
236-
// TODO: for high-precision, use double-conversion here
237-
#else
238-
poco_assert (decSep != thSep);
239-
240-
if (pStr == 0 || *pStr == '\0') return false;
241-
242-
// parser states:
243-
const char STATE_LEADING_SPACES = 0;
244-
const char STATE_DIGITS_BEFORE_DEC_POINT = 1;
245-
const char STATE_DIGITS_AFTER_DEC_POINT = 2;
246-
const char STATE_EXP_CHAR = 3;
247-
const char STATE_EXP_DIGITS = 4;
248-
const char STATE_SUFFIX = 5; // 'f' suffix
249-
250-
char numSign = 1, expSign = 1;
251-
char state = STATE_LEADING_SPACES;
252-
F mantissa = 0.0, exponent = 0.0, pow10 = 1.0;
253-
254-
result = 0.0;
255-
eu = 0;
256-
for (; *pStr != '\0'; ++pStr)
257-
{
258-
switch (*pStr)
259-
{
260-
case '.':
261-
if (decSep == '.')
262-
{
263-
if (state >= STATE_DIGITS_AFTER_DEC_POINT) return false;
264-
state = STATE_DIGITS_AFTER_DEC_POINT;
265-
break;
266-
}
267-
else if ((thSep == '.') && (state == STATE_DIGITS_BEFORE_DEC_POINT))
268-
break;
269-
else
270-
return false;
271-
272-
case ',':
273-
if (decSep == ',')
274-
{
275-
if (state >= STATE_DIGITS_AFTER_DEC_POINT) return false;
276-
state = STATE_DIGITS_AFTER_DEC_POINT;
277-
break;
278-
}
279-
else if ((thSep == ',') && (state == STATE_DIGITS_BEFORE_DEC_POINT))
280-
break;
281-
else
282-
return false;
283-
284-
case ' ': // space (SPC)
285-
if ((thSep == ' ') && (state == STATE_DIGITS_BEFORE_DEC_POINT)) break;
286-
case '\t': // horizontal tab (TAB)
287-
case '\n': // line feed (LF)
288-
case '\v': // vertical tab (VT)
289-
case '\f': // form feed (FF)
290-
case '\r': // carriage return (CR)
291-
if ((state >= STATE_DIGITS_AFTER_DEC_POINT) || (state >= STATE_EXP_DIGITS))
292-
break;
293-
else if ((state > STATE_LEADING_SPACES) && (state < STATE_DIGITS_AFTER_DEC_POINT))
294-
return false;
295-
break;
296-
297-
case '-':
298-
if (state == STATE_LEADING_SPACES)
299-
numSign = -1;
300-
else if (state == STATE_EXP_CHAR) // exponential char
301-
expSign = -1;
302-
else return false;
303-
case '+':
304-
break;
305-
306-
case '0':
307-
case '1':
308-
case '2':
309-
case '3':
310-
case '4':
311-
case '5':
312-
case '6':
313-
case '7':
314-
case '8':
315-
case '9':
316-
if (state >= STATE_SUFFIX) return false; // constant suffix
317-
if (state <= STATE_DIGITS_BEFORE_DEC_POINT) // integral part digits
318-
{
319-
result = result * 10 + (*pStr - '0');
320-
state = STATE_DIGITS_BEFORE_DEC_POINT;
321-
}
322-
else if (state <= STATE_DIGITS_AFTER_DEC_POINT) // fractional part digits
323-
{
324-
mantissa += F(*pStr - '0') / (pow10 *= 10.);
325-
state = STATE_DIGITS_AFTER_DEC_POINT;
326-
}
327-
else if (state <= STATE_EXP_DIGITS) // exponent digits
328-
{
329-
exponent = exponent * 10. + (*pStr - '0');
330-
state = STATE_EXP_DIGITS;
331-
}
332-
else return false;
333-
break;
334-
335-
case 'E':
336-
case 'e':
337-
if (state > STATE_DIGITS_AFTER_DEC_POINT) return false;
338-
state = STATE_EXP_CHAR;
339-
break;
340-
341-
case 'F':
342-
case 'f':
343-
state = STATE_SUFFIX;
344-
break;
345-
346-
default:
347-
return false;
348-
}
349-
}
350-
351-
if (exponent > std::numeric_limits<F>::max_exponent10)
352-
{
353-
eu = expSign;
354-
exponent = std::numeric_limits<F>::max_exponent10;
355-
}
356-
357-
result += mantissa;
358-
if (numSign != 1) result *= numSign;
359-
if (exponent > 1.0)
360-
{
361-
F scale = std::pow(10., exponent);
362-
result = (expSign < 0) ? (result / scale) : (result * scale);
363-
}
364-
365-
return (state != STATE_LEADING_SPACES) && // empty/zero-length string
366-
!FPEnvironment::isInfinite(result) &&
367-
!FPEnvironment::isNaN(result);
368-
#endif // POCO_STR_TO_FLOAT_FAST
369-
}
370-
371-
372-
template <typename F>
373-
bool strToFloat (const std::string& s, F& result, char& eu = Impl::DUMMY_EXP_UNDERFLOW, char decSep = '.', char thSep = ',')
374-
/// Converts string to floating-point number;
375-
/// This is a wrapper function, for details see see the
376-
/// bool strToFloat(const char*, F&, char&, char, char) implementation.
377-
{
378-
return strToFloat(s.c_str(), result, eu, decSep, thSep);
379-
}
380211

381212

382213
//
@@ -636,12 +467,10 @@ bool uIntToStr (T number, unsigned short base, std::string& result, bool prefix
636467

637468

638469
//
639-
// Functions using double-conversion library (http://code.google.com/p/double-conversion/).
640-
// Library is the implementation of the Grisu algorithm as described in Florian Loitsch's paper:
641-
// http://florian.loitsch.com/publications/dtoa-pldi2010.pdf
470+
// Wrappers for double-conversion library (http://code.google.com/p/double-conversion/).
642471
//
643-
// For a complete (and simpler) story on floating-point numbers rendering accuracy and performance, see:
644-
// http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/
472+
// Library is the implementation of the algorithm described in Florian Loitsch's paper:
473+
// http://florian.loitsch.com/publications/dtoa-pldi2010.pdf
645474
//
646475

647476
Foundation_API void floatToStr(char* buffer,
@@ -688,12 +517,31 @@ Foundation_API std::string& doubleToStr(std::string& str,
688517
/// precision (total number of digits after the decimal point) and width (total length of formatted string).
689518

690519

691-
Foundation_API float strToFloatDC(const char* str);
692-
/// For testing and performance comparison purposes only.
520+
Foundation_API float strToFloat(const char* str);
521+
/// Converts the string of characters into single-precision floating point number.
522+
/// Function uses double_convesrion::DoubleToStringConverter to do the conversion.
523+
524+
525+
Foundation_API bool strToFloat(const std::string&, float& result, char decSep = '.', char thSep = ',');
526+
/// Converts the string of characters into single-precision floating point number.
527+
/// The conversion result is assigned to the result parameter.
528+
/// If decimal separator and/or thousand separator are different from defaults, they should be
529+
/// supplied to ensure proper conversion.
530+
///
531+
/// Returns true if succesful, false otherwise.
532+
533+
534+
Foundation_API double strToDouble(const char* str);
535+
/// Converts the string of characters into double-precision floating point number.
693536

694537

695-
Foundation_API double strToDoubleDC(const char* str);
696-
/// For testing and performance comparison purposes only.
538+
Foundation_API bool strToDouble(const std::string& str, double& result, char decSep = '.', char thSep = ',');
539+
/// Converts the string of characters into double-precision floating point number.
540+
/// The conversion result is assigned to the result parameter.
541+
/// If decimal separator and/or thousand separator are different from defaults, they should be
542+
/// supplied to ensure proper conversion.
543+
///
544+
/// Returns true if succesful, false otherwise.
697545

698546
//
699547
// end double-conversion functions declarations

Foundation/include/Poco/String.h

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -482,21 +482,32 @@ S& replaceInPlace(S& str, const typename S::value_type* from, const typename S::
482482

483483

484484
template <class S>
485-
S& replaceInPlace(S& str, const typename S::value_type from, const typename S::value_type to, typename S::size_type start = 0)
485+
S& replaceInPlace(S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
486486
{
487487
if (from == to) return str;
488488

489489
typename S::size_type pos = 0;
490490
do
491491
{
492492
pos = str.find(from, start);
493-
if (pos != S::npos) str[pos] = to;
493+
if (pos != S::npos)
494+
{
495+
if (to) str[pos] = to;
496+
else str.erase(pos, 1);
497+
}
494498
} while (pos != S::npos);
495499

496500
return str;
497501
}
498502

499503

504+
template <class S>
505+
S& removeInPlace(S& str, const typename S::value_type ch, typename S::size_type start = 0)
506+
{
507+
return replaceInPlace(str, ch, 0, start);
508+
}
509+
510+
500511
template <class S>
501512
S replace(const S& str, const S& from, const S& to, typename S::size_type start = 0)
502513
/// Replace all occurences of from (which must not be the empty string)
@@ -517,14 +528,36 @@ S replace(const S& str, const typename S::value_type* from, const typename S::va
517528
}
518529

519530

531+
template <class S>
532+
S replace(const S& str, const typename S::value_type from, const typename S::value_type to = 0, typename S::size_type start = 0)
533+
{
534+
S result(str);
535+
replaceInPlace(result, from, to, start);
536+
return result;
537+
}
538+
539+
540+
template <class S>
541+
S remove(const S& str, const typename S::value_type ch, typename S::size_type start = 0)
542+
{
543+
S result(str);
544+
replaceInPlace(result, ch, 0, start);
545+
return result;
546+
}
547+
548+
520549
#else
521550

522551

523-
std::string Foundation_API replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
524-
std::string Foundation_API replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
525-
std::string& Foundation_API replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
526-
std::string& Foundation_API replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
527-
552+
Foundation_API std::string replace(const std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
553+
Foundation_API std::string replace(const std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
554+
Foundation_API std::string replace(const std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
555+
Foundation_API std::string remove(const std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
556+
Foundation_API std::string& replaceInPlace(std::string& str, const std::string& from, const std::string& to, std::string::size_type start = 0);
557+
Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type* from, const std::string::value_type* to, std::string::size_type start = 0);
558+
Foundation_API std::string& replaceInPlace(std::string& str, const std::string::value_type from, const std::string::value_type to = 0, std::string::size_type start = 0);
559+
Foundation_API std::string& removeInPlace(std::string& str, const std::string::value_type ch, std::string::size_type start = 0);
560+
528561

529562
#endif
530563

0 commit comments

Comments
 (0)