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