| Index: testing/gmock/include/gmock/internal/gmock-internal-utils.h
|
| diff --git a/testing/gmock/include/gmock/internal/gmock-internal-utils.h b/testing/gmock/include/gmock/internal/gmock-internal-utils.h
|
| index b02682f874492122b2a8d75a0eee43a03c51fff2..ee6aa1e239ffd1805d92cd1b91b3a5de259145ef 100644
|
| --- a/testing/gmock/include/gmock/internal/gmock-internal-utils.h
|
| +++ b/testing/gmock/include/gmock/internal/gmock-internal-utils.h
|
| @@ -99,6 +99,17 @@ struct RemoveConst { typedef T type; }; // NOLINT
|
| template <typename T>
|
| struct RemoveConst<const T> { typedef T type; }; // NOLINT
|
|
|
| +// MSVC 8.0 has a bug which causes the above definition to fail to
|
| +// remove the const in 'const int[3]'. The following specialization
|
| +// works around the bug. However, it causes trouble with gcc and thus
|
| +// needs to be conditionally compiled.
|
| +#ifdef _MSC_VER
|
| +template <typename T, size_t N>
|
| +struct RemoveConst<T[N]> {
|
| + typedef typename RemoveConst<T>::type type[N];
|
| +};
|
| +#endif // _MSC_VER
|
| +
|
| // A handy wrapper around RemoveConst that works when the argument
|
| // T depends on template parameters.
|
| #define GMOCK_REMOVE_CONST_(T) \
|
| @@ -438,6 +449,10 @@ const char kWarningVerbosity[] = "warning";
|
| // No logs are printed.
|
| const char kErrorVerbosity[] = "error";
|
|
|
| +// Returns true iff a log with the given severity is visible according
|
| +// to the --gmock_verbose flag.
|
| +bool LogIsVisible(LogSeverity severity);
|
| +
|
| // Prints the given message to stdout iff 'severity' >= the level
|
| // specified by the --gmock_verbose flag. If stack_frames_to_skip >=
|
| // 0, also prints the stack trace excluding the top
|
| @@ -447,10 +462,6 @@ const char kErrorVerbosity[] = "error";
|
| // conservative.
|
| void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
|
|
|
| -// The universal value printer (public/gmock-printers.h) needs this
|
| -// to declare an unused << operator in the global namespace.
|
| -struct Unused {};
|
| -
|
| // TODO(wan@google.com): group all type utilities together.
|
|
|
| // Type traits.
|
| @@ -478,6 +489,238 @@ inline T Invalid() {
|
| template <>
|
| inline void Invalid<void>() {}
|
|
|
| +// Utilities for native arrays.
|
| +
|
| +// ArrayEq() compares two k-dimensional native arrays using the
|
| +// elements' operator==, where k can be any integer >= 0. When k is
|
| +// 0, ArrayEq() degenerates into comparing a single pair of values.
|
| +
|
| +template <typename T, typename U>
|
| +bool ArrayEq(const T* lhs, size_t size, const U* rhs);
|
| +
|
| +// This generic version is used when k is 0.
|
| +template <typename T, typename U>
|
| +inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
|
| +
|
| +// This overload is used when k >= 1.
|
| +template <typename T, typename U, size_t N>
|
| +inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
|
| + return internal::ArrayEq(lhs, N, rhs);
|
| +}
|
| +
|
| +// This helper reduces code bloat. If we instead put its logic inside
|
| +// the previous ArrayEq() function, arrays with different sizes would
|
| +// lead to different copies of the template code.
|
| +template <typename T, typename U>
|
| +bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
|
| + for (size_t i = 0; i != size; i++) {
|
| + if (!internal::ArrayEq(lhs[i], rhs[i]))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// Finds the first element in the iterator range [begin, end) that
|
| +// equals elem. Element may be a native array type itself.
|
| +template <typename Iter, typename Element>
|
| +Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
|
| + for (Iter it = begin; it != end; ++it) {
|
| + if (internal::ArrayEq(*it, elem))
|
| + return it;
|
| + }
|
| + return end;
|
| +}
|
| +
|
| +// CopyArray() copies a k-dimensional native array using the elements'
|
| +// operator=, where k can be any integer >= 0. When k is 0,
|
| +// CopyArray() degenerates into copying a single value.
|
| +
|
| +template <typename T, typename U>
|
| +void CopyArray(const T* from, size_t size, U* to);
|
| +
|
| +// This generic version is used when k is 0.
|
| +template <typename T, typename U>
|
| +inline void CopyArray(const T& from, U* to) { *to = from; }
|
| +
|
| +// This overload is used when k >= 1.
|
| +template <typename T, typename U, size_t N>
|
| +inline void CopyArray(const T(&from)[N], U(*to)[N]) {
|
| + internal::CopyArray(from, N, *to);
|
| +}
|
| +
|
| +// This helper reduces code bloat. If we instead put its logic inside
|
| +// the previous CopyArray() function, arrays with different sizes
|
| +// would lead to different copies of the template code.
|
| +template <typename T, typename U>
|
| +void CopyArray(const T* from, size_t size, U* to) {
|
| + for (size_t i = 0; i != size; i++) {
|
| + internal::CopyArray(from[i], to + i);
|
| + }
|
| +}
|
| +
|
| +// The relation between an NativeArray object (see below) and the
|
| +// native array it represents.
|
| +enum RelationToSource {
|
| + kReference, // The NativeArray references the native array.
|
| + kCopy // The NativeArray makes a copy of the native array and
|
| + // owns the copy.
|
| +};
|
| +
|
| +// Adapts a native array to a read-only STL-style container. Instead
|
| +// of the complete STL container concept, this adaptor only implements
|
| +// members useful for Google Mock's container matchers. New members
|
| +// should be added as needed. To simplify the implementation, we only
|
| +// support Element being a raw type (i.e. having no top-level const or
|
| +// reference modifier). It's the client's responsibility to satisfy
|
| +// this requirement. Element can be an array type itself (hence
|
| +// multi-dimensional arrays are supported).
|
| +template <typename Element>
|
| +class NativeArray {
|
| + public:
|
| + // STL-style container typedefs.
|
| + typedef Element value_type;
|
| + typedef const Element* const_iterator;
|
| +
|
| + // Constructs from a native array passed by reference.
|
| + template <size_t N>
|
| + NativeArray(const Element (&array)[N], RelationToSource relation) {
|
| + Init(array, N, relation);
|
| + }
|
| +
|
| + // Constructs from a native array passed by a pointer and a size.
|
| + // For generality we don't artificially restrict the types of the
|
| + // pointer and the size.
|
| + template <typename Pointer, typename Size>
|
| + NativeArray(const ::std::tr1::tuple<Pointer, Size>& array,
|
| + RelationToSource relation) {
|
| + Init(internal::GetRawPointer(::std::tr1::get<0>(array)),
|
| + ::std::tr1::get<1>(array),
|
| + relation);
|
| + }
|
| +
|
| + // Copy constructor.
|
| + NativeArray(const NativeArray& rhs) {
|
| + Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
|
| + }
|
| +
|
| + ~NativeArray() {
|
| + // Ensures that the user doesn't instantiate NativeArray with a
|
| + // const or reference type.
|
| + testing::StaticAssertTypeEq<Element,
|
| + GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>();
|
| + if (relation_to_source_ == kCopy)
|
| + delete[] array_;
|
| + }
|
| +
|
| + // STL-style container methods.
|
| + size_t size() const { return size_; }
|
| + const_iterator begin() const { return array_; }
|
| + const_iterator end() const { return array_ + size_; }
|
| + bool operator==(const NativeArray& rhs) const {
|
| + return size() == rhs.size() &&
|
| + ArrayEq(begin(), size(), rhs.begin());
|
| + }
|
| +
|
| + private:
|
| + // Not implemented as we don't want to support assignment.
|
| + void operator=(const NativeArray& rhs);
|
| +
|
| + // Initializes this object; makes a copy of the input array if
|
| + // 'relation' is kCopy.
|
| + void Init(const Element* array, size_t size, RelationToSource relation) {
|
| + if (relation == kReference) {
|
| + array_ = array;
|
| + } else {
|
| + Element* const copy = new Element[size];
|
| + CopyArray(array, size, copy);
|
| + array_ = copy;
|
| + }
|
| + size_ = size;
|
| + relation_to_source_ = relation;
|
| + }
|
| +
|
| + const Element* array_;
|
| + size_t size_;
|
| + RelationToSource relation_to_source_;
|
| +};
|
| +
|
| +// Given a raw type (i.e. having no top-level reference or const
|
| +// modifier) RawContainer that's either an STL-style container or a
|
| +// native array, class StlContainerView<RawContainer> has the
|
| +// following members:
|
| +//
|
| +// - type is a type that provides an STL-style container view to
|
| +// (i.e. implements the STL container concept for) RawContainer;
|
| +// - const_reference is a type that provides a reference to a const
|
| +// RawContainer;
|
| +// - ConstReference(raw_container) returns a const reference to an STL-style
|
| +// container view to raw_container, which is a RawContainer.
|
| +// - Copy(raw_container) returns an STL-style container view of a
|
| +// copy of raw_container, which is a RawContainer.
|
| +//
|
| +// This generic version is used when RawContainer itself is already an
|
| +// STL-style container.
|
| +template <class RawContainer>
|
| +class StlContainerView {
|
| + public:
|
| + typedef RawContainer type;
|
| + typedef const type& const_reference;
|
| +
|
| + static const_reference ConstReference(const RawContainer& container) {
|
| + // Ensures that RawContainer is not a const type.
|
| + testing::StaticAssertTypeEq<RawContainer,
|
| + GMOCK_REMOVE_CONST_(RawContainer)>();
|
| + return container;
|
| + }
|
| + static type Copy(const RawContainer& container) { return container; }
|
| +};
|
| +
|
| +// This specialization is used when RawContainer is a native array type.
|
| +template <typename Element, size_t N>
|
| +class StlContainerView<Element[N]> {
|
| + public:
|
| + typedef GMOCK_REMOVE_CONST_(Element) RawElement;
|
| + typedef internal::NativeArray<RawElement> type;
|
| + // NativeArray<T> can represent a native array either by value or by
|
| + // reference (selected by a constructor argument), so 'const type'
|
| + // can be used to reference a const native array. We cannot
|
| + // 'typedef const type& const_reference' here, as that would mean
|
| + // ConstReference() has to return a reference to a local variable.
|
| + typedef const type const_reference;
|
| +
|
| + static const_reference ConstReference(const Element (&array)[N]) {
|
| + // Ensures that Element is not a const type.
|
| + testing::StaticAssertTypeEq<Element, RawElement>();
|
| + return type(array, kReference);
|
| + }
|
| + static type Copy(const Element (&array)[N]) {
|
| + return type(array, kCopy);
|
| + }
|
| +};
|
| +
|
| +// This specialization is used when RawContainer is a native array
|
| +// represented as a (pointer, size) tuple.
|
| +template <typename ElementPointer, typename Size>
|
| +class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
|
| + public:
|
| + typedef GMOCK_REMOVE_CONST_(
|
| + typename internal::PointeeOf<ElementPointer>::type) RawElement;
|
| + typedef internal::NativeArray<RawElement> type;
|
| + typedef const type const_reference;
|
| +
|
| + static const_reference ConstReference(
|
| + const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
| + return type(array, kReference);
|
| + }
|
| + static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
|
| + return type(array, kCopy);
|
| + }
|
| +};
|
| +
|
| +// The following specialization prevents the user from instantiating
|
| +// StlContainer with a reference type.
|
| +template <typename T> class StlContainerView<T&>;
|
| +
|
| } // namespace internal
|
| } // namespace testing
|
|
|
|
|