1 // Copyright 2007, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: wan@google.com (Zhanyong Wan)
31 
32 // Google Mock - a framework for writing C++ mock classes.
33 //
34 // This file defines some utilities useful for implementing Google
35 // Mock.  They are subject to change without notice, so please DO NOT
36 // USE THEM IN USER CODE.
37 
38 #ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
39 #define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
40 
41 #include <stdio.h>
42 #include <ostream>  // NOLINT
43 #include <string>
44 
45 #include <gmock/internal/gmock-generated-internal-utils.h>
46 #include <gmock/internal/gmock-port.h>
47 #include <gtest/gtest.h>
48 
49 // Concatenates two pre-processor symbols; works for concatenating
50 // built-in macros like __FILE__ and __LINE__.
51 #define GMOCK_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
52 #define GMOCK_CONCAT_TOKEN_(foo, bar) GMOCK_CONCAT_TOKEN_IMPL_(foo, bar)
53 
54 #ifdef __GNUC__
55 #define GMOCK_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
56 #else
57 #define GMOCK_ATTRIBUTE_UNUSED_
58 #endif  // __GNUC__
59 
60 class ProtocolMessage;
61 namespace proto2 { class Message; }
62 
63 namespace testing {
64 namespace internal {
65 
66 // Converts an identifier name to a space-separated list of lower-case
67 // words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
68 // treated as one word.  For example, both "FooBar123" and
69 // "foo_bar_123" are converted to "foo bar 123".
70 string ConvertIdentifierNameToWords(const char* id_name);
71 
72 // Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
73 // compiler error iff T1 and T2 are different types.
74 template <typename T1, typename T2>
75 struct CompileAssertTypesEqual;
76 
77 template <typename T>
78 struct CompileAssertTypesEqual<T, T> {
79 };
80 
81 // Removes the reference from a type if it is a reference type,
82 // otherwise leaves it unchanged.  This is the same as
83 // tr1::remove_reference, which is not widely available yet.
84 template <typename T>
85 struct RemoveReference { typedef T type; };  // NOLINT
86 template <typename T>
87 struct RemoveReference<T&> { typedef T type; };  // NOLINT
88 
89 // A handy wrapper around RemoveReference that works when the argument
90 // T depends on template parameters.
91 #define GMOCK_REMOVE_REFERENCE_(T) \
92     typename ::testing::internal::RemoveReference<T>::type
93 
94 // Removes const from a type if it is a const type, otherwise leaves
95 // it unchanged.  This is the same as tr1::remove_const, which is not
96 // widely available yet.
97 template <typename T>
98 struct RemoveConst { typedef T type; };  // NOLINT
99 template <typename T>
100 struct RemoveConst<const T> { typedef T type; };  // NOLINT
101 
102 // MSVC 8.0 has a bug which causes the above definition to fail to
103 // remove the const in 'const int[3]'.  The following specialization
104 // works around the bug.  However, it causes trouble with gcc and thus
105 // needs to be conditionally compiled.
106 #ifdef _MSC_VER
107 template <typename T, size_t N>
108 struct RemoveConst<T[N]> {
109   typedef typename RemoveConst<T>::type type[N];
110 };
111 #endif  // _MSC_VER
112 
113 // A handy wrapper around RemoveConst that works when the argument
114 // T depends on template parameters.
115 #define GMOCK_REMOVE_CONST_(T) \
116     typename ::testing::internal::RemoveConst<T>::type
117 
118 // Adds reference to a type if it is not a reference type,
119 // otherwise leaves it unchanged.  This is the same as
120 // tr1::add_reference, which is not widely available yet.
121 template <typename T>
122 struct AddReference { typedef T& type; };  // NOLINT
123 template <typename T>
124 struct AddReference<T&> { typedef T& type; };  // NOLINT
125 
126 // A handy wrapper around AddReference that works when the argument T
127 // depends on template parameters.
128 #define GMOCK_ADD_REFERENCE_(T) \
129     typename ::testing::internal::AddReference<T>::type
130 
131 // Adds a reference to const on top of T as necessary.  For example,
132 // it transforms
133 //
134 //   char         ==> const char&
135 //   const char   ==> const char&
136 //   char&        ==> const char&
137 //   const char&  ==> const char&
138 //
139 // The argument T must depend on some template parameters.
140 #define GMOCK_REFERENCE_TO_CONST_(T) \
141     GMOCK_ADD_REFERENCE_(const GMOCK_REMOVE_REFERENCE_(T))
142 
143 // PointeeOf<Pointer>::type is the type of a value pointed to by a
144 // Pointer, which can be either a smart pointer or a raw pointer.  The
145 // following default implementation is for the case where Pointer is a
146 // smart pointer.
147 template <typename Pointer>
148 struct PointeeOf {
149   // Smart pointer classes define type element_type as the type of
150   // their pointees.
151   typedef typename Pointer::element_type type;
152 };
153 // This specialization is for the raw pointer case.
154 template <typename T>
155 struct PointeeOf<T*> { typedef T type; };  // NOLINT
156 
157 // GetRawPointer(p) returns the raw pointer underlying p when p is a
158 // smart pointer, or returns p itself when p is already a raw pointer.
159 // The following default implementation is for the smart pointer case.
160 template <typename Pointer>
161 inline typename Pointer::element_type* GetRawPointer(const Pointer& p) {
162   return p.get();
163 }
164 // This overloaded version is for the raw pointer case.
165 template <typename Element>
166 inline Element* GetRawPointer(Element* p) { return p; }
167 
168 // This comparator allows linked_ptr to be stored in sets.
169 template <typename T>
170 struct LinkedPtrLessThan {
171   bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
172                   const ::testing::internal::linked_ptr<T>& rhs) const {
173     return lhs.get() < rhs.get();
174   }
175 };
176 
177 // ImplicitlyConvertible<From, To>::value is a compile-time bool
178 // constant that's true iff type From can be implicitly converted to
179 // type To.
180 template <typename From, typename To>
181 class ImplicitlyConvertible {
182  private:
183   // We need the following helper functions only for their types.
184   // They have no implementations.
185 
186   // MakeFrom() is an expression whose type is From.  We cannot simply
187   // use From(), as the type From may not have a public default
188   // constructor.
189   static From MakeFrom();
190 
191   // These two functions are overloaded.  Given an expression
192   // Helper(x), the compiler will pick the first version if x can be
193   // implicitly converted to type To; otherwise it will pick the
194   // second version.
195   //
196   // The first version returns a value of size 1, and the second
197   // version returns a value of size 2.  Therefore, by checking the
198   // size of Helper(x), which can be done at compile time, we can tell
199   // which version of Helper() is used, and hence whether x can be
200   // implicitly converted to type To.
201   static char Helper(To);
202   static char (&Helper(...))[2];  // NOLINT
203 
204   // We have to put the 'public' section after the 'private' section,
205   // or MSVC refuses to compile the code.
206  public:
207   // MSVC warns about implicitly converting from double to int for
208   // possible loss of data, so we need to temporarily disable the
209   // warning.
210 #ifdef _MSC_VER
211 #pragma warning(push)          // Saves the current warning state.
212 #pragma warning(disable:4244)  // Temporarily disables warning 4244.
213   static const bool value =
214       sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
215 #pragma warning(pop)           // Restores the warning state.
216 #else
217   static const bool value =
218       sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
219 #endif  // _MSV_VER
220 };
221 template <typename From, typename To>
222 const bool ImplicitlyConvertible<From, To>::value;
223 
224 // In what follows, we use the term "kind" to indicate whether a type
225 // is bool, an integer type (excluding bool), a floating-point type,
226 // or none of them.  This categorization is useful for determining
227 // when a matcher argument type can be safely converted to another
228 // type in the implementation of SafeMatcherCast.
229 enum TypeKind {
230   kBool, kInteger, kFloatingPoint, kOther
231 };
232 
233 // KindOf<T>::value is the kind of type T.
234 template <typename T> struct KindOf {
235   enum { value = kOther };  // The default kind.
236 };
237 
238 // This macro declares that the kind of 'type' is 'kind'.
239 #define GMOCK_DECLARE_KIND_(type, kind) \
240   template <> struct KindOf<type> { enum { value = kind }; }
241 
242 GMOCK_DECLARE_KIND_(bool, kBool);
243 
244 // All standard integer types.
245 GMOCK_DECLARE_KIND_(char, kInteger);
246 GMOCK_DECLARE_KIND_(signed char, kInteger);
247 GMOCK_DECLARE_KIND_(unsigned char, kInteger);
248 GMOCK_DECLARE_KIND_(short, kInteger);  // NOLINT
249 GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
250 GMOCK_DECLARE_KIND_(int, kInteger);
251 GMOCK_DECLARE_KIND_(unsigned int, kInteger);
252 GMOCK_DECLARE_KIND_(long, kInteger);  // NOLINT
253 GMOCK_DECLARE_KIND_(unsigned long, kInteger);  // NOLINT
254 
255 // MSVC can be configured to define wchar_t as a typedef of unsigned
256 // short. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t is a
257 // native type.
258 #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
259 GMOCK_DECLARE_KIND_(wchar_t, kInteger);
260 #endif
261 
262 // Non-standard integer types.
263 GMOCK_DECLARE_KIND_(Int64, kInteger);
264 GMOCK_DECLARE_KIND_(UInt64, kInteger);
265 
266 // All standard floating-point types.
267 GMOCK_DECLARE_KIND_(float, kFloatingPoint);
268 GMOCK_DECLARE_KIND_(double, kFloatingPoint);
269 GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
270 
271 #undef GMOCK_DECLARE_KIND_
272 
273 // Evaluates to the kind of 'type'.
274 #define GMOCK_KIND_OF_(type) \
275   static_cast< ::testing::internal::TypeKind>( \
276       ::testing::internal::KindOf<type>::value)
277 
278 // Evaluates to true iff integer type T is signed.
279 #define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
280 
281 // LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
282 // is true iff arithmetic type From can be losslessly converted to
283 // arithmetic type To.
284 //
285 // It's the user's responsibility to ensure that both From and To are
286 // raw (i.e. has no CV modifier, is not a pointer, and is not a
287 // reference) built-in arithmetic types, kFromKind is the kind of
288 // From, and kToKind is the kind of To; the value is
289 // implementation-defined when the above pre-condition is violated.
290 template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
291 struct LosslessArithmeticConvertibleImpl : public false_type {};
292 
293 // Converting bool to bool is lossless.
294 template <>
295 struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
296     : public true_type {};  // NOLINT
297 
298 // Converting bool to any integer type is lossless.
299 template <typename To>
300 struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
301     : public true_type {};  // NOLINT
302 
303 // Converting bool to any floating-point type is lossless.
304 template <typename To>
305 struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
306     : public true_type {};  // NOLINT
307 
308 // Converting an integer to bool is lossy.
309 template <typename From>
310 struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
311     : public false_type {};  // NOLINT
312 
313 // Converting an integer to another non-bool integer is lossless iff
314 // the target type's range encloses the source type's range.
315 template <typename From, typename To>
316 struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
317     : public bool_constant<
318       // When converting from a smaller size to a larger size, we are
319       // fine as long as we are not converting from signed to unsigned.
320       ((sizeof(From) < sizeof(To)) &&
321        (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
322       // When converting between the same size, the signedness must match.
323       ((sizeof(From) == sizeof(To)) &&
324        (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {};  // NOLINT
325 
326 #undef GMOCK_IS_SIGNED_
327 
328 // Converting an integer to a floating-point type may be lossy, since
329 // the format of a floating-point number is implementation-defined.
330 template <typename From, typename To>
331 struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
332     : public false_type {};  // NOLINT
333 
334 // Converting a floating-point to bool is lossy.
335 template <typename From>
336 struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
337     : public false_type {};  // NOLINT
338 
339 // Converting a floating-point to an integer is lossy.
340 template <typename From, typename To>
341 struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
342     : public false_type {};  // NOLINT
343 
344 // Converting a floating-point to another floating-point is lossless
345 // iff the target type is at least as big as the source type.
346 template <typename From, typename To>
347 struct LosslessArithmeticConvertibleImpl<
348   kFloatingPoint, From, kFloatingPoint, To>
349     : public bool_constant<sizeof(From) <= sizeof(To)> {};  // NOLINT
350 
351 // LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
352 // type From can be losslessly converted to arithmetic type To.
353 //
354 // It's the user's responsibility to ensure that both From and To are
355 // raw (i.e. has no CV modifier, is not a pointer, and is not a
356 // reference) built-in arithmetic types; the value is
357 // implementation-defined when the above pre-condition is violated.
358 template <typename From, typename To>
359 struct LosslessArithmeticConvertible
360     : public LosslessArithmeticConvertibleImpl<
361   GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {};  // NOLINT
362 
363 // IsAProtocolMessage<T>::value is a compile-time bool constant that's
364 // true iff T is type ProtocolMessage, proto2::Message, or a subclass
365 // of those.
366 template <typename T>
367 struct IsAProtocolMessage
368     : public bool_constant<
369   ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
370   ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
371 };
372 
373 // When the compiler sees expression IsContainerTest<C>(0), the first
374 // overload of IsContainerTest will be picked if C is an STL-style
375 // container class (since C::const_iterator* is a valid type and 0 can
376 // be converted to it), while the second overload will be picked
377 // otherwise (since C::const_iterator will be an invalid type in this
378 // case).  Therefore, we can determine whether C is a container class
379 // by checking the type of IsContainerTest<C>(0).  The value of the
380 // expression is insignificant.
381 typedef int IsContainer;
382 template <class C>
383 IsContainer IsContainerTest(typename C::const_iterator*) { return 0; }
384 
385 typedef char IsNotContainer;
386 template <class C>
387 IsNotContainer IsContainerTest(...) { return '\0'; }
388 
389 // This interface knows how to report a Google Mock failure (either
390 // non-fatal or fatal).
391 class FailureReporterInterface {
392  public:
393   // The type of a failure (either non-fatal or fatal).
394   enum FailureType {
395     NONFATAL, FATAL
396   };
397 
398   virtual ~FailureReporterInterface() {}
399 
400   // Reports a failure that occurred at the given source file location.
401   virtual void ReportFailure(FailureType type, const char* file, int line,
402                              const string& message) = 0;
403 };
404 
405 // Returns the failure reporter used by Google Mock.
406 FailureReporterInterface* GetFailureReporter();
407 
408 // Asserts that condition is true; aborts the process with the given
409 // message if condition is false.  We cannot use LOG(FATAL) or CHECK()
410 // as Google Mock might be used to mock the log sink itself.  We
411 // inline this function to prevent it from showing up in the stack
412 // trace.
413 inline void Assert(bool condition, const char* file, int line,
414                    const string& msg) {
415   if (!condition) {
416     GetFailureReporter()->ReportFailure(FailureReporterInterface::FATAL,
417                                         file, line, msg);
418   }
419 }
420 inline void Assert(bool condition, const char* file, int line) {
421   Assert(condition, file, line, "Assertion failed.");
422 }
423 
424 // Verifies that condition is true; generates a non-fatal failure if
425 // condition is false.
426 inline void Expect(bool condition, const char* file, int line,
427                    const string& msg) {
428   if (!condition) {
429     GetFailureReporter()->ReportFailure(FailureReporterInterface::NONFATAL,
430                                         file, line, msg);
431   }
432 }
433 inline void Expect(bool condition, const char* file, int line) {
434   Expect(condition, file, line, "Expectation failed.");
435 }
436 
437 // Severity level of a log.
438 enum LogSeverity {
439   INFO = 0,
440   WARNING = 1,
441 };
442 
443 // Valid values for the --gmock_verbose flag.
444 
445 // All logs (informational and warnings) are printed.
446 const char kInfoVerbosity[] = "info";
447 // Only warnings are printed.
448 const char kWarningVerbosity[] = "warning";
449 // No logs are printed.
450 const char kErrorVerbosity[] = "error";
451 
452 // Returns true iff a log with the given severity is visible according
453 // to the --gmock_verbose flag.
454 bool LogIsVisible(LogSeverity severity);
455 
456 // Prints the given message to stdout iff 'severity' >= the level
457 // specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
458 // 0, also prints the stack trace excluding the top
459 // stack_frames_to_skip frames.  In opt mode, any positive
460 // stack_frames_to_skip is treated as 0, since we don't know which
461 // function calls will be inlined by the compiler and need to be
462 // conservative.
463 void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
464 
465 // TODO(wan@google.com): group all type utilities together.
466 
467 // Type traits.
468 
469 // is_reference<T>::value is non-zero iff T is a reference type.
470 template <typename T> struct is_reference : public false_type {};
471 template <typename T> struct is_reference<T&> : public true_type {};
472 
473 // type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
474 template <typename T1, typename T2> struct type_equals : public false_type {};
475 template <typename T> struct type_equals<T, T> : public true_type {};
476 
477 // remove_reference<T>::type removes the reference from type T, if any.
478 template <typename T> struct remove_reference { typedef T type; };  // NOLINT
479 template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
480 
481 // Invalid<T>() returns an invalid value of type T.  This is useful
482 // when a value of type T is needed for compilation, but the statement
483 // will not really be executed (or we don't care if the statement
484 // crashes).
485 template <typename T>
486 inline T Invalid() {
487   return *static_cast<typename remove_reference<T>::type*>(NULL);
488 }
489 template <>
490 inline void Invalid<void>() {}
491 
492 // Utilities for native arrays.
493 
494 // ArrayEq() compares two k-dimensional native arrays using the
495 // elements' operator==, where k can be any integer >= 0.  When k is
496 // 0, ArrayEq() degenerates into comparing a single pair of values.
497 
498 template <typename T, typename U>
499 bool ArrayEq(const T* lhs, size_t size, const U* rhs);
500 
501 // This generic version is used when k is 0.
502 template <typename T, typename U>
503 inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
504 
505 // This overload is used when k >= 1.
506 template <typename T, typename U, size_t N>
507 inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
508   return internal::ArrayEq(lhs, N, rhs);
509 }
510 
511 // This helper reduces code bloat.  If we instead put its logic inside
512 // the previous ArrayEq() function, arrays with different sizes would
513 // lead to different copies of the template code.
514 template <typename T, typename U>
515 bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
516   for (size_t i = 0; i != size; i++) {
517     if (!internal::ArrayEq(lhs[i], rhs[i]))
518       return false;
519   }
520   return true;
521 }
522 
523 // Finds the first element in the iterator range [begin, end) that
524 // equals elem.  Element may be a native array type itself.
525 template <typename Iter, typename Element>
526 Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
527   for (Iter it = begin; it != end; ++it) {
528     if (internal::ArrayEq(*it, elem))
529       return it;
530   }
531   return end;
532 }
533 
534 // CopyArray() copies a k-dimensional native array using the elements'
535 // operator=, where k can be any integer >= 0.  When k is 0,
536 // CopyArray() degenerates into copying a single value.
537 
538 template <typename T, typename U>
539 void CopyArray(const T* from, size_t size, U* to);
540 
541 // This generic version is used when k is 0.
542 template <typename T, typename U>
543 inline void CopyArray(const T& from, U* to) { *to = from; }
544 
545 // This overload is used when k >= 1.
546 template <typename T, typename U, size_t N>
547 inline void CopyArray(const T(&from)[N], U(*to)[N]) {
548   internal::CopyArray(from, N, *to);
549 }
550 
551 // This helper reduces code bloat.  If we instead put its logic inside
552 // the previous CopyArray() function, arrays with different sizes
553 // would lead to different copies of the template code.
554 template <typename T, typename U>
555 void CopyArray(const T* from, size_t size, U* to) {
556   for (size_t i = 0; i != size; i++) {
557     internal::CopyArray(from[i], to + i);
558   }
559 }
560 
561 // The relation between an NativeArray object (see below) and the
562 // native array it represents.
563 enum RelationToSource {
564   kReference,  // The NativeArray references the native array.
565   kCopy        // The NativeArray makes a copy of the native array and
566                // owns the copy.
567 };
568 
569 // Adapts a native array to a read-only STL-style container.  Instead
570 // of the complete STL container concept, this adaptor only implements
571 // members useful for Google Mock's container matchers.  New members
572 // should be added as needed.  To simplify the implementation, we only
573 // support Element being a raw type (i.e. having no top-level const or
574 // reference modifier).  It's the client's responsibility to satisfy
575 // this requirement.  Element can be an array type itself (hence
576 // multi-dimensional arrays are supported).
577 template <typename Element>
578 class NativeArray {
579  public:
580   // STL-style container typedefs.
581   typedef Element value_type;
582   typedef const Element* const_iterator;
583 
584   // Constructs from a native array passed by reference.
585   template <size_t N>
586   NativeArray(const Element (&array)[N], RelationToSource relation) {
587     Init(array, N, relation);
588   }
589 
590   // Constructs from a native array passed by a pointer and a size.
591   // For generality we don't artificially restrict the types of the
592   // pointer and the size.
593   template <typename Pointer, typename Size>
594   NativeArray(const ::std::tr1::tuple<Pointer, Size>& array,
595               RelationToSource relation) {
596     Init(internal::GetRawPointer(::std::tr1::get<0>(array)),
597          ::std::tr1::get<1>(array),
598          relation);
599   }
600 
601   // Copy constructor.
602   NativeArray(const NativeArray& rhs) {
603     Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
604   }
605 
606   ~NativeArray() {
607     // Ensures that the user doesn't instantiate NativeArray with a
608     // const or reference type.
609     testing::StaticAssertTypeEq<Element,
610         GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>();
611     if (relation_to_source_ == kCopy)
612       delete[] array_;
613   }
614 
615   // STL-style container methods.
616   size_t size() const { return size_; }
617   const_iterator begin() const { return array_; }
618   const_iterator end() const { return array_ + size_; }
619   bool operator==(const NativeArray& rhs) const {
620     return size() == rhs.size() &&
621         ArrayEq(begin(), size(), rhs.begin());
622   }
623 
624  private:
625   // Not implemented as we don't want to support assignment.
626   void operator=(const NativeArray& rhs);
627 
628   // Initializes this object; makes a copy of the input array if
629   // 'relation' is kCopy.
630   void Init(const Element* array, size_t size, RelationToSource relation) {
631     if (relation == kReference) {
632       array_ = array;
633     } else {
634       Element* const copy = new Element[size];
635       CopyArray(array, size, copy);
636       array_ = copy;
637     }
638     size_ = size;
639     relation_to_source_ = relation;
640   }
641 
642   const Element* array_;
643   size_t size_;
644   RelationToSource relation_to_source_;
645 };
646 
647 // Given a raw type (i.e. having no top-level reference or const
648 // modifier) RawContainer that's either an STL-style container or a
649 // native array, class StlContainerView<RawContainer> has the
650 // following members:
651 //
652 //   - type is a type that provides an STL-style container view to
653 //     (i.e. implements the STL container concept for) RawContainer;
654 //   - const_reference is a type that provides a reference to a const
655 //     RawContainer;
656 //   - ConstReference(raw_container) returns a const reference to an STL-style
657 //     container view to raw_container, which is a RawContainer.
658 //   - Copy(raw_container) returns an STL-style container view of a
659 //     copy of raw_container, which is a RawContainer.
660 //
661 // This generic version is used when RawContainer itself is already an
662 // STL-style container.
663 template <class RawContainer>
664 class StlContainerView {
665  public:
666   typedef RawContainer type;
667   typedef const type& const_reference;
668 
669   static const_reference ConstReference(const RawContainer& container) {
670     // Ensures that RawContainer is not a const type.
671     testing::StaticAssertTypeEq<RawContainer,
672         GMOCK_REMOVE_CONST_(RawContainer)>();
673     return container;
674   }
675   static type Copy(const RawContainer& container) { return container; }
676 };
677 
678 // This specialization is used when RawContainer is a native array type.
679 template <typename Element, size_t N>
680 class StlContainerView<Element[N]> {
681  public:
682   typedef GMOCK_REMOVE_CONST_(Element) RawElement;
683   typedef internal::NativeArray<RawElement> type;
684   // NativeArray<T> can represent a native array either by value or by
685   // reference (selected by a constructor argument), so 'const type'
686   // can be used to reference a const native array.  We cannot
687   // 'typedef const type& const_reference' here, as that would mean
688   // ConstReference() has to return a reference to a local variable.
689   typedef const type const_reference;
690 
691   static const_reference ConstReference(const Element (&array)[N]) {
692     // Ensures that Element is not a const type.
693     testing::StaticAssertTypeEq<Element, RawElement>();
694     return type(array, kReference);
695   }
696   static type Copy(const Element (&array)[N]) {
697     return type(array, kCopy);
698   }
699 };
700 
701 // This specialization is used when RawContainer is a native array
702 // represented as a (pointer, size) tuple.
703 template <typename ElementPointer, typename Size>
704 class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
705  public:
706   typedef GMOCK_REMOVE_CONST_(
707       typename internal::PointeeOf<ElementPointer>::type) RawElement;
708   typedef internal::NativeArray<RawElement> type;
709   typedef const type const_reference;
710 
711   static const_reference ConstReference(
712       const ::std::tr1::tuple<ElementPointer, Size>& array) {
713     return type(array, kReference);
714   }
715   static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
716     return type(array, kCopy);
717   }
718 };
719 
720 // The following specialization prevents the user from instantiating
721 // StlContainer with a reference type.
722 template <typename T> class StlContainerView<T&>;
723 
724 }  // namespace internal
725 }  // namespace testing
726 
727 #endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
728