Compare commits

63 Commits

Author SHA1 Message Date
hugogogo
38e82e4e11 improved makefile 2022-07-11 19:17:22 +02:00
hugogogo
ed7d1d1ed9 abandon changes in balancing algo 2022-07-06 22:19:35 +02:00
Hugo LAMY
3280f4a754 wip balance identical for erase and insert now 2022-07-06 04:10:07 +02:00
Hugo LAMY
81b76ae040 correct map insert to use _comp, add tests iterators in swap, and add correction screenshot 2022-07-05 21:22:34 +02:00
Hugo LAMY
ca066489a7 makefile with special rules for deps 2022-07-05 15:09:19 +02:00
Hugo LAMY
56c42a66b6 makefile without special rules for deps 2022-07-05 15:06:57 +02:00
hugogogo
581458ca37 avoid mystruct at begining of choosen testswith SFINAE technic 2022-07-04 15:50:26 +02:00
Hugo LAMY
52fa6ff65b all broken 2022-07-02 18:30:27 +02:00
Hugo LAMY
9bde325ece merged from home 2022-07-02 17:08:32 +02:00
hugogogo
9a87539680 mv old mains into dir 2022-07-01 12:57:07 +02:00
hugogogo
de5f718d0c separate stack hpp and stack tpp 2022-07-01 12:52:57 +02:00
hugogogo
ef70cc5938 correct a test that differ between c++11 and c++98 2022-07-01 12:28:26 +02:00
hugogogo
e27bf01db4 clean makefile compilation flags 2022-07-01 12:07:36 +02:00
hugogogo
6e230109db separate make pair 2022-07-01 11:56:23 +02:00
hugogogo
ae646ee58a new version of map erase 2022-06-30 20:02:18 +02:00
hugogogo
a968b4d791 add rules to gitignore 2022-06-29 14:45:47 +02:00
hugogogo
38804caea9 small clean up of the files 2022-06-29 14:42:03 +02:00
hugogogo
eeb3c7dfc0 small changes in map insert and erase 2022-06-29 14:39:36 +02:00
hugogogo
b0b63d6238 makefile really improved on header dependencies 2022-06-29 14:10:17 +02:00
hugogogo
26436c8d8a ready for surrender 2022-06-27 15:55:18 +02:00
hugogogo
6617d6cdf5 stack almost good 2022-06-24 02:23:53 +02:00
hugogogo
58d417742b map is bst 2022-06-22 00:22:04 +02:00
hugogogo
0d98268a74 all tests except one ok on map 2022-06-21 18:38:28 +02:00
hugogogo
844701201f half tests ok on map 2022-06-21 14:41:24 +02:00
hugogogo
28acc5ef51 map filled luky style 2022-06-21 01:50:41 +02:00
hugogogo
c7114c1db2 using functionning luke bst 2022-06-20 19:05:52 +02:00
hugogogo
8c181b6407 map pair ok 2022-06-20 15:40:35 +02:00
hugogogo
8a404b0839 little correction on macro for map tests 2022-06-19 12:36:01 +02:00
hugogogo
3074f7c93c tests for map ope 2022-06-19 12:33:18 +02:00
hugogogo
50224fb432 tests are receving as much argument as necessary, and print works with map 2022-06-19 11:51:23 +02:00
hugogogo
94745ca8a9 resolve template specialization with inline keyword 2022-06-18 17:58:14 +02:00
hugogogo
72762a79cb re-organisation of files 2022-06-17 15:30:58 +02:00
hugogogo
a939bfc66f solved pbm in vector reserve 2022-06-17 10:46:21 +02:00
hugogogo
64d87cb5d4 no more leaks in vector 2022-06-17 01:36:45 +02:00
hugogogo
df6332b496 all vector tests pass 2022-06-17 01:20:46 +02:00
hugogogo
da4ebc13fd correction of core dump 2022-06-17 01:00:53 +02:00
hugogogo
e3151bce4e correction of valgrin error 2022-06-16 18:48:46 +02:00
hugogogo
5ee4202020 implemented delete correction for leaks 2022-06-16 18:05:28 +02:00
hugogogo
1cc5dabb7b added print 2022-06-15 21:23:19 +02:00
hugogogo
32c413f741 add type in tests 2022-06-15 21:04:31 +02:00
hugogogo
bb4ac9963d tests multi types 2022-06-15 19:33:39 +02:00
hugogogo
005382a3ac vector finish 2022-06-14 21:25:16 +02:00
hugogogo
988d67e908 better test organisation 2022-06-13 22:03:46 +02:00
hugogogo
c187d34ce7 vector insert ok 2022-06-10 16:47:56 +02:00
hugogogo
68ada8ca68 first insert ok 2022-06-10 11:21:19 +02:00
hugogogo
8326f7f283 added resize and _increment_capacity 2022-06-09 14:14:13 +02:00
hugogogo
b385f6220a resolved pbm assign iterator 2022-06-08 21:17:39 +02:00
hugogogo
5d0e631cb7 add tests for vector assign iterator, and tests script 2022-06-08 20:54:44 +02:00
hugogogo
8c232df375 assign sfinae is integral detection 2022-06-08 15:24:44 +02:00
hugogogo
647b6eee25 save before closing pc 2022-06-05 13:26:53 +02:00
hugogogo
a4550a9bb9 save before closing pc 2022-06-04 10:57:57 +02:00
hugogogo
556807669e fix push_back reserve growth 2022-06-03 19:49:09 +02:00
hugogogo
7d857c5e4e add capacity() and basic assign() 2022-06-03 17:10:53 +02:00
hugogogo
aecd2caa1c add namespace, make stl, and template allocator 2022-06-03 14:49:22 +02:00
hugogogo
6362a50ffa little formating improvement 2022-06-02 19:41:34 +02:00
hugogogo
dea7818dfa push back is working 2022-06-02 18:18:38 +02:00
hugogogo
0146ebcbf1 working typedef 2022-06-01 22:05:23 +02:00
hugogogo
f765779b27 wip added all prototypes of members of vector 2022-06-01 20:20:05 +02:00
hugogogo
99f67b808c first implementation, badly, of allocator 2022-06-01 15:41:14 +02:00
hugogogo
0e51cc655c creation of tests.h 2022-05-31 19:52:03 +02:00
hugogogo
5e65691bc8 test structure is functionnal 2022-05-31 19:28:22 +02:00
hugogogo
1a8b81c3cf added standard test from cplusplus 2022-05-31 15:49:14 +02:00
Hugo LAMY
27c6d387ad main of officials tests for vector 2022-05-25 16:55:48 +02:00
37 changed files with 6518 additions and 1 deletions

4
.gitignore vendored
View File

@@ -36,6 +36,10 @@ Thumbs.db
*.zip
*.pdf
/builds
/builds_ft
/builds_stl
# cube3d
containers
containers_ft
containers_stl

129
Makefile Normal file
View File

@@ -0,0 +1,129 @@
# - - - - - - - #
# #
# COLORS #
# #
# - - - - - - - #
GRAY = "\e[0;30m"
RED = "\e[0;31m"
GREEN = "\e[0;32m"
YELLOW = "\e[0;33m"
BLUE = "\e[0;34m"
PURPLE = "\e[0;35m"
CYAN = "\e[0;36m"
WHITE = "\e[0;37m"
B_GRAY = "\e[1;30m"
B_RED = "\e[1;31m"
B_GREEN = "\e[1;32m"
B_YELLOW = "\e[1;33m"
B_BLUE = "\e[1;34m"
B_PURPLE = "\e[1;35m"
B_CYAN = "\e[1;36m"
B_WHITE = "\e[1;37m"
RESET = "\e[0m"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# . name = value \ . += append to a variable #
# VARIABLES . value . != set result of command #
# . . ?= set if not already set #
# . (case sensitive) . := expand once at definition line #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
NAME = containers
NAME_FT = containers_ft
NAME_STL = containers_stl
CC = c++
EXT = cpp
CFLAGS = -Wall -Wextra -Werror $(INCLUDES)
CFLAGS += -MMD -MP #see end-page note on header dependencie
CFLAGS += -std=c++98
CFLAGS += -g3
CFLAGS_STL = $(CFLAGS)
CFLAGS_STL += -D STL
VPATH = $(D_SRCS)
LIBS =
D_INCLUDE = ./headers \
./templates \
./tests/includes
INCLUDES = $(D_INCLUDE:%=-I%)
D_SRCS = ./tests
#SRCS = main42.cpp
#SRCS = main_map_1.cpp
#SRCS = main_map_2.cpp
#SRCS = main_stack_1.cpp
SRCS = main.cpp \
tests_definitions.cpp \
tests_vector.cpp \
tests_map.cpp \
tests_stack.cpp
D_OBJS_FT = builds_ft
OBJS_FT = $(SRCS:%.$(EXT)=$(D_OBJS_FT)/%.o)
D_OBJS_STL = builds_stl
OBJS_STL = $(SRCS:%.$(EXT)=$(D_OBJS_STL)/%.o)
OBJS = $(OBJS_FT) $(OBJS_STL)
DEPS = $(OBJS:.o=.d) #see end-page note on header dependencie
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# . target: prerequisites . $@ : target #
# RULES . recipe . $< : 1st prerequisite #
# . @recipe (silent) . $^ : all prerequisites #
# . target: VAR = assignment . | : order-only prereq. #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
all: $(NAME_FT) $(NAME_STL)
stl: $(NAME_STL)
ft: $(NAME_FT)
$(D_OBJS_FT)/%.o: %.$(EXT) | $(D_OBJS_FT)
@echo $(CYAN)"compilation " $@ $(RESET)
@$(CC) $(CFLAGS) -c $< -o $@
$(D_OBJS_STL)/%.o: %.$(EXT) | $(D_OBJS_STL)
@echo $(CYAN)"compilation -D STL" $@ $(RESET)
@$(CC) $(CFLAGS) -D STL -c $< -o $@
$(D_OBJS_FT) $(D_OBJS_STL):
mkdir $@
$(NAME_FT): $(OBJS_FT)
$(NAME_STL): $(OBJS_STL)
$(NAME_FT) $(NAME_STL):
@echo $(PURPLE)"linkage (link objects.o)"$(RESET)
@$(CC) $^ -o $@ $(LIBS)
leaks: leaksft
leaksft: $(NAME_FT)
valgrind --leak-check=full --show-leak-kinds=all ./$<
leakstl: $(NAME_STL)
valgrind --leak-check=full --show-leak-kinds=all ./$<
clean:
rm -rf $(D_OBJS_FT)
rm -rf $(D_OBJS_STL)
fclean: clean
rm -f $(NAME_FT) $(NAME_STL)
re: fclean all
.PHONY : all clean fclean re
# header dependencie
# https://spin.atomicobject.com/2016/08/26/makefile-c-projects
# https://stackoverflow.com/questions/13432127/how-to-use-the-include-directive-in-a-makefile-for-a-specific-target
-include $(DEPS)

View File

@@ -1,3 +1,4 @@
# CONTAINERS #
### Compilation
@@ -62,3 +63,4 @@ saires. Cependant, vous devez éviter le problème de la double inclusion en les
* Vous devez créer deux binaires faisant tourner les mêmes tests : lun avec vos containers et lautre avec les containers standards.
* Comparez les sorties et les performances / temps (vos containers peuvent être jusquà 20 fois plus lents que les originaux).
* Pour tester vos containers : ft::<container>.

BIN
correction.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 KiB

26
headers/colors.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef COLORS_H
# define COLORS_H
# define GRAY "\e[0;30m"
# define RED "\e[0;31m"
# define GREEN "\e[0;32m"
# define YELLOW "\e[0;33m"
# define BLUE "\e[0;34m"
# define PURPLE "\e[0;35m"
# define CYAN "\e[0;36m"
# define WHITE "\e[0;37m"
# define B_GRAY "\e[1;30m"
# define B_RED "\e[1;31m"
# define B_GREEN "\e[1;32m"
# define B_YELLOW "\e[1;33m"
# define B_BLUE "\e[1;34m"
# define B_PURPLE "\e[1;35m"
# define B_CYAN "\e[1;36m"
# define B_WHITE "\e[1;37m"
# define RESET "\e[0m"
#endif

16
headers/enable_if.hpp Normal file
View File

@@ -0,0 +1,16 @@
#ifndef ENABLE_IF_HPP
# define ENABLE_IF_HPP
namespace ft {
template <bool B, class T = void>
struct enable_if {};
template <class T>
struct enable_if<true, T> { typedef T type; };
} // namespace ft
#endif

36
headers/equal.hpp Normal file
View File

@@ -0,0 +1,36 @@
#ifndef EQUAL_HPP
# define EQUAL_HPP
namespace ft {
template < typename InputIt1, typename InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2) {
while (first1 != last1)
{
if (!(*first1 == *first2))
return false;
++first1;
++first2;
}
return true;
}
template < class InputIt1, class InputIt2, class BinaryPred >
bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPred pred) {
while (first1 != last1)
{
if (!pred(*first1, *first2))
return false;
++first1;
++first2;
}
return true;
}
} // namespace ft
#endif

46
headers/is_integral.hpp Normal file
View File

@@ -0,0 +1,46 @@
#ifndef IS_INTEGRAL_HPP
# define IS_INTEGRAL_HPP
namespace ft {
template <class T> struct is_integral
{
typedef char yes[1];
typedef yes no[2];
static T type;
// integral types : https://www.cplusplus.com/reference/type_traits/is_integral/
static yes& test(bool);
static yes& test(char);
// static yes& test(char16_t);
// static yes& test(char32_t);
static yes& test(wchar_t);
static yes& test(signed char);
static yes& test(short int);
static yes& test(int);
static yes& test(long int);
static yes& test(long long int);
static yes& test(unsigned char);
static yes& test(unsigned short int);
static yes& test(unsigned int);
static yes& test(unsigned long int);
static yes& test(unsigned long long int);
// non-template function with direct matching are always considered first
// then the function template with direct matching are considered
// https://stackoverflow.com/questions/12877546/how-do-i-avoid-implicit-conversions-on
template <class C> static no& test(C);
static const bool value = sizeof(test(type)) == sizeof(yes);
};
} // namespace ft
// "template <>" introduce a total specialization of a template :
// https://stackoverflow.com/questions/6288812/what-is-the-meaning-of-template-with-empty-angle-brackets-in-c
// SFINAE : https://jguegant.github.io/blogs/tech/sfinae-introduction.html
#endif

View File

