ОШ 2018. Группа B. День 2 / std.check.src.typeinfo.hpp

ru en cn

с начала прошло: 1947 д. 03:25
страница обновлена: 19.03.2024 20:05

std.check.src.typeinfo.hpp: src/typeinfo.hpp

/*!
  \file typeinfo.hpp
  \brief Header file which gives general information on
  how to name, read, write and compare built-in types.
*/
#ifndef CHECK_TYPEINFO_HPP
#define CHECK_TYPEINFO_HPP

#include 
#include 
#include "global.hpp"
#include "formatter.hpp"

// Determine non-standard format specifiers for 64-bit types
#undef CHECK_SCAN64D
#undef CHECK_SCAN64U
#undef CHECK_PRINT64D
#undef CHECK_PRINT64U
#if CHECK_MSC_VERSION(13, 10)
// Available since MS Visual Studio .NET 2003
#  define CHECK_SCAN64D "I64d"
#  define CHECK_SCAN64U "I64u"
#  define CHECK_PRINT64D CHECK_SCAN64D
#  define CHECK_PRINT64U CHECK_SCAN64U
#elif defined(CHECK_GCC)
#  define __STDC_FORMAT_MACROS
#  include 
#  if defined(SCNd64)
#    define CHECK_SCAN64D SCNd64
#  endif
#  if defined(SCNu64)
#    define CHECK_SCAN64U SCNu64
#  endif
#  if defined(PRId64)
#    define CHECK_PRINT64D PRId64
#  endif
#  if defined(PRIu64)
#    define CHECK_PRINT64U PRIu64
#  endif
#endif


namespace Check
{


//! The largest representable value of type \c size_t.
extern const size_t MaxSizeValue;


/*!
  \brief The %TypeInfo class provides general information about
  input/output of a type \a Type.

  This class gives static methods that returns display name, scanf and printf
  format specifiers for a type \a Type.

  \see Comparer
*/
template 
class TypeInfo
{
public:
  /*!
    Returns display name of the type as \c const \c char \c * string.
    If name is undefined or unknown, returns \c NULL pointer.

    \see scanFormat() and printFormat()
  */
  static const char *name() { return NULL; }

  /*!
    Returns scanf format specifier (including percent sign) of the type as
    \c const \c char \c * string.
    If it's undefined or unknown, returns \c NULL pointer.

    \see name() and printFormat()
  */
  static const char *scanFormat() { return NULL; }

  /*!
    Returns printf format specifier (including percent sign) of the type as
    \c const \c char \c * string.
    If it's undefined or unknown, returns \c NULL pointer.

    \see name() and scanFormat()
  */
  static const char *printFormat() { return NULL; }
};


/*!
  Declares class that provides general information about built-in type \a TYPE
  with scanf specifier \a SCAN and printf specifier \a PRINT.
*/
#define CHECK_DECLARE_TYPEINFO(TYPE, SCAN, PRINT) \
  template <> \
  class TypeInfo \
  { \
  public: \
    /*! \cond */ \
    static const char *name() { return #TYPE; } \
    static const char *scanFormat() { return "%" SCAN; } \
    static const char *printFormat() { return "%" PRINT; } \
    /*! \endcond */ \
  }


//! TypeInfo class specialized for \c short \c int.
CHECK_DECLARE_TYPEINFO(short int, "hd", "hd");

//! TypeInfo class specialized for \c unsigned \c short \c int.
CHECK_DECLARE_TYPEINFO(unsigned short int, "hu", "hu");

//! TypeInfo class specialized for \c int.
CHECK_DECLARE_TYPEINFO(int, "d", "d");

//! TypeInfo class specialized for \c unsigned \c int.
CHECK_DECLARE_TYPEINFO(unsigned int, "u", "u");

//! TypeInfo class specialized for \c long \c int.
CHECK_DECLARE_TYPEINFO(long int, "ld", "ld");

//! TypeInfo class specialized for \c unsigned \c long \c int.
CHECK_DECLARE_TYPEINFO(unsigned long int, "lu", "lu");

#if defined(CHECK_SCAN64D) && defined(CHECK_PRINT64D)
//! TypeInfo class specialized for \c long \c long \c int.
CHECK_DECLARE_TYPEINFO(long long int, CHECK_SCAN64D, CHECK_PRINT64D);
#endif

#if defined(CHECK_SCAN64U) && defined(CHECK_PRINT64U)
//! TypeInfo class specialized for \c unsigned \c long \c long \c int.
CHECK_DECLARE_TYPEINFO(unsigned long long int, CHECK_SCAN64U, CHECK_PRINT64U);
#endif

//! TypeInfo class specialized for \c float.
CHECK_DECLARE_TYPEINFO(float, "e", "g");

//! TypeInfo class specialized for \c double.
CHECK_DECLARE_TYPEINFO(double, "le", "g");

//! TypeInfo class specialized for \c long \c double.
CHECK_DECLARE_TYPEINFO(long double, "Le", "lg");


#undef CHECK_DECLARE_TYPEINFO

/*!
  \relates Comparer

  \brief The %Difference class provides ability to store string representation
  of difference between some values. Used primarily by Comparer class.

  \see Comparer
*/
class Difference
{
  template 
  friend class Comparer;

private:
  static const Difference Empty;

  const std::string left;
  const std::string right;

  Difference() { /* Do Nothing */ }
  Difference(const std::string &first, const std::string &second)
    : left(first), right(second)
  { /* Do Nothing */ }

