File: crit_action.hpp

package info (click to toggle)
dar 2.6.13-2
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 10,364 kB
  • sloc: cpp: 77,385; sh: 6,192; ansic: 776; makefile: 435; python: 242; csh: 95; perl: 43; sed: 16
file content (216 lines) | stat: -rw-r--r-- 9,043 bytes parent folder | download
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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*********************************************************************/
// dar - disk archive - a backup/restoration program
// Copyright (C) 2002-2020 Denis Corbin
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// to contact the author : http://dar.linux.free.fr/email.html
/*********************************************************************/

    /// \file crit_action.hpp
    /// \brief contains classes that let the user define the policy for overwriting files
    /// \ingroup API

#ifndef CRIT_ACTION_HPP
#define CRIT_ACTION_HPP

#include "../my_config.h"

#include <deque>

#include "criterium.hpp"

namespace libdar
{

	/// \addtogroup API
	/// @{

	/// no need to dig into class cat_nomme here
    class cat_nomme;

	/// the possible actions for overwriting data

    enum over_action_data
    {
	data_preserve,                     ///< do not overwrite (keep the 'in place' entry)
	data_overwrite,                    ///< overwirte the 'in place' entry by the 'to be added' one
	data_preserve_mark_already_saved,  ///< keep the 'in place' but mark it as already saved in the archive of reference
	data_overwrite_mark_already_saved, ///< overwrite the 'in place' but mark the 'to be added' as already saved in the archive of reference
	data_remove,                       ///< remove the original data/EA (file is completely deleted)
	data_undefined,                    ///< action still undefined at this step of the evaluation
	data_ask                           ///< ask for user decision about file's data
    };


	/// the possible action for overwriting EA

	/// define the action to apply to each EA entry (not to the EA set of a particular inode)
    enum over_action_ea
    {
	EA_preserve,                     ///< keep the EA of the 'in place' entry
	EA_overwrite,                    ///< keep the EA of the 'to be added' entry
	EA_clear,                        ///< drop the EA for the elected entry
        EA_preserve_mark_already_saved,  ///< drop any EA but mark them as already saved in the archive of reference (ctime is the one of the 'in place' inode)
        EA_overwrite_mark_already_saved, ///< drop any EA but mark them as already saved in the archive of reference (ctime is the one of the 'to be added' inode)
	EA_merge_preserve,               ///< merge EA but do not overwrite existing EA of 'in place' by one of the same name of 'to be added' inode
	EA_merge_overwrite,              ///< merge EA but if both inode share an EA with the same name, take keep the one of the 'to be added' inode
	EA_undefined,                    ///< action still undefined at this step of the evaluation
	EA_ask                           ///< ask for user decision about EA
    };


	/// the global action for overwriting

	/// this class is a generic interface to handle what action to perform on both EA and Data
	/// based on two files to evaluate.

    class crit_action
    {
    public:
	crit_action() = default;
	crit_action(const crit_action & ref) = default;
	crit_action(crit_action && ref) noexcept = default;
	crit_action & operator = (const crit_action & ref) = default;
	crit_action & operator = (crit_action && ref) noexcept = default;

	    /// the destructor
	virtual ~crit_action() = default;

	    /// the action to take based on the files to compare

	    /// \param[in] first is the 'in place' inode
	    /// \param[in] second is the 'to be added' inode
	    /// \param[out] data is the action to perform with file's data
	    /// \param[out] ea is the action to perform with file's EA
	virtual void get_action(const cat_nomme & first, const cat_nomme & second, over_action_data & data, over_action_ea & ea) const = 0;

	    /// clone construction method

	    /// \return a new object of the same type,
	    /// \note this method must be implemented in all the leaf classes of the
	    /// class crit_action hierarchy
	virtual crit_action *clone() const = 0;
    };


	/// the basic constant action

	/// the resulting action is not dependant on the files to compare
	/// it always returns the action provided through its constructor

    class crit_constant_action : public crit_action
    {
    public:
	    /// the constuctor

