Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

textfileparser.h 13.3 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
13
14
15
16
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 
// except in compliance with the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
17
// 
18
19
20
21
// Unless required by applicable law or agreed to in writing, software distributed under the 
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
// either express or implied. See the License for the specific language governing permissions 
// and limitations under the License.
22
23
24
// 
// ================================================================================================

25
26
27
#ifndef TEXTFILEPARSER_H__
#define TEXTFILEPARSER_H__

28
29
30
#include "cgt/exception.h"
#include "cgt/filesystem.h"
#include "cgt/vector.h"
31

32
#include "core/coreapi.h"
33
34
35
36
37
38
39
#include "core/tools/stringutils.h"

#include <map>
#include <functional>
#include <string>
#include <vector>

schultezub's avatar
schultezub committed
40
namespace campvis {
41
42
43
44
45
46
47
48
49

    /**
     * Helper class for parsing simple text files containing key-value pairs.
     * The file will be read in text mode and split into single key-value items using the template argument
     * functor of parse(). Finally, each item will be split into key and value using the given delimiters.
     *
     * \todo    Better vector support (e.g. "x,y,z" format)
     *          Test and debug o_O
     */
50
    class CAMPVIS_CORE_API TextFileParser {
51
52
53
54
55
    public:
        /**
         * Item separator for letting each line in the file result in one key-value pair item.
         * \note    The behaviour is not implemented as functor but by template specialization!
         */
56
        struct CAMPVIS_CORE_API ItemSeparatorLines {
57
58
59
60
61
62
63
64
65
66
            // no operator() to implement due to template specialization
        };

        /**
         * Creates a new text file parser with the given settings.
         * \param url               URL of file
         * \param caseSensitiveKeys Flag whether keys are case-sensitive or not
         * \param delimiters        Set of delimiters for separating key-value pair
         * \param whitespace        Set of characters identifying whitespace
         */
67
        TextFileParser(const std::string& url, bool caseSensitiveKeys, const std::string& delimiters, const std::string& whitespace = " \t\n\r");
68
69
70
71
72


        /**
         * Performs the parsing of the text file into key-value pairs.
         * The file will be read in text mode and split into single items using the template argument
schultezub's avatar
schultezub committed
73
         * functor \a T. Then, each item will be split into key-value pairs.
74
75
76
77
78
79
80
81
82
83
84
85
86
         * 
         * \sa TextFileParser::ItemSeparatorLines
         * \tparam  T   Functor for splitting the file into items, must implement std::unary_function<std::string, std::vector<std::string> >
         * \throw   tgt::FileException if file not found/not readable, tgt::CorruptedFileException on parsing errors during key-value pair parsing.
         */
        template<class T>
        void parse() throw (tgt::FileException, tgt::CorruptedFileException);

        /**
         * Checks whether there exists a token with the given key \a key.
         * \param key   The key to search for.
         * \return  True if a key-value pair with the given key is existent, otherwise false.
         */
schultezub's avatar
schultezub committed
87
        bool hasKey(const std::string& key) const;
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

        /**
         * Returns the value to the given key \a key.
         * \param key   The key to search for.
         * \return      The corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent.
         */
        const std::string& getString(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the bool representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      Boolean representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        bool getBool(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the integer representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      Integer representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        int getInt(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the ivec2 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      ivec2 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::ivec2 getIvec2(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the ivec3 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      ivec3 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::ivec3 getIvec3(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the ivec4 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      ivec4 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::ivec4 getIvec4(const std::string& key) const throw (tgt::CorruptedFileException);


schultezub's avatar
schultezub committed
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
        /**
         * Returns the size_t representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      size_t representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        size_t getSizeT(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the svec2 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      svec2 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::svec2 getSvec2(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the svec3 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      svec3 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::svec3 getSvec3(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the svec4 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      svec4 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::svec4 getSvec4(const std::string& key) const throw (tgt::CorruptedFileException);


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
        /**
         * Returns the float representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      Float representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        float getFloat(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the vec2 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      vec2 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::vec2 getVec2(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the vec3 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      vec3 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::vec3 getVec3(const std::string& key) const throw (tgt::CorruptedFileException);

        /**
         * Returns the vec4 representation of the value for the given key \a key.
         * \param key   The key to search for.
         * \return      vec4 representation for the corresponding value to the given key.
         * \throw       tgt::CorruptedFileException if no such key existent or conversion failed.
         */
        tgt::vec4 getVec4(const std::string& key) const throw (tgt::CorruptedFileException);


    protected:
        /**
         * Loads the text file and parses it into items.
         * Item parsing is done using the Functor of the template parameter.
         * 
         * \sa TextFileParser::ItemSeparatorLines
         * \tparam  T   Functor for splitting the file into items, must implement std::unary_function<std::string, std::vector<std::string> >
         * \throw   tgt::FileException if file not found/not readable, tgt::CorruptedFileException on parsing errors during key-value pair parsing.
         */
        template<class T>
        inline std::vector<std::string> readAndParseItems() const throw (tgt::FileException, tgt::CorruptedFileException) ;

        std::string _url;                               ///< URL of file
        bool _caseSensitiveKeys;                        ///< Flag whether keys are case-sensitive or not
        std::string _delimiters;                        ///< Set of delimiters for separating key-value pair
        std::string _whitespace;                        ///< Set of characters identifying whitespace

        std::map<std::string, std::string> _tokens;     ///< map of key-value pairs
    };

// - Template definitions -------------------------------------------------------------------------

    template<typename T>
    void TextFileParser::parse() throw (tgt::FileException, tgt::CorruptedFileException) {
        _tokens.clear();
        std::vector<std::string> items = readAndParseItems<T>();

        for (std::vector<std::string>::const_iterator it = items.begin(); it != items.end(); ++it) {
            std::vector<std::string> tokens = StringUtils::split(*it, _delimiters);
            if (tokens.size() == 2) {
                if (_caseSensitiveKeys)
                    _tokens.insert(std::make_pair(StringUtils::trim(tokens[0], _whitespace), StringUtils::trim(tokens[1], _whitespace)));
                else
                    _tokens.insert(std::make_pair(StringUtils::lowercase(StringUtils::trim(tokens[0], _whitespace)), StringUtils::trim(tokens[1], _whitespace)));
            }
            else {
                throw tgt::CorruptedFileException("Error parsing item '" + *it + "': expected delimiter.", _url);
            }
        }
    }

    template<typename T>
246
    inline std::vector<std::string> TextFileParser::readAndParseItems() const throw (tgt::FileException, tgt::CorruptedFileException) {
247
248
249
250
251
252
253
254
255
256
257
        tgt::File* file = FileSys.open(_url);
        if (!file || !file->isOpen())
            throw tgt::FileException("Could not open file " + _url + " for reading.", _url);

        // somewhat cumbersome but it works:
        // read file line-based, glue them back together and run item spitter.
        std::vector<std::string> lines;
        while (!file->eof()) {
            lines.push_back(file->getLine('\n'));
        }
        std::string data = StringUtils::join(lines, "\n");
schultezub's avatar
schultezub committed
258
259
        file->close();
        delete file;
260
261
262
263
264
265
266
267
268

        T itemSplitter;
        return itemSplitter(data);
    }

// - Template specializations ---------------------------------------------------------------------

    /// Template specialization for avoiding redundant split-join-split of lines.
    template<>
269
    CAMPVIS_CORE_API std::vector<std::string> TextFileParser::readAndParseItems<TextFileParser::ItemSeparatorLines>() const throw (tgt::FileException, tgt::CorruptedFileException);
270
271
272
273

}

#endif // TEXTFILEPARSER_H__