#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_