@@ -0,0 +1,44 @@
#ifndef ITERATOR_TRAITS_HPP
# define ITERATOR_TRAITS_HPP
# include <iterator> // iterator_tag
# include <cstddef> // ptrdiff_t
namespace ft {
template < typename Iterator >
struct iterator_traits
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
template < typename T >
struct iterator_traits<T*>
{
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
template < typename T >
struct iterator_traits<const T*>
{
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
};
} // namespace ft
#endif
// https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/

View File

@@ -0,0 +1,23 @@
#ifndef LEXICOGRAPHICAL_COMPARE_HPP
# define LEXICOGRAPHICAL_COMPARE_HPP
namespace ft {
template <class InputIt1, class InputIt2>
bool lexicographical_compare
( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 ) {
for (; first1 != last1; first1++, first2++) {
if (*first1 < *first2)
return true;
if (*first2 < *first1)
return false;
}
return (first1 == last1 && first2 != last2);
}
} // namespace ft
#endif

23
headers/make_pair.hpp Normal file
View File

@@ -0,0 +1,23 @@
#ifndef MAKE_PAIR_HPP
# define MAKE_PAIR_HPP
# define PR_TPL template < class T1, class T2 >
# define PR pair<T1, T2>
#include "pair.hpp"
namespace ft {
PR_TPL PR
make_pair(T1 x, T2 y) {
return PR(x, y) ;
}
} // namespace ft
# undef PR
# undef PR_TPL
#endif

222
headers/map.hpp Normal file
View File

@@ -0,0 +1,222 @@
#ifndef MAP_HPP
# define MAP_HPP
# include <memory> // std::allocator
# include <cstddef> // NULL, std::size_t, std::ptrdiff_t
# include <algorithm> // std::max()
# include <functional> // std::less, std::binary_function
# include "reverse_iterator.hpp"
# include "equal.hpp"
# include "lexicographical_compare.hpp"
# include "pair.hpp"
# include "make_pair.hpp"
# include "map_node.hpp"
# include "map_iterator.hpp"
namespace ft {
template <
class Key, // map::key_type
class T, // map::mapped_type
class Compare = std::less<Key>, // map::key_compare
class Alloc = std::allocator< ft::pair<const Key, T> > // map::allocator_type
> class map {
public:
typedef Key key_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef Compare key_compare;
typedef Alloc allocator_type;
typedef map_iterator<Key, T, Compare, Alloc> iterator;
typedef map_const_iterator<Key, T, Compare, Alloc> const_iterator;
typedef ft::reverse_iterator<iterator> reverse_iterator;
typedef ft::reverse_iterator<const_iterator> const_reverse_iterator;
/****************
* member class :
****************/
// https://en.cppreference.com/w/cpp/container/map/value_compare
// https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c
class value_compare : public std::binary_function<value_type, value_type, bool> {
friend class map;
protected:
Compare comp;
value_compare(Compare c) : comp(c) {}
public:
bool operator() (const value_type& x, const value_type& y) const
{ return comp(x.first, y.first); }
};
/************
* copliens :
************/
// constructors ------------------------------
explicit map (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
template <class InputIterator>
map (InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());
map(const map& x);
// destructor --------------------------------
~map();
// operator= ---------------------------------
map& operator= (const map& x);
/*************
* iterators :
*************/
// begin -------------------------------------
iterator begin();
const_iterator begin() const;
// end ---------------------------------------
iterator end();
const_iterator end() const;
// rbegin ------------------------------------
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
// rend --------------------------------------
reverse_iterator rend();
const_reverse_iterator rend() const;
/************
* capacity :
************/
// empty -------------------------------------
bool empty() const;
// size --------------------------------------
size_type size() const;
// max_size ----------------------------------
size_type max_size() const;
/******************
* element access :
******************/
// operator[] --------------------------------
mapped_type & operator[] (const key_type& k);
/*************
* modifiers :
*************/
// insert ------------------------------------
pair<iterator,bool> insert (const value_type& val);
iterator insert (iterator position, const value_type& val);
template <class InputIterator>
void insert (InputIterator first, InputIterator last);
// erase -------------------------------------
void erase (iterator position);
size_type erase (const key_type& k);
void erase (iterator first, iterator last);
// swap --------------------------------------
void swap (map& x);
// clear -------------------------------------
void clear();
/*************
* observers :
*************/
// key_comp ----------------------------------
key_compare key_comp() const;
// value_comp --------------------------------
value_compare value_comp() const;
/**************
* operations :
**************/
// find --------------------------------------
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;
// count -------------------------------------
size_type count (const key_type& k) const;
// lower_bound -------------------------------
iterator lower_bound (const key_type& k);
const_iterator lower_bound (const key_type& k) const;
// upper_bound -------------------------------
iterator upper_bound (const key_type& k);
const_iterator upper_bound (const key_type& k) const;
// equal_range -------------------------------
pair<const_iterator,const_iterator> equal_range (const key_type& k) const;
pair<iterator,iterator> equal_range (const key_type& k);
/*************
* allocator :
*************/
// get_allocator -----------------------------
allocator_type get_allocator() const;
private:
size_type _size;
node<value_type>* _root;
sentinel<value_type>* _sentinel;
Compare _comp;
Alloc _allocator;
// https://stackoverflow.com/questions/14148756/what-does-template-rebind-do
typename Alloc::template rebind< node<value_type> >::other _allocator_node;
typename Alloc::template rebind< sentinel<value_type> >::other _allocator_sentinel;
// BBST
enum {INSERT, ERASE};
void _balance(node<value_type>* n);
short _compute_height(node<value_type>* n);
short _balance_factor(node<value_type>* n);
node<value_type>* _rotate_left(node<value_type>* n);
node<value_type>* _rotate_right(node<value_type>* n);
};
/************************
* non-member functions :
************************/
// operator == -------------------------------
template< class K, class T, class Comp, class Alloc > bool operator==
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// operator != -------------------------------
template< class K, class T, class Comp, class Alloc > bool operator!=
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// operator < --------------------------------
template< class K, class T, class Comp, class Alloc > bool operator<
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// operator <= -------------------------------
template< class K, class T, class Comp, class Alloc > bool operator<=
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// operator > --------------------------------
template< class K, class T, class Comp, class Alloc > bool operator>
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// operator >= -------------------------------
template< class K, class T, class Comp, class Alloc > bool operator>=
( const std::map<K,T,Comp,Alloc>& lhs, const std::map<K,T,Comp,Alloc>& rhs );
// swap (map) -----------------------------
template< class Key, class T, class Compare, class Alloc > void swap
( std::map<Key,T,Compare,Alloc>& lhs, std::map<Key,T,Compare,Alloc>& rhs );
} // namespace ft
# include "map.tpp"
// banlanced binary search tree :
// https://www.youtube.com/watch?v=vRwi_UcZGjU
// entinel node :
// https://en.wikipedia.org/wiki/Sentinel_node
#endif

193
headers/map_iterator.hpp Normal file
View File

@@ -0,0 +1,193 @@
#ifndef MAP_ITERATOR_HPP
# define MAP_ITERATOR_HPP
# include <cstddef> // NULL, ptrdiff_t
# include <iterator> // iterator_tag
# include "pair.hpp"
# include "map_node.hpp"
namespace ft {
template <
typename Key,
typename T,
typename Compare,
typename Allocator
> class map_iterator {
private:
typedef map_iterator self;
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef pair<const Key, T> value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type* pointer;
typedef value_type& reference;
map_iterator() : _node(), _sentinel() {}
map_iterator(node<value_type>* n, sentinel<value_type>* sentinel)
: _node(n), _sentinel(sentinel) {}
reference operator*() const {
return _node->value; }
pointer operator->() const {
return &_node->value; }
self& operator++() {
if (_node == NULL)
_node = _sentinel->child->min();
else if (_node->right)
_node = _node->right->min();
else
{
node<value_type>* up = _node->up;
while (up != NULL && _node == up->right)
{
_node = up;
up = up->up;
}
_node = up;
}
return *this;
}
self& operator--() {
if (_node == NULL)
_node = _sentinel->child->max();
else if (_node->left)
_node = _node->left->max();
else
{
node<value_type>* up = _node->up;
while (up != NULL && _node == up->left)
{
_node = up;
up = up->up;
}
_node = up;
}
return *this;
}
self operator++(int) {
self old = *this;
++(*this);
return old;
}
self operator--(int) {
self old = *this;
--(*this);
return old;
}
node<value_type>* get_node() { return _node; }
const node<value_type>* get_node() const { return _node; }
const sentinel<value_type>* getSentinel() const { return _sentinel; }
friend bool operator==(const self &lhs, const self &rhs) {
return lhs._node == rhs._node; }
friend bool operator!=(const self &lhs, const self &rhs) {
return !(lhs._node == rhs._node); }
private:
node<value_type>* _node;
sentinel<value_type>* _sentinel;
};
template <
typename Key,
typename T,
typename Compare,
typename Allocator
> class map_const_iterator {
private:
typedef map_const_iterator self;
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef pair<const Key, T> value_type;
typedef std::ptrdiff_t difference_type;
typedef const value_type* pointer;
typedef const value_type& reference;
map_const_iterator() : _node(), _sentinel() {}
map_const_iterator (
const node<value_type>* node,
const sentinel<value_type>* sentinel)
: _node(node), _sentinel(sentinel) {}
map_const_iterator (const map_iterator< Key, T, Compare, Allocator >& src)
: _node(src.get_node()), _sentinel(src.getSentinel()) {}
reference operator*() const {
return _node->value; }
pointer operator->() const {
return &_node->value; }
self& operator++() {
if (_node == NULL)
_node = _sentinel->child->min();
else if (_node->right)
_node = _node->right->min();
else
{
node<value_type>* up = _node->up;
while (up != NULL && _node == up->right)
{
_node = up;
up = up->up;
}
_node = up;
}
return *this;
}
self& operator--() {
if (_node == NULL)
_node = _sentinel->child->max();
else if (_node->left)
_node = _node->left->max();
else
{
node<value_type>* up = _node->up;
while (up != NULL && _node == up->left)
{
_node = up;
up = up->up;
}
_node = up;
}
return *this;
}
self operator++(int) {
self old = *this;
++(*this);
return old;
}
self operator--(int) {
self old = *this;
--(*this);
return old;
}
node<value_type>* get_node() const { return _node; }
friend bool operator==(const self &lhs, const self &rhs) {
return lhs._node == rhs._node; }
friend bool operator!=(const self &lhs, const self &rhs) {
return !(lhs._node == rhs._node); }
private:
const node<value_type>* _node;
const sentinel<value_type>* _sentinel;
};
} // namespace ft
#endif

56
headers/map_node.hpp Normal file
View File

@@ -0,0 +1,56 @@
#ifndef MAP_NODE_HPP
# define MAP_NODE_HPP
# include <cstddef> // NULL
namespace ft {
template < typename ValueType >
struct node {
ValueType value;
node *up;
node *left;
node *right;
short height;
node(const ValueType& val)
: value(val)
, up(NULL)
, left(NULL)
, right(NULL)
, height(1)
{}
node* min() {
node* n = this;
while (n->left)
n = n->left;
return n;
}
node* max() {
node* n = this;
while (n->right)
n = n->right;
return n;
}
};
template < typename ValueType >
struct sentinel {
node<ValueType> *child;
sentinel() : child(NULL) {}
};
} // namespace ft
#endif

86
headers/pair.hpp Normal file
View File

@@ -0,0 +1,86 @@
#ifndef PAIR_HPP
# define PAIR_HPP
# define PR_TPL template < class T1, class T2 >
# define PR pair<T1, T2>
namespace ft {
PR_TPL
struct pair {
typedef T1 first_type;
typedef T2 second_type;
pair();
template< typename U, typename V >
pair(const pair<U,V>& pr);
pair(const first_type& a, const second_type& b);
T1 first;
T2 second;
};
/************
* copliens :
************/
PR_TPL PR::
pair() {}
PR_TPL template< typename U, typename V > PR::
pair(const pair<U,V>& pr)
: first(pr.first)
, second(pr.second) {
}
PR_TPL PR::
pair(const first_type& a, const second_type& b)
: first(a)
, second(b) {
}
/************************
* non-member functions :
************************/
PR_TPL
bool operator==(const PR& lhs, const PR& rhs) {
return (lhs.first == rhs.first) && (lhs.second == rhs.second);
}
PR_TPL
bool operator<(const PR& lhs, const PR& rhs) {
return (lhs.first < rhs.first
|| ( !(rhs.first < lhs.first) && (lhs.second < rhs.second) )
);
}
PR_TPL
bool operator!=(const PR& lhs, const PR& rhs) {
return !(lhs == rhs);
}
PR_TPL
bool operator>(const PR& lhs, const PR& rhs) {
return (rhs < lhs);
}
PR_TPL
bool operator<=(const PR& lhs, const PR& rhs) {
return !(lhs > rhs);
}
PR_TPL
bool operator>=(const PR& lhs, const PR& rhs) {
return !(lhs < rhs);
}
} // namespace ft
# undef PR
# undef PR_TPL
#endif

View File

@@ -0,0 +1,140 @@
#ifndef REVERSE_ITERATOR_HPP
# define REVERSE_ITERATOR_HPP
# include <iterator> // iterator_tag
# include "iterator_traits.hpp"
namespace ft {
template < class Iter >
class reverse_iterator {
private:
Iter _it;
typedef ft::iterator_traits<Iter> _traits;
public:
typedef Iter iterator_type;
typedef typename _traits::iterator_category iterator_category;
typedef typename _traits::value_type value_type;
typedef typename _traits::difference_type difference_type;
typedef typename _traits::pointer pointer;
typedef typename _traits::reference reference;
/****************
* constructors :
****************/
reverse_iterator()
: _it()
{}
explicit reverse_iterator(iterator_type it)
: _it(it)
{}
// reverse_iterator(const reverse_iterator& src)
// : _it(src._it)
// {}
template < class Iterator >
reverse_iterator(const reverse_iterator<Iterator>& rev_it)
: _it(rev_it.base())
{}
/*********************
* members functions :
*********************/
// base --------------------------------------
iterator_type base() const
{ return _it; }
// operator * --------------------------------
reference operator*() const
{ Iter tmp = _it; return *--tmp; }
// operator + --------------------------------
reverse_iterator operator+(difference_type n) const
{ return reverse_iterator(_it - n); }
// operator ++ -------------------------------
reverse_iterator operator++(int)
{ reverse_iterator old(*this); ++(*this); return old; }
reverse_iterator & operator++()
{ --_it; return *this; }
// operator += -------------------------------
reverse_iterator & operator+=(difference_type n)
{ _it -= n; return *this; }
// operator - --------------------------------
reverse_iterator operator-(difference_type n) const
{ return reverse_iterator(_it + n); }
// operator -- -------------------------------
reverse_iterator operator--(int)
{ reverse_iterator old(*this); --(*this); return old; }
reverse_iterator & operator--()
{ ++_it; return *this; }
// operator -= -------------------------------
reverse_iterator & operator-=(difference_type n)
{ _it += n; return *this; }
// operator -> -------------------------------
pointer operator->() const
{ return &(operator*()); }
// operator [] -------------------------------
reference operator[] (difference_type n) const
{ return _it[-n-1]; }
};
/*************************
* non-members functions :
*************************/
// operator == -------------------------------
template <class Iterator>
bool operator== (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() == rhs.base(); }
// operator != -------------------------------
template <class Iterator>
bool operator!= (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() != rhs.base(); }
// operator < --------------------------------
template <class Iterator>
bool operator< (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() > rhs.base(); }
// operator <= -------------------------------
template <class Iterator>
bool operator<= (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() >= rhs.base(); }
// operator > --------------------------------
template <class Iterator>
bool operator> (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() < rhs.base(); }
// operator >= -------------------------------
template <class Iterator>
bool operator>= (const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{ return lhs.base() <= rhs.base(); }
/*******************
* other operators :
*******************/
// operator + non-member overload ------------
template <class Iterator>
reverse_iterator<Iterator> operator+
(typename reverse_iterator<Iterator>::difference_type n
,const reverse_iterator<Iterator>& rhs)
{ return reverse_iterator<Iterator>(rhs.base() - n); }
// operator - non-member overload ------------
template <class Iterator>
typename reverse_iterator<Iterator>::difference_type operator-
(const reverse_iterator<Iterator>& lhs
,const reverse_iterator<Iterator>& rhs)
{ return rhs.base() - lhs.base(); }
} // namespace ft
#endif

68
headers/stack.hpp Normal file
View File

@@ -0,0 +1,68 @@
#ifndef STACK_HPP
# define STACK_HPP
# include "vector.hpp"
namespace ft {
template <
typename T,
typename Container = ft::vector<T>
> class stack {
public:
typedef Container container_type;
typedef typename Container::value_type value_type;
typedef typename Container::size_type size_type;
/************
* copliens :
************/
// constructors ------------------------------
explicit stack(const container_type& cont = Container());
/**********************
* overload functions :
**********************/
// empty -------------------------------------
bool empty() const ;
// size --------------------------------------
size_type size() const ;
// top ---------------------------------------
value_type& top();
const value_type& top() const ;
// push --------------------------------------
void push(const value_type& value);
// pop ---------------------------------------
void pop();
/*********************************
* Relational Operators (friend) :
*********************************/
template < typename T2, typename C2 >
friend bool operator==(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
template < typename T2, typename C2 >
friend bool operator!=(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
template < typename T2, typename C2 >
friend bool operator<(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
template < typename T2, typename C2 >
friend bool operator>(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
template < typename T2, typename C2 >
friend bool operator<=(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
template < typename T2, typename C2 >
friend bool operator>=(const stack<T2,C2>& lhs, const stack<T2,C2>& rhs);
protected:
container_type c;
};
} // namespace ft
# include "stack.tpp"
#endif

188
headers/vector.hpp Normal file
View File

@@ -0,0 +1,188 @@
#ifndef VECTOR_HPP
# define VECTOR_HPP
# include "colors.h"
# include <iostream>
# include <string>
# include <memory> // std::allocator
# include <algorithm> // std::min, std::max
# include <stdexcept> // out_of_range, length_error, logic_error
# include <cstddef> // NULL, std::size_t, std::ptrdiff_t
# include "enable_if.hpp"
# include "is_integral.hpp"
# include "reverse_iterator.hpp"
# include "equal.hpp"
# include "lexicographical_compare.hpp"
namespace ft {
template <
class T,
class Allocator = std::allocator<T> >
class vector {
public:
typedef T value_type;
typedef Allocator allocator_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T * iterator;
typedef T const * const_iterator;
typedef ft::reverse_iterator<iterator> reverse_iterator;
typedef ft::reverse_iterator<const_iterator> const_reverse_iterator;
// dependent qualified name :
// https://en.cppreference.com/w/cpp/keyword/typename
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
/************
* copliens :
************/
// constructors ------------------------------
explicit vector (const allocator_type & alloc = allocator_type());
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
vector( vector const & src );
// destructor --------------------------------
~vector();
// operator= ---------------------------------
vector & operator=( vector const & rhs );
/*************
* iterators :
*************/
// begin -------------------------------------
iterator begin();
const_iterator begin() const;
// end ---------------------------------------
iterator end();
const_iterator end() const;
// rbegin ------------------------------------
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
// rend --------------------------------------
reverse_iterator rend();
const_reverse_iterator rend() const;
/************
* capacity :
************/
// size --------------------------------------
size_type size() const;
// max_size ----------------------------------
size_type max_size() const;
// resize ------------------------------------
void resize(size_type n, value_type val = value_type());
// capacity ----------------------------------
size_type capacity() const;
// empty -------------------------------------
bool empty() const;
// reserve -----------------------------------
void reserve(size_type n);
/******************
* element access :
******************/
// operator[] --------------------------------
reference operator[](size_type n);
const_reference operator[](size_type n) const;
// at ----------------------------------------
reference at(size_type n);
const_reference at(size_type n) const;
// front -------------------------------------
reference front();
const_reference front() const;
// back --------------------------------------
reference back();
const_reference back() const;
/*************
* modifiers :
*************/
// assign ------------------------------------
template <class InputIterator>
typename enable_if< !is_integral<InputIterator>::value,void >::type
assign(InputIterator first, InputIterator last);
void assign(size_type n, const value_type& val);
// push_back ---------------------------------
void push_back(const value_type & val);
// pop_back ----------------------------------
void pop_back();
// insert ------------------------------------
iterator insert(iterator position, const value_type& val);
void insert(iterator position, size_type n, const value_type& val);
template <class InputIterator>
typename enable_if< !is_integral<InputIterator>::value,void >::type
insert(iterator position, InputIterator first, InputIterator last);
// erase -------------------------------------
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
// swap --------------------------------------
void swap(vector& x);
// clear -------------------------------------
void clear();
/*************
* allocator :
*************/
// get_allocator -----------------------------
allocator_type get_allocator() const;
private:
size_type _size;
size_type _capacity;
value_type * _mem_ptr;
allocator_type _allocator;
void _destroy(iterator first, iterator last);
void _increment_capacity(size_type n);
};
/************************
* non-member functions :
************************/
// operator == -------------------------------
template <class T, class Alloc>
bool operator== (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator != -------------------------------
template <class T, class Alloc>
bool operator!= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator < --------------------------------
template <class T, class Alloc>
bool operator< (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator <= -------------------------------
template <class T, class Alloc>
bool operator<= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator > --------------------------------
template <class T, class Alloc>
bool operator> (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// operator >= -------------------------------
template <class T, class Alloc>
bool operator>= (const vector<T,Alloc>& lhs, const vector<T,Alloc>& rhs);
// swap (vector) -----------------------------
template <class T, class Alloc>
void swap (vector<T,Alloc>& x, vector<T,Alloc>& y);
} // namespace ft
# include "vector.tpp"
#endif

575
templates/map.tpp Normal file
View File

@@ -0,0 +1,575 @@
#define MP_TPL template < typename Key, typename T, typename Compare, typename Allocator >
#define MP map<Key, T, Compare, Allocator>
namespace ft {
/************
* copliens :
************/
// constructors ------------------------------
MP_TPL MP::
map (const key_compare & comp, const allocator_type & alloc)
: _size(0)
, _root(NULL)
, _comp(comp)
, _allocator(alloc) {
_sentinel = _allocator_sentinel.allocate(1);
_allocator_sentinel.construct(_sentinel, sentinel<value_type>());
}
MP_TPL template < typename InputIt > MP::
map (InputIt first, InputIt last, const key_compare& comp, const allocator_type& alloc)
: _size(0)
, _root(NULL)
, _comp(comp)
, _allocator(alloc) {
_sentinel = _allocator_sentinel.allocate(1);
_allocator_sentinel.construct(_sentinel, sentinel<value_type>());
insert(first, last);
}
MP_TPL MP::
map(const map& src)
: _size(0)
, _root(NULL)
, _comp(src._comp)
, _allocator(src._allocator) {
_sentinel = _allocator_sentinel.allocate(1);
_allocator_sentinel.construct(_sentinel, sentinel<value_type>());
*this = src;
}
// destructor --------------------------------
MP_TPL MP::
~map() {
clear();
_allocator_sentinel.destroy(_sentinel);
_allocator_sentinel.deallocate(_sentinel, 1);
}
// operator= ---------------------------------
MP_TPL MP& MP::
operator=(const map& rhs) {
if (this == &rhs)
return (*this);
map new_bst(rhs.begin(), rhs.end());
swap(new_bst);
return (*this);
}
/*************
* iterators :
*************/
// begin -------------------------------------
MP_TPL typename MP::iterator MP::
begin() {
if (_root)
return iterator(_root->min(), _sentinel);
else
return end();
}
MP_TPL typename MP::const_iterator MP::
begin() const {
if (_root)
return const_iterator(_root->min(), _sentinel);
else
return end();
}
// end ---------------------------------------
MP_TPL typename MP::iterator MP::
end() { return iterator(NULL, _sentinel); }
MP_TPL typename MP::const_iterator MP::
end() const { return const_iterator(NULL, _sentinel); }
// rbegin ------------------------------------
MP_TPL typename MP::reverse_iterator MP::
rbegin() { return reverse_iterator(end()); }
MP_TPL typename MP::const_reverse_iterator MP::
rbegin() const { return const_reverse_iterator(end()); }
// rend --------------------------------------
MP_TPL typename MP::reverse_iterator MP::
rend() { return reverse_iterator(begin()); }
MP_TPL typename MP::const_reverse_iterator MP::
rend() const { return const_reverse_iterator(begin()); }
/************
* capacity :
************/
// empty -------------------------------------
MP_TPL bool MP::
empty() const { return (_size == 0); }
// size --------------------------------------
MP_TPL typename MP::size_type MP::
size() const { return (_size); }
// max_size ----------------------------------
MP_TPL typename MP::size_type MP::
max_size() const { return ( _allocator_node.max_size() ); }
/******************
* element access :
******************/
// operator[] --------------------------------
MP_TPL typename MP::mapped_type& MP::
operator[](const Key& key) {
node<value_type>* n = _root;
while (n)
{
if (_comp(key, n->value.first))
n = n->left;
else if (_comp(n->value.first, key))
n = n->right;
else
return (n->value.second);
}
n = insert( ft::make_pair(key, mapped_type()) ).first.get_node();
return (n->value.second);
}
/*************
* modifiers :
*************/
// insert ------------------------------------
MP_TPL pair<typename MP::iterator, bool> MP::
insert(const value_type& value) {
node<value_type>* n = _root;
node<value_type>* next = n;
while (next != NULL)
{
if (value.first == n->value.first)
return ft::make_pair(iterator(n, _sentinel), false);
n = next;
if (_comp(value.first, n->value.first))
next = n->left;
else if (_comp(n->value.first, value.first))
next = n->right;
}
next = _allocator_node.allocate(1);
_allocator_node.construct(next, node<value_type>(value));
if (_root == NULL)
{
_root = next;
_sentinel->child = next;
}
else
{
if (_comp(value.first, n->value.first))
n->left = next;
else if (_comp(n->value.first, value.first))
n->right = next;
}
next->up = n;
_size++;
_balance(n);
return (ft::make_pair(iterator(next, _sentinel), true));
}
MP_TPL typename MP::iterator MP::
insert(iterator hint, const value_type& value) {
(void)hint;
return insert(value).first;
}
MP_TPL template < typename InputIt > void MP::
insert(InputIt first, InputIt last) {
for (; first != last; first++)
insert(*first);
}
// erase -------------------------------------
// https://www.geeksforgeeks.org/binary-search-tree-set-2-delete
MP_TPL void MP::
erase(iterator pos) {
node<value_type>* n = pos.get_node();
node<value_type>* replace = NULL;
if (n->left && n->right)
{
replace = n->right->min();
replace->left = n->left;
replace->left->up = replace;
if (replace->up != n)
{
replace->up->left = replace->right;
if (replace->right != NULL)
replace->right->up = replace->up;
replace->right = n->right;
replace->right->up = replace;
}
}
else if (n->left)
replace = n->left;
else if (n->right)
replace = n->right;
else
replace = NULL;
// share parents from n to replace
if (n == _root)
{
_root = replace;
_sentinel->child = _root;
}
else if (n == n->up->left)
n->up->left = replace;
else
n->up->right = replace;
if (replace != NULL)
replace->up = n->up;
_allocator_node.destroy(n);
_allocator_node.deallocate(n, 1);
_size--;
_balance(replace);
}
MP_TPL void MP::
erase(iterator first, iterator last) {
while (first != last)
erase(first++);
}
MP_TPL typename MP::size_type MP::
erase(const Key& key) {
iterator pos;
pos = find(key);
if (pos == end())
return (0);
erase(pos);
return (1);
}
// swap --------------------------------------
MP_TPL void MP::
swap(map& other) {
node<value_type>* tmp_root = _root;
sentinel<value_type>* tmp_sentinel = _sentinel;
size_type tmp_size = _size;
_root = other._root;
_sentinel = other._sentinel;
_size = other._size;
other._root = tmp_root;
other._sentinel = tmp_sentinel;
other._size = tmp_size;
}
// clear -------------------------------------
MP_TPL void MP::
clear() { erase(begin(), end()); }
/*************
* observers :
*************/
// key_comp ----------------------------------
MP_TPL typename MP::key_compare MP::
key_comp() const { return (value_compare(_comp).comp); }
// value_comp --------------------------------
MP_TPL typename MP::value_compare MP::
value_comp() const { return (value_compare(_comp)); }
/**************
* operations :
**************/
// find --------------------------------------
MP_TPL typename MP::iterator MP::
find(const Key& key) {
node<value_type>* n = _root;
while (n)
{
if (_comp(key, n->value.first))
n = n->left;
else if (_comp(n->value.first, key))
n = n->right;
else
return (iterator(n, _sentinel));
}
return (end());
}
MP_TPL typename MP::const_iterator MP::
find(const Key& key) const {
node<value_type>* n = _root;
while (n)
{
if (_comp(key, n->value.first))
n = n->left;
else if (_comp(n->value.first, key))
n = n->right;
else
return (const_iterator(n, _sentinel));
}
return (end());
}
// count -------------------------------------
MP_TPL typename MP::size_type MP::
count(const Key& key) const {
if (find(key) != end())
return (1);
else
return (0);
}
// lower_bound -------------------------------
MP_TPL typename MP::iterator MP::
lower_bound (const key_type& k) {
iterator it = begin();
iterator it_end = end();
while (it != it_end)
{
if (_comp(it->first, k) == false)
return (it);
++it;
}
return (it_end);
}
MP_TPL typename MP::const_iterator MP::
lower_bound (const key_type& k) const {
const_iterator it = begin();
const_iterator it_end = end();
while (it != it_end)
{
if (_comp(it->first, k) == false)
return (it);
++it;
}
return (it_end);
}
// upper_bound -------------------------------
MP_TPL typename MP::iterator MP::
upper_bound (const key_type& k) {
iterator it = begin();
iterator it_end = end();
while (it != it_end)
{
if (_comp(k, it->first))
return (it);
++it;
}
return (it_end);
}
MP_TPL typename MP::const_iterator MP::
upper_bound (const key_type& k) const {
const_iterator it = begin();
const_iterator it_end = end();
while (it != it_end)
{
if (_comp(k, it->first))
return (it);
++it;
}
return (it_end);
}
// equal_range -------------------------------
MP_TPL pair<typename MP::const_iterator, typename MP::const_iterator> MP::
equal_range (const key_type& k) const {
return ft::make_pair( lower_bound(k), upper_bound(k) );
}
MP_TPL pair<typename MP::iterator, typename MP::iterator> MP::
equal_range (const key_type& k) {
return ft::make_pair( lower_bound(k), upper_bound(k) );
}
/*************
* allocator :
*************/
// get_allocator -----------------------------
MP_TPL typename MP::allocator_type MP::
get_allocator() const { return (_allocator); }
/*********************
* private functions :
*********************/
MP_TPL void MP::
_balance(node<value_type>* n) {
node<value_type>* old_n;
node<value_type>* parent = NULL;
while (n)
{
n->height = _compute_height(n);
if (_balance_factor(n) > 1) // Left Heavy
{
parent = n->up;
if (_balance_factor(n->left) < 0) // Left-Right Case (BF == -1)
n->left = _rotate_left(n->left);
// Left-Left Case
n = _rotate_right(n);
old_n = n->right;
}
else if (_balance_factor(n) < -1) // Right Heavy
{
parent = n->up;
if (_balance_factor(n->right) > 0) // Right-Left Case (BF == 1)
n->right = _rotate_right(n->right);
// Right-Right Case
n = _rotate_left(n);
old_n = n->left;
}
if (parent)
{
if (parent->left == old_n)
parent->left = n;
else
parent->right = n;
parent = NULL;
}
n = n->up;
}
}
MP_TPL short MP::
_compute_height(node<value_type>* n) {
if (n->left && n->right)
return std::max(n->left->height, n->right->height) + 1;
else if (n->left)
return n->left->height + 1;
else if (n->right)
return n->right->height + 1;
else
return 1;
}
MP_TPL short MP::
_balance_factor(node<value_type>* n) {
if (n->left && n->right)
return n->left->height - n->right->height;
else if (n->left)
return n->left->height;
else if (n->right)
return (-(n->right->height));
else
return 0;
}
MP_TPL node<typename MP::value_type>* MP::
_rotate_left(node<value_type>* n) {
node<value_type>* ori_right = n->right;
ori_right->up = n->up;
n->up = ori_right;
n->right = ori_right->left;
if (n->right != NULL)
n->right->up = n;
ori_right->left = n;
n->height = _compute_height(n);
ori_right->height = _compute_height(ori_right);
if (n == _root)
{
_root = ori_right;
_sentinel->child = _root;
}
return ori_right;
}
MP_TPL node<typename MP::value_type>* MP::
_rotate_right(node<value_type>* n) {
node<value_type>* ori_left = n->left;
ori_left->up = n->up;
n->up = ori_left;
n->left = ori_left->right;
if (n->left != NULL)
n->left->up = n;
ori_left->right = n;
n->height = _compute_height(n);
ori_left->height = _compute_height(ori_left);
if (n == _root)
{
_root = ori_left;
_sentinel->child = _root;
}
return ori_left;
}
/************************
* non-member functions :
************************/
// operator == -------------------------------
MP_TPL bool operator== (const MP& lhs, const MP& rhs) {
if (lhs.size() != rhs.size())
return false;
return ft::equal(lhs.begin(), lhs.end(), rhs.begin());
}
// operator < --------------------------------
MP_TPL bool operator< (const MP& lhs, const MP& rhs) {
return ft::lexicographical_compare(
lhs.begin(),
lhs.end(),
rhs.begin(),
rhs.end()
);
}
// operator != -------------------------------
MP_TPL bool operator!= (const MP& lhs, const MP& rhs) {
return !(lhs == rhs); }
// operator <= -------------------------------
MP_TPL bool operator<= (const MP& lhs, const MP& rhs) {
return !(lhs > rhs); }
// operator > --------------------------------
MP_TPL bool operator> (const MP& lhs, const MP& rhs) {
return (rhs < lhs); }
// operator >= -------------------------------
MP_TPL bool operator>= (const MP& lhs, const MP& rhs) {
return !(lhs < rhs); }
// swap (map) -----------------------------
MP_TPL void swap(MP& lhs, MP& rhs) {
lhs.swap(rhs); }
} // namespace ft
#undef MP
#undef MP_TPL

72
templates/stack.tpp Normal file
View File

@@ -0,0 +1,72 @@
#define ST_TPL template <class T, class Container>
#define ST stack<T, Container>
namespace ft {
/************
* copliens :
************/
// constructors ------------------------------
ST_TPL ST::
stack(const container_type& cont)
: c(cont) {}
/**********************
* overload functions :
**********************/
// empty -------------------------------------
ST_TPL bool ST::
empty() const { return c.empty(); }
// size --------------------------------------
ST_TPL typename ST::size_type ST::
size() const { return c.size(); }
// top ---------------------------------------
ST_TPL typename ST::value_type& ST::
top() { return c.back(); }
ST_TPL const typename ST::value_type& ST::
top() const { return c.back(); }
// push --------------------------------------
ST_TPL void ST::
push(const value_type& value) { c.push_back(value); }
// pop ---------------------------------------
ST_TPL void ST::
pop() { c.pop_back(); }
/************************
* non-member functions :
************************/
// operator == -------------------------------
ST_TPL bool
operator==(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c == rhs.c; }
// operator != -------------------------------
ST_TPL bool
operator!=(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c != rhs.c; }
// operator < --------------------------------
ST_TPL bool
operator<(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c < rhs.c; }
// operator > --------------------------------
ST_TPL bool
operator>(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c > rhs.c; }
// operator <= -------------------------------
ST_TPL bool
operator<=(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c <= rhs.c; }
// operator >= -------------------------------
ST_TPL bool
operator>=(const stack<T, Container>& lhs, const stack<T, Container>& rhs)
{ return lhs.c >= rhs.c; }
} // namespace ft
#undef VT
#undef VT_TPL

497
templates/vector.tpp Normal file
View File

@@ -0,0 +1,497 @@
#define VT_TPL template <class T, class Allocator>
#define VT vector<T, Allocator>
namespace ft {
/*********************************************
* COPLIENS
*********************************************/
// constructors ------------------------------
VT_TPL VT::
vector( const Allocator & alloc )
: _size(0)
, _capacity(0)
, _mem_ptr(NULL)
, _allocator(alloc) {
return;
}
VT_TPL VT::
vector( size_type n, const T & val, const Allocator & alloc )
: _size(0)
, _capacity(0)
, _mem_ptr(NULL)
, _allocator(alloc) {
assign(n, val);
return;
}
VT_TPL template <class InputIterator> VT::
vector(InputIterator first, InputIterator last, const Allocator & alloc)
: _size(0)
, _capacity(0)
, _mem_ptr(NULL)
, _allocator(alloc) {
assign(first, last);
return;
}
// copy constructor --------------------------
VT_TPL VT::
vector( vector const & src )
: _size(0)
, _capacity(0)
, _mem_ptr(NULL)
, _allocator(src._allocator) {
*this = src;
return;
}
// destructors -------------------------------
VT_TPL VT::
~vector() {
clear();
_allocator.deallocate(_mem_ptr, _capacity);
return;
}
// operator= ---------------------------------
VT_TPL VT & VT::
operator=( vector const & rhs ) {
vector new_vector;
if ( this != &rhs )
{
new_vector.reserve(_capacity);
new_vector.assign(rhs.begin(), rhs.end());
swap(new_vector);
}
return *this;
}
/*************
* iterators :
*************/
// begin -------------------------------------
VT_TPL typename VT::iterator VT::
begin() { return _mem_ptr; }
VT_TPL typename VT::const_iterator VT::
begin() const { return _mem_ptr; }
// end ---------------------------------------
VT_TPL typename VT::iterator VT::
end() { return &_mem_ptr[_size]; }
VT_TPL typename VT::const_iterator VT::
end() const { return &_mem_ptr[_size]; }
// rbegin ------------------------------------
VT_TPL typename VT::reverse_iterator VT::
rbegin() { return reverse_iterator(end()); }
VT_TPL typename VT::const_reverse_iterator VT::
rbegin() const { return const_reverse_iterator(end()); }
// rend --------------------------------------
VT_TPL typename VT::reverse_iterator VT::
rend() { return reverse_iterator(begin()); }
VT_TPL typename VT::const_reverse_iterator VT::
rend() const { return const_reverse_iterator(begin()); }
/************
* capacity :
************/
// size --------------------------------------
VT_TPL typename VT::size_type VT::
size( ) const { return _size; }
// max_size ----------------------------------
VT_TPL typename VT::size_type VT::
max_size() const { return (_allocator.max_size()); }
// resize ------------------------------------
VT_TPL void VT::
resize(size_type n, value_type val) {
if (n > _size)
{
if (n > _capacity)
_increment_capacity(n);
while (_size != n)
{
_allocator.construct(&_mem_ptr[_size], val);
++_size;
}
}
else if (n < _size)
{
while (_size != n)
_allocator.destroy(&_mem_ptr[--_size]);
}
}
// capacity ----------------------------------
VT_TPL typename VT::size_type VT::
capacity() const { return _capacity; }
// empty -------------------------------------
VT_TPL bool VT::
empty() const { return (_size == 0); }
// reserve -----------------------------------
VT_TPL void VT::
reserve( size_type new_cap ) {
value_type * tmp_ptr;
value_type * old_ptr = _mem_ptr;
iterator first = begin();
iterator last = end();
if (new_cap > _allocator.max_size())
throw std::length_error("reserve: new_cap > max_size");
if (_capacity == _allocator.max_size())
throw std::length_error("reserve: capacity == max_size");
if (new_cap <= _capacity)
return ;
_capacity = new_cap;
tmp_ptr = _allocator.allocate(new_cap);
_mem_ptr = tmp_ptr;
if (old_ptr)
{
_size = 0;
assign(first, last);
_destroy(begin(), end());
_allocator.deallocate(old_ptr, _capacity);
}
}
/******************
* element access :
******************/
// operator[] --------------------------------
VT_TPL typename VT::reference VT::
operator[](size_type n) { return _mem_ptr[n]; }
VT_TPL typename VT::const_reference VT::
operator[](size_type n) const { return _mem_ptr[n]; }
// at ----------------------------------------
VT_TPL typename VT::reference VT::
at(size_type n) {
if (n >= _size)
throw std::out_of_range("vector out of range");
return (_mem_ptr[n]);
}
VT_TPL typename VT::const_reference VT::
at(size_type n) const {
if (n >= _size)
throw std::out_of_range("vector out of range");
return (_mem_ptr[n]);
}
// front -------------------------------------
VT_TPL typename VT::reference VT::
front() { return (*_mem_ptr); }
VT_TPL typename VT::const_reference VT::
front() const { return (*_mem_ptr); }
// back --------------------------------------
VT_TPL typename VT::reference VT::
back() { return (_mem_ptr[_size - 1]); }
VT_TPL typename VT::const_reference VT::
back() const { return (_mem_ptr[_size - 1]); }
/*************
* modifiers :
*************/
// assign ------------------------------------
VT_TPL template <class InputIterator>
typename enable_if< !is_integral<InputIterator>::value,void >::type VT::
assign( InputIterator first, InputIterator last) {
InputIterator tmp = first;
unsigned int range = 0;
clear();
while (tmp++ != last)
range++;
if (range >= _capacity)
_increment_capacity(range);
while (first != last)
{
_allocator.construct(&_mem_ptr[_size], *first);
first++;
_size++;
}
}
VT_TPL void VT::
assign( size_type n, const T & val ) {
if (n > _allocator.max_size())
throw std::length_error("assign: n > max_size");
value_type * tmp_ptr;
_destroy(begin(), end());
if (n > _capacity)
{
_capacity = n;
tmp_ptr = _allocator.allocate(n);
if (_mem_ptr)
_allocator.deallocate(_mem_ptr, _capacity);
_mem_ptr = tmp_ptr;
}
_size = n;
while (n)
_allocator.construct(&_mem_ptr[--n], val);
}
// push_back ---------------------------------
VT_TPL void VT::
push_back( const value_type & element ) {
if (_size >= _capacity)
_increment_capacity(1);
_allocator.construct(&_mem_ptr[_size], element);
_size++;
}
// pop_back ----------------------------------
VT_TPL void VT::
pop_back() { _allocator.destroy(end() - 1); _size--; }
// insert ------------------------------------
VT_TPL typename VT::iterator VT::
insert(iterator position, const value_type& val) {
difference_type distance;
iterator it;
if (_size + 1 > _capacity)
{
distance = position - begin();
_increment_capacity(1);
position = begin() + distance;
}
it = end();
if (position != it)
{
_allocator.construct(it, *(it - 1));
while (it-- != position)
*(it + 1) = *it;
_allocator.destroy(position);
}
_allocator.construct(position, val);
_size++;
return (position);
}
VT_TPL void VT::
insert(iterator position, size_type n, const value_type& val) {
difference_type distance;
iterator it_end;
iterator it;
if (_size + n > _capacity)
{
distance = position - begin();
_increment_capacity(n);
position = begin() + distance;
}
it_end = end();
if (position != it_end)
{
it = it_end;
while (it + n != it_end && it != position)
{
it--;
_allocator.construct(it + n, *it);
}
while (it != position)
{
it--;
*(it + n) = *it;
}
_destroy(position, std::min(position + n, it_end));
}
for (size_type i = 0; i < n; i++, position++)
_allocator.construct(position, val);
_size += n;
}
VT_TPL template <class InputIterator>
typename enable_if< !is_integral<InputIterator>::value,void >::type VT::
insert(iterator position, InputIterator first, InputIterator last) {
difference_type dist;
difference_type n;
iterator it_end;
iterator it;
n = std::distance(first, last);
if (_size + n > _capacity)
{
dist = position - begin();
_increment_capacity(n);
position = begin() + dist;
}
it_end = end();
if (position != it_end)
{
it = it_end;
while (it + n != it_end && it != position)
{
it--;
_allocator.construct(it + n, *it);
}
while (it != position)
{
it--;
*(it + n) = *it;
}
_destroy(position, std::min(position + n, it_end));
}
while (first != last)
{
_allocator.construct(position, *first);
++position;
++first;
}
_size += n;
}
// erase -------------------------------------
VT_TPL typename VT::iterator VT::
erase(iterator position) {
iterator i = position;
iterator it_end = end() - 1;
while (i != it_end)
{
*i = *(i + 1);
++i;
}
_allocator.destroy(it_end);
_size -= 1;
return (position);
}
VT_TPL typename VT::iterator VT::
erase(iterator first, iterator last) {
iterator it_end = end();
difference_type diff = std::distance(first, last);
if (diff <= 0)
return (first);
it_end = end();
while (last != it_end)
{
*first = *last;
first++;
last++;
}
_destroy(it_end - diff, it_end);
_size -= diff;
return (first);
}
// swap --------------------------------------
VT_TPL void VT::
swap(vector& x) {
T* tmp_mem_ptr;
size_type tmp_size;
size_type tmp_capacity;
tmp_mem_ptr = x._mem_ptr;
tmp_size = x._size;
tmp_capacity = x._capacity;
x._mem_ptr = _mem_ptr;
x._size = _size;
x._capacity = _capacity;
_mem_ptr = tmp_mem_ptr;
_size = tmp_size;
_capacity = tmp_capacity;
}
// clear -------------------------------------
VT_TPL void VT::
clear() { _destroy(begin(), end()); _size = 0; }
/*************
* allocator :
*************/
// get_allocator -----------------------------
VT_TPL typename VT::allocator_type VT::
get_allocator() const { return (_allocator); }
/*********************************************
* PRIVATE MEMBER FUNCTIONS
*********************************************/
VT_TPL void VT::
_destroy(iterator first, iterator last) {
while (first != last)
{
_allocator.destroy(first);
first++;
}
}
VT_TPL void VT::
_increment_capacity(size_type n) {
size_type res;
res = std::max(_size * 2, n);
reserve(std::min(res, _allocator.max_size()));
}
/************************
* non-member functions :
************************/
// operator == -------------------------------
VT_TPL bool
operator== (const VT & lhs, const VT & rhs) {
if (lhs.size() != rhs.size())
return false;
return ft::equal(lhs.begin(), lhs.end(), rhs.begin());
}
// operator < --------------------------------
VT_TPL bool
operator< (const VT & lhs, const VT & rhs) {
return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
// operator != -------------------------------
VT_TPL bool
operator!= (const VT & lhs, const VT & rhs) { return !(lhs == rhs); }
// operator <= -------------------------------
VT_TPL bool
operator<= (const VT & lhs, const VT & rhs) { return !(lhs > rhs); }
// operator > --------------------------------
VT_TPL bool
operator> (const VT & lhs, const VT & rhs) { return (rhs < lhs); }
// operator >= -------------------------------
VT_TPL bool
operator>= (const VT & lhs, const VT & rhs) { return !(lhs < rhs); }
// swap (vector) -------------------------------
VT_TPL void
swap (VT & lhs, VT & rhs) { lhs.swap(rhs); }
} // namespace ft
#undef VT
#undef VT_TPL

84
tests/includes/main.hpp Normal file
View File

@@ -0,0 +1,84 @@
#ifndef MAIN_HPP
# define MAIN_HPP
#include "colors.h"
#include <iostream>
#include <string>
#include <iomanip> // std::setw()
#include <vector>
#include "tests_structs.hpp"
// global variables
// ***************************************
std::vector< std::vector<A_test*> > test_list;
std::vector< mystruct* > mem_list;
// prototypes
// *********************************************
// vectors
void tests_vector_constructor();
void tests_vector_operator_assignation();
void tests_vector_begin();
void tests_vector_end();
void tests_vector_rbegin();
void tests_vector_rend();
void tests_vector_size();
void tests_vector_max_size();
void tests_vector_resize();
void tests_vector_capacity();
void tests_vector_empty();
void tests_vector_reserve();
void tests_vector_operator_access();
void tests_vector_at();
void tests_vector_front();
void tests_vector_back();
void tests_vector_assign();
void tests_vector_push_back();
void tests_vector_pop_back();
void tests_vector_insert();
void tests_vector_erase();
void tests_vector_swap();
void tests_vector_clear();
void tests_vector_get_allocator();
void tests_vector_relational_operators();
void tests_vector_swap_non_member();
void tests_vector_reverse_iterators();
// map
void tests_map_simple();
void tests_map_constructor();
void tests_map_operator_assignation();
void tests_map_begin();
void tests_map_end();
void tests_map_rbegin();
void tests_map_rend();
void tests_map_empty();
void tests_map_size();
void tests_map_max_size();
void tests_map_operator_access();
void tests_map_insert();
void tests_map_erase();
void tests_map_swap();
void tests_map_clear();
void tests_map_key_comp();
void tests_map_value_comp();
void tests_map_find();
void tests_map_count();
void tests_map_lower_bound();
void tests_map_upper_bound();
void tests_map_equal_range();
void tests_map_get_allocator();
void tests_map_relational_operators();
void tests_map_swap_non_member();
// stack
void tests_stack_constructor();
void tests_stack_empty();
void tests_stack_size();
void tests_stack_top();
void tests_stack_push();
void tests_stack_pop();
#endif

View File

@@ -0,0 +1,33 @@
#ifndef TESTS_MAP_HPP
# define TESTS_MAP_HPP
#include "tests_utils.hpp"
// toogle between test ft and stl
// *************************
#ifdef STL
namespace ft = std;
#else
#include "map.hpp"
#include "reverse_iterator.hpp"
#endif
// templates print
// *****************************************
template <class T, class U>
void print(ft::map<T, U>& mp, std::string name) {
int i = 0;
typename ft::map<T, U>::iterator it;
typename ft::map<T, U>::iterator it_end = mp.end();
std::cout << "\n" << name << ":(map)\n";
for (it = mp.begin(); it != it_end; ++it, i++)
std::cout << "[" << i << "]" << it->first << ":" << it->second << " ";
std::cout << "\nsize:" << mp.size() << "\n";
}
#endif

View File

@@ -0,0 +1,28 @@
#ifndef TESTS_STACK_HPP
# define TESTS_STACK_HPP
#include "tests_utils.hpp"
// toogle between test ft and stl
// *************************
#ifdef STL
namespace ft = std;
#else
#include "stack.hpp"
#endif
// templates print
// *****************************************
template <class T, class cont>
void print(ft::stack<T,cont>& st, std::string name) {
std::cout << "\n" << name << ":(map)\n";
for (int i = st.size(); i > 0 ; i--, st.pop())
std::cout << "[" << i << "]" << st.top() << " ";
std::cout << "\nsize:" << st.size() << "\n";
}
#endif

View File

@@ -0,0 +1,24 @@
#ifndef TESTS_STRUCTS_HPP
# define TESTS_STRUCTS_HPP
// abstract class test -----------------------
struct A_test
{
virtual ~A_test(){};
std::string title;
std::string type;
virtual void func() = 0;
};
// mystruct ----------------------------------
struct mystruct {
public:
mystruct(int data = 0);
~mystruct();
int * get_data() const;
private:
int * _val;
};
std::ostream & operator<<(std::ostream & o, mystruct const * rhs);
#endif

View File

@@ -0,0 +1,170 @@
#ifndef TESTS_UTILS_HPP
# define TESTS_UTILS_HPP
#include "colors.h"
#include <iostream>
#include <string>
#include <iomanip> // std::setw()
#include <iterator> // std::reverse_iterator
#include <utility> // std::make_pair
#include <sstream> // std::stringstream
#include <deque>
#include <vector>
#include <map>
#include <stack>
#include "tests_structs.hpp"
// defines
// ****************************************
# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n";
# define VAL(n) val<T>(n)
# define VALT(n) val<T>(n)
# define VALU(n) val<U>(n)
# define TOI(n) toi<T>(n)
# define PRINT(n) print<>(n, #n);
# define DELETE delete_structs();
# define AVOID_MYSTRUCT(T) if (is_mystruct_type<T>::value) {return;}
// prototypes
// *********************************************
void add_to_list(std::string title, std::string type, A_test* test);
void delete_structs();
// global variables
// ***************************************
extern std::vector< std::vector<A_test*> > test_list;
extern std::vector< mystruct* > mem_list;
// adding each test to the list
// ***************************
#define TEST_S(f_name) TEST_V(f_name)
/*
*/
#define TEST_V(f_name) \
template <class T> struct s_ ## f_name : public A_test\
{ void func(); };\
void f_name () {\
add_to_list("", "", NULL);\
add_to_list(#f_name, "int", new(s_ ## f_name <int>));\
add_to_list(#f_name, "char", new(s_ ## f_name <char>));\
add_to_list(#f_name, "std::string", new(s_ ## f_name <std::string>));\
add_to_list(#f_name, "mystruct*", new(s_ ## f_name <mystruct*>));\
}\
template <class T>\
void s_ ## f_name <T>::func()
#define TEST_M(f_name) \
template <class T, class U> struct s_ ## f_name : public A_test\
{ void func(); };\
void f_name () {\
add_to_list("", "", NULL);\
add_to_list(#f_name, "char, int", new(s_ ## f_name <char, int>));\
add_to_list(#f_name, "char, char", new(s_ ## f_name <char, char>));\
add_to_list(#f_name, "char, std::string", new(s_ ## f_name <char, std::string>));\
add_to_list(#f_name, "char, mystruct*", new(s_ ## f_name <char, mystruct*>));\
add_to_list(#f_name, "int, int", new(s_ ## f_name <int, int>));\
add_to_list(#f_name, "int, char", new(s_ ## f_name <int, char>));\
add_to_list(#f_name, "int, std::string", new(s_ ## f_name <int, std::string>));\
add_to_list(#f_name, "int, mystruct*", new(s_ ## f_name <int, mystruct*>));\
}\
template <class T, class U>\
void s_ ## f_name <T, U>::func()
/*
*/
// templates get value
// *************************************
template <class T> struct is_mystruct_type
{
typedef char yes[1];
typedef yes no[2];
static T type;
static yes& test(mystruct*);
template <class C> static no& test(C);
static const bool value = sizeof(test(type)) == sizeof(yes);
};
// specialization in header, make it inline :
// https://stackoverflow.com/questions/63529059/c-specialized-method-templates-produce-multiple-definition-errors
template <class T>
T val(int n) { (void)n; return (T()); }
template <>
inline int val(int n) { return (n); }
template <>
inline char val(int n) {
if (n <= 126 && n >= 33)
return n;
return (n % 94 + 33);
}
template <>
inline std::string val(int n) {
std::string str;
std::stringstream stream;
stream << n;
stream >> str;
stream.clear();
return (str);
}
template <>
inline mystruct* val(int n) {
mystruct *s = new mystruct(n);
mem_list.push_back(s);
return ( s );
}
template <class T>
T val(std::string str) { (void)str; return (T()); }
template <>
inline int val(std::string str) { int i = str[0]; return (val<int>(i)); }
template <>
inline char val(std::string str) { int i = str[0]; return (val<char>(i)); }
template <>
inline std::string val(std::string str) { return (str); }
template <>
inline mystruct* val(std::string str) { int i = str[0]; return (val<mystruct*>(i)); }
// templates to value
// **************************************
template <class T>
int toi(T t) {(void)t; return (0);
}
template <>
inline int toi(int i) {return (i);
}
template <>
inline int toi(char c) {return (c);
}
template <>
inline int toi(std::string str) {
int i;
std::stringstream stream;
stream << str;
stream >> i;
stream.clear();
return (i);
}
template <>
inline int toi(mystruct* s) {
return ( s->get_data()[0] );
}
#endif

View File

@@ -0,0 +1,33 @@
#ifndef TESTS_VECTOR_HPP
# define TESTS_VECTOR_HPP
#include "tests_utils.hpp"
// toogle between test ft and stl
// *************************
#ifdef STL
namespace ft = std;
#else
#include "vector.hpp"
#include "reverse_iterator.hpp"
#endif
// templates print
// *****************************************
template <class T>
void print(ft::vector<T>& vec, std::string name) {
int i = 0;
typename ft::vector<T>::iterator it;
typename ft::vector<T>::iterator it_end = vec.end();
std::cout << "\n" << name << ":(vector)\n";
for (it = vec.begin(); it != it_end; ++it, i++)
std::cout << "[" << i << "]" << *it << " ";
std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n";
}
#endif

90
tests/main.cpp Normal file
View File

@@ -0,0 +1,90 @@
#include "main.hpp"
int main() {
// VECTOR
tests_vector_constructor();
tests_vector_operator_assignation();
tests_vector_begin();
tests_vector_end();
tests_vector_rbegin();
tests_vector_rend();
tests_vector_size();
tests_vector_max_size();
tests_vector_resize();
tests_vector_capacity();
tests_vector_empty();
tests_vector_reserve();
tests_vector_operator_access();
tests_vector_at();
tests_vector_front();
tests_vector_back();
tests_vector_assign();
tests_vector_push_back();
tests_vector_pop_back();
tests_vector_insert();
tests_vector_erase();
tests_vector_swap();
tests_vector_clear();
tests_vector_get_allocator();
tests_vector_swap_non_member();
tests_vector_reverse_iterators();
tests_vector_relational_operators();
// MAP
tests_map_simple();
tests_map_constructor();
tests_map_operator_assignation();
tests_map_begin();
tests_map_end();
tests_map_rbegin();
tests_map_rend();
tests_map_empty();
tests_map_size();
tests_map_max_size();
tests_map_operator_access();
tests_map_insert();
tests_map_erase();
tests_map_swap();
tests_map_clear();
tests_map_key_comp();
tests_map_value_comp();
tests_map_find();
tests_map_count();
tests_map_lower_bound();
tests_map_upper_bound();
tests_map_equal_range();
tests_map_get_allocator();
tests_map_swap_non_member();
tests_map_relational_operators();
// STACK
tests_stack_constructor();
tests_stack_empty();
tests_stack_size();
tests_stack_top();
tests_stack_push();
tests_stack_pop();
// execute tests and print them :
int size = test_list.size();
int sub_size;
for(int i = 0; i < size; i++)
{
std::cout << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] "
<< test_list[i][0]->title << RESET << "\n";
sub_size = test_list[i].size();
for (int j = 0; j < sub_size; j++)
{
std::cout << "\n" << B_CYAN << "-- " << test_list[i][j]->type
<< " --" << RESET "\n";
test_list[i][j]->func();
delete test_list[i][j];
}
}
std::cout << "\n";
return 0;
}

View File

@@ -1,3 +1,4 @@
#include <iostream>
#include <string>
#include <deque>
@@ -87,7 +88,7 @@ int main(int argc, char** argv) {
{
//NORMAL ! :P
}
for (int i = 0; i < COUNT; ++i)
{
map_int.insert(ft::make_pair(rand(), rand()));
@@ -114,3 +115,4 @@ int main(int argc, char** argv) {
std::cout << std::endl;
return (0);
}

View File

@@ -0,0 +1,741 @@
#include <iostream>
#include <string>
#include <iomanip> // std::setw()
#include <iterator> // std::reverse_iterator
#include <utility> // std::make_pair
#include <sstream> // std::stringstream
#include <vector>
#include <map>
// toogle ft in stl
#ifdef STL
namespace ft = std;
#else
#include "map.hpp"
#include "reverse_iterator.hpp"
#endif
// defines
# define TEST_M(s) template <class T, class U> void s ()
# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n";
# define VALT(n) val<T>(n)
# define VALU(n) val<U>(n)
# define TOI(n) toi<T>(n)
# define PRINT(n) print<>(n, #n);
# define DELETE delete_structs();
// colors
# define GRAY "\e[0;30m"
# define RED "\e[0;31m"
# define GREEN "\e[0;32m"
# define YELLOW "\e[0;33m"
# define BLUE "\e[0;34m"
# define PURPLE "\e[0;35m"
# define CYAN "\e[0;36m"
# define WHITE "\e[0;37m"
# define B_GRAY "\e[1;30m"
# define B_RED "\e[1;31m"
# define B_GREEN "\e[1;32m"
# define B_YELLOW "\e[1;33m"
# define B_BLUE "\e[1;34m"
# define B_PURPLE "\e[1;35m"
# define B_CYAN "\e[1;36m"
# define B_WHITE "\e[1;37m"
# define RESET "\e[0m"
// mystruct declaration
struct mystruct {
public:
mystruct(int data = 0);
~mystruct();
int * get_data() const;
private:
int * _val;
};
std::ostream & operator<<(std::ostream & o, mystruct const * rhs);
// mystruct definition
mystruct::mystruct(int data)
{_val = new int[2]; _val[0] = data; _val[1] = data;}
mystruct::~mystruct()
{delete[] _val;}
int * mystruct::get_data() const
{return _val;}
std::ostream & operator<<(std::ostream & o, mystruct const * rhs) {
if (rhs != NULL)
o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1];
else
o << "NULL";
return (o);
}
// global variable for mem gestion of mystruct
std::vector< mystruct* > mem_list;
// template print function
template <class T, class U>
void print(ft::map<T, U> mp, std::string name) {
int i = 0;
typename ft::map<T, U>::iterator it;
typename ft::map<T, U>::iterator it_end = mp.end();
std::cout << "\n" << name << ":(map)\n";
for (it = mp.begin(); it != it_end; ++it, i++)
std::cout << "[" << i << "]" << it->first << ":" << it->second << " ";
std::cout << "\nsize:" << mp.size() << "\n";
}
// template val() for instanciation of values for types :
// int, char, std::string, and mystruct*
template <class T>
T val(int n) { (void)n; return (T()); }
template <>
inline int val(int n) { return (n); }
template <>
inline char val(int n) {
if (n <= 126 && n >= 33)
return n;
return (n % 94 + 33);
}
template <>
inline std::string val(int n) {
std::string str;
std::stringstream stream;
stream << n;
stream >> str;
stream.clear();
return (str);
}
template <>
inline mystruct* val(int n) {
mystruct *s = new mystruct(n);
mem_list.push_back(s);
return ( s );
}
template <class T>
T val(std::string str) { (void)str; return (T()); }
template <>
inline int val(std::string str) { int i = str[0]; return (val<int>(i)); }
template <>
inline char val(std::string str) { int i = str[0]; return (val<char>(i)); }
template <>
inline std::string val(std::string str) { return (str); }
template <>
inline mystruct* val(std::string str) { int i = str[0]; return (val<mystruct*>(i)); }
// delete function for mem gestion of mystruct*
void delete_structs() {
std::vector<mystruct*>::iterator it;
std::vector<mystruct*>::iterator it_end = mem_list.end();
for (it = mem_list.begin(); it != it_end; ++it)
delete *it;
mem_list.clear();
}
// all tests
TEST_M(tests_map_operator_assignation)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> first;
ft::map<T,U> second;
first[VALT('x')]=VALU(8);
first[VALT('y')]=VALU(16);
first[VALT('z')]=VALU(32);
PRINT(first)
PRINT(second)
second=first; // second now contains 3 ints
first=ft::map<T,U>(); // and first is now empty
std::cout << "Size of first: " << first.size() << '\n';
std::cout << "Size of second: " << second.size() << '\n';
PRINT(first)
PRINT(second)
DELETE
}
TEST_M(tests_map_begin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_end)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_rbegin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_rend)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_empty)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
while (!mymap.empty())
{
std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n';
mymap.erase(mymap.begin());
}
DELETE
}
TEST_M(tests_map_size)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(101);
mymap[VALT('b')]=VALU(202);
mymap[VALT('c')]=VALU(302);
std::cout << "mymap.size() is " << mymap.size() << '\n';
PRINT(mymap)
DELETE
}
TEST_M(tests_map_max_size)
{
// title
TITLE(cplusplus.com reference)
int i;
std::map<T,U> mymap;
if (mymap.max_size()>1000)
{
for (i=0; i<1000; i++) mymap[i]=VALU(0);
std::cout << "The map contains 1000 elements.\n";
}
else std::cout << "The map could not hold 1000 elements.\n";
DELETE
}
TEST_M(tests_map_operator_access)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU("An element");
mymap[VALT('b')]=VALU("another element");
mymap[VALT('c')]=mymap[VALT('b')];
std::cout << "mymap['a'] is " << mymap[VALT('a')] << '\n';
std::cout << "mymap['b'] is " << mymap[VALT('b')] << '\n';
std::cout << "mymap['c'] is " << mymap[VALT('c')] << '\n';
std::cout << "mymap['d'] is " << mymap[VALT('d')] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
DELETE
}
TEST_M(tests_map_insert)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
// first insert function version (single parameter):
mymap.insert ( ft::pair<T,U>(VALT('a'),VALU(100)) );
mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(200)) );
ft::pair<typename ft::map<T,U>::iterator, bool> ret;
ret = mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(500)) );
if (ret.second==false) {
std::cout << "element 'z' already existed";
std::cout << " with a value of " << ret.first->second << '\n';
}
// second insert function version (with hint position):
typename ft::map<T,U>::iterator it = mymap.begin();
mymap.insert (it, ft::pair<T,U>(VALT('b'),VALU(300))); // max efficiency inserting
mymap.insert (it, ft::pair<T,U>(VALT('c'),VALU(400))); // no max efficiency inserting
// third insert function version (range insertion):
ft::map<T,U> anothermap;
anothermap.insert(mymap.begin(),mymap.find('c'));
PRINT(mymap)
PRINT(anothermap)
DELETE
}
TEST_M(tests_map_erase)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
// insert some values:
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
mymap[VALT('d')]=VALU(40);
mymap[VALT('e')]=VALU(50);
mymap[VALT('f')]=VALU(60);
it=mymap.find(VALT('b'));
mymap.erase (it); // erasing by iterator
mymap.erase (VALT('c')); // erasing by key
it=mymap.find (VALT('e'));
mymap.erase ( it, mymap.end() ); // erasing by range
PRINT(mymap)
DELETE
}
TEST_M(tests_map_swap)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> foo,bar;
foo[VALT('x')]=VALU(100);
foo[VALT('y')]=VALU(200);
bar[VALT('a')]=VALU(11);
bar[VALT('b')]=VALU(22);
bar[VALT('c')]=VALU(33);
foo.swap(bar);
PRINT(foo)
PRINT(bar)
DELETE
}
TEST_M(tests_map_clear)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(100);
mymap[VALT('y')]=VALU(200);
mymap[VALT('z')]=VALU(300);
PRINT(mymap)
mymap.clear();
mymap[VALT('a')]=VALU(1101);
mymap[VALT('b')]=VALU(2202);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_key_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::key_compare mycomp = mymap.key_comp();
mymap[VALT('a')]=VALU(100);
mymap[VALT('b')]=VALU(200);
mymap[VALT('c')]=VALU(300);
std::cout << "mymap contains:\n";
T highest = mymap.rbegin()->first; // key value of last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mycomp((*it++).first, highest) );
std::cout << '\n';
DELETE
}
TEST_M(tests_map_value_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(1001);
mymap[VALT('y')]=VALU(2002);
mymap[VALT('z')]=VALU(3003);
std::cout << "mymap contains:\n";
ft::pair<T,U> highest = *mymap.rbegin(); // last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mymap.value_comp()(*it++, highest) );
DELETE
}
TEST_M(tests_map_find)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
mymap[VALT('a')]=VALU(50);
mymap[VALT('b')]=VALU(100);
mymap[VALT('c')]=VALU(150);
mymap[VALT('d')]=VALU(200);
it = mymap.find(VALT('b'));
if (it != mymap.end())
mymap.erase (it);
// print content:
std::cout << "elements in mymap:" << '\n';
std::cout << "a => " << mymap.find(VALT('a'))->second << '\n';
std::cout << "c => " << mymap.find(VALT('c'))->second << '\n';
std::cout << "d => " << mymap.find(VALT('d'))->second << '\n';
DELETE
}
TEST_M(tests_map_count)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
T c;
mymap [VALT('a')]=VALU(101);
mymap [VALT('c')]=VALU(202);
mymap [VALT('f')]=VALU(303);
// to do this test with T as a 'string' or 'mystruct*' we should add overload
for (c=VALT('a'); c<VALT('h'); c++)
{
std::cout << c;
if (mymap.count(c)>0)
std::cout << " is an element of mymap.\n";
else
std::cout << " is not an element of mymap.\n";
}
DELETE
}
TEST_M(tests_map_lower_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_upper_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_equal_range)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
ft::pair<typename ft::map<T,U>::iterator,typename ft::map<T,U>::iterator> ret;
ret = mymap.equal_range(VALT('b'));
std::cout << "lower bound points to: ";
std::cout << ret.first->first << " => " << ret.first->second << '\n';
std::cout << "upper bound points to: ";
std::cout << ret.second->first << " => " << ret.second->second << '\n';
DELETE
}
TEST_M(tests_map_get_allocator)
{
// title
TITLE(cplusplus.com reference)
int psize;
ft::map<T,U> mymap;
ft::pair<const T,U>* p;
// allocate an array of 5 elements using mymap's allocator:
p=mymap.get_allocator().allocate(5);
// assign some values to array
psize = sizeof(typename ft::map<T,U>::value_type)*5;
std::cout << "The allocated array has a size of " << psize << " bytes.\n";
mymap.get_allocator().deallocate(p,5);
DELETE
}
TEST_M(tests_map_relational_operators)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> alice;
ft::map<T,U> bob;
ft::map<T,U> eve;
(void)alice;
(void)bob;
(void)eve;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
eve[VALT(1)]=VALU('a');
eve[VALT(2)]=VALU('b');
eve[VALT(3)]=VALU('c');
std::cout << std::boolalpha;
// Compare non equal containers
std::cout << "alice == bob returns " << (alice == bob) << '\n';
std::cout << "alice != bob returns " << (alice != bob) << '\n';
std::cout << "alice < bob returns " << (alice < bob) << '\n';
std::cout << "alice <= bob returns " << (alice <= bob) << '\n';
std::cout << "alice > bob returns " << (alice > bob) << '\n';
std::cout << "alice >= bob returns " << (alice >= bob) << '\n';
std::cout << '\n';
// Compare equal containers
std::cout << "alice == eve returns " << (alice == eve) << '\n';
std::cout << "alice != eve returns " << (alice != eve) << '\n';
std::cout << "alice < eve returns " << (alice < eve) << '\n';
std::cout << "alice <= eve returns " << (alice <= eve) << '\n';
std::cout << "alice > eve returns " << (alice > eve) << '\n';
std::cout << "alice >= eve returns " << (alice >= eve) << '\n';
DELETE
}
TEST_M(tests_map_swap_non_member)
{
// title
TITLE(cplusplus.com reference)
ft::map<T, U> alice;
ft::map<T, U> bob;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
// Print state before swap
PRINT(alice)
PRINT(bob)
std::cout << "-- SWAP\n";
std::swap(alice, bob);
// Print state after swap
PRINT(alice)
PRINT(bob)
DELETE
}
template <class T, class U>
void call_tests() {
tests_map_operator_assignation<T,U>();
tests_map_begin<T,U>();
tests_map_end<T,U>();
tests_map_rbegin<T,U>();
tests_map_rend<T,U>();
tests_map_empty<T,U>();
tests_map_size<T,U>();
tests_map_max_size<T,U>();
tests_map_operator_access<T,U>();
tests_map_insert<T,U>();
tests_map_erase<T,U>();
tests_map_swap<T,U>();
tests_map_clear<T,U>();
tests_map_key_comp<T,U>();
tests_map_value_comp<T,U>();
tests_map_find<T,U>();
tests_map_count<T,U>();
tests_map_lower_bound<T,U>();
tests_map_upper_bound<T,U>();
tests_map_equal_range<T,U>();
tests_map_get_allocator<T,U>();
tests_map_relational_operators<T,U>();
tests_map_swap_non_member<T,U>();
}
int main() {
call_tests<char,int>();
call_tests<char,char>();
call_tests<char,std::string>();
call_tests<char,mystruct*>();
call_tests<int,int>();
call_tests<int,char>();
call_tests<int,std::string>();
call_tests<int,mystruct*>();
return 0;
}

View File

@@ -0,0 +1,862 @@
#include <iostream>
#include <string>
#include <iomanip> // std::setw()
#include <iterator> // std::reverse_iterator
#include <utility> // std::make_pair
#include <sstream> // std::stringstream
#include <vector>
// toogle between test ft and stl
// *************************
#include <map>
#ifdef STL
namespace ft = std;
#else
#include "vector.hpp"
#include "map.hpp"
#include "reverse_iterator.hpp"
#endif
// colors
// *************************************************
# define GRAY "\e[0;30m"
# define RED "\e[0;31m"
# define GREEN "\e[0;32m"
# define YELLOW "\e[0;33m"
# define BLUE "\e[0;34m"
# define PURPLE "\e[0;35m"
# define CYAN "\e[0;36m"
# define WHITE "\e[0;37m"
# define B_GRAY "\e[1;30m"
# define B_RED "\e[1;31m"
# define B_GREEN "\e[1;32m"
# define B_YELLOW "\e[1;33m"
# define B_BLUE "\e[1;34m"
# define B_PURPLE "\e[1;35m"
# define B_CYAN "\e[1;36m"
# define B_WHITE "\e[1;37m"
# define RESET "\e[0m"
// defines
// ****************************************
# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n";
# define VAL(n) val<T>(n)
# define VALT(n) val<T>(n)
# define VALU(n) val<U>(n)
# define TOI(n) toi<T>(n)
# define PRINT(n) print<>(n, #n);
# define DELETE delete_structs();
// adding each test to the list
// ***************************
#define TEST_V(f_name) \
template <class T> struct s_ ## f_name : public A_test\
{ void func(); };\
void f_name () {\
add_to_list("", "", NULL);\
add_to_list(#f_name, "int", new(s_ ## f_name <int>));\
add_to_list(#f_name, "char", new(s_ ## f_name <char>));\
add_to_list(#f_name, "std::string", new(s_ ## f_name <std::string>));\
add_to_list(#f_name, "mystruct*", new(s_ ## f_name <mystruct*>));\
}\
template <class T>\
void s_ ## f_name <T>::func()
#define TEST_M(f_name) \
template <class T, class U> struct s_ ## f_name : public A_test\
{ void func(); };\
void f_name () {\
add_to_list("", "", NULL);\
add_to_list(#f_name, "char, int", new(s_ ## f_name <char, int>));\
add_to_list(#f_name, "char, char", new(s_ ## f_name <char, char>));\
add_to_list(#f_name, "char, std::string", new(s_ ## f_name <char, std::string>));\
add_to_list(#f_name, "char, mystruct*", new(s_ ## f_name <char, mystruct*>));\
add_to_list(#f_name, "int, int", new(s_ ## f_name <int, int>));\
add_to_list(#f_name, "int, char", new(s_ ## f_name <int, char>));\
add_to_list(#f_name, "int, std::string", new(s_ ## f_name <int, std::string>));\
add_to_list(#f_name, "int, mystruct*", new(s_ ## f_name <int, mystruct*>));\
}\
template <class T, class U>\
void s_ ## f_name <T, U>::func()
// structures
// *********************************************
struct A_test
{
virtual ~A_test(){};
std::string title;
std::string type;
virtual void func() = 0;
};
struct mystruct {
public:
mystruct(int data = 0)
{_val = new int[2]; _val[0] = data; _val[1] = data;}
~mystruct()
{delete[] _val;}
int * get_data() const
{return _val;}
private:
int * _val;
};
std::ostream & operator<<(std::ostream & o, mystruct const * rhs) {
if (rhs != NULL)
o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1];
else
o << "NULL";
return (o);
}
// global variables
// ***************************************
std::vector< std::vector<A_test*> > test_list;
std::vector< mystruct* > mem_list;
// functions utiles
// ***************************************
void add_to_list(std::string title, std::string type, A_test* test) {
std::vector<A_test*> test_sub_list;
std::vector< std::vector<A_test*> >::iterator it;
// title != NULL for the first element
if (test == NULL)
{
test_list.push_back(test_sub_list);
return;
}
test->title = title;
test->type = type;
it = test_list.end() - 1;
(*it).push_back(test);
}
void delete_structs() {
std::vector<mystruct*>::iterator it;
std::vector<mystruct*>::iterator it_end = mem_list.end();
for (it = mem_list.begin(); it != it_end; ++it)
delete *it;
mem_list.clear();
}
// templates print
// *****************************************
template <class T>
void print(ft::vector<T> vec, std::string name) {
int i = 0;
typename ft::vector<T>::iterator it;
typename ft::vector<T>::iterator it_end = vec.end();
std::cout << "\n" << name << ":(vector)\n";
for (it = vec.begin(); it != it_end; ++it, i++)
std::cout << "[" << i << "]" << *it << " ";
std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n";
}
template <class T, class U>
void print(ft::map<T, U> mp, std::string name) {
int i = 0;
typename ft::map<T, U>::iterator it;
typename ft::map<T, U>::iterator it_end = mp.end();
std::cout << "\n" << name << ":(map)\n";
for (it = mp.begin(); it != it_end; ++it, i++)
std::cout << "[" << i << "]" << it->first << ":" << it->second << " ";
std::cout << "\nsize:" << mp.size() << "\n";
}
// templates get value
// *************************************
// specialization in header, make it inline :
// https://stackoverflow.com/questions/63529059/c-specialized-method-templates-produce-multiple-definition-errors
template <class T>
T val(int n) { (void)n; return (T()); }
template <>
inline int val(int n) { return (n); }
template <>
inline char val(int n) {
if (n <= 126 && n >= 33)
return n;
return (n % 94 + 33);
}
template <>
inline std::string val(int n) {
std::string str;
std::stringstream stream;
stream << n;
stream >> str;
stream.clear();
return (str);
}
template <>
inline mystruct* val(int n) {
mystruct *s = new mystruct(n);
mem_list.push_back(s);
return ( s );
}
template <class T>
T val(std::string str) { (void)str; return (T()); }
template <>
inline int val(std::string str) { int i = str[0]; return (val<int>(i)); }
template <>
inline char val(std::string str) { int i = str[0]; return (val<char>(i)); }
template <>
inline std::string val(std::string str) { return (str); }
template <>
inline mystruct* val(std::string str) { int i = str[0]; return (val<mystruct*>(i)); }
// templates to value
// **************************************
template <class T>
int toi(T t) {(void)t; return (0);
}
template <>
inline int toi(int i) {return (i);
}
template <>
inline int toi(char c) {return (c);
}
template <>
inline int toi(std::string str) {
int i;
std::stringstream stream;
stream << str;
stream >> i;
stream.clear();
return (i);
}
template <>
inline int toi(mystruct* s) {
return ( s->get_data()[0] );
}
// tests functions
// *****************************************
TEST_M(tests_map_operator_assignation)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> first;
ft::map<T,U> second;
first[VALT('x')]=VALU(8);
first[VALT('y')]=VALU(16);
first[VALT('z')]=VALU(32);
PRINT(first)
PRINT(second)
second=first; // second now contains 3 ints
first=ft::map<T,U>(); // and first is now empty
std::cout << "Size of first: " << first.size() << '\n';
std::cout << "Size of second: " << second.size() << '\n';
PRINT(first)
PRINT(second)
DELETE
}
TEST_M(tests_map_begin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_end)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_rbegin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_rend)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_empty)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
while (!mymap.empty())
{
std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n';
mymap.erase(mymap.begin());
}
DELETE
}
TEST_M(tests_map_size)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(101);
mymap[VALT('b')]=VALU(202);
mymap[VALT('c')]=VALU(302);
std::cout << "mymap.size() is " << mymap.size() << '\n';
PRINT(mymap)
DELETE
}
TEST_M(tests_map_max_size)
{
// title
TITLE(cplusplus.com reference)
int i;
std::map<T,U> mymap;
if (mymap.max_size()>1000)
{
for (i=0; i<1000; i++) mymap[i]=VALU(0);
std::cout << "The map contains 1000 elements.\n";
}
else std::cout << "The map could not hold 1000 elements.\n";
DELETE
}
TEST_M(tests_map_operator_access)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU("An element");
mymap[VALT('b')]=VALU("another element");
mymap[VALT('c')]=mymap[VAL('b')];
std::cout << "mymap['a'] is " << mymap[VALT('a')] << '\n';
std::cout << "mymap['b'] is " << mymap[VALT('b')] << '\n';
std::cout << "mymap['c'] is " << mymap[VALT('c')] << '\n';
std::cout << "mymap['d'] is " << mymap[VALT('d')] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
DELETE
}
TEST_M(tests_map_insert)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
// first insert function version (single parameter):
mymap.insert ( ft::pair<T,U>(VALT('a'),VALU(100)) );
mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(200)) );
ft::pair<typename ft::map<T,U>::iterator, bool> ret;
ret = mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(500)) );
if (ret.second==false) {
std::cout << "element 'z' already existed";
std::cout << " with a value of " << ret.first->second << '\n';
}
// second insert function version (with hint position):
typename ft::map<T,U>::iterator it = mymap.begin();
mymap.insert (it, ft::pair<T,U>(VALT('b'),VALU(300))); // max efficiency inserting
mymap.insert (it, ft::pair<T,U>(VALT('c'),VALU(400))); // no max efficiency inserting
// third insert function version (range insertion):
ft::map<T,U> anothermap;
anothermap.insert(mymap.begin(),mymap.find('c'));
PRINT(mymap)
PRINT(anothermap)
DELETE
}
TEST_M(tests_map_erase)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
// insert some values:
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
mymap[VALT('d')]=VALU(40);
mymap[VALT('e')]=VALU(50);
mymap[VALT('f')]=VALU(60);
it=mymap.find(VALT('b'));
mymap.erase (it); // erasing by iterator
mymap.erase (VALT('c')); // erasing by key
it=mymap.find (VALT('e'));
mymap.erase ( it, mymap.end() ); // erasing by range
PRINT(mymap)
DELETE
}
TEST_M(tests_map_swap)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> foo,bar;
foo[VALT('x')]=VALU(100);
foo[VALT('y')]=VALU(200);
bar[VALT('a')]=VALU(11);
bar[VALT('b')]=VALU(22);
bar[VALT('c')]=VALU(33);
foo.swap(bar);
PRINT(foo)
PRINT(bar)
DELETE
}
TEST_M(tests_map_clear)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(100);
mymap[VALT('y')]=VALU(200);
mymap[VALT('z')]=VALU(300);
PRINT(mymap)
mymap.clear();
mymap[VALT('a')]=VALU(1101);
mymap[VALT('b')]=VALU(2202);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_key_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::key_compare mycomp = mymap.key_comp();
mymap[VALT('a')]=VALU(100);
mymap[VALT('b')]=VALU(200);
mymap[VALT('c')]=VALU(300);
std::cout << "mymap contains:\n";
T highest = mymap.rbegin()->first; // key value of last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mycomp((*it++).first, highest) );
std::cout << '\n';
DELETE
}
TEST_M(tests_map_value_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(1001);
mymap[VALT('y')]=VALU(2002);
mymap[VALT('z')]=VALU(3003);
std::cout << "mymap contains:\n";
ft::pair<T,U> highest = *mymap.rbegin(); // last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mymap.value_comp()(*it++, highest) );
DELETE
}
TEST_M(tests_map_find)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
mymap[VALT('a')]=VALU(50);
mymap[VALT('b')]=VALU(100);
mymap[VALT('c')]=VALU(150);
mymap[VALT('d')]=VALU(200);
it = mymap.find(VALT('b'));
if (it != mymap.end())
mymap.erase (it);
// print content:
std::cout << "elements in mymap:" << '\n';
std::cout << "a => " << mymap.find(VALT('a'))->second << '\n';
std::cout << "c => " << mymap.find(VALT('c'))->second << '\n';
std::cout << "d => " << mymap.find(VALT('d'))->second << '\n';
DELETE
}
TEST_M(tests_map_count)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
T c;
mymap [VALT('a')]=VALU(101);
mymap [VALT('c')]=VALU(202);
mymap [VALT('f')]=VALU(303);
// to do this test with T as a 'string' or 'mystruct*' we should add overload
for (c=VALT('a'); c<VALT('h'); c++)
{
std::cout << c;
if (mymap.count(c)>0)
std::cout << " is an element of mymap.\n";
else
std::cout << " is not an element of mymap.\n";
}
DELETE
}
TEST_M(tests_map_lower_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_upper_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_equal_range)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
ft::pair<typename ft::map<T,U>::iterator,typename ft::map<T,U>::iterator> ret;
ret = mymap.equal_range(VALT('b'));
std::cout << "lower bound points to: ";
std::cout << ret.first->first << " => " << ret.first->second << '\n';
std::cout << "upper bound points to: ";
std::cout << ret.second->first << " => " << ret.second->second << '\n';
DELETE
}
TEST_M(tests_map_get_allocator)
{
// title
TITLE(cplusplus.com reference)
int psize;
ft::map<T,U> mymap;
ft::pair<const T,U>* p;
// allocate an array of 5 elements using mymap's allocator:
p=mymap.get_allocator().allocate(5);
// assign some values to array
psize = sizeof(typename ft::map<T,U>::value_type)*5;
std::cout << "The allocated array has a size of " << psize << " bytes.\n";
mymap.get_allocator().deallocate(p,5);
DELETE
}
TEST_M(tests_map_relational_operators)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> alice;
ft::map<T,U> bob;
ft::map<T,U> eve;
(void)alice;
(void)bob;
(void)eve;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
eve[VALT(1)]=VALU('a');
eve[VALT(2)]=VALU('b');
eve[VALT(3)]=VALU('c');
std::cout << std::boolalpha;
// Compare non equal containers
std::cout << "alice == bob returns " << (alice == bob) << '\n';
std::cout << "alice != bob returns " << (alice != bob) << '\n';
std::cout << "alice < bob returns " << (alice < bob) << '\n';
std::cout << "alice <= bob returns " << (alice <= bob) << '\n';
std::cout << "alice > bob returns " << (alice > bob) << '\n';
std::cout << "alice >= bob returns " << (alice >= bob) << '\n';
std::cout << '\n';
// Compare equal containers
std::cout << "alice == eve returns " << (alice == eve) << '\n';
std::cout << "alice != eve returns " << (alice != eve) << '\n';
std::cout << "alice < eve returns " << (alice < eve) << '\n';
std::cout << "alice <= eve returns " << (alice <= eve) << '\n';
std::cout << "alice > eve returns " << (alice > eve) << '\n';
std::cout << "alice >= eve returns " << (alice >= eve) << '\n';
DELETE
}
TEST_M(tests_map_swap_non_member)
{
// title
TITLE(cplusplus.com reference)
ft::map<T, U> alice;
ft::map<T, U> bob;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
// Print state before swap
PRINT(alice)
PRINT(bob)
std::cout << "-- SWAP\n";
std::swap(alice, bob);
// Print state after swap
PRINT(alice)
PRINT(bob)
DELETE
}
int main() {
tests_map_operator_assignation();
tests_map_begin();
tests_map_end();
tests_map_rbegin();
tests_map_rend();
tests_map_empty();
tests_map_size();
tests_map_max_size();
tests_map_operator_access();
tests_map_insert();
tests_map_erase();
tests_map_swap();
tests_map_clear();
tests_map_key_comp();
tests_map_value_comp();
tests_map_find();
tests_map_count();
tests_map_lower_bound();
tests_map_upper_bound();
tests_map_equal_range();
tests_map_get_allocator();
tests_map_relational_operators();
tests_map_swap_non_member();
// execute tests and print them :
int size = test_list.size();
int sub_size;
for(int i = 0; i < size; i++)
{
std::cout << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] "
<< test_list[i][0]->title << RESET << "\n";
sub_size = test_list[i].size();
for (int j = 0; j < sub_size; j++)
{
std::cout << "\n" << B_CYAN << "-- " << test_list[i][j]->type
<< " --" << RESET "\n";
test_list[i][j]->func();
delete test_list[i][j];
}
}
std::cout << "\n";
return 0;
}