	    /// \param[in] data the action to perform on data
	    /// \param[in] ea the action to perform on EA
	crit_constant_action(over_action_data data, over_action_ea ea) { x_data = data; x_ea = ea; };
	crit_constant_action(const crit_constant_action & ref) = default;
	crit_constant_action & operator = (const crit_constant_action & ref) = default;
	~crit_constant_action() = default;


	    /// the inherited pure virtual methods from class action that must be implemented
	virtual void get_action(const cat_nomme & first, const cat_nomme & second, over_action_data & data, over_action_ea & ea) const override { data = x_data; ea = x_ea; };
	virtual crit_action *clone() const override { return new (std::nothrow) crit_constant_action(*this); };

    private:
	over_action_data x_data;
	over_action_ea x_ea;
    };


	/// the testing class binds criterium to actions

	/// a testing class is also an action that let the user build complex
	/// testing. It is thus possible to recursively use testing inside testing

    class testing : public crit_action
    {
    public:
	    /// the constructor

	    /// \param[in] input is the criterium to base the evaluation on
	    /// \param[in] go_true is the action to use for evaluation if the criterium states true
	    /// \param[in] go_false is the action to use for evaluation if the criterium states false
	testing(const criterium & input, const crit_action & go_true, const crit_action & go_false);
	testing(const testing & ref) : crit_action(ref) { copy_from(ref); if(!check()) throw Ememory("testing::testing(const testing &)"); };
	testing(testing && ref) noexcept : crit_action(std::move(ref)) { nullifyptr(); move_from(std::move(ref)); };
	testing & operator = (const testing & ref) { free(); copy_from(ref); if(!check()) throw Ememory("testing::testing(const testing &)"); return *this; };
	testing & operator = (testing && ref) noexcept { crit_action::operator = (std::move(ref)); move_from(std::move(ref)); return *this; };
	~testing() { free(); };


	    /// the inherited pure virtual method from class crit_action that must be implemented
	virtual void get_action(const cat_nomme & first, const cat_nomme & second, over_action_data & data, over_action_ea & ea) const override
	{
	    if(x_input->evaluate(first, second))
		x_go_true->get_action(first, second, data, ea);
	    else
		x_go_false->get_action(first, second, data, ea);
	};

	virtual crit_action *clone() const override { return new (std::nothrow) testing(*this); };

    private:
	criterium *x_input;
	crit_action *x_go_true;
	crit_action *x_go_false;

	void nullifyptr() noexcept { x_input = nullptr; x_go_true = x_go_false = nullptr; };
	void free() noexcept;
	void copy_from(const testing & ref);
	void move_from(testing && ref) noexcept;
	bool check() const; ///< returns false if an field is nullptr
    };


	/// the crit_chain class sequences crit_actions up to full definition of the action

	/// several expressions must be added. The first is evaluated, then the second, up to the last
	/// or up to the step the data_action and ea_action are both fully defined (no data_undefined nor ea_undefined)

    class crit_chain : public crit_action
    {
    public:
	crit_chain() { sequence.clear(); };
	crit_chain(const crit_chain & ref) : crit_action(ref) { copy_from(ref); };
	crit_chain(crit_chain && ref) noexcept : crit_action(std::move(ref)) { sequence = std::move(ref.sequence); };
	crit_chain & operator = (const crit_chain & ref) { destroy(); copy_from(ref); return *this; };
	crit_chain & operator = (crit_chain && ref) noexcept { crit_action::operator = (std::move(ref)); sequence = std::move(ref.sequence); return *this; };
	~crit_chain() { destroy(); };

	void add(const crit_action & act);
	void clear() { destroy(); };
	void gobe(crit_chain & to_be_voided);

	virtual void get_action(const cat_nomme & first, const cat_nomme & second, over_action_data & data, over_action_ea & ea) const override;

	virtual crit_action *clone() const override { return new (std::nothrow) crit_chain(*this); };

    private:
	std::deque<crit_action *> sequence;

	void destroy();
	void copy_from(const crit_chain & ref);
    };

	/// @}

} // end of namespace

#endif