-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSequenceParsing.h
287 lines (237 loc) · 11.7 KB
/
SequenceParsing.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
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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/* ***** BEGIN LICENSE BLOCK *****
* This file is part of Natron <http://www.natron.fr/>,
* Copyright (C) 2013-2018 INRIA and Alexandre Gauthier-Foichat
*
* Natron 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.
*
* Natron 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. If not, see <http://www.gnu.org/licenses/gpl-2.0.html>
* ***** END LICENSE BLOCK ***** */
#ifndef __IO__SequenceParser__
#define __IO__SequenceParser__
#include <map>
#include <vector>
#include <list>
#include <string>
#include <memory>
namespace SequenceParsing {
#if __cplusplus >= 201103L
template <typename T>
using auto_ptr = std::unique_ptr<T>;
#else
using std::auto_ptr;
#endif
typedef std::vector<std::string> StringList;
/**
* @brief A class representing the content of a filename.
* Initialize it passing it a real filename and it will initialize the data structures
* depending on the filename content. This class is used by the file dialog to find sequences.
**/
struct FileNameContentPrivate;
class FileNameContent
{
public:
explicit FileNameContent(const std::string& absoluteFilename);
FileNameContent(const FileNameContent& other);
~FileNameContent();
void operator=(const FileNameContent& other);
/**
* @brief Returns the file path, e.g: /Users/Lala/Pictures/ with the trailing separator.
**/
const std::string& getPath() const;
/**
* @brief Returns the filename without its path.
**/
const std::string& fileName() const;
/**
* @brief Returns the absolute filename as it was given in the constructor arguments.
**/
const std::string& absoluteFileName() const;
/**
* @brief Returns the file extension
**/
const std::string& getExtension() const;
/**
* @brief Returns the file pattern found in the filename with hash characters style for frame number (i.e: ###)
* A few things about this pattern:
* - The file path is not prepended to the file name.
* - Each hash tag corresponding to a potential frame number will be indexed. For example,
* The following filename:
* my80sequence001.jpg would be transformed in my##1sequence###2.jpg.
* This is because there may be several numbers existing in the filename, and we have
* no clue given just this filename what actually corresponds to the frame number.
* Nb: this pattern is not an absolute path.
**/
const std::string& getFilePattern(int numHashes) const;
/**
* @brief Returns how many '0' are prepended to the frame number of the file
**/
int getLeadingZeroes() const;
/**
* @brief Expands the string returned by getFilePattern to a valid pattern.
* In order to make it a valid pattern we remove all hash tags indexes and expand
* the tags that do not correspond to index.
* The pattern will have its file path prepended so it is absolute.
**/
void generatePatternWithFrameNumberAtIndex(int index, int numHashes, std::string* pattern) const;
/**
* @brief If the filename is composed of several numbers (e.g: file08_001.png),
* this functions returns the number at index as a string that will be stored in numberString.
* If Index is greater than the number of numbers in the filename or if this filename doesn't
* contain any number, this function returns false.
**/
bool getNumberByIndex(int index, std::string* numberString) const;
/**
* @brief Returns the number of potential frame numbers the filename is composed of.
* e.g: file08_001.png would return 2.
**/
int getPotentialFrameNumbersCount() const;
/**
* @brief Given the pattern of this file, it tries to match the other file name to this
* pattern.
* @param numberIndexToVary [out] In case the pattern contains several numbers (@see getNumberByIndex)
* this value will be fed the appropriate number index that should be used for frame number.
* For example, if this filename is myfile001_000.jpg and the other file is myfile001_001.jpg
* numberIndexesToVary would have a single element (1) as the frame number string indentied in that case is the last number.
* Another example: my00file000_000.jpg and my00file001_001.jpg would produce 1 and 2 in numberIndexesToVary.
* @returns True if it identified 'other' as belonging to the same sequence, false otherwise.
* Note that this function will return false if this and other are exactly the same.
**/
bool matchesPattern(const FileNameContent& other, int* numberIndexToVary) const;
private:
auto_ptr<FileNameContentPrivate> _imp; // PImpl
};
/**
* @brief Removes from str any path it may have and returns the path.
* The file doesn't have to necessarily exist on the disk.
* For example: /Users/Lala/Pictures/mySequence001.jpg would transform 'filename' in
* mySequence001.jpg and would return /Users/Lala/Pictures/
**/
std::string removePath(std::string& filename);
///map: < time, map < view_index, file name > >
///Explanation: for each frame number, there may be multiple views, each mapped to a filename.
///If there'are 2 views, index 0 is considered to be the left view and index 1 is considered to be the right view.
///If there'are multiple views, the index is corresponding to the view
///This type is used when retrieving an existing file sequence out of a pattern.
typedef std::map<int, std::map<int, std::string> > SequenceFromPattern;
/**
* @brief Given a pattern string, returns a string list with all the existing file names
* matching the mattern.
* The rules of the pattern are:
*
* 1) Hashes character ('#') are counted as one digit. One digit account for extra
* 0 padding that may exist leading the actual number. Therefore
* /Users/Lala/Pictures/mySequence###.jpg will accept the following filenames:
* /Users/Lala/Pictures/mySequence001.jpg
* /Users/Lala/Pictures/mySequence100.jpg
* /Users/Lala/Pictures/mySequence1000.jpg
* But not /Users/Lala/Pictures/mySequence01.jpg because it has less digits than the hashes characters specified.
* Neither /Users/Lala/Pictures/mySequence01000.jpg because it has extra padding and more digits than hashes characters specified.
*
* 2) The same as hashes characters can be achieved by specifying the option %0<paddingCharactersCount>d
* Ex: /Users/Lala/Pictures/mySequence###.jpg can be achieved the same way with /Users/Lala/Pictures/mySequence%03d.jpg
* You can also use %d which will just match any number.
*
* 3) %v will be replaced automatically by 'l' or 'r' to search for a matching filename.
* For example /Users/Lala/Pictures/mySequence###_%v.jpg would accept:
* /Users/Lala/Pictures/mySequence001_l.jpg and /Users/Lala/Pictures/mySequence001_r.jpg
*
* %V would achieve exactly the same but would be replaced by 'left' or 'right' instead.
* For multi-view it would expend to 'view2','view3', etc...
*
* @returns True if it could extract a valid sequence from the pattern (even with 1 filename in it). False if the pattern
* is not valid.
*
* WARNING: This function may be VERY slow on Windows when operating on a folder over the network because the underlying library (tinydir)
* doesn't make the appropriate function calls. Instead use filesListFromPattern_fast if possible.
**/
bool filesListFromPattern_slow(const std::string& pattern, SequenceParsing::SequenceFromPattern* sequence);
/**
* @brief Same as filesListFromPattern_slow except that it takes the pattern (without path) and a list of filenames in the same directory.
* This avoids the tinydir bottleneck when reading from files over the network.
**/
bool filesListFromPattern_fast(const std::string& pattern, const StringList& files, SequenceParsing::SequenceFromPattern* sequence);
/**
* @brief Transforms a sequence parsed from a pattern to a absolute file names list. If
* onlyViewIndex is greater or equal to 0 it will append to the string list only file names
* whose view index matches 'onlyViewIndex'. Otherwise, it is equal to -1, all files
* will be appended to the return value, regardless of the view index.
**/
StringList sequenceFromPatternToFilesList(const SequenceParsing::SequenceFromPattern& sequence,
int onlyViewIndex = -1);
/**
* @brief Generates a filename out of a pattern
* @see filesListFromPattern
**/
std::string generateFileNameFromPattern(const std::string& pattern,
const std::vector<std::string>& viewNames,
int frameNumber,
int viewNumber);
/**
* @struct Used to gather file together that seem to belong to the same sequence.
* This is used for example in the sequence dialog. It aims to produce a pattern
* out of a series of file.
**/
struct SequenceFromFilesPrivate;
class SequenceFromFiles
{
public:
explicit SequenceFromFiles(bool enableSizeEstimation = false);
/**
* @brief Initializes a sequence with a first file.
* @param enableSizeEstimation If true, it will try to evaluate the cumulated sizes
* of all files in the sequence.
**/
SequenceFromFiles(const FileNameContent& firstFile, bool enableSizeEstimation);
SequenceFromFiles(const SequenceFromFiles& other);
~SequenceFromFiles();
void operator=(const SequenceFromFiles& other) const;
///Tries to insert a file in the sequence and returns true if it succeeded,
///indicating that the file matches the sequence or it is already contained in this sequence.
///@param checkPath If true then this function will check if the path of the file is the same as
///the sequence
bool tryInsertFile(const FileNameContent& file, bool checkPath = true);
///Returns true if this sequence contains the given file.
bool contains(const std::string& absoluteFileName) const;
///is the sequence empty ?
bool empty() const;
///get the number of files
int count() const;
///get the file extension (e.g: "jpg")
std::string fileExtension() const;
///Returns the path with a trailing separator.
std::string getPath() const;
///true if there's only a single file in this sequence
bool isSingleFile() const;
/// INT_MIN if there's no index
int getFirstFrame() const;
/// INT_MAX if there's no index
int getLastFrame() const;
///all the frame indexes. Empty if this is not a sequence.
const std::map<int, FileNameContent>& getFrameIndexes() const;
///Returns the total cumulated size of all files in the sequence.
///If enableSizeEstimation is false, it will return 0.
unsigned long long getEstimatedTotalSize() const;
///Generates a pattern from this sequence.
///Normally calling filesListFromPattern on the result of this function
///should find the exact same files as getFilesList() would return.
std::string generateValidSequencePattern() const;
////Generates a string from this sequence so the user can have a global
////understanding of the content of the sequence.
////If the sequence contains only a single file, it will be the exact same name
////the filename without the path.
std::string generateUserFriendlySequencePattern() const;
std::string generateUserFriendlySequencePatternFromValidPattern(const std::string& pattern) const;
private:
auto_ptr<SequenceFromFilesPrivate> _imp; // PImpl
};
} //namespace SequenceParsing
#endif /* defined(__IO__SequenceParser__) */