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 // Symbian compilation can be done with wchar_t being either a native 225 // type or a typedef. Using Google Mock with OpenC without wchar_t 226 // should require the definition of _STLP_NO_WCHAR_T. 227 // 228 // MSVC treats wchar_t as a native type usually, but treats it as the 229 // same as unsigned short when the compiler option /Zc:wchar_t- is 230 // specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t 231 // is a native type. 232 #if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \ 233 (defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)) 234 // wchar_t is a typedef. 235 #else 236 #define GMOCK_WCHAR_T_IS_NATIVE_ 1 237 #endif 238 239 // signed wchar_t and unsigned wchar_t are NOT in the C++ standard. 240 // Using them is a bad practice and not portable. So DON'T use them. 241 // 242 // Still, Google Mock is designed to work even if the user uses signed 243 // wchar_t or unsigned wchar_t (obviously, assuming the compiler 244 // supports them). 245 // 246 // To gcc, 247 // wchar_t == signed wchar_t != unsigned wchar_t == unsigned int 248 #ifdef __GNUC__ 249 #define GMOCK_HAS_SIGNED_WCHAR_T_ 1 // signed/unsigned wchar_t are valid types. 250 #endif 251 252 // In what follows, we use the term "kind" to indicate whether a type 253 // is bool, an integer type (excluding bool), a floating-point type, 254 // or none of them. This categorization is useful for determining 255 // when a matcher argument type can be safely converted to another 256 // type in the implementation of SafeMatcherCast. 257 enum TypeKind { 258 kBool, kInteger, kFloatingPoint, kOther 259 }; 260 261 // KindOf<T>::value is the kind of type T. 262 template <typename T> struct KindOf { 263 enum { value = kOther }; // The default kind. 264 }; 265 266 // This macro declares that the kind of 'type' is 'kind'. 267 #define GMOCK_DECLARE_KIND_(type, kind) \ 268 template <> struct KindOf<type> { enum { value = kind }; } 269 270 GMOCK_DECLARE_KIND_(bool, kBool); 271 272 // All standard integer types. 273 GMOCK_DECLARE_KIND_(char, kInteger); 274 GMOCK_DECLARE_KIND_(signed char, kInteger); 275 GMOCK_DECLARE_KIND_(unsigned char, kInteger); 276 GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT 277 GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT 278 GMOCK_DECLARE_KIND_(int, kInteger); 279 GMOCK_DECLARE_KIND_(unsigned int, kInteger); 280 GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT 281 GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT 282 283 #if GMOCK_WCHAR_T_IS_NATIVE_ 284 GMOCK_DECLARE_KIND_(wchar_t, kInteger); 285 #endif 286 287 // Non-standard integer types. 288 GMOCK_DECLARE_KIND_(Int64, kInteger); 289 GMOCK_DECLARE_KIND_(UInt64, kInteger); 290 291 // All standard floating-point types. 292 GMOCK_DECLARE_KIND_(float, kFloatingPoint); 293 GMOCK_DECLARE_KIND_(double, kFloatingPoint); 294 GMOCK_DECLARE_KIND_(long double, kFloatingPoint); 295 296 #undef GMOCK_DECLARE_KIND_ 297 298 // Evaluates to the kind of 'type'. 299 #define GMOCK_KIND_OF_(type) \ 300 static_cast< ::testing::internal::TypeKind>( \ 301 ::testing::internal::KindOf<type>::value) 302 303 // Evaluates to true iff integer type T is signed. 304 #define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0) 305 306 // LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value 307 // is true iff arithmetic type From can be losslessly converted to 308 // arithmetic type To. 309 // 310 // It's the user's responsibility to ensure that both From and To are 311 // raw (i.e. has no CV modifier, is not a pointer, and is not a 312 // reference) built-in arithmetic types, kFromKind is the kind of 313 // From, and kToKind is the kind of To; the value is 314 // implementation-defined when the above pre-condition is violated. 315 template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To> 316 struct LosslessArithmeticConvertibleImpl : public false_type {}; 317 318 // Converting bool to bool is lossless. 319 template <> 320 struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool> 321 : public true_type {}; // NOLINT 322 323 // Converting bool to any integer type is lossless. 324 template <typename To> 325 struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To> 326 : public true_type {}; // NOLINT 327 328 // Converting bool to any floating-point type is lossless. 329 template <typename To> 330 struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To> 331 : public true_type {}; // NOLINT 332 333 // Converting an integer to bool is lossy. 334 template <typename From> 335 struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool> 336 : public false_type {}; // NOLINT 337 338 // Converting an integer to another non-bool integer is lossless iff 339 // the target type's range encloses the source type's range. 340 template <typename From, typename To> 341 struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To> 342 : public bool_constant< 343 // When converting from a smaller size to a larger size, we are 344 // fine as long as we are not converting from signed to unsigned. 345 ((sizeof(From) < sizeof(To)) && 346 (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) || 347 // When converting between the same size, the signedness must match. 348 ((sizeof(From) == sizeof(To)) && 349 (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT 350 351 #undef GMOCK_IS_SIGNED_ 352 353 // Converting an integer to a floating-point type may be lossy, since 354 // the format of a floating-point number is implementation-defined. 355 template <typename From, typename To> 356 struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To> 357 : public false_type {}; // NOLINT 358 359 // Converting a floating-point to bool is lossy. 360 template <typename From> 361 struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool> 362 : public false_type {}; // NOLINT 363 364 // Converting a floating-point to an integer is lossy. 365 template <typename From, typename To> 366 struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To> 367 : public false_type {}; // NOLINT 368 369 // Converting a floating-point to another floating-point is lossless 370 // iff the target type is at least as big as the source type. 371 template <typename From, typename To> 372 struct LosslessArithmeticConvertibleImpl< 373 kFloatingPoint, From, kFloatingPoint, To> 374 : public bool_constant<sizeof(From) <= sizeof(To)> {}; // NOLINT 375 376 // LosslessArithmeticConvertible<From, To>::value is true iff arithmetic 377 // type From can be losslessly converted to arithmetic type To. 378 // 379 // It's the user's responsibility to ensure that both From and To are 380 // raw (i.e. has no CV modifier, is not a pointer, and is not a 381 // reference) built-in arithmetic types; the value is 382 // implementation-defined when the above pre-condition is violated. 383 template <typename From, typename To> 384 struct LosslessArithmeticConvertible 385 : public LosslessArithmeticConvertibleImpl< 386 GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT 387 388 // IsAProtocolMessage<T>::value is a compile-time bool constant that's 389 // true iff T is type ProtocolMessage, proto2::Message, or a subclass 390 // of those. 391 template <typename T> 392 struct IsAProtocolMessage 393 : public bool_constant< 394 ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value || 395 ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> { 396 }; 397 398 // When the compiler sees expression IsContainerTest<C>(0), the first 399 // overload of IsContainerTest will be picked if C is an STL-style 400 // container class (since C::const_iterator* is a valid type and 0 can 401 // be converted to it), while the second overload will be picked 402 // otherwise (since C::const_iterator will be an invalid type in this 403 // case). Therefore, we can determine whether C is a container class 404 // by checking the type of IsContainerTest<C>(0). The value of the 405 // expression is insignificant. 406 typedef int IsContainer; 407 template <class C> 408 IsContainer IsContainerTest(typename C::const_iterator*) { return 0; } 409 410 typedef char IsNotContainer; 411 template <class C> 412 IsNotContainer IsContainerTest(...) { return '\0'; } 413 414 // This interface knows how to report a Google Mock failure (either 415 // non-fatal or fatal). 416 class FailureReporterInterface { 417 public: 418 // The type of a failure (either non-fatal or fatal). 419 enum FailureType { 420 NONFATAL, FATAL 421 }; 422 423 virtual ~FailureReporterInterface() {} 424 425 // Reports a failure that occurred at the given source file location. 426 virtual void ReportFailure(FailureType type, const char* file, int line, 427 const string& message) = 0; 428 }; 429 430 // Returns the failure reporter used by Google Mock. 431 FailureReporterInterface* GetFailureReporter(); 432 433 // Asserts that condition is true; aborts the process with the given 434 // message if condition is false. We cannot use LOG(FATAL) or CHECK() 435 // as Google Mock might be used to mock the log sink itself. We 436 // inline this function to prevent it from showing up in the stack 437 // trace. 438 inline void Assert(bool condition, const char* file, int line, 439 const string& msg) { 440 if (!condition) { 441 GetFailureReporter()->ReportFailure(FailureReporterInterface::FATAL, 442 file, line, msg); 443 } 444 } 445 inline void Assert(bool condition, const char* file, int line) { 446 Assert(condition, file, line, "Assertion failed."); 447 } 448 449 // Verifies that condition is true; generates a non-fatal failure if 450 // condition is false. 451 inline void Expect(bool condition, const char* file, int line, 452 const string& msg) { 453 if (!condition) { 454 GetFailureReporter()->ReportFailure(FailureReporterInterface::NONFATAL, 455 file, line, msg); 456 } 457 } 458 inline void Expect(bool condition, const char* file, int line) { 459 Expect(condition, file, line, "Expectation failed."); 460 } 461 462 // Severity level of a log. 463 enum LogSeverity { 464 INFO = 0, 465 WARNING = 1, 466 }; 467 468 // Valid values for the --gmock_verbose flag. 469 470 // All logs (informational and warnings) are printed. 471 const char kInfoVerbosity[] = "info"; 472 // Only warnings are printed. 473 const char kWarningVerbosity[] = "warning"; 474 // No logs are printed. 475 const char kErrorVerbosity[] = "error"; 476 477 // Returns true iff a log with the given severity is visible according 478 // to the --gmock_verbose flag. 479 bool LogIsVisible(LogSeverity severity); 480 481 // Prints the given message to stdout iff 'severity' >= the level 482 // specified by the --gmock_verbose flag. If stack_frames_to_skip >= 483 // 0, also prints the stack trace excluding the top 484 // stack_frames_to_skip frames. In opt mode, any positive 485 // stack_frames_to_skip is treated as 0, since we don't know which 486 // function calls will be inlined by the compiler and need to be 487 // conservative. 488 void Log(LogSeverity severity, const string& message, int stack_frames_to_skip); 489 490 // TODO(wan@google.com): group all type utilities together. 491 492 // Type traits. 493 494 // is_reference<T>::value is non-zero iff T is a reference type. 495 template <typename T> struct is_reference : public false_type {}; 496 template <typename T> struct is_reference<T&> : public true_type {}; 497 498 // type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type. 499 template <typename T1, typename T2> struct type_equals : public false_type {}; 500 template <typename T> struct type_equals<T, T> : public true_type {}; 501 502 // remove_reference<T>::type removes the reference from type T, if any. 503 template <typename T> struct remove_reference { typedef T type; }; // NOLINT 504 template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT 505 506 // Invalid<T>() returns an invalid value of type T. This is useful 507 // when a value of type T is needed for compilation, but the statement 508 // will not really be executed (or we don't care if the statement 509 // crashes). 510 template <typename T> 511 inline T Invalid() { 512 return *static_cast<typename remove_reference<T>::type*>(NULL); 513 } 514 template <> 515 inline void Invalid<void>() {} 516 517 // Utilities for native arrays. 518 519 // ArrayEq() compares two k-dimensional native arrays using the 520 // elements' operator==, where k can be any integer >= 0. When k is 521 // 0, ArrayEq() degenerates into comparing a single pair of values. 522 523 template <typename T, typename U> 524 bool ArrayEq(const T* lhs, size_t size, const U* rhs); 525 526 // This generic version is used when k is 0. 527 template <typename T, typename U> 528 inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; } 529 530 // This overload is used when k >= 1. 531 template <typename T, typename U, size_t N> 532 inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) { 533 return internal::ArrayEq(lhs, N, rhs); 534 } 535 536 // This helper reduces code bloat. If we instead put its logic inside 537 // the previous ArrayEq() function, arrays with different sizes would 538 // lead to different copies of the template code. 539 template <typename T, typename U> 540 bool ArrayEq(const T* lhs, size_t size, const U* rhs) { 541 for (size_t i = 0; i != size; i++) { 542 if (!internal::ArrayEq(lhs[i], rhs[i])) 543 return false; 544 } 545 return true; 546 } 547 548 // Finds the first element in the iterator range [begin, end) that 549 // equals elem. Element may be a native array type itself. 550 template <typename Iter, typename Element> 551 Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) { 552 for (Iter it = begin; it != end; ++it) { 553 if (internal::ArrayEq(*it, elem)) 554 return it; 555 } 556 return end; 557 } 558 559 // CopyArray() copies a k-dimensional native array using the elements' 560 // operator=, where k can be any integer >= 0. When k is 0, 561 // CopyArray() degenerates into copying a single value. 562 563 template <typename T, typename U> 564 void CopyArray(const T* from, size_t size, U* to); 565 566 // This generic version is used when k is 0. 567 template <typename T, typename U> 568 inline void CopyArray(const T& from, U* to) { *to = from; } 569 570 // This overload is used when k >= 1. 571 template <typename T, typename U, size_t N> 572 inline void CopyArray(const T(&from)[N], U(*to)[N]) { 573 internal::CopyArray(from, N, *to); 574 } 575 576 // This helper reduces code bloat. If we instead put its logic inside 577 // the previous CopyArray() function, arrays with different sizes 578 // would lead to different copies of the template code. 579 template <typename T, typename U> 580 void CopyArray(const T* from, size_t size, U* to) { 581 for (size_t i = 0; i != size; i++) { 582 internal::CopyArray(from[i], to + i); 583 } 584 } 585 586 // The relation between an NativeArray object (see below) and the 587 // native array it represents. 588 enum RelationToSource { 589 kReference, // The NativeArray references the native array. 590 kCopy // The NativeArray makes a copy of the native array and 591 // owns the copy. 592 }; 593 594 // Adapts a native array to a read-only STL-style container. Instead 595 // of the complete STL container concept, this adaptor only implements 596 // members useful for Google Mock's container matchers. New members 597 // should be added as needed. To simplify the implementation, we only 598 // support Element being a raw type (i.e. having no top-level const or 599 // reference modifier). It's the client's responsibility to satisfy 600 // this requirement. Element can be an array type itself (hence 601 // multi-dimensional arrays are supported). 602 template <typename Element> 603 class NativeArray { 604 public: 605 // STL-style container typedefs. 606 typedef Element value_type; 607 typedef const Element* const_iterator; 608 609 // Constructs from a native array. 610 NativeArray(const Element* array, size_t count, RelationToSource relation) { 611 Init(array, count, relation); 612 } 613 614 // Copy constructor. 615 NativeArray(const NativeArray& rhs) { 616 Init(rhs.array_, rhs.size_, rhs.relation_to_source_); 617 } 618 619 ~NativeArray() { 620 // Ensures that the user doesn't instantiate NativeArray with a 621 // const or reference type. 622 testing::StaticAssertTypeEq<Element, 623 GMOCK_REMOVE_CONST_(GMOCK_REMOVE_REFERENCE_(Element))>(); 624 if (relation_to_source_ == kCopy) 625 delete[] array_; 626 } 627 628 // STL-style container methods. 629 size_t size() const { return size_; } 630 const_iterator begin() const { return array_; } 631 const_iterator end() const { return array_ + size_; } 632 bool operator==(const NativeArray& rhs) const { 633 return size() == rhs.size() && 634 ArrayEq(begin(), size(), rhs.begin()); 635 } 636 637 private: 638 // Not implemented as we don't want to support assignment. 639 void operator=(const NativeArray& rhs); 640 641 // Initializes this object; makes a copy of the input array if 642 // 'relation' is kCopy. 643 void Init(const Element* array, size_t a_size, RelationToSource relation) { 644 if (relation == kReference) { 645 array_ = array; 646 } else { 647 Element* const copy = new Element[a_size]; 648 CopyArray(array, a_size, copy); 649 array_ = copy; 650 } 651 size_ = a_size; 652 relation_to_source_ = relation; 653 } 654 655 const Element* array_; 656 size_t size_; 657 RelationToSource relation_to_source_; 658 }; 659 660 // Given a raw type (i.e. having no top-level reference or const 661 // modifier) RawContainer that's either an STL-style container or a 662 // native array, class StlContainerView<RawContainer> has the 663 // following members: 664 // 665 // - type is a type that provides an STL-style container view to 666 // (i.e. implements the STL container concept for) RawContainer; 667 // - const_reference is a type that provides a reference to a const 668 // RawContainer; 669 // - ConstReference(raw_container) returns a const reference to an STL-style 670 // container view to raw_container, which is a RawContainer. 671 // - Copy(raw_container) returns an STL-style container view of a 672 // copy of raw_container, which is a RawContainer. 673 // 674 // This generic version is used when RawContainer itself is already an 675 // STL-style container. 676 template <class RawContainer> 677 class StlContainerView { 678 public: 679 typedef RawContainer type; 680 typedef const type& const_reference; 681 682 static const_reference ConstReference(const RawContainer& container) { 683 // Ensures that RawContainer is not a const type. 684 testing::StaticAssertTypeEq<RawContainer, 685 GMOCK_REMOVE_CONST_(RawContainer)>(); 686 return container; 687 } 688 static type Copy(const RawContainer& container) { return container; } 689 }; 690 691 // This specialization is used when RawContainer is a native array type. 692 template <typename Element, size_t N> 693 class StlContainerView<Element[N]> { 694 public: 695 typedef GMOCK_REMOVE_CONST_(Element) RawElement; 696 typedef internal::NativeArray<RawElement> type; 697 // NativeArray<T> can represent a native array either by value or by 698 // reference (selected by a constructor argument), so 'const type' 699 // can be used to reference a const native array. We cannot 700 // 'typedef const type& const_reference' here, as that would mean 701 // ConstReference() has to return a reference to a local variable. 702 typedef const type const_reference; 703 704 static const_reference ConstReference(const Element (&array)[N]) { 705 // Ensures that Element is not a const type. 706 testing::StaticAssertTypeEq<Element, RawElement>(); 707 #if GTEST_OS_SYMBIAN 708 // The Nokia Symbian compiler confuses itself in template instantiation 709 // for this call without the cast to Element*: 710 // function call '[testing::internal::NativeArray<char *>].NativeArray( 711 // {lval} const char *[4], long, testing::internal::RelationToSource)' 712 // does not match 713 // 'testing::internal::NativeArray<char *>::NativeArray( 714 // char *const *, unsigned int, testing::internal::RelationToSource)' 715 // (instantiating: 'testing::internal::ContainsMatcherImpl 716 // <const char * (&)[4]>::Matches(const char * (&)[4]) const') 717 // (instantiating: 'testing::internal::StlContainerView<char *[4]>:: 718 // ConstReference(const char * (&)[4])') 719 // (and though the N parameter type is mismatched in the above explicit 720 // conversion of it doesn't help - only the conversion of the array). 721 return type(const_cast<Element*>(&array[0]), N, kReference); 722 #else 723 return type(array, N, kReference); 724 #endif // GTEST_OS_SYMBIAN 725 } 726 static type Copy(const Element (&array)[N]) { 727 #if GTEST_OS_SYMBIAN 728 return type(const_cast<Element*>(&array[0]), N, kCopy); 729 #else 730 return type(array, N, kCopy); 731 #endif // GTEST_OS_SYMBIAN 732 } 733 }; 734 735 // This specialization is used when RawContainer is a native array 736 // represented as a (pointer, size) tuple. 737 template <typename ElementPointer, typename Size> 738 class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > { 739 public: 740 typedef GMOCK_REMOVE_CONST_( 741 typename internal::PointeeOf<ElementPointer>::type) RawElement; 742 typedef internal::NativeArray<RawElement> type; 743 typedef const type const_reference; 744 745 static const_reference ConstReference( 746 const ::std::tr1::tuple<ElementPointer, Size>& array) { 747 using ::std::tr1::get; 748 return type(get<0>(array), get<1>(array), kReference); 749 } 750 static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) { 751 using ::std::tr1::get; 752 return type(get<0>(array), get<1>(array), kCopy); 753 } 754 }; 755 756 // The following specialization prevents the user from instantiating 757 // StlContainer with a reference type. 758 template <typename T> class StlContainerView<T&>; 759 760 } // namespace internal 761 } // namespace testing 762 763 #endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ 764