| /************************************************************************ |
| * |
| * 23.containers.h - definitions of helpers used in clause 23 tests |
| * |
| * $Id: 23.containers.h |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| **************************************************************************/ |
| |
| #ifndef RW_23_CONTAINERS_H_INCLUDED |
| #define RW_23_CONTAINERS_H_INCLUDED |
| |
| #include <testdefs.h> |
| #include <rw_value.h> // for UserClass, UserPOD |
| #include <rw_char.h> // for rw_expand () |
| #include <driver.h> // for rw_assert () |
| |
| /**************************************************************************/ |
| |
| // defines enumerations identifying the general template arguments, |
| // sets of overloaded functions, member types used in the declarations |
| // of their signatures, and specific overloads of such member functions |
| struct ContainerIds { |
| |
| // identifiers for the T template argument |
| enum ElemId { UserPOD, UserClass }; |
| |
| // identifiers for the Allocator template argument |
| enum AllocId { DefaultAlloc, UserAlloc }; |
| |
| // identifiers for the Iterator template argument |
| // used with member templates |
| enum IteratorId { |
| None, |
| Input, Forward, Bidir, Random, |
| Pointer, ConstPointer, |
| Iterator, ConstIterator, |
| ReverseIterator, ConstReverseIterator |
| }; |
| |
| enum ContainerId { |
| List, Vector, Deque, Queue, Stack |
| }; |
| |
| // identifies a set of overloaded member or non-member |
| // container functions |
| enum FuncId { |
| // 6 bits, 64 functions max |
| // common |
| /* 0 */ fid_ctor, |
| /* 1 */ fid_op_set, |
| /* 2 */ fid_assign, |
| /* 3 */ fid_get_allocator, |
| /* 4 */ fid_begin, |
| /* */ fid_begin_const = fid_begin, |
| /* 5 */ fid_end, |
| /* */ fid_end_const = fid_end, |
| /* 6 */ fid_rbegin, |
| /* */ fid_rbegin_const = fid_rbegin, |
| /* 7 */ fid_rend, |
| /* */ fid_rend_const = fid_rend, |
| /* 8 */ fid_empty, |
| /* 9 */ fid_size, |
| /* 10 */ fid_max_size, |
| /* 11 */ fid_resize, |
| /* 12 */ fid_insert, |
| /* 13 */ fid_erase, |
| /* 14 */ fid_swap, |
| /* 15 */ fid_clear, |
| /* 16 */ fid_op_equal, |
| /* 17 */ fid_op_less, |
| /* 18 */ fid_op_not_equal, |
| /* 19 */ fid_op_greater, |
| /* 20 */ fid_op_greater_equal, |
| /* 21 */ fid_op_less_equal, |
| /* 22 */ fid_push_back, |
| |
| // list, deque, vector |
| /* 23 */ fid_front, |
| /* */ fid_front_const = fid_front, |
| /* 24 */ fid_back, |
| /* */ fid_back_const = fid_back, |
| /* 25 */ fid_pop_back, |
| |
| // list, deque |
| /* 26 */ fid_push_front, |
| /* 27 */ fid_pop_front, |
| |
| // list |
| /* 28 */ fid_splice, |
| /* 29 */ fid_remove, |
| /* 30 */ fid_remove_if, |
| /* 31 */ fid_unique, |
| /* 32 */ fid_merge, |
| /* 33 */ fid_sort, |
| /* 34 */ fid_reverse, |
| |
| // vector, string, deque |
| /* 35 */ fid_op_index, |
| /* */ fid_op_index_const = fid_op_index, |
| /* 36 */ fid_at, |
| /* */ fid_at_const = fid_at, |
| |
| // vector, string |
| /* 37 */ fid_capacity, |
| /* 38 */ fid_reserve, |
| |
| // vector<bool> |
| /* 39 */ fid_flip, |
| |
| /* -- */ fid_bits = 6, |
| /* -- */ fid_mask = 63 |
| }; |
| |
| // identifies the type of a function argument, including |
| // the implicit this |
| enum ArgId { |
| // 4 bits, 16 types max |
| /* 0 */ arg_void, // void |
| /* 1 */ arg_size, // size_type |
| /* 2 */ arg_val, // value_type |
| /* 3 */ arg_ref, // reference |
| /* 4 */ arg_cref, // const_reference |
| /* 5 */ arg_iter, // iterator |
| /* 6 */ arg_citer, // const_iterator |
| /* 7 */ arg_range, // Iterator, Iterator |
| /* 8 */ arg_cont, // container& (or this for member functions) |
| /* 9 */ arg_ccont, // const container& (or const this for members) |
| /* 10 */ arg_alloc, // const allocator& |
| /* 11 */ arg_pred, // Predicate |
| /* 12 */ arg_bpred, // BinaryPredicate |
| /* 13 */ arg_comp, // Compare |
| /* -- */ arg_bits = 4, |
| /* -- */ arg_mask = 15 |
| }; |
| |
| enum { |
| // bit designating a member function |
| bit_member = 1 << (fid_bits + 6 * arg_bits) |
| }; |
| |
| static ArgId arg_type (_RWSTD_SIZE_T id, int argno) { |
| return ArgId (((id >> fid_bits) >> argno * arg_bits) & arg_mask); |
| } |
| }; |
| |
| /**************************************************************************/ |
| |
| struct ContainerFunc |
| { |
| ContainerIds::ElemId elem_id_; |
| ContainerIds::AllocId alloc_id_; |
| ContainerIds::IteratorId iter_id_; |
| ContainerIds::ContainerId cont_id_; |
| _RWSTD_SIZE_T which_; |
| }; |
| |
| |
| // describes a single test case for any overload of any container |
| // function (the same test case can be used to exercise more |
| // than one overload of the same function) |
| struct ContainerTestCase |
| { |
| int line; // test case line number |
| |
| int off; // offset (position argument) |
| int size; // size (count argument) |
| |
| int off2; // offset 2 (position argument) |
| int size2; // size 2 (count argument) |
| |
| int val; // value (single character to append) |
| |
| const char* str; // controlled sequence |
| _RWSTD_SIZE_T str_len; // length of sequence |
| |
| const char* arg; // sequence to insert |
| _RWSTD_SIZE_T arg_len; // length of sequence |
| |
| const char* res; // resulting sequence |
| _RWSTD_SIZE_T nres; // length of sequence or expected result value |
| |
| int bthrow; // exception expected |
| }; |
| |
| |
| // describes a set of test cases for a single overload of a function |
| struct ContainerTest |
| { |
| // container function overload to exercise |
| _RWSTD_SIZE_T which; |
| |
| // test cases to exercise overload with |
| const ContainerTestCase *cases; |
| |
| // number of test cases |
| _RWSTD_SIZE_T case_count; |
| }; |
| |
| |
| typedef void ContainerTestFunc (const ContainerFunc&, const ContainerTestCase&); |
| |
| _TEST_EXPORT int |
| rw_run_cont_test (int, char**, const char*, const char*, |
| ContainerIds::ContainerId, ContainerTestFunc*, |
| const ContainerTest*, _RWSTD_SIZE_T); |
| |
| typedef void VoidFunc (); |
| |
| _TEST_EXPORT int |
| rw_run_cont_test (int, char**, const char*, const char*, |
| ContainerIds::ContainerId, VoidFunc* const*, |
| const ContainerTest*, _RWSTD_SIZE_T); |
| |
| /**************************************************************************/ |
| |
| template <class T> |
| class ContainerTestCaseData |
| { |
| private: |
| |
| // not defined, not copyable, not assignable |
| ContainerTestCaseData (const ContainerTestCaseData&); |
| void operator= (const ContainerTestCaseData&); |
| |
| // for convenience |
| typedef _RWSTD_SIZE_T SizeType; |
| |
| public: |
| |
| SizeType strlen_; // the length of the expanded string |
| SizeType arglen_; // the length of the expanded argument |
| SizeType reslen_; // the length of the expanded result |
| |
| // the offset and extent (the number of elements) of |
| // the first range into the container object being modified |
| SizeType off1_; |
| SizeType ext1_; |
| |
| // the offset and extent (the number of elements) of |
| // the argument of the function call |
| SizeType off2_; |
| SizeType ext2_; |
| |
| const T* str_; // pointer to the expanded string |
| const T* arg_; // pointer to the expanded argument |
| const T* res_; // pointer to the expanded result |
| |
| const ContainerFunc &func_; |
| const ContainerTestCase &tcase_; |
| |
| // converts the narrow (and possibly) condensed strings to fully |
| // expanded wide character arrays that can be used to construct |
| // container objects |
| ContainerTestCaseData (const ContainerFunc &func, |
| const ContainerTestCase &tcase) |
| : func_ (func), tcase_ (tcase) { |
| |
| char buf [256]; |
| |
| strlen_ = sizeof (buf); |
| char* str = rw_expand (buf, tcase.str, tcase.str_len, &strlen_); |
| str_ = T::from_char (str, strlen_); |
| if (str != buf) |
| delete[] str; |
| |
| arglen_ = sizeof (buf); |
| str = rw_expand (buf, tcase.arg, tcase.arg_len, &arglen_); |
| arg_ = T::from_char (str, arglen_); |
| if (str != buf) |
| delete[] str; |
| |
| reslen_ = sizeof (buf); |
| str = rw_expand (buf, tcase.res, tcase.nres, &reslen_); |
| res_ = T::from_char (str, reslen_); |
| if (str != buf) |
| delete[] str; |
| |
| // compute the offset and extent of the container object |
| // representing the controlled sequence and the offset |
| // and extent of the argument of the function call |
| const SizeType argl = tcase_.arg ? arglen_ : strlen_; |
| |
| off1_ = SizeType (tcase_.off) < strlen_ ? |
| SizeType (tcase_.off) : strlen_; |
| |
| ext1_ = off1_ + tcase_.size < strlen_ ? |
| SizeType (tcase_.size) : strlen_ - off1_; |
| |
| off2_ = SizeType (tcase_.off2) < argl ? |
| SizeType (tcase_.off2) : argl; |
| |
| ext2_ = off2_ + tcase_.size2 < argl ? |
| SizeType (tcase_.size2) : argl - off2_; |
| } |
| |
| ~ContainerTestCaseData () { |
| // clean up dynamically allocated memory |
| delete[] str_; |
| delete[] arg_; |
| delete[] res_; |
| } |
| }; |
| |
| /**************************************************************************/ |
| |
| // base class-functor for the range template overloads testing |
| template <class Cont> |
| struct ContRangeBase { |
| |
| typedef typename Cont::value_type ContVal; |
| typedef typename Cont::iterator ContIter; |
| typedef typename Cont::const_iterator ContConstIter; |
| typedef typename Cont::reverse_iterator ContRevIter; |
| typedef typename Cont::const_reverse_iterator ContConstRevIter; |
| |
| ContRangeBase () { } |
| |
| virtual ~ContRangeBase () { /* silence warnings */ } |
| |
| static ContIter |
| begin (Cont &cont, ContIter*) { |
| return cont.begin (); |
| } |
| |
| static ContConstIter |
| begin (const Cont &cont, ContConstIter*) { |
| return cont.begin (); |
| } |
| |
| static ContRevIter |
| begin (Cont &cont, ContRevIter*) { |
| return cont.rbegin (); |
| } |
| |
| static ContConstRevIter |
| begin (const Cont &cont, ContConstRevIter*) { |
| return cont.rbegin (); |
| } |
| |
| virtual Cont& |
| operator() (Cont &cont, const ContainerTestCaseData<ContVal>&) const { |
| RW_ASSERT (!"logic error: should be never called"); |
| return cont; |
| } |
| }; |
| |
| /**************************************************************************/ |
| |
| # define CONTAINER_TEST_DISPATCH(Alloc, fname, func, tcase) \ |
| if (ContainerIds::UserPOD == func.elem_id_) \ |
| fname (UserPOD (), (Alloc<UserPOD>*)0, func, tcase); \ |
| else \ |
| fname (UserClass (), (Alloc<UserClass>*)0, func, tcase) |
| |
| |
| #define DEFINE_CONTAINER_TEST_DISPATCH(fname) \ |
| static void \ |
| fname (const ContainerFunc &func, \ |
| const ContainerTestCase &tcase) { \ |
| if (ContainerIds::DefaultAlloc == func.alloc_id_) { \ |
| CONTAINER_TEST_DISPATCH (std::allocator, fname, func, tcase); \ |
| } \ |
| else if (ContainerIds::UserAlloc == func.alloc_id_) { \ |
| CONTAINER_TEST_DISPATCH (UserAlloc, fname, func, tcase); \ |
| } \ |
| else \ |
| RW_ASSERT (!"logic error: bad allocator"); \ |
| } typedef void rw_unused_typedef |
| |
| |
| #define CONTAINER_TFUNC(T, Allocator) \ |
| void (*)(T*, Allocator<T>*, \ |
| const ContainerTestCaseData<T>&) |
| |
| #define CONTAINER_TFUNC_ADDR(fname, T, Allocator) \ |
| (VoidFunc*)(CONTAINER_TFUNC (T, Allocator)) \ |
| &fname<T, Allocator<T> > |
| |
| #define DEFINE_CONTAINER_TEST_FUNCTIONS(fname) \ |
| static VoidFunc* const fname ## _func_array [] = { \ |
| CONTAINER_TFUNC_ADDR (fname, UserPOD, std::allocator), \ |
| CONTAINER_TFUNC_ADDR (fname, UserPOD, UserAlloc), \ |
| \ |
| CONTAINER_TFUNC_ADDR (fname, UserClass, std::allocator), \ |
| CONTAINER_TFUNC_ADDR (fname, UserClass, UserAlloc) \ |
| } |
| |
| #endif // RW_23_CONTAINERS_H_INCLUDED |