View File

@@ -0,0 +1,187 @@
#include <iostream>
#include <string>
#include <iomanip> // std::setw()
#include <iterator> // std::reverse_iterator
#include <utility> // std::make_pair
#include <sstream> // std::stringstream
#include <vector>
#include <map>
#include <stack>
// toogle ft in stl
#ifdef STL
namespace ft = std;
#else
#include "vector.hpp"
#include "map.hpp"
#include "stack.hpp"
#include "reverse_iterator.hpp"
#endif
// defines
# define TEST(s) template <class T> void s ()
# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n";
# define VAL(n) val<T>(n)
# define TOI(n) toi<T>(n)
# define PRINT(n) print<>(n, #n);
# define DELETE delete_structs();
// colors
# define GRAY "\e[0;30m"
# define RED "\e[0;31m"
# define GREEN "\e[0;32m"
# define YELLOW "\e[0;33m"
# define BLUE "\e[0;34m"
# define PURPLE "\e[0;35m"
# define CYAN "\e[0;36m"
# define WHITE "\e[0;37m"
# define B_GRAY "\e[1;30m"
# define B_RED "\e[1;31m"
# define B_GREEN "\e[1;32m"
# define B_YELLOW "\e[1;33m"
# define B_BLUE "\e[1;34m"
# define B_PURPLE "\e[1;35m"
# define B_CYAN "\e[1;36m"
# define B_WHITE "\e[1;37m"
# define RESET "\e[0m"
// mystruct declaration
struct mystruct {
public:
mystruct(int data = 0);
~mystruct();
int * get_data() const;
private:
int * _val;
};
std::ostream & operator<<(std::ostream & o, mystruct const * rhs);
// mystruct definition
mystruct::mystruct(int data)
{_val = new int[2]; _val[0] = data; _val[1] = data;}
mystruct::~mystruct()
{delete[] _val;}
int * mystruct::get_data() const
{return _val;}
std::ostream & operator<<(std::ostream & o, mystruct const * rhs) {
if (rhs != NULL)
o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1];
else
o << "NULL";
return (o);
}
// global variable for mem gestion of mystruct
std::vector< mystruct* > mem_list;
// template print function
template <class T, class cont>
void print(ft::stack<T,cont>& st, std::string name) {
std::cout << "\n" << name << ":(map)\n";
for (int i = st.size(); i > 0 ; i--, st.pop())
std::cout << "[" << i << "]" << st.top() << " ";
std::cout << "\nsize:" << st.size() << "\n";
}
// template val() for instanciation of values for types :
// int, char, std::string, and mystruct*
template <class T>
T val(int n) { (void)n; return (T()); }
template <>
inline int val(int n) { return (n); }
template <>
inline char val(int n) {
if (n <= 126 && n >= 33)
return n;
return (n % 94 + 33);
}
template <>
inline std::string val(int n) {
std::string str;
std::stringstream stream;
stream << n;
stream >> str;
stream.clear();
return (str);
}
template <>
inline mystruct* val(int n) {
mystruct *s = new mystruct(n);
mem_list.push_back(s);
return ( s );
}
template <class T>
T val(std::string str) { (void)str; return (T()); }
template <>
inline int val(std::string str) { int i = str[0]; return (val<int>(i)); }
template <>
inline char val(std::string str) { int i = str[0]; return (val<char>(i)); }
template <>
inline std::string val(std::string str) { return (str); }
template <>
inline mystruct* val(std::string str) { int i = str[0]; return (val<mystruct*>(i)); }
// delete function for mem gestion of mystruct*
void delete_structs() {
std::vector<mystruct*>::iterator it;
std::vector<mystruct*>::iterator it_end = mem_list.end();
for (it = mem_list.begin(); it != it_end; ++it)
delete *it;
mem_list.clear();
}
// all tests
TEST(tests_stack_constructor)
{
// title
TITLE(simple test)
std::deque<T> mydeque (3,VAL(100)); // deque with 3 elements
std::vector<T> myvector (2,VAL(200)); // vector with 2 elements
ft::stack<T> first; // empty stack
ft::stack<T> second (mydeque); // stack initialized to copy of deque
// ft::stack< T,std::vector<T> > third; // empty stack using vector
// ft::stack< T,std::vector<T> > fourth (myvector);
//
// std::cout << "size of first: " << first.size() << '\n';
// std::cout << "size of second: " << second.size() << '\n';
// std::cout << "size of third: " << third.size() << '\n';
// std::cout << "size of fourth: " << fourth.size() << '\n';
//
// PRINT(first)
// PRINT(second)
// PRINT(third)
// PRINT(fourth)
//
// DELETE
}
template <class T>
void call_tests() {
tests_stack_constructor<T>();
}
int main() {
call_tests<int>();
// call_tests<char>();
// call_tests<std::string>();
// call_tests<mystruct*>();
return 0;
}

