blob: 91b30b5f9ec9523430df647e6cd08d113f14b447 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _IGNITE_COMMON_UTILS
#define _IGNITE_COMMON_UTILS
#include <stdint.h>
#include <cstring>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <ignite/common/common.h>
#include <ignite/common/platform_utils.h>
#include <ignite/date.h>
#include <ignite/timestamp.h>
#include "ignite/time.h"
#ifdef IGNITE_FRIEND
# define IGNITE_FRIEND_EXPORT IGNITE_EXPORT
#else
# define IGNITE_FRIEND_EXPORT
#endif
namespace ignite
{
namespace common
{
/**
* Replace all alphabetic symbols of the string with their lowercase
* versions.
* @param str String to be transformed.
*/
inline void IntoLower(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
/**
* Get lowercase version of the string.
*
* @param str Input string.
* @return Lowercased version of the string.
*/
inline std::string ToLower(const std::string& str)
{
std::string res(str);
IntoLower(res);
return res;
}
/**
* Replace all alphabetic symbols of the string with their uppercase
* versions.
* @param str String to be transformed.
*/
inline void IntoUpper(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}
/**
* Get uppercase version of the string.
*
* @param str Input string.
* @return Upper cased version of the string.
*/
inline std::string ToUpper(const std::string& str)
{
std::string res(str);
IntoUpper(res);
return res;
}
/**
* Strips leading and trailing whitespaces from string.
*
* @param str String to be transformed.
*/
IGNITE_IMPORT_EXPORT void StripSurroundingWhitespaces(std::string& str);
/**
* Skip leading spaces.
*
* @param begin Iterator to the beginning of the character sequence.
* @param end Iterator to the end of the character sequence.
* @return Iterator to first non-blanc character.
*/
template<typename Iterator>
Iterator SkipLeadingSpaces(Iterator begin, Iterator end)
{
Iterator res = begin;
while (isspace(*res) && res != end)
++res;
return res;
}
/**
* Skip trailing spaces.
*
* @param begin Iterator to the beginning of the character sequence.
* @param end Iterator to the end of the character sequence.
* @return Iterator to last non-blanc character.
*/
template<typename Iterator>
Iterator SkipTrailingSpaces(Iterator begin, Iterator end)
{
Iterator res = end - 1;
while (isspace(*res) && res != begin - 1)
--res;
return res + 1;
}
/**
* Remove leading and trailing spaces.
*
* @param begin Iterator to the beginning of the character sequence.
* @param end Iterator to the end of the character sequence.
* @return String without leading and trailing spaces.
*/
template<typename Iterator>
std::string StripSurroundingWhitespaces(Iterator begin, Iterator end)
{
std::string res;
if (begin >= end)
return res;
Iterator skipped_leading = SkipLeadingSpaces(begin, end);
Iterator skipped_trailing = SkipTrailingSpaces(skipped_leading, end);
res.reserve(skipped_trailing - skipped_leading);
std::copy(skipped_leading, skipped_trailing, std::back_inserter(res));
return res;
}
/**
* Get string representation of long in decimal form.
*
* @param val Long value to be converted to string.
* @return String contataining decimal representation of the value.
*/
inline std::string LongToString(long val)
{
std::stringstream tmp;
tmp << val;
return tmp.str();
}
/**
* Parse string to try and get int value.
*
* @param str String to be parsed.
* @return String contataining decimal representation of the value.
*/
inline int ParseInt(const std::string& str)
{
return atoi(str.c_str());
}
/**
* Copy characters.
*
* @param val Value.
* @return Result.
*/
IGNITE_IMPORT_EXPORT char* CopyChars(const char* val);
/**
* Release characters.
*
* @param val Value.
*/
IGNITE_IMPORT_EXPORT void ReleaseChars(char* val);
/**
* Casts value of one type to another type, using stringstream.
*
* @param val Input value.
* @param res Resulted value.
*/
template<typename T1, typename T2>
void LexicalCast(const T2& val, T1& res)
{
std::stringstream converter;
converter << val;
converter >> res;
}
/**
* Casts value of one type to another type, using stringstream.
*
* @param val Input value.
* @return Resulted value.
*/
template<typename T1, typename T2>
T1 LexicalCast(const T2& val)
{
T1 res;
LexicalCast<T1, T2>(val, res);
return res;
}
/**
* Check if all characters are digits.
*
* @param val Value to check.
*/
IGNITE_IMPORT_EXPORT bool AllDigits(const std::string& val);
/**
* Converts 32-bit integer to big endian format
*
* @param value Input value
* @return Resulting value
*/
IGNITE_IMPORT_EXPORT uint32_t ToBigEndian(uint32_t value);
/**
* Convert Date type to standard C type time_t.
*
* @param date Date type value.
* @return Corresponding value of time_t.
*/
inline time_t DateToCTime(const Date& date)
{
return static_cast<time_t>(date.GetSeconds());
}
/**
* Convert Timestamp type to standard C type time_t.
*
* @param ts Timestamp type value.
* @return Corresponding value of time_t.
*/
inline time_t TimestampToCTime(const Timestamp& ts)
{
return static_cast<time_t>(ts.GetSeconds());
}
/**
* Convert Time type to standard C type time_t.
*
* @param time Time type value.
* @return Corresponding value of time_t.
*/
inline time_t TimeToCTime(const Time& time)
{
return static_cast<time_t>(time.GetSeconds());
}
/**
* Convert Date type to standard C type time_t.
*
* @param date Date type value.
* @param ctime Corresponding value of struct tm.
* @return True on success.
*/
inline bool DateToCTm(const Date& date, tm& ctime)
{
time_t tmt = DateToCTime(date);
return common::IgniteGmTime(tmt, ctime);
}
/**
* Convert Timestamp type to standard C type struct tm.
*
* @param ts Timestamp type value.
* @param ctime Corresponding value of struct tm.
* @return True on success.
*/
inline bool TimestampToCTm(const Timestamp& ts, tm& ctime)
{
time_t tmt = TimestampToCTime(ts);
return common::IgniteGmTime(tmt, ctime);
}
/**
* Convert Time type to standard C type struct tm.
*
* @param time Time type value.
* @param ctime Corresponding value of struct tm.
* @return True on success.
*/
inline bool TimeToCTm(const Time& time, tm& ctime)
{
time_t tmt = TimeToCTime(time);
return common::IgniteGmTime(tmt, ctime);
}
/**
* Convert standard C type time_t to Date.
*
* @param ctime Standard C type time_t.
* @return Corresponding value of Date.
*/
inline Date CTimeToDate(time_t ctime)
{
return Date(ctime * 1000);
}
/**
* Convert standard C type time_t to Time.
*
* @param ctime Standard C type time_t.
* @return Corresponding value of Time.
*/
inline Time CTimeToTime(time_t ctime)
{
return Time(ctime * 1000);
}
/**
* Convert standard C type time_t to Timestamp type.
*
* @param ctime Standard C type time_t.
* @param ns Nanoseconds second fraction.
* @return Corresponding value of Timestamp.
*/
inline Timestamp CTimeToTimestamp(time_t ctime, int32_t ns)
{
return Timestamp(ctime, ns);
}
/**
* Convert standard C type struct tm to Date type.
*
* @param ctime Standard C type struct tm.
* @return Corresponding value of Date.
*/
inline Date CTmToDate(const tm& ctime)
{
time_t time = common::IgniteTimeGm(ctime);
return CTimeToDate(time);
}
/**
* Convert standard C type struct tm to Time type.
*
* @param ctime Standard C type struct tm.
* @return Corresponding value of Time.
*/
inline Time CTmToTime(const tm& ctime)
{
time_t time = common::IgniteTimeGm(ctime);
return CTimeToTime(time);
}
/**
* Convert standard C type struct tm to Timestamp type.
*
* @param ctime Standard C type struct tm.
* @param ns Nanoseconds second fraction.
* @return Corresponding value of Timestamp.
*/
inline Timestamp CTmToTimestamp(const tm& ctime, int32_t ns)
{
time_t time = common::IgniteTimeGm(ctime);
return CTimeToTimestamp(time, ns);
}
/**
* Make Date in human understandable way.
*
* Created Date uses GMT timezone.
*
* @param year Year.
* @param month Month.
* @param day Day.
* @param hour Hour.
* @param min Min.
* @param sec Sec.
* @return Date.
*/
IGNITE_FRIEND_EXPORT Date MakeDateGmt(int year = 1900, int month = 1,
int day = 1, int hour = 0, int min = 0, int sec = 0);
/**
* Make Date in human understandable way.
*
* Created Date uses local timezone.
*
* @param year Year.
* @param month Month.
* @param day Day.
* @param hour Hour.
* @param min Min.
* @param sec Sec.
* @return Date.
*/
IGNITE_FRIEND_EXPORT Date MakeDateLocal(int year = 1900, int month = 1,
int day = 1, int hour = 0, int min = 0, int sec = 0);
/**
* Make Time in human understandable way.
*
* Created Time uses GMT timezone.
*
* @param hour Hour.
* @param min Minute.
* @param sec Second.
* @return Time.
*/
IGNITE_FRIEND_EXPORT Time MakeTimeGmt(int hour = 0, int min = 0, int sec = 0);
/**
* Make Time in human understandable way.
*
* Created Time uses Local timezone.
*
* @param hour Hour.
* @param min Minute.
* @param sec Second.
* @return Time.
*/
IGNITE_FRIEND_EXPORT Time MakeTimeLocal(int hour = 0, int min = 0, int sec = 0);
/**
* Make Timestamp in human understandable way.
*
* Created Timestamp uses GMT timezone.
*
* @param year Year.
* @param month Month.
* @param day Day.
* @param hour Hour.
* @param min Minute.
* @param sec Second.
* @param ns Nanosecond.
* @return Timestamp.
*/
IGNITE_FRIEND_EXPORT Timestamp MakeTimestampGmt(int year = 1900, int month = 1,
int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0);
/**
* Make Date in human understandable way.
*
* Created Timestamp uses Local timezone.
*
* @param year Year.
* @param month Month.
* @param day Day.
* @param hour Hour.
* @param min Minute.
* @param sec Second.
* @param ns Nanosecond.
* @return Timestamp.
*/
IGNITE_FRIEND_EXPORT Timestamp MakeTimestampLocal(int year = 1900, int month = 1,
int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0);
/**
* Meta-programming class.
* Defines T1 as ::type if the condition is true, otherwise
* defines T2 as ::type.
*/
template<bool, typename T1, typename T2>
struct Conditional
{
typedef T1 type;
};
/**
* Specialization for the false case.
*/
template<typename T1, typename T2>
struct Conditional<false, T1, T2>
{
typedef T2 type;
};
/**
* Returns the bigger type.
*/
template<typename T1, typename T2>
struct Bigger
{
typedef typename Conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type type;
};
/**
* Utility class to bind class instance with member function.
*/
template<typename R, typename T>
class BoundInstance
{
public:
typedef R FunctionReturnType;
typedef T ClassType;
typedef FunctionReturnType(ClassType::* MemberFunctionType)();
/**
* Constructor.
*
* @param instance Class instance.
* @param mfunc Member function.
*/
BoundInstance(ClassType* instance, MemberFunctionType mfunc) :
instance(instance),
mfunc(mfunc)
{
// No-op.
}
/**
* Invoke operator.
*
* @return Result of the invokation of the member function on the bound instance.
*/
FunctionReturnType operator()()
{
return (instance->*mfunc)();
}
private:
/** Instance reference. */
ClassType* instance;
/** Member function pointer. */
MemberFunctionType mfunc;
};
/**
* Utility function for binding.
*/
template<typename R, typename T>
BoundInstance<R, T> Bind(T* instance, R(T::* mfunc)())
{
return BoundInstance<R, T>(instance, mfunc);
}
/**
* Method guard class template.
*
* Upon destruction calls provided method on provided class instance.
*
* @tparam T Value type.
*/
template<typename T>
class MethodGuard
{
public:
/** Value type. */
typedef T ValueType;
/** Mehtod type. */
typedef void (ValueType::*MethodType)();
/**
* Constructor.
*
* @param val Instance, to call method on.
* @param method Method to call.
*/
MethodGuard(ValueType* val, MethodType method) :
val(val),
method(method)
{
// No-op.
}
/**
* Destructor.
*/
~MethodGuard()
{
if (val && method)
(val->*method)();
}
/**
* Release control over object.
*/
void Release()
{
val = 0;
method = 0;
}
private:
/** Instance, to call method on. */
ValueType* val;
/** Method to call. */
MethodType method;
};
/**
* De-init guard class template.
*
* Upon destruction calls provided deinit function on provided instance.
*
* @tparam T Value type.
*/
template<typename T>
class DeinitGuard
{
public:
/** Value type. */
typedef T ValueType;
/** Deinit function type. */
typedef void (*FuncType)(ValueType*);
/**
* Constructor.
*
* @param val Instance, to call method on.
* @param method Method to call.
*/
DeinitGuard(ValueType* val, FuncType method) :
val(val),
func(method)
{
// No-op.
}
/**
* Destructor.
*/
~DeinitGuard()
{
if (val && func)
(func)(val);
}
/**
* Release control over object.
*/
void Release()
{
val = 0;
func = 0;
}
private:
/** Instance, to call method on. */
ValueType* val;
/** Method to call. */
FuncType func;
};
/**
* Get dynamic library full name.
* @param name Name without extension.
* @return Full name.
*/
IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const std::string& name);
/**
* Get hex dump of binary data in string form.
* @param data Data.
* @param count Number of bytes.
* @return Hex dump string.
*/
IGNITE_IMPORT_EXPORT std::string HexDump(const void* data, size_t count);
/**
* Fibonacci sequence iterator.
*
* @tparam S Sequence length. Should be >= 2.
*/
template<size_t S>
class FibonacciSequence
{
public:
/** Size. */
static const size_t size = S > 2 ? S : 2;
/**
* Constructor.
*/
FibonacciSequence()
{
sequence[0] = 0;
sequence[1] = 1;
for (size_t i = 2; i < size; ++i)
sequence[i] = sequence[i - 1] + sequence[i - 2];
}
/**
* Get n-th or max member of sequence.
*
* @param n Member position.
* @return N-th member of sequence if n < size, or max member.
*/
size_t GetValue(size_t n) const
{
if (n < size)
return sequence[n];
return sequence[size-1];
}
private:
/** Sequence of fibonacci numbers */
size_t sequence[size];
};
/**
* Throw platform-specific error.
*
* @param msg Error message.
*/
IGNITE_IMPORT_EXPORT void ThrowSystemError(const std::string& msg);
/**
* Try extract from system error stack and throw platform-specific error.
*
* @param description Error description.
* @param advice User advice.
*/
IGNITE_IMPORT_EXPORT void ThrowLastSystemError(const std::string& description, const std::string& advice);
/**
* Try extract from system error stack and throw platform-specific error.
*
* @param description Error description.
*/
IGNITE_IMPORT_EXPORT void ThrowLastSystemError(const std::string& description);
/**
* Format error message.
*
* @param description Error description.
* @param description Error details.
* @param advice User advice.
*/
IGNITE_IMPORT_EXPORT std::string FormatErrorMessage(const std::string& description, const std::string& details,
const std::string& advice);
/**
* Try extract from system error stack, format and return platform-specific error.
*
* @param description Error description.
* @return Error in human-readable format.
*/
IGNITE_IMPORT_EXPORT std::string GetLastSystemError(const std::string& description);
/**
* Try extract from system error stack, format and return platform-specific error.
*
* @param description Error description.
* @param advice User advice.
* @return Error in human-readable format.
*/
IGNITE_IMPORT_EXPORT std::string GetLastSystemError(const std::string& description, const std::string& advice);
}
}
#endif //_IGNITE_COMMON_UTILS