blob: ee6aa1e239ffd1805d92cd1b91b3a5de259145ef [file] [log] [blame]
shiqiane35fdd92008-12-10 05:08:54 +00001// 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__.
zhanyong.wane0d051e2009-02-19 00:33:37 +000051#define GMOCK_CONCAT_TOKEN_IMPL_(foo, bar) foo##bar
52#define GMOCK_CONCAT_TOKEN_(foo, bar) GMOCK_CONCAT_TOKEN_IMPL_(foo, bar)
shiqiane35fdd92008-12-10 05:08:54 +000053
54#ifdef __GNUC__
zhanyong.wane0d051e2009-02-19 00:33:37 +000055#define GMOCK_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
shiqiane35fdd92008-12-10 05:08:54 +000056#else
zhanyong.wane0d051e2009-02-19 00:33:37 +000057#define GMOCK_ATTRIBUTE_UNUSED_
shiqiane35fdd92008-12-10 05:08:54 +000058#endif // __GNUC__
59
60class ProtocolMessage;
61namespace proto2 { class Message; }
62
63namespace testing {
64namespace internal {
65
zhanyong.wance198ff2009-02-12 01:34:27 +000066// 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".
70string ConvertIdentifierNameToWords(const char* id_name);
71
shiqiane35fdd92008-12-10 05:08:54 +000072// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
73// compiler error iff T1 and T2 are different types.
74template <typename T1, typename T2>
75struct CompileAssertTypesEqual;
76
77template <typename T>
78struct 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.
84template <typename T>
85struct RemoveReference { typedef T type; }; // NOLINT
86template <typename T>
87struct RemoveReference<T&> { typedef T type; }; // NOLINT
88
89// A handy wrapper around RemoveReference that works when the argument
90// T depends on template parameters.
zhanyong.wane0d051e2009-02-19 00:33:37 +000091#define GMOCK_REMOVE_REFERENCE_(T) \
shiqiane35fdd92008-12-10 05:08:54 +000092 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.
97template <typename T>
98struct RemoveConst { typedef T type; }; // NOLINT
99template <typename T>
100struct RemoveConst<const T> { typedef T type; }; // NOLINT
101
zhanyong.wanb8243162009-06-04 05:48:20 +0000102// 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
107template <typename T, size_t N>
108struct RemoveConst<T[N]> {
109 typedef typename RemoveConst<T>::type type[N];
110};
111#endif // _MSC_VER
112
shiqiane35fdd92008-12-10 05:08:54 +0000113// A handy wrapper around RemoveConst that works when the argument
114// T depends on template parameters.
zhanyong.wane0d051e2009-02-19 00:33:37 +0000115#define GMOCK_REMOVE_CONST_(T) \
shiqiane35fdd92008-12-10 05:08:54 +0000116 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.
121template <typename T>
122struct AddReference { typedef T& type; }; // NOLINT
123template <typename T>
124struct AddReference<T&> { typedef T& type; }; // NOLINT
125
126// A handy wrapper around AddReference that works when the argument T
127// depends on template parameters.
zhanyong.wane0d051e2009-02-19 00:33:37 +0000128#define GMOCK_ADD_REFERENCE_(T) \
shiqiane35fdd92008-12-10 05:08:54 +0000129 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.
zhanyong.wane0d051e2009-02-19 00:33:37 +0000140#define GMOCK_REFERENCE_TO_CONST_(T) \
141 GMOCK_ADD_REFERENCE_(const GMOCK_REMOVE_REFERENCE_(T))
shiqiane35fdd92008-12-10 05:08:54 +0000142
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.
147template <typename Pointer>
148struct 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.
154template <typename T>
155struct 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.
160template <typename Pointer>
161inline typename Pointer::element_type* GetRawPointer(const Pointer& p) {
162 return p.get();
163}
164// This overloaded version is for the raw pointer case.
165template <typename Element>
166inline Element* GetRawPointer(Element* p) { return p; }
167
168// This comparator allows linked_ptr to be stored in sets.
169template <typename T>
170struct LinkedPtrLessThan {
zhanyong.wan16cf4732009-05-14 20:55:30 +0000171 bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
shiqiane35fdd92008-12-10 05:08:54 +0000172 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.
180template <typename From, typename To>
181class 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};
221template <typename From, typename To>
222const bool ImplicitlyConvertible<From, To>::value;
223
zhanyong.wan16cf4732009-05-14 20:55:30 +0000224// 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.
229enum TypeKind {
230 kBool, kInteger, kFloatingPoint, kOther
231};
232
233// KindOf<T>::value is the kind of type T.
234template <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
242GMOCK_DECLARE_KIND_(bool, kBool);
243
244// All standard integer types.
245GMOCK_DECLARE_KIND_(char, kInteger);
246GMOCK_DECLARE_KIND_(signed char, kInteger);
247GMOCK_DECLARE_KIND_(unsigned char, kInteger);
248GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT
249GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT
250GMOCK_DECLARE_KIND_(int, kInteger);
251GMOCK_DECLARE_KIND_(unsigned int, kInteger);
252GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT
253GMOCK_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)
259GMOCK_DECLARE_KIND_(wchar_t, kInteger);
260#endif
261
262// Non-standard integer types.
263GMOCK_DECLARE_KIND_(Int64, kInteger);
264GMOCK_DECLARE_KIND_(UInt64, kInteger);
265
266// All standard floating-point types.
267GMOCK_DECLARE_KIND_(float, kFloatingPoint);
268GMOCK_DECLARE_KIND_(double, kFloatingPoint);
269GMOCK_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.
290template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
291struct LosslessArithmeticConvertibleImpl : public false_type {};
292
293// Converting bool to bool is lossless.
294template <>
295struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
296 : public true_type {}; // NOLINT
297
298// Converting bool to any integer type is lossless.
299template <typename To>
300struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
301 : public true_type {}; // NOLINT
302
303// Converting bool to any floating-point type is lossless.
304template <typename To>
305struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
306 : public true_type {}; // NOLINT
307
308// Converting an integer to bool is lossy.
309template <typename From>
310struct 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.
315template <typename From, typename To>
316struct 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.
330template <typename From, typename To>
331struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
332 : public false_type {}; // NOLINT
333
334// Converting a floating-point to bool is lossy.
335template <typename From>
336struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
337 : public false_type {}; // NOLINT
338
339// Converting a floating-point to an integer is lossy.
340template <typename From, typename To>
341struct 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.
346template <typename From, typename To>
347struct 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.
358template <typename From, typename To>
359struct LosslessArithmeticConvertible
360 : public LosslessArithmeticConvertibleImpl<
361 GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT
362
shiqiane35fdd92008-12-10 05:08:54 +0000363// 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.
366template <typename T>
zhanyong.wan16cf4732009-05-14 20:55:30 +0000367struct IsAProtocolMessage
368 : public bool_constant<
369 ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
370 ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
shiqiane35fdd92008-12-10 05:08:54 +0000371};
shiqiane35fdd92008-12-10 05:08:54 +0000372
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.
381typedef int IsContainer;
382template <class C>
383IsContainer IsContainerTest(typename C::const_iterator*) { return 0; }
384
385typedef char IsNotContainer;
386template <class C>
387IsNotContainer IsContainerTest(...) { return '\0'; }
388
389// This interface knows how to report a Google Mock failure (either
390// non-fatal or fatal).
391class 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.
406FailureReporterInterface* 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.
413inline 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}
420inline 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.
426inline 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}
433inline void Expect(bool condition, const char* file, int line) {
434 Expect(condition, file, line, "Expectation failed.");
435}
436
437// Severity level of a log.
438enum 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.
446const char kInfoVerbosity[] = "info";
447// Only warnings are printed.
448const char kWarningVerbosity[] = "warning";
449// No logs are printed.
450const char kErrorVerbosity[] = "error";
451
zhanyong.wan9413f2f2009-05-29 19:50:06 +0000452// Returns true iff a log with the given severity is visible according
453// to the --gmock_verbose flag.
454bool LogIsVisible(LogSeverity severity);
455
shiqiane35fdd92008-12-10 05:08:54 +0000456// 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.
463void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
464
zhanyong.wan16cf4732009-05-14 20:55:30 +0000465// TODO(wan@google.com): group all type utilities together.
466
shiqiane35fdd92008-12-10 05:08:54 +0000467// Type traits.
468
469// is_reference<T>::value is non-zero iff T is a reference type.
470template <typename T> struct is_reference : public false_type {};
471template <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.
474template <typename T1, typename T2> struct type_equals : public false_type {};
475template <typename T> struct type_equals<T, T> : public true_type {};
476
477// remove_reference<T>::type removes the reference from type T, if any.
zhanyong.wan16cf4732009-05-14 20:55:30 +0000478template <typename T> struct remove_reference { typedef T type; }; // NOLINT
479template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
shiqiane35fdd92008-12-10 05:08:54 +0000480
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).
485template <typename T>
486inline T Invalid() {
487 return *static_cast<typename remove_reference<T>::type*>(NULL);
488}
489template <>
490inline void Invalid<void>() {}
491
zhanyong.wanb8243162009-06-04 05:48:20 +0000492// 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
498template <typename T, typename U>
499bool ArrayEq(const T* lhs, size_t size, const U* rhs);
500
501// This generic version is used when k is 0.
502template <typename T, typename U>
503inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
504
505// This overload is used when k >= 1.
506template <typename T, typename U, size_t N>
507inline 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.
514template <typename T, typename U>
515bool 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.
525template <typename Iter, typename Element>
526Iter 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
538template <typename T, typename U>
539void CopyArray(const T* from, size_t size, U* to);
540
541// This generic version is used when k is 0.
542template <typename T, typename U>
543inline void CopyArray(const T& from, U* to) { *to = from; }
544
545// This overload is used when k >= 1.
546template <typename T, typename U, size_t N>
547inline 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.
554template <typename T, typename U>
555void 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.
563enum 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).
577template <typename Element>
578class 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.
663template <class RawContainer>
664class 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.
679template <typename Element, size_t N>
680class 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.
703template <typename ElementPointer, typename Size>
704class 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.
722template <typename T> class StlContainerView<T&>;
723
shiqiane35fdd92008-12-10 05:08:54 +0000724} // namespace internal
725} // namespace testing
726
727#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_