19
tests/test.sh Normal file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
# cd $(dirname $0)
TEST_DIR=$(dirname $0)
OUTPUT_STL="output_stl.log"
OUTPUT_FT="output_ft.log"
#make -j > /dev/null
make -j
echo -e "\nstl :"
time ./containers_stl > tests/$OUTPUT_STL
echo -e "\nft :"
time ./containers_ft > tests/$OUTPUT_FT
diff --context=0 --color=always tests/$OUTPUT_STL tests/$OUTPUT_FT
#/bin/rm $TEST_DIR/$OUTPUT_STL $TEST_DIR/$OUTPUT_FT

View File

@@ -0,0 +1,50 @@
#include "tests_utils.hpp"
// functions
// **********************************************
void add_to_list(std::string title, std::string type, A_test* test) {
std::vector<A_test*> test_sub_list;
std::vector< std::vector<A_test*> >::iterator it;
// title != NULL for the first element
if (test == NULL)
{
test_list.push_back(test_sub_list);
return;
}
test->title = title;
test->type = type;
it = test_list.end() - 1;
(*it).push_back(test);
}
void delete_structs() {
std::vector<mystruct*>::iterator it;
std::vector<mystruct*>::iterator it_end = mem_list.end();
for (it = mem_list.begin(); it != it_end; ++it)
delete *it;
mem_list.clear();
}
// mystruct
// ***********************************************
mystruct::mystruct(int data)
{_val = new int[2]; _val[0] = data; _val[1] = data;}
mystruct::~mystruct()
{delete[] _val;}
int * mystruct::get_data() const
{return _val;}
std::ostream & operator<<(std::ostream & o, mystruct const * rhs) {
if (rhs != NULL)
o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1];
else
o << "NULL";
return (o);
}

