#ifndef _GATS_UTILITIES_HPP_
#define _GATS_UTILITIES_HPP_
/**
@file GATS_Utilities.hpp
@brief Provides prototypes and code for a collection of useful functions that needed a home.
@date $Date$
@version $Rev$
@author
- Lance Deaver
@copyright
(©) Copyright 2006 by GATS Inc.
11864 Canon Blvd., Suite 101, Newport News, VA 23606
All Rights Reserved. No part of this software or publication may be
reproduced, stored in a retrieval system, or transmitted, in any form
or by any means, electronic, mechanical, photocopying, recording, or
otherwise without the prior written permission of GATS Inc.
@bug None known
@todo add EXPORT so windows users can build DLL with decspcl
$Id$
*/
#include "GATS_Exception.h"
#include
#include
#include
#include
#include
#include
#include
namespace GATS_Utilities {
/**
* @brief Processes the data in the input string and outputs a data type T.
*
* This function receives a std::string s, a ios_base
* operator, and a boolean indicating its strictness in accepting
* non-valid characters and converts the string into the data type T.
*
* @param[in] s A std::string containing the data you which to convert to type T.
* @param[in] std::ios_base& A std::ios_base method which controls the casting. Usually
* you would pass in std::dec, or std::scientific, but std::hex is another option. Is it
* clear I really don't know much about this parameter?
* @param[in] failIfLeftoverChars A boolean that controls if the conversion can still be
* if there are non-valid characters in the string. Default is true.
*
* @retval T The converted value.
*
* @exception BadTypeConversion The conversion from string into another data type was not successful.
*
*/
template
T ConvertFromString(const std::string& s, std::ios_base& (*f)(std::ios_base&),
const bool failIfLeftoverChars=true )
{
T t;
char c;
std::istringstream iss(s);
if ((iss >> f >> t).fail() || ( failIfLeftoverChars && iss.get(c))) {
std::string k =std::string("ConvertFromString: Tried to convert \"") + s
+ "\" to a \"" + std::string(typeid(T).name() ) + "\"";
THROW_GATS_EXCEPTION(BadTypeConversion, k.c_str() );
}
return t;
}
/**
* @brief Takes a packed byte string and converts it to std::vector
*
* This function accepts a const char* and a length and places this data into
* a std::vector of type T.
*
* @param[in] C A const char* pointing to the data you want in the vector
* @param[in] length The length of the data referenced by C in bytes.
*
* @retval std::vector The vector of type T containing the data.
*
* @exception BadTypeConversion The conversion into a std::vector was not successful.
*
*/
template
std::vector ConvertToVector(const char* C, const size_t length)
{
if(C == NULL) {
THROW_GATS_EXCEPTION(BadTypeConversion, "ConvertToVector: Tried converting a NULL pointer" );
}
if(length == 0 || length % sizeof(T) != 0 ) {
std::string k =std::string("ConvertToVector: length parameter is zero or a non-even multiple of sizeof(")+
std::string(typeid(T).name() ) + ")";
THROW_GATS_EXCEPTION(BadTypeConversion, k.c_str() );
}
const T *p = reinterpret_cast(C); //(T*)C;
return std::vector(p,p+length/sizeof(T) );
}
/**
* @brief Takes a value of type T and places it in a string
*
* This function uses the std::ostringstream operators place a data value
* of type T into a std::string.
*
* @note You should use ConvertToStringPrec to cast float type variables which
* gives an additional parameter which controls the number of significant digits to
* retain.
*
* @param[in] val A data value of type T.
*
* @retval std::string The string containing the data value representation.
*
* @exception BadTypeConversion The conversion into a string was not successful.
*/
template
std::string ConvertToString(const T& val) {
std::ostringstream myStream;
if( (myStream << val << std::flush).fail() ) {
std::string k =std::string("ConvertToString: Error converting a \"")
+ std::string(typeid(T).name() ) + "\" to a std::string";
THROW_GATS_EXCEPTION(BadTypeConversion, k.c_str() );
}
return myStream.str();
}
/**
* @brief Takes a value of type T and places it in a string maintaining a number of significant digits.
*
* This function uses the std::ostringstream operators place a data value
* of type T into a std::string.
*
* @note You should use this function when casting float type data types.
* generally using the following values defined in are adequate.
* @li sigdigits=std::numeric_limits::digits10 for float values.
* @li sigdigits=std::numeric_limits::digits10 for double values.
* @li sigdigits=std::numeric_limits::digits10 for long double values.
*
* @param[in] val A data value of type T.
* @param[in] sigdigits The number of significant digits to maintain while converting.
*
* @retval std::string The string containing the data value representation.
*
* @exception BadTypeConversion The conversion into a string was not successful.
*/
template
std::string ConvertToStringPrec(const T& val, const unsigned int sigdigits=std::numeric_limits::digits10 ) {
std::ostringstream myStream;
if( (myStream << std::setprecision(sigdigits) << val << std::flush).fail() ) {
std::ostringstream g;
g << sigdigits;
std::string k =std::string("ConvertToStringPrec: Error converting a \"")
+ std::string(typeid(T).name() ) + "\" to a std::string using precision= " + g.str();
THROW_GATS_EXCEPTION(BadTypeConversion, k.c_str() );
}
return myStream.str();
}
/**
* @brief A templated function that will indicate if a container is monotonic.
*
* This function receives a beginning iterator, an ending iterator and a predicate and returns a bool
* which indicates if the values between the two iterators are monotonic. Based on the
* predicate it is possible to the check for strictly montotonically increasing or decreasing values or
* allow two or more adjancent values to equal the same value. Original source from here
* http://home.arcor.de/ghorwin/html/en/cpp.html. An example
* @li vector V = Something_Returning_A_Vector();
* @li if(monotonic_if(V.begin(),V.end(), std::greater() ) { cout << "V is strictly monotonically decreasing" << endl;}
*
* @param[in] first A std::iterator which contains the first value to check for monotonicity.
* @param[in] last A std::iterator which contains the last value to check for monotonicity.
* @param[in] pred A a predicate which controls how the monotonicity is checked. Usually something like
* std::greater(), std::less_equal() assuming the container holds type double.
*
* @retval bool Indicates if the monotonic_if check was true or false.
*/
template
bool monotonic_if(InputIt first, InputIt last, Predicate pred) {
if (first==last) return true;
typename std::iterator_traits::value_type lastValue = *first;
while (++first != last) {
if (!pred(lastValue, *first)) return false;
lastValue = *first;
};
return true;
}
template
std::string Implode(InputIt first, InputIt last, std::string delim=", ") {
std::string S;
if (first == last) return S;
typename std::iterator_traits::value_type value = *first;
while(++first != last) {
S += ConvertToString( value ) + delim;
value = *first;
}
S += ConvertToString( value );
return S;
}
} //namespace
#endif //_GATS_UTILITIES_HPP_