You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
8.6 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software and the related documents are Intel copyrighted materials, and your
* use of them is governed by the express license under which they were provided to
* you ("License"). Unless the License provides otherwise, you may not use, modify,
* copy, publish, distribute, disclose or transmit this software or the related
* documents without Intel's prior written permission.
*
* This software and the related documents are provided as is, with no express or
* implied warranties, other than those that are expressly stated in the License.
*/
// <COMPONENT>: util
// <FILE-TYPE>: component public header
#ifndef UTIL_STRINGS_HPP
#define UTIL_STRINGS_HPP
#include <sstream>
#include <iomanip>
#include <cctype>
namespace UTIL {
/*!
* Convert an integral value to a decimal string.
*
* @param[in] val Integral value.
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a decimal integer.
*/
template<typename T> std::string GetDecString(T val, int width = 0)
{
std::ostringstream s;
s << std::dec << std::setfill('0') << std::setw(width) << val;
return s.str();
}
/*!
* Convert a pointer value to a decimal string.
*
* @param[in] val Pointer value.
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a decimal integer.
*/
template<typename T> std::string GetDecString(T * val, int width = 0)
{
return GetDecString(reinterpret_cast<uintptr_t>(val), width);
}
/*!
* Convert an integral value to a decimal string.
*
* @param[in] val Integral value.
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a decimal integer.
*/
template<typename T> std::wstring GetDecStringW(T val, int width = 0)
{
std::wostringstream s;
s << std::dec << std::setfill(L'0') << std::setw(width) << val;
return s.str();
}
/*!
* Convert a pointer value to a decimal string.
*
* @param[in] val Pointer value.
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a decimal integer.
*/
template<typename T> std::wstring GetDecStringW(T * val, int width = 0)
{
return GetDecStringW(reinterpret_cast<uintptr_t>(val), width);
}
/*!
* Convert an integral value to a hex string.
*
* @param[in] val Integral value.
* @param[in] showBase If TRUE, the string is prefix with "0x".
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a hex string.
*/
template<typename T> std::string GetHexString(T val, bool showBase = true,
int width = 0)
{
std::ostringstream s;
if (showBase)
s << "0x";
s << std::hex << std::noshowbase << std::setfill('0') << std::setw(width) << val;
return s.str();
}
/*!
* Convert a pointer value to a hex string.
*
* @param[in] val Pointer value.
* @param[in] showBase If TRUE, the string is prefix with "0x".
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a hex string.
*/
template<typename T> std::string GetHexString(T * val, bool showBase = true,
int width = 0)
{
return GetHexString(reinterpret_cast<uintptr_t>(val), showBase, width);
}
/*!
* Convert an integral value to a hex string.
*
* @param[in] val Integral value.
* @param[in] showBase If TRUE, the string is prefix with "0x".
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a hex string.
*/
template<typename T> std::wstring GetHexStringW(T val, bool showBase = true,
int width = 0)
{
std::wostringstream s;
if (showBase)
s << L"0x";
s << std::hex << std::noshowbase << std::setfill(L'0') << std::setw(width) << val;
return s.str();
}
/*!
* Convert a pointer value to a hex string.
*
* @param[in] val Pointer value.
* @param[in] showBase If TRUE, the string is prefix with "0x".
* @param[in] width If not zero, "0"'s are prefixed if the
* number has less than \a width digits.
*
* @return String representation of \a val as a hex string.
*/
template<typename T> std::wstring GetHexStringW(T * val, bool showBase = true,
int width = 0)
{
return GetHexStringW(reinterpret_cast<uintptr_t>(val), showBase, width);
}
/*!
* This function is similar to strtoul(), with two differences: 1) the type of
* the result is a template argument instead of hard-coded to "long", 2) the input
* is specified as two STL-style iterators into a sequence of items that are
* convertible to "char".
*
* Parse an unsigned integral value from a sequence of char's, or other items that
* are convertible to char. If the sequence starts with whitespace characters, it
* is skipped before any parsing is done.
*
* The \a base parameter specifies the radix to use when parsing the number and may
* be any value from 0 to 37. Each digit in the parsed number must be one of the
* characters '0' - '9 or 'a' - 'z' depending on the value of \a base. When \a base
* is greater than 10, digits may include the letters 'a' - 'z' in either upper or
* lower case.
*
* When \a base is zero, the radix is determined by the prefix of the input, after
* the initial whitespace has been ignored. If the prefix is "0x", the radix is 16.
* If the prefix is "0", the radix is 8. Otherwise, the radix is 10. When \a base
* is 16, the prefix "0x" is also allowed.
*
* This function fails if the input sequence (after ignoring initial whitespace)
* does not start with a valid number. The function also fails if the parsed number
* would overflow its type or if \a base is out or range.
*
* @param[in] start Input iterator to the start of the input sequence.
* @param[in] end Input iterator to the end of the input sequence.
* @param[in] base Tells the radix to use when parsing the value, which must
* be less than 37.
* @param[out] val On success, receives the parsed value.
*
* @return On success, an iterator that points to the first unparsed position in
* the sequence. On failure, this function returns \a start.
*/
template<typename InputIterator, typename T> InputIterator ParseUnsigned(
InputIterator first, InputIterator last, unsigned base, T *val)
{
// Make sure the radix is in range.
//
if (base > 37)
return first;
// Skip initial whitespace.
//
InputIterator it = first;
while (it != last && std::isspace(*it))
it++;
if (it == last)
return first;
InputIterator itAfterWs = it;
// See if there is a leading zero (e.g. the prefix is "0x" or "0").
//
bool zeroPending = false;
if (*it == '0')
{
zeroPending = true;
it++;
if (it == last)
{
*val = 0;
return it;
}
}
// Check for a "0x" prefix if the radix is 0 or 16.
//
if ((base == 16 || base == 0) && zeroPending && (*it == 'x' || *it == 'X'))
{
InputIterator it2 = it++;
if (it == last || !std::isxdigit(*it))
{
// If the prefix is "0x" with NO subsequent digits, parse the
// value zero and stop parsing before the "x".
//
*val = 0;
return it2;
}
base = 16;
}
if (base == 0)
base = (zeroPending) ? 8 : 10;
// Parse each digit.
//
T myVal = 0;
while (it != last)
{
char c = std::tolower(*it);
unsigned digit;
if (c >= '0' && c <= '9')
digit = c - '0';
else if (c >= 'a' && c <= 'z')
digit = 10 + c - 'a';
else
break;
if (digit >= base)
break;
T newVal = myVal * base + digit;
// Check for overflow.
//
if (((newVal - digit) / base) != myVal)
return first;
myVal = newVal;
it++;
}
// We must parse at least one digit for success.
//
if (it == itAfterWs)
return first;
*val = myVal;
return it;
}
} // namespace
#endif // file guard