739
tests/tests_map.cpp Normal file
View File

@@ -0,0 +1,739 @@
#include "tests_map.hpp"
/**/ // UTILS for some tests
/**/ bool fncomp (char lhs, char rhs) {return lhs<rhs;}
/**/
/**/ struct classcomp {
/**/ bool operator() (const char& lhs, const char& rhs) const
/**/ {return lhs<rhs;}
/**/ };
/**/ ///////////////////////
TEST_M(tests_map_simple)
{
// title
TITLE(simple test)
typename ft::map<T, U> mp;
typename std::map<T, U>::iterator it;
mp[VALT('a')] = VALU(10);
PRINT(mp)
DELETE
}
TEST_M(tests_map_constructor)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> first;
first[VALT('a')]=VALU(10);
first[VALT('b')]=VALU(30);
first[VALT('c')]=VALU(50);
first[VALT('d')]=VALU(70);
ft::map<T,U> second (first.begin(),first.end());
ft::map<T,U> third (second);
ft::map<T,U,classcomp> fourth; // class as Compare
bool(*fn_pt)(char,char) = fncomp;
ft::map<T,U,bool(*)(char,char)> fifth (fn_pt); // function pointer as Compare
PRINT(first)
PRINT(second)
PRINT(third)
DELETE
}
TEST_M(tests_map_operator_assignation)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> first;
ft::map<T,U> second;
first[VALT('x')]=VALU(8);
first[VALT('y')]=VALU(16);
first[VALT('z')]=VALU(32);
PRINT(first)
PRINT(second)
second=first; // second now contains 3 ints
first=ft::map<T,U>(); // and first is now empty
std::cout << "Size of first: " << first.size() << '\n';
std::cout << "Size of second: " << second.size() << '\n';
PRINT(first)
PRINT(second)
DELETE
}
TEST_M(tests_map_begin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_end)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('b')] = VALU(100);
mymap[VALT('a')] = VALU(200);
mymap[VALT('c')] = VALU(300);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_rbegin)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_rend)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')] = VALU(100);
mymap[VALT('y')] = VALU(200);
mymap[VALT('z')] = VALU(300);
// show content:
typename ft::map<T,U>::reverse_iterator rit;
for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit)
std::cout << rit->first << " => " << rit->second << '\n';
DELETE
}
TEST_M(tests_map_empty)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
while (!mymap.empty())
{
std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n';
mymap.erase(mymap.begin());
}
DELETE
}
TEST_M(tests_map_size)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(101);
mymap[VALT('b')]=VALU(202);
mymap[VALT('c')]=VALU(302);
std::cout << "mymap.size() is " << mymap.size() << '\n';
PRINT(mymap)
DELETE
}
TEST_M(tests_map_max_size)
{
// title
TITLE(cplusplus.com reference)
int i;
std::map<T,U> mymap;
if (mymap.max_size()>1000)
{
for (i=0; i<1000; i++) mymap[i]=VALU(0);
std::cout << "The map contains 1000 elements.\n";
}
else std::cout << "The map could not hold 1000 elements.\n";
DELETE
}
TEST_M(tests_map_operator_access)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU("An element");
mymap[VALT('b')]=VALU("another element");
mymap[VALT('c')]=mymap[VAL('b')];
std::cout << "mymap['a'] is " << mymap[VALT('a')] << '\n';
std::cout << "mymap['b'] is " << mymap[VALT('b')] << '\n';
std::cout << "mymap['c'] is " << mymap[VALT('c')] << '\n';
std::cout << "mymap['d'] is " << mymap[VALT('d')] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
DELETE
}
TEST_M(tests_map_insert)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
// first insert function version (single parameter):
mymap.insert ( ft::pair<T,U>(VALT('a'),VALU(100)) );
mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(200)) );
ft::pair<typename ft::map<T,U>::iterator, bool> ret;
ret = mymap.insert ( ft::pair<T,U>(VALT('z'),VALU(500)) );
if (ret.second==false) {
std::cout << "element 'z' already existed";
std::cout << " with a value of " << ret.first->second << '\n';
}
// second insert function version (with hint position):
typename ft::map<T,U>::iterator it = mymap.begin();
mymap.insert (it, ft::pair<T,U>(VALT('b'),VALU(300))); // max efficiency inserting
mymap.insert (it, ft::pair<T,U>(VALT('c'),VALU(400))); // no max efficiency inserting
// third insert function version (range insertion):
ft::map<T,U> anothermap;
anothermap.insert(mymap.begin(),mymap.find('c'));
PRINT(mymap)
PRINT(anothermap)
DELETE
}
TEST_M(tests_map_erase)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
// insert some values:
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
mymap[VALT('d')]=VALU(40);
mymap[VALT('e')]=VALU(50);
mymap[VALT('f')]=VALU(60);
it=mymap.find(VALT('b'));
mymap.erase (it); // erasing by iterator
mymap.erase (VALT('c')); // erasing by key
it=mymap.find (VALT('e'));
mymap.erase ( it, mymap.end() ); // erasing by range
PRINT(mymap)
// title
TITLE(more complexe tree)
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
mymap[VALT('e')]=VALU(50);
mymap[VALT('g')]=VALU(24);
mymap[VALT('h')]=VALU(64);
mymap[VALT('i')]=VALU(52);
mymap[VALT('j')]=VALU(14);
mymap[VALT('k')]=VALU(12);
mymap[VALT('l')]=VALU(46);
mymap[VALT('m')]=VALU(37);
mymap[VALT('n')]=VALU(31);
mymap[VALT('o')]=VALU(58);
mymap[VALT('p')]=VALU(18);
mymap[VALT('q')]=VALU(25);
mymap[VALT('r')]=VALU(36);
mymap[VALT('s')]=VALU(43);
mymap[VALT('t')]=VALU(49);
mymap[VALT('u')]=VALU(21);
mymap[VALT('v')]=VALU(55);
mymap[VALT('w')]=VALU(33);
mymap[VALT('x')]=VALU(44);
mymap[VALT('y')]=VALU(11);
mymap[VALT('z')]=VALU(22);
mymap.erase (VALT('a'));
mymap[VALT('a')]=VALU(10);
mymap.erase (VALT('b'));
mymap[VALT('b')]=VALU(20);
mymap.erase (VALT('c'));
mymap[VALT('c')]=VALU(30);
mymap.erase (VALT('d'));
mymap[VALT('d')]=VALU(40);
mymap.erase (VALT('e'));
mymap[VALT('e')]=VALU(50);
mymap.erase (VALT('f'));
mymap[VALT('f')]=VALU(60);
mymap.erase (VALT('g'));
mymap[VALT('g')]=VALU(24);
mymap.erase (VALT('h'));
mymap[VALT('h')]=VALU(64);
mymap.erase (VALT('i'));
mymap[VALT('i')]=VALU(52);
mymap.erase (VALT('j'));
mymap[VALT('j')]=VALU(14);
mymap.erase (VALT('k'));
mymap[VALT('k')]=VALU(12);
mymap.erase (VALT('l'));
mymap[VALT('l')]=VALU(46);
mymap.erase (VALT('m'));
mymap[VALT('m')]=VALU(37);
mymap.erase (VALT('n'));
mymap[VALT('n')]=VALU(31);
mymap.erase (VALT('o'));
mymap[VALT('o')]=VALU(58);
mymap.erase (VALT('p'));
mymap[VALT('p')]=VALU(18);
mymap.erase (VALT('q'));
mymap[VALT('q')]=VALU(25);
mymap.erase (VALT('r'));
mymap[VALT('r')]=VALU(36);
mymap.erase (VALT('s'));
mymap[VALT('s')]=VALU(43);
mymap.erase (VALT('t'));
mymap[VALT('t')]=VALU(49);
mymap.erase (VALT('u'));
mymap[VALT('u')]=VALU(21);
mymap.erase (VALT('v'));
mymap[VALT('v')]=VALU(55);
mymap.erase (VALT('w'));
mymap[VALT('w')]=VALU(33);
mymap.erase (VALT('x'));
mymap[VALT('x')]=VALU(44);
mymap.erase (VALT('y'));
mymap[VALT('y')]=VALU(11);
mymap.erase (VALT('z'));
mymap[VALT('z')]=VALU(22);
PRINT(mymap)
// title
TITLE(erasing entire tree)
mymap.erase (VALT('a'));
mymap.erase (VALT('b'));
mymap.erase (VALT('c'));
mymap.erase (VALT('d'));
mymap.erase (VALT('e'));
mymap.erase (VALT('f'));
mymap.erase (VALT('g'));
mymap.erase (VALT('h'));
mymap.erase (VALT('i'));
mymap.erase (VALT('j'));
mymap.erase (VALT('k'));
mymap.erase (VALT('l'));
mymap.erase (VALT('m'));
mymap.erase (VALT('n'));
mymap.erase (VALT('o'));
mymap.erase (VALT('p'));
mymap.erase (VALT('q'));
mymap.erase (VALT('r'));
mymap.erase (VALT('s'));
mymap.erase (VALT('t'));
mymap.erase (VALT('u'));
mymap.erase (VALT('v'));
mymap.erase (VALT('w'));
mymap.erase (VALT('x'));
mymap.erase (VALT('y'));
mymap.erase (VALT('z'));
PRINT(mymap)
// title
TITLE(big tree)
int i;
for (i = 0; i < 10000; i++)
mymap[VALT(i)]=VALU(i);
while (i)
mymap.erase (VAL(i--));
PRINT(mymap)
DELETE
}
TEST_M(tests_map_swap)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> foo,bar;
foo[VALT('x')]=VALU(100);
foo[VALT('y')]=VALU(200);
bar[VALT('a')]=VALU(11);
bar[VALT('b')]=VALU(22);
bar[VALT('c')]=VALU(33);
foo.swap(bar);
PRINT(foo)
PRINT(bar)
DELETE
}
TEST_M(tests_map_clear)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(100);
mymap[VALT('y')]=VALU(200);
mymap[VALT('z')]=VALU(300);
PRINT(mymap)
mymap.clear();
mymap[VALT('a')]=VALU(1101);
mymap[VALT('b')]=VALU(2202);
PRINT(mymap)
DELETE
}
TEST_M(tests_map_key_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::key_compare mycomp = mymap.key_comp();
mymap[VALT('a')]=VALU(100);
mymap[VALT('b')]=VALU(200);
mymap[VALT('c')]=VALU(300);
std::cout << "mymap contains:\n";
T highest = mymap.rbegin()->first; // key value of last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mycomp((*it++).first, highest) );
std::cout << '\n';
DELETE
}
TEST_M(tests_map_value_comp)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('x')]=VALU(1001);
mymap[VALT('y')]=VALU(2002);
mymap[VALT('z')]=VALU(3003);
std::cout << "mymap contains:\n";
ft::pair<T,U> highest = *mymap.rbegin(); // last element
typename ft::map<T,U>::iterator it = mymap.begin();
do {
std::cout << it->first << " => " << it->second << '\n';
} while ( mymap.value_comp()(*it++, highest) );
DELETE
}
TEST_M(tests_map_find)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator it;
mymap[VALT('a')]=VALU(50);
mymap[VALT('b')]=VALU(100);
mymap[VALT('c')]=VALU(150);
mymap[VALT('d')]=VALU(200);
it = mymap.find(VALT('b'));
if (it != mymap.end())
mymap.erase (it);
// print content:
std::cout << "elements in mymap:" << '\n';
std::cout << "a => " << mymap.find(VALT('a'))->second << '\n';
std::cout << "c => " << mymap.find(VALT('c'))->second << '\n';
std::cout << "d => " << mymap.find(VALT('d'))->second << '\n';
DELETE
}
TEST_M(tests_map_count)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
T c;
mymap [VALT('a')]=VALU(101);
mymap [VALT('c')]=VALU(202);
mymap [VALT('f')]=VALU(303);
// to do this test with T as a 'string' or 'mystruct*' we should add overload
for (c=VALT('a'); c<VALT('h'); c++)
{
std::cout << c;
if (mymap.count(c)>0)
std::cout << " is an element of mymap.\n";
else
std::cout << " is not an element of mymap.\n";
}
DELETE
}
TEST_M(tests_map_lower_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_upper_bound)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
typename ft::map<T,U>::iterator itlow,itup;
mymap[VALT('a')]=VALU(20);
mymap[VALT('b')]=VALU(40);
mymap[VALT('c')]=VALU(60);
mymap[VALT('d')]=VALU(80);
mymap[VALT('e')]=VALU(100);
itlow=mymap.lower_bound (VALT('b')); // itlow points to b
itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
PRINT(mymap)
DELETE
}
TEST_M(tests_map_equal_range)
{
// title
TITLE(cplusplus.com reference)
ft::map<T,U> mymap;
mymap[VALT('a')]=VALU(10);
mymap[VALT('b')]=VALU(20);
mymap[VALT('c')]=VALU(30);
ft::pair<typename ft::map<T,U>::iterator,typename ft::map<T,U>::iterator> ret;
ret = mymap.equal_range(VALT('b'));
std::cout << "lower bound points to: ";
std::cout << ret.first->first << " => " << ret.first->second << '\n';
std::cout << "upper bound points to: ";
std::cout << ret.second->first << " => " << ret.second->second << '\n';
DELETE
}
TEST_M(tests_map_get_allocator)
{
// title
TITLE(cplusplus.com reference)
int psize;
ft::map<T,U> mymap;
ft::pair<const T,U>* p;
// allocate an array of 5 elements using mymap's allocator:
p=mymap.get_allocator().allocate(5);
// assign some values to array
psize = sizeof(typename ft::map<T,U>::value_type)*5;
std::cout << "The allocated array has a size of " << psize << " bytes.\n";
mymap.get_allocator().deallocate(p,5);
DELETE
}
TEST_M(tests_map_relational_operators)
{
AVOID_MYSTRUCT(U)
// title
TITLE(cplusplus.com reference)
ft::map<T,U> alice;
ft::map<T,U> bob;
ft::map<T,U> eve;
(void)alice;
(void)bob;
(void)eve;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
eve[VALT(1)]=VALU('a');
eve[VALT(2)]=VALU('b');
eve[VALT(3)]=VALU('c');
std::cout << std::boolalpha;
// Compare non equal containers
std::cout << "alice == bob returns " << (alice == bob) << '\n';
std::cout << "alice != bob returns " << (alice != bob) << '\n';
std::cout << "alice < bob returns " << (alice < bob) << '\n';
std::cout << "alice <= bob returns " << (alice <= bob) << '\n';
std::cout << "alice > bob returns " << (alice > bob) << '\n';
std::cout << "alice >= bob returns " << (alice >= bob) << '\n';
std::cout << '\n';
// Compare equal containers
std::cout << "alice == eve returns " << (alice == eve) << '\n';
std::cout << "alice != eve returns " << (alice != eve) << '\n';
std::cout << "alice < eve returns " << (alice < eve) << '\n';
std::cout << "alice <= eve returns " << (alice <= eve) << '\n';
std::cout << "alice > eve returns " << (alice > eve) << '\n';
std::cout << "alice >= eve returns " << (alice >= eve) << '\n';
DELETE
}
TEST_M(tests_map_swap_non_member)
{
// title
TITLE(cplusplus.com reference)
ft::map<T, U> alice;
ft::map<T, U> bob;
alice[VALT(1)]=VALU('a');
alice[VALT(2)]=VALU('b');
alice[VALT(3)]=VALU('c');
bob[VALT(7)]=VALU('Z');
bob[VALT(8)]=VALU('Y');
bob[VALT(9)]=VALU('X');
bob[VALT(10)]=VALU('W');
// Print state before swap
PRINT(alice)
PRINT(bob)
std::cout << "-- SWAP\n";
std::swap(alice, bob);
// Print state after swap
PRINT(alice)
PRINT(bob)
DELETE
}

