-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathContainer.h
185 lines (153 loc) · 4.93 KB
/
Container.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Package Container library (paco)
// Copyright 2017 (c) Thomas Pollok (tom dot pollok at gmail dot com)
// https://github.com/tompollok/paco
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef CONTAINER_H
#define CONTAINER_H
#include <algorithm>
#include "Packet.h"
#include "PacketType.h"
#include "Specification.h"
namespace paco
{
/**
* @brief The Container class is a datastructure that can carry data with varying data types.
* The container is organized in as a list so that you can use typical methods like append and insert to add types and
* remove or clear to remove a single or all objects from the container. All data that is stored is enveloped in a package that
* allows to check the typeid of an object at runtime.
*
* When interacting with a container you always have to specify the object type in the angle brackets.
*
* Here are some examples of how to add objects to the container:
*
* - to add an <int>, container.append<int>(value);
* - to add an <std::string>, container.append<std::string>(value);
* - to add an <QVector*>, container.append<QVector*>(value);
* - etc.
*
* The type in the angle brackets has to match the type of the value, or otherwise the compiler will not proceed.
*/
class Container
{
public:
/**
* @brief Container default constructor.
*/
Container()
{
}
/**
* @brief ~Container destructor.
*/
~Container()
{
this->clear();
}
private:
/**
* template_type_must_be_specified_when_calling_append is a helper to force the programmer
* to use angle brackets <type> in append<type>(value). If not specified the compiler will not be able to compile.
*/
template <typename T>
struct template_type_must_be_specified_when_calling_append
{
using type = T;
};
public:
/**
* @brief size
* @return the number of elements in the container.
*/
int size()
{
return mPackets.size();
}
/**
* @brief append the method for appending objects into the container.
* The object is automatically wrapped into a package.
*/
template <class T>
void append(typename template_type_must_be_specified_when_calling_append<T>::type value)
{
mPackets.push_back(new paco::Packet_T<T>(value));
}
/**
* @brief insert the method for inserting objects into the container into specific locations.
* The object is automatically wrapped into a package.
* @param index the desired index.
*/
template <class T>
void insert(int index, typename template_type_must_be_specified_when_calling_append<T>::type value)
{
mPackets.insert(mPackets.begin() + index, new paco::Packet_T<T>(value));
}
/**
* @brief removeAt removes an object from the container at a certain index position.
* The container class is not responsible for your memory management of the objects.
* @param index the index of the object that has to be removed.
*/
void removeAt(int index)
{
if(index >= 0 && index < mPackets.size())
{
paco::Packet* packet = mPackets.at(index);
mPackets.erase(mPackets.begin()+index);
delete packet;
}
}
/**
* @brief removeAt removes an object from the container at a certain index position.
* @param index the index of the object that has to be removed.
*/
void clear()
{
for(int i = 0; i < mPackets.size(); i++)
{
paco::Packet* packet = mPackets.at(i);
delete packet;
}
mPackets.clear();
}
/**
* @brief replace replaces an object from the container at a certain index position.
* @param index the index of the object that has to be replaced.
*/
template <class T>
void replace(int i, const T value)
{
paco::Packet* old = mPackets.at(i);
std::replace(mPackets.begin(), mPackets.end(), old, dynamic_cast<Packet*>(new paco::Packet_T<T>(value)));
delete old;
}
/**
* @brief at
* @param index the index of the package with the object.
* @return returns the package carrying the object at position i.
*/
paco::Packet* at(int index)
{
return mPackets.at(index);
}
/**
* @brief getSpecification returns a specification of the objects of this container.
* @return the current specification of the container.
*/
Specification getSpecification()
{
Specification specification;
for(int i = 0; i < mPackets.size(); i++)
{
specification.append_friend_class_only(mPackets.at(i)->packetType());
}
return specification;
}
private:
/**
* @brief mPackets the actual container.
*/
std::vector<paco::Packet*> mPackets;
};
}
#endif // CONTAINER_H