  template 
  static Difference number(const Class first, const Class second)
  {
    const char *str = TypeInfo::printFormat();
    return Difference(format(str, first), format(str, second));
  }

public:
  //! Constructs a copy of \a other.
  Difference(const Difference &other)
    : left(other.left), right(other.right)
  { /* Do Nothing */ }

  /*!
    Returns true if one of the differences is empty string;
    otherwise returns false.
  */
  bool isEmpty() const { return left.empty() || right.empty(); }

  /*!
    Returns value of the first difference.

    \see second()
  */
  const std::string &first() const { return left; }

  /*!
    Returns value of the second difference.

    \see first()
  */
  const std::string &second() const { return right; }
};


/*!
  \brief The %Comparer class provides interface to compare values of
  type \a Type and report difference between them.

  This class tests two objects of type \a Type for equality and
  reports strings to illustrate an inequality.

  \see TypeInfo
*/
template 
class Comparer
{
private:
  const bool equals;

public:
  //! Constructs an object for comparison between \a first and \a second.
  Comparer(const Type &first, const Type &second)
    : equals(first == second)
  { /* Do Nothing */ }

  /*!
    Returns true if values passed during creation of the object are equal;
    otherwise returns false.

    Values are considered equal if \c operator \c == returns true for it.

    \see difference()
  */
  bool isEqual() const { return equals; }

  /*!
    Returns string representation of difference illustrating inequality
    in both of the examining values. If it's impossible to illustrate
    difference for one of the values empty string corresponds to that value.

    This function should not be called if isEqual() returns true.

    \see Difference and isEqual()
  */
  Difference difference() const { return Difference::Empty; }
};


//! Declares comparer class for built-in integer types.
#define CHECK_DECLARE_INTEGER_COMPARER(TYPE) \
  template <> \
  class Comparer \
  { \
  private: \
    const TYPE left; \
    const TYPE right; \
    \
  public: \
    /*! \cond */ \
    Comparer(const TYPE first, const TYPE second) \
      : left(first), right(second) \
    { /* Do Nothing */ } \
    \
    bool isEqual() const { return left == right; } \
    Difference difference() const \
    { return Difference::number(left, right); } \
    /*! \endcond */ \
  }


//! Declares comparer class for built-in floating point types.
#define CHECK_DECLARE_FLOAT_COMPARER(TYPE) \
  template <> \
  class Comparer \
  { \
  private: \
    static TYPE epsilon; \
    \
    const TYPE left; \
    const TYPE right; \
    const bool equals; \
    \
  public: \
    /*! \cond */ \
    Comparer(const TYPE first, const TYPE second) \
      : left(first), right(second), equals(std::abs(first - second) < epsilon) \
    { /* Do Nothing */ } \
    \
    bool isEqual() const { return equals; } \
    Difference difference() const \
    { return Difference::number(left, right); } \
    /*! \endcond */ \
    \
    /*! Returns current accuracy of equality testing. \see setAccuracy() */ \
    static TYPE accuracy() { return epsilon; } \
    /*! Changes current accuracy of equality testing to \a value. */ \
    /*! \see accuracy() */ \
    static void setAccuracy(const TYPE value) { epsilon = value; } \
  }


//! Comparer class specialized for \c short \c int.
CHECK_DECLARE_INTEGER_COMPARER(short int);

//! Comparer class specialized for \c unsigned \c short \c int.
CHECK_DECLARE_INTEGER_COMPARER(unsigned short int);

//! Comparer class specialized for \c int.
CHECK_DECLARE_INTEGER_COMPARER(int);

//! Comparer class specialized for \c unsigned \c int.
CHECK_DECLARE_INTEGER_COMPARER(unsigned int);

//! Comparer class specialized for \c long \c int.
CHECK_DECLARE_INTEGER_COMPARER(long int);

//! Comparer class specialized for \c unsigned \c long \c int.
CHECK_DECLARE_INTEGER_COMPARER(unsigned long int);

#if defined(CHECK_SCAN64D) && defined(CHECK_PRINT64D)
//! Comparer class specialized for \c long \c long \c int.
CHECK_DECLARE_INTEGER_COMPARER(long long int);
#endif

#if defined(CHECK_SCAN64U) && defined(CHECK_PRINT64U)
//! Comparer class specialized for \c unsigned \c long \c long \c int.
CHECK_DECLARE_INTEGER_COMPARER(unsigned long long int);
#endif

//! Comparer class specialized for \c float.
CHECK_DECLARE_FLOAT_COMPARER(float);

//! Comparer class specialized for \c double.
CHECK_DECLARE_FLOAT_COMPARER(double);

//! Comparer class specialized for \c long \c double.
CHECK_DECLARE_FLOAT_COMPARER(long double);


#undef CHECK_DECLARE_INTEGER_COMPARER
#undef CHECK_DECLARE_FLOAT_COMPARER


//! Comparer class specialized for \c std::string.
template <>
class Comparer
{
private:
  static size_t slitWidth;

  const std::string left;
  const std::string right;
  const bool equals;
  size_t diffPos;

  bool compare();

public:
  /*! \cond */
  Comparer(const std::string &first, const std::string &second)
    : left(first), right(second), equals(compare())
  { /* Do Nothing */ }

  bool isEqual() const { return equals; }
  Difference difference() const;
  /*! \endcond */

  /*!
    Returns current number of charaters reported around an inequality place.

    \see setSlitSize()
  */
  static size_t slitSize() { return slitWidth; }

  /*!
    Changes current number of charaters reported around an inequality place
    to \a value.

    \see slitSize()
  */
  static void setSlitSize(const size_t value) { slitWidth = value; }
};


}


#endif /* CHECK_TYPEINFO_HPP */
Дальневосточный федеральный университет