135
tests/tests_stack.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include "tests_stack.hpp"
#ifdef STL
#define DEQ_VEC deque
#else
#define DEQ_VEC vector
#endif
TEST_S(tests_stack_constructor)
{
// title
TITLE(simple test)
ft::DEQ_VEC<T> mycont (2,VAL(200)); // ft::vector/stl::deque with 2 elements
ft::vector<T> myvector (2,VAL(200)); // vector with 2 elements
ft::stack<T> first; // empty stack
ft::stack<T> second (mycont); // stack initialized to copy of vector
ft::stack< T,ft::vector<T> > third; // empty stack using vector
ft::stack< T,ft::vector<T> > fourth (myvector);
std::cout << "size of first: " << first.size() << '\n';
std::cout << "size of second: " << second.size() << '\n';
std::cout << "size of third: " << third.size() << '\n';
std::cout << "size of fourth: " << fourth.size() << '\n';
PRINT(first)
PRINT(second)
PRINT(third)
PRINT(fourth)
DELETE
}
TEST_S(tests_stack_empty)
{
// title
TITLE(simple test)
ft::stack<T> mystack;
int sum (0);
for (int i=1;i<=10;i++) mystack.push(VAL(i));
while (!mystack.empty())
{
sum += TOI(mystack.top());
mystack.pop();
}
std::cout << "total: " << sum << '\n';
PRINT(mystack)
DELETE
}
TEST_S(tests_stack_size)
{
// title
TITLE(simple test)
ft::stack<T> myints;
std::cout << "0. size: " << myints.size() << '\n';
for (int i=0; i<5; i++) myints.push(VAL(i));
std::cout << "1. size: " << myints.size() << '\n';
myints.pop();
std::cout << "2. size: " << myints.size() << '\n';
PRINT(myints)
DELETE
}
TEST_S(tests_stack_top)
{
// title
TITLE(simple test)
ft::stack<T> mystack;
mystack.push(VAL(10));
std::cout << "mystack.top() is now " << mystack.top() << '\n';
mystack.push(VAL(20));
std::cout << "mystack.top() is now " << mystack.top() << '\n';
mystack.push(VAL(-12));
std::cout << "mystack.top() is now " << mystack.top() << '\n';
mystack.push(VAL(26));
std::cout << "mystack.top() is now " << mystack.top() << '\n';
// mystack.top() -= VAL(5);
PRINT(mystack)
DELETE
}
TEST_S(tests_stack_push)
{
// title
TITLE(simple test)
ft::stack<T> mystack;
for (int i=0; i<5; ++i) mystack.push(VAL(i));
PRINT(mystack)
DELETE
}
TEST_S(tests_stack_pop)
{
// title
TITLE(simple test)
ft::stack<T> mystack;
for (int i=0; i<5; ++i) mystack.push(VAL(i));
std::cout << "Popping out elements...";
while (!mystack.empty())
{
std::cout << ' ' << mystack.top();
mystack.pop();
}
std::cout << '\n';
DELETE
}

874
tests/tests_vector.cpp Normal file
View File

@@ -0,0 +1,874 @@
#include "tests_vector.hpp"
TEST_V(tests_vector_constructor)
{
// title
TITLE(cplusplus.com reference)
// constructors used in the same order as described above:
ft::vector<T> first; // empty vector of ints
ft::vector<T> second (4,VAL(100)); // four ints with value 100
ft::vector<T> third (second.begin(),second.end()); // iterating through second
ft::vector<T> fourth (third); // a copy of third
// the iterator constructor can also be used to construct from arrays:
T myints[] = {VAL(16),VAL(2),VAL(77),VAL(29)};
ft::vector<T> fifth (myints, myints + sizeof(myints) / sizeof(T) );
PRINT(fifth);
DELETE
}
TEST_V(tests_vector_operator_assignation)
{
// title
TITLE(cplusplus.com reference)
ft::vector<T> foo (3,VAL(0));
ft::vector<T> bar (5,VAL(0));
bar = foo;
foo = ft::vector<T>();
std::cout << "Size of foo: " << int(foo.size()) << '\n';
std::cout << "Size of bar: " << int(bar.size()) << '\n';
DELETE
}
TEST_V(tests_vector_begin)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
for (int i=1; i<=5; i++) myvector.push_back(VAL(i));
PRINT(myvector);
DELETE
}
TEST_V(tests_vector_end)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
for (int i=1; i<=5; i++) myvector.push_back(VAL(i));
PRINT(myvector);
DELETE
}
TEST_V(tests_vector_rbegin)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector (5);
int i=0;
typename ft::vector<T>::reverse_iterator rit = myvector.rbegin();
for (; rit!= myvector.rend(); ++rit)
*rit = VAL(++i);
PRINT(myvector);
DELETE
}
TEST_V(tests_vector_rend)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector (5); // 5 default-constructed Ts
typename ft::vector<T>::reverse_iterator rit = myvector.rbegin();
int i=0;
for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit)
*rit = VAL(++i);
PRINT(myvector);
DELETE
}
TEST_V(tests_vector_size)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myarr;
std::cout << "0. size: " << myarr.size() << '\n';
for (int i=0; i<10; i++) myarr.push_back(VAL(i));
std::cout << "1. size: " << myarr.size() << '\n';
myarr.insert (myarr.end(),10,VAL(100));
std::cout << "2. size: " << myarr.size() << '\n';
myarr.pop_back();
std::cout << "3. size: " << myarr.size() << '\n';
PRINT(myarr);
DELETE
}
TEST_V(tests_vector_max_size)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
// set some content in the vector:
for (int i=0; i<100; i++) myvector.push_back(VAL(i));
std::cout << "size: " << myvector.size() << "\n";
std::cout << "capacity: " << myvector.capacity() << "\n";
std::cout << "max_size: " << myvector.max_size() << "\n";
PRINT(myvector);
DELETE
}
TEST_V(tests_vector_resize)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
// set some initial content:
for (int i = 1; i < 10; i++) myvector.push_back(VAL(i));
myvector.resize(5);
myvector.resize(8,VAL(100));
myvector.resize(12);
PRINT(myvector);
// title
TITLE(test size and capacity 1 :)
ft::vector<T> vector2;
std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n";
std::cout << "assign(10, 1)\n";
vector2.assign(10, VAL(1));
PRINT(vector2);
std::cout << "\n";
std::cout << "resize(15)\n";
vector2.resize(15);
PRINT(vector2);
std::cout << "\n";
std::cout << "resize(10)\n";
vector2.resize(10);
PRINT(vector2);
std::cout << "\n";
std::cout << "resize(19)\n";
vector2.resize(19);
PRINT(vector2);
std::cout << "\n";
std::cout << "resize(20)\n";
vector2.resize(20);
PRINT(vector2);
std::cout << "\n";
std::cout << "resize(21)\n";
vector2.resize(21);
PRINT(vector2);
std::cout << "\n";
// title
TITLE(test size and capacity 2 :)
ft::vector<T> vector3;
std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n";
std::cout << "assign(10, 1)\n";
vector3.assign(10, VAL(1));
PRINT(vector3);
std::cout << "\n";
std::cout << "resize(21)\n";
vector3.resize(21);
PRINT(vector3);
std::cout << "\n";
DELETE
}
TEST_V(tests_vector_capacity)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
// set some content in the vector:
for (int i=0; i<100; i++) myvector.push_back(VAL(i));
std::cout << "size: " << (int) myvector.size() << '\n';
std::cout << "capacity: " << (int) myvector.capacity() << '\n';
std::cout << "max_size: " << (int) myvector.max_size() << '\n';
DELETE
}
TEST_V(tests_vector_empty)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
int sum (0);
for (int i=1;i<=10;i++) myvector.push_back(VAL(i));
while (!myvector.empty())
{
sum+=TOI(myvector.back());
myvector.pop_back();
}
std::cout << "total: " << sum << '\n';
DELETE
}
TEST_V(tests_vector_reserve)
{
// title
TITLE(cplusplus.com reference :)
typename ft::vector<T>::size_type sz;
ft::vector<T> foo;
sz = foo.capacity();
std::cout << "making foo grow:\n";
for (int i=0; i<100; ++i) {
foo.push_back(VAL(i));
if (sz!=foo.capacity()) {
sz = foo.capacity();
std::cout << "capacity changed: " << sz << '\n';
}
}
ft::vector<T> bar;
sz = bar.capacity();
bar.reserve(100); // this is the only difference with foo above
std::cout << "making bar grow:\n";
for (int i=0; i<100; ++i) {
bar.push_back(VAL(i));
if (sz!=bar.capacity()) {
sz = bar.capacity();
std::cout << "capacity changed: " << sz << '\n';
}
}
DELETE
}
TEST_V(tests_vector_operator_access)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector (10); // 10 zero-initialized elements
typename ft::vector<T>::size_type sz = myvector.size();
// assign some values:
for (unsigned i=0; i<sz; i++) myvector[i]=VAL(i);
// reverse vector using operator[]:
for (unsigned i=0; i<sz/2; i++)
{
T temp;
temp = myvector[sz-1-i];
myvector[sz-1-i]=myvector[i];
myvector[i]=temp;
}
PRINT(myvector)
DELETE
}
TEST_V(tests_vector_at)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector (10); // 10 zero-initialized ints
// assign some values:
for (unsigned i=0; i<myvector.size(); i++)
myvector.at(i)=VAL(i);
PRINT(myvector)
DELETE
}
TEST_V(tests_vector_front)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
myvector.push_back(VAL(78));
myvector.push_back(VAL(16));
// now front equals 78, and back 16
//myvector.front() -= myvector.back();
std::cout << "myvector.front() is now " << myvector.front() << '\n';
PRINT(myvector)
DELETE
}
TEST_V(tests_vector_back)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
myvector.push_back(VAL(78));
myvector.push_back(VAL(16));
// now front equals 78, and back 16
// myvector.front() -= myvector.back();
std::cout << "myvector.front() is now " << myvector.front() << '\n';
PRINT(myvector)
DELETE
}
TEST_V(tests_vector_assign)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> first;
ft::vector<T> second;
ft::vector<T> third;
first.assign (7,VAL(100)); // 7 ints with a value of 100
typename ft::vector<T>::iterator it;
it=first.begin()+1;
second.assign (it,first.end()-1); // the 5 central values of first
T myints[] = {VAL(1776),VAL(7),VAL(4)};
third.assign (myints,myints+3); // assigning from array.
std::cout << "Size of first: " << int (first.size()) << '\n';
std::cout << "Size of second: " << int (second.size()) << '\n';
std::cout << "Size of third: " << int (third.size()) << '\n';
// title
TITLE(capacity tests of assignation :)
ft::vector<T> myvector;
std::cout << "capacity before assignation : " << myvector.capacity() << "\n";
std::cout << "\nassign 1\n";
myvector.assign(1, VAL(12));
PRINT(myvector)
std::cout << "\nassign 3\n";
myvector.assign(3, VAL(12));
PRINT(myvector)
std::cout << "\nassign 7268\n";
myvector.assign(7268, VAL(12));
PRINT(myvector)
// title
TITLE(tests of iterators :)
ft::vector<T> int_vector_1;
ft::vector<T> int_vector_2;
ft::vector<T> int_vector_3;
ft::vector<T> it_vector;
std::cout << "\nassign 1\n";
int_vector_1.assign(1, VAL(12));
it_vector.assign(int_vector_1.begin(), int_vector_1.end());
PRINT(it_vector)
std::cout << "\nassign 0\n";
int_vector_2.assign(1, VAL(6));
it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1);
PRINT(it_vector)
std::cout << "\nassign 266 - 13 - 172 = 81\n";
int_vector_3.assign(266, VAL(1));
it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172);
PRINT(it_vector)
DELETE
}
TEST_V(tests_vector_push_back)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1};
int size = sizeof(myint) / sizeof(myint[0]);
for (int i = 0; i < size; i++)
{
myvector.push_back(VAL(myint[i]));
std::cout << "[capacity : "
<< std::setw(2) << myvector.capacity() << "] "
<< myvector[i] << "\n";
}
PRINT(myvector)
// title
TITLE(big push back :)
for (int i = 0; i < 72363; i++)
{
myvector.push_back(VAL(9));
std::cout << "[" << i
<< ":" << myvector.capacity() << "] ";
}
std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n";
DELETE
}
TEST_V(tests_vector_pop_back)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
int sum (0);
myvector.push_back (VAL(100));
myvector.push_back (VAL(200));
myvector.push_back (VAL(300));
while (!myvector.empty())
{
sum+=TOI(myvector.back());
myvector.pop_back();
}
std::cout << "The elements of myvector add up to " << sum << '\n';
// title
TITLE(check state :)
std::cout << "size : " << myvector.size() << '\n';
std::cout << "capacity : " << myvector.capacity() << '\n';
DELETE
}
TEST_V(tests_vector_insert)
{
typename ft::vector<T>::iterator it;
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector (3,VAL(100));
it = myvector.begin();
it = myvector.insert ( it , VAL(200) );
myvector.insert (it,2,VAL(300));
ft::vector<T> anothervector (2,VAL(400));
it = myvector.begin();
myvector.insert (it+2,anothervector.begin(),anothervector.end());
T myarray [] = { VAL(501),VAL(502),VAL(503) };
myvector.insert (myvector.begin(), myarray, myarray+3);
PRINT(myvector)
// title
TITLE(tests positions on insert(pos, value) :)
ft::vector<T> myvector2 (3,VAL(100));
it = myvector2.begin();
std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n";
myvector2.insert ( it , VAL(200) );
PRINT(myvector2)
ft::vector<T> myvector3 (3,VAL(100));
it = myvector3.end();
std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n";
myvector3.insert ( it , VAL(200) );
PRINT(myvector3)
ft::vector<T> myvector4 (3,VAL(100));
it = myvector4.begin() + 2;
std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n";
myvector4.insert ( it , VAL(200) );
PRINT(myvector4)
// title
TITLE(tests insert(pos, size, value) :)
ft::vector<T> myvector5;
for (int i = 1; i <= 5; i++)
myvector5.push_back(VAL(i * 100));
it = myvector5.begin() + 1;
myvector5.insert ( it , VAL(150) );
it = myvector5.end();
myvector5.insert (it,2,VAL(600));
it = myvector5.end() - 2;
myvector5.insert (it,2,VAL(550));
PRINT(myvector5)
// title
TITLE(tests insert(pos, first, last) :)
ft::vector<T> myvector6;
myvector6.assign(5, VAL(42));
it = myvector6.begin() + 2;
myvector6.insert ( it, myvector5.begin() + 3, myvector5.end() - 2 );
PRINT(myvector6)
DELETE
}
TEST_V(tests_vector_erase)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
// set some values (from 1 to 10)
for (int i=1; i<=10; i++) myvector.push_back(VAL(i));
// erase the 6th element
myvector.erase (myvector.begin()+5);
// erase the first 3 elements:
myvector.erase (myvector.begin(),myvector.begin()+3);
PRINT(myvector)
// title
TITLE(test iterator bigger or equal :)
ft::vector<T> vector2;
for (int i=1; i<=100; i++) vector2.push_back(VAL(i));
PRINT(vector2)
std::cout << "\nerase pos(7,36) :\n";
vector2.erase(vector2.begin() + 7, vector2.begin() + 36);
PRINT(vector2)
std::cout << "\nerase pos(46,54) :\n";
vector2.erase(vector2.begin() + 46, vector2.begin() + 54);
PRINT(vector2)
std::cout << "\nerase pos(7,7) :\n";
vector2.erase(vector2.begin() + 7, vector2.begin() + 7);
PRINT(vector2)
DELETE
}
TEST_V(tests_vector_swap)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> foo (3,VAL(100)); // three ints with a value of 100
ft::vector<T> bar (5,VAL(200)); // five ints with a value of 200
typename ft::vector<T>::iterator it1 = foo.begin();
typename ft::vector<T>::iterator it2 = bar.begin();
std::cout << "it1:" << *it1 << " - it2:" << *it2 << "\n";
std::cout << "foo.begin():" << *(foo.begin()) << " - bar.begin():" << *(bar.begin()) << "\n";
foo.swap(bar);
std::cout << "swap\n";
std::cout << "it1:" << *it1 << " - it2:" << *it2 << "\n";
std::cout << "foo.begin():" << *(foo.begin()) << " - bar.begin():" << *(bar.begin()) << "\n";
PRINT(foo)
PRINT(bar)
DELETE
}
TEST_V(tests_vector_clear)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
myvector.push_back (VAL(100));
myvector.push_back (VAL(200));
myvector.push_back (VAL(300));
PRINT(myvector)
myvector.clear();
myvector.push_back (VAL(1101));
myvector.push_back (VAL(2202));
PRINT(myvector)
DELETE
}
TEST_V(tests_vector_get_allocator)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> myvector;
T * p;
unsigned int i;
// allocate an array with space for 5 elements using vector's allocator:
p = myvector.get_allocator().allocate(5);
// construct values in-place on the array:
for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],VAL(i));
std::cout << "The allocated array contains:";
for (i=0; i<5; i++) std::cout << ' ' << p[i];
std::cout << '\n';
// destroy and deallocate:
for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]);
myvector.get_allocator().deallocate(p,5);
DELETE
}
TEST_V(tests_vector_relational_operators)
{
AVOID_MYSTRUCT(T)
// title
TITLE(cplusplus.com reference :)
ft::vector<T> foo (3,VAL(100)); // three ints with a value of 100
ft::vector<T> bar (2,VAL(200)); // two ints with a value of 200
if (foo==bar) std::cout << "foo and bar are equal\n";
if (foo!=bar) std::cout << "foo and bar are not equal\n";
if (foo< bar) std::cout << "foo is less than bar\n";
if (foo> bar) std::cout << "foo is greater than bar\n";
if (foo<=bar) std::cout << "foo is less than or equal to bar\n";
if (foo>=bar) std::cout << "foo is greater than or equal to bar\n";
DELETE
}
TEST_V(tests_vector_swap_non_member)
{
// title
TITLE(cplusplus.com reference :)
ft::vector<T> foo (3,VAL(100)); // three ints with a value of 100
ft::vector<T> bar (5,VAL(200)); // five ints with a value of 200
foo.swap(bar);
PRINT(foo)
PRINT(bar)
DELETE
}
TEST_V(tests_vector_reverse_iterators)
{
// title
TITLE(cplusplus.com reference)
TITLE(::constructor ::operator* ::operator++(val))
ft::vector<T> myvector;
for (int i=0; i<10; i++) myvector.push_back(VAL(i));
typedef typename ft::vector<T>::iterator iter_type;
// ? 0 1 2 3 4 5 6 7 8 9 ?
iter_type from (myvector.begin()); // ^
iter_type until (myvector.end()); // ^
ft::reverse_iterator<iter_type> rev_until (from); // ^
ft::reverse_iterator<iter_type> rev_from (until); // ^
std::cout << "myvector:";
while (rev_from != rev_until)
std::cout << ' ' << *rev_from++;
std::cout << '\n';
// title
TITLE(::operator++)
std::cout << "myvector:";
while (rev_from != rev_until) {
std::cout << ' ' << *rev_from;
++rev_from;
}
std::cout << '\n';
// title
TITLE(::base)
ft::reverse_iterator<iter_type> rev_end (myvector.begin());
ft::reverse_iterator<iter_type> rev_begin (myvector.end());
std::cout << "myvector:";
for (iter_type it = rev_end.base(); it != rev_begin.base(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
// title
TITLE(::operator+)
ft::reverse_iterator<iter_type> rev_it_add;
rev_it_add = myvector.rbegin() +3;
std::cout << "The fourth element from the end is: " << *rev_it_add << '\n';
// title
TITLE(::operator+=)
ft::reverse_iterator<iter_type> rev_it_add_equal = myvector.rbegin();
rev_it_add_equal += 2;
std::cout << "The third element from the end is: " << *rev_it_add_equal << '\n';
// title
TITLE(::operator-)
ft::reverse_iterator<iter_type> rev_it_minus;
rev_it_minus = myvector.rend() - 3;
std::cout << "myvector.rend()-3 points to: " << *rev_it_minus << '\n';
// title
TITLE(::operator--)
ft::reverse_iterator<iter_type> rev_it_minus_minus = rev_begin;
while ( rev_it_minus_minus != rev_end )
std::cout << *rev_it_minus_minus++ << ' ';
std::cout << '\n';
while ( rev_it_minus_minus != rev_begin )
std::cout << *(--rev_it_minus_minus) << ' ';
std::cout << '\n';
// title
TITLE(::operator-=)
ft::reverse_iterator<iter_type> rev_it_minus_equal = myvector.rend();
rev_it_minus_equal -= 4;
std::cout << "rev_it_minus_equal now points to: " << *rev_it_minus_equal << '\n';
// title
TITLE(::operator->)
std::map<int,std::string> numbers;
numbers.insert (std::make_pair(1,"one"));
numbers.insert (std::make_pair(2,"two"));
numbers.insert (std::make_pair(3,"three"));
typedef std::map<int,std::string>::iterator map_iter;
ft::reverse_iterator<map_iter> rev_map_end (numbers.begin());
ft::reverse_iterator<map_iter> rev_map_ite (numbers.end());
for ( ; rev_map_ite != rev_map_end ; ++rev_map_ite )
std::cout << rev_map_ite->first << ' ' << rev_map_ite->second << '\n';
// title
TITLE(::operator[])
ft::reverse_iterator<iter_type> rev_it_at = myvector.rbegin();
std::cout << "The fourth element from the end is: " << rev_it_at[3] << '\n';
// title
TITLE(::operator- non-member)
ft::reverse_iterator<typename ft::vector<T>::iterator> rev_it_from,rev_it_until;
rev_it_from = myvector.rbegin();
rev_it_until = myvector.rend();
std::cout << "myvector has " << (rev_it_until-rev_it_from) << " elements.\n";
// title
TITLE(::operator+ non-member)
ft::reverse_iterator<iter_type> rev_it_n_memb;
rev_it_n_memb = 3 + myvector.rbegin();
std::cout << "The fourth element from the end is: " << *rev_it_n_memb << '\n';
DELETE
}