text: /**
   * @file src/utils/utils.h
   * @brief Declaration of utility functions.
   * @copyright (c) 2017 Avast Software, licensed under the MIT license
   */
  
  #pragma once
  
  #include <sstream>
  #include <string>
  
  namespace yaramod {
  
  bool isValidIdentifier(const std::string& id);
  std::string escapeString(const std::string& str);
  
  bool endsWith(const std::string& str, const std::string& withWhat);
  bool endsWith(const std::string& str, char withWhat);
  
  std::string trim(std::string str);
  
  /**
   * Checks whether string starts with another string or character.
   *
   * @param str String to check.
   * @param withWhat Prefix to check.
   *
   * @return `true` if it starts, otherwise `false`.
   */
  template <typename T>
  bool startsWith(const std::string& str, const T& withWhat)
  {
  	return str.find(withWhat) == 0;
  }
  
  /**
   * Converts number to string according to the specified format. Prepends base of number if requested.
   *
   * @param num Number to convert.
   * @param format Format to use when converting.
   * @param showbase Indicates whether to prepend base or not.
   *
   * @return Number converted to string.
   */
  template <typename T>
  std::string numToStr(const T num, std::ios_base &(*format)(std::ios_base&) = std::dec, bool showbase = false)
  {
  	std::ostringstream os;
  	if (showbase)
  		os << format << std::showbase << num;
  	else
  		os << format << num;
  	return os.str();
  }
  
  /**
   * Converts string to number according to the specified format.
   *
   * @param str String to convert.
   * @param[out] num Numeric result.
   * @param format Format of the number.
   *
   * @return `true` if conversion was successful, otherwise `false`.
   */
  template <typename T>
  bool strToNum(const std::string& str, T& num, std::ios_base &(*format)(std::ios_base&) = std::dec)
  {
  	std::istringstream is(str);
  	T tmp = 0;
  	is >> format >> tmp;
  	if (!is.fail() && is.eof())
  	{
  		num = tmp;
  		return true;
  	}
  	return false;
  }
  
  /**
   * With `isAnyOf` you can determine if one type is one of the other types in compile time.
   *
   * Usage:
   * isAnyOf<some_type, list_of_possible_types...>::value
   * `value` will be `true` or `false` depending whether `some_type` is in `list_of_possible_values`.
   *
   * Examples:
   * isAnyOf<int, long, float>::value == false
   * isAnyOf<int, long, float, int>::value == true
   */
  template <typename T, typename... Args>
  struct isAnyOf : std::false_type {};
  
  template <typename T, typename Head, typename... Args>
  struct isAnyOf<T, Head, Args...> : isAnyOf<T, Args...> {};
  
  template <typename T, typename... Args>
  struct isAnyOf<T, T, Args...> : std::true_type {};
  
  }
  