source: miniini/miniini/include/inisection.h @ 5:bcf82ebed545

Last change on this file since 5:bcf82ebed545 was 5:bcf82ebed545, checked in by vadim@…, 3 years ago

Implement exports for DLL builds on WIN32 paltform

File size: 20.4 KB
Line 
1// Copyright (C) 2009-2010 Ferdinand Majerech
2// This file is part of MiniINI
3// For conditions of distribution and use, see copyright notice in LICENSE.txt
4
5#ifndef INISECTION_H_INCLUDED
6#define INISECTION_H_INCLUDED
7
8#include <cstring>
9#include <cstdlib>
10
11#include "typedefs.h"
12#include "allocator.h"
13#include "linetoken.h"
14#ifndef INI_NO_STL
15#include <string>
16#include <vector>
17#endif
18
19
20///Section of ini file.
21/**
22 * Stores tags of an ini file section.
23 */
24class MINIINI_EXPORT INISection
25{
26    friend class INIFile;
27    private:
28
29        ///Name of the section. Taken from section header.
30        miniini_private::c * Name;
31        ///Length of the section, i.e. number of tags in it.
32        miniini_private::ui Length;
33        ///Tags in the section.
34        /**
35         * Each tag is stored as a char buffer containing tag name, a trailing
36         * zero, tag value and another trailing zero.
37         */
38        miniini_private::c * * Tags;
39        ///Allocator for character data in the section.
40        miniini_private::Allocator * Alloc;
41
42
43        ///Data that doesn't need to be reinitialized in every ctor call.
44        ///Temp tags buffer capacity.
45        static miniini_private::ui temptagscap;
46        ///Temp tags buffer - stores tags during loading.
47        static miniini_private::c * * temptags;
48        ///Tag buffer capacity.
49        static miniini_private::ui tagcap;
50        ///Temp tag buffer - stores currently processed tag during loading.
51        static miniini_private::c * tagbuf;
52
53    public:
54
55        ///@return name of this section.
56        const char * GetName() const
57        {
58            return Name;
59        }
60       
61        ///Read a string value from given tag.
62        /**
63         * @note Unlike other ReadXXX methods, ReadString only gives a
64         * pointer to data inside the INISection. If you want to use this
65         * data after INIFile is destroyed, you have to copy it.
66         * @param name Name of the tag to read from. Must be a valid zero terminated string.
67         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
68         * @return true if the value was read succesfully.
69         * @return false if the tag does not exist. (value was not read)
70         */
71        bool ReadString(const char * const name, const char * & out) const;
72         
73        ///Read a string value from given tag. (STL version)
74        /**
75         * Unlike non-STL ReadString, string data does get copied here
76         * (using std::string constructor) so there is no need to copy
77         * it manually.
78         * @param name Name of the tag to read from.
79         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
80         * @return true if the value was read succesfully.
81         * @return false if the tag does not exist. (value was not read)
82         */ 
83        #ifndef INI_NO_STL
84        bool ReadString(const std::string & name, std::string & out) const
85        {
86            const miniini_private::c * tempout;
87            bool ret = ReadString(name.c_str(), tempout);
88            if(ret)
89            {
90                out = tempout;
91            }
92            return ret;
93        }
94        #endif
95
96        ///Read an int value from given tag.
97        /**
98         * @param name Name of the tag to read from. Must be a valid zero terminated string.
99         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
100         * @return true if the value was read succesfully
101         * @return false if the tag does not exist (value was not read)
102         */
103        bool ReadInt(const char * const name, int & out) const;
104
105        ///Read an int value from given tag. (STL version)
106        /**
107         * @param name Name of the tag to read from.
108         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
109         * @return true if the value was read succesfully
110         * @return false if the tag does not exist (value was not read)
111         */
112        #ifndef INI_NO_STL
113        bool ReadInt(const std::string & name, int & out) const
114        {
115            return ReadInt(name.c_str(), out);
116        }
117        #endif
118
119        ///Read a float value from given tag.
120        /**
121         * @param name Name of the tag to read from. Must be a valid zero terminated string.
122         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
123         * @return true if the value was read succesfully
124         * @return false if the tag does not exist (value was not read)
125         */
126        bool ReadFloat(const char * const name, float & out) const;
127       
128        ///Read a float value from given tag. (STL version)
129        /**
130         * @param name Name of the tag to read from.
131         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
132         * @return true if the value was read succesfully
133         * @return false if the tag does not exist (value was not read)
134         */
135        #ifndef INI_NO_STL
136        bool ReadFloat(const std::string & name, float & out) const
137        {
138            return ReadFloat(name.c_str(), out);
139        }
140        #endif
141       
142        ///Read a bool value from given tag.
143        /**
144         * @param name Name of the tag to read from. Must be a valid zero terminated string.
145         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
146         * @return true if the value was read succesfully
147         * @return false if the tag does not exist (value was not read)
148         */
149        bool ReadBool(const char * const name, bool & out) const;
150       
151        ///Read a bool value from given tag. (STL version)
152        /**
153         * @param name Name of the tag to read from.
154         * @param out Reference to variable to read to. If tag not found, out won't be chaged.
155         * @return true if the value was read succesfully
156         * @return false if the tag does not exist (value was not read)
157         */
158        #ifndef INI_NO_STL
159        bool ReadBool(const std::string & name, bool & out) const
160        {
161            return ReadBool(name.c_str(), out);
162        }
163        #endif
164
165        ///Determine size of array of tags with given base name.
166        /**
167         * Counts tags named name1=, name2=, etc. where name is the
168         * given base name for the tags.
169         * @param name Base name of tags in the array. Must be a valid zero terminated string.
170         * @return number of elements in the array.
171         */
172        unsigned ArraySize(const char * const name) const;
173
174        ///Determine size of array of tags with given base name. (STL version)
175        /**
176         * Counts tags named name1=, name2=, etc. where name is the
177         * given base name for the tags.
178         * @param name Base name of tags in the array.
179         * @return number of elements in the array.
180         */
181        #ifndef INI_NO_STL
182        unsigned ArraySize(const std::string name) const
183        {
184            return ArraySize(name.c_str());
185        }
186        #endif
187
188        ///Read an array of strings with given base name.
189        /**
190         * Reads values from tags named name1=, name2=, etc. where name is the
191         * given base name for the tags.
192         * @note Unlike other ReadXXXs methods, ReadStrings only gives a
193         * pointer to data inside the INISection. If you want to use this
194         * data after INIFile is destroyed, you have to copy it.
195         * @param name Base name of the tags to read from. Must be a valid zero terminated string.
196         * @param out Pointer to buffer to read to.
197         * @param cap Capacity of the buffer.
198         * @return number of values read.
199         */
200        unsigned ReadStrings(const char * const name, const char * * out, 
201                             const unsigned cap) const;
202
203        ///Read an array of strings with given base name. (STL version)
204        /**
205         * Reads values from tags named name1=, name2=, etc. where name is the
206         * given base name for the tags. This version of ReadStrings will read
207         * as many elements as there are in the ini file to given vector.
208         * @note Elements read are appended to the given vector.
209         * Unlike non-STL ReadString, string data does get copied here
210         * (using std::string constructor) so there is no need to copy
211         * it manually.
212         * @param name Base name of the tags to read from.
213         * @param out Reference to the vector to read to.
214         * @return number of values read.
215         */
216        #ifndef INI_NO_STL
217        unsigned ReadStrings(const std::string & name, 
218                             std::vector<std::string> & out) const;
219        #endif
220       
221        ///Read an array of ints with given base name.
222        /**
223         * Reads values from tags named name1=, name2=, etc. where name is the
224         * given base name for the tags. Continues to read successive elements
225         * until it either reads as many elements as given capacity, there
226         * are no more elements left in section, or it encounters an element
227         * in wrong order, e.g. name4= after name2= .
228         * @param name Base name of the tags to read from. Must be a valid zero terminated string.
229         * @param out Pointer to buffer to read to.
230         * @param cap Capacity of the buffer.
231         * @return number of values read
232         */
233        unsigned ReadInts(const char * const name, int * out, 
234                          const unsigned cap) const;
235
236        ///Read an array of ints with given base name. (STL version)
237        /**
238         * Reads values from tags named name1=, name2=, etc. where name is the
239         * given base name for the tags. This version of ReadInts will read
240         * as many elements as there are in the ini file to given vector.
241         * @note Elements read are appended to the given vector.
242         * @param name Base name of the tags to read from.
243         * @param out Reference to the vector to read to.
244         * @return number of values read
245         */
246        #ifndef INI_NO_STL
247        unsigned ReadInts(const std::string & name, 
248                          std::vector<int> & out) const;
249        #endif
250       
251        ///Read an array of floats with given base name.
252        /**
253         * Reads values from tags named name1=, name2=, etc. where name is the
254         * given base name for the tags. Continues to read successive elements
255         * until it either reads as many elements as given capacity, there
256         * are no more elements left in section, or it encounters an element
257         * in wrong order, e.g. name4= after name2= .
258         * @param name Base name of the tags to read from. Must be a valid zero terminated string.
259         * @param out Pointer to buffer to read to.
260         * @param cap Capacity of the buffer.
261         * @return number of values read
262         */
263        unsigned ReadFloats(const char * const name, float * out, 
264                            const unsigned cap) const;
265
266        ///Read an array of floats with given base name. (STL version)
267        /**
268         * Reads values from tags named name1=, name2=, etc. where name is the
269         * given base name for the tags. This version of ReadFloats will read
270         * as many elements as there are in the ini file to given vector.
271         * @note Elements read are appended to the given vector.
272         * @param name Base name of the tags to read from.
273         * @param out Reference to the vector to read to.
274         * @return number of values read
275         */
276        #ifndef INI_NO_STL
277        unsigned ReadFloats(const std::string & name, 
278                            std::vector<float> & out) const;
279        #endif
280
281        ///Read an array of bools with given base name.
282        /**
283         * Reads values from tags named name1=, name2=, etc. where name is the
284         * given base name for the tags. Continues to read successive elements
285         * until it either reads as many elements as given capacity, there
286         * are no more elements left in section, or it encounters an element
287         * in wrong order, e.g. name4= after name2= .
288         * @param name Base name of the tags to read from. Must be a valid zero terminated string.
289         * @param out Pointer to buffer to read to.
290         * @param cap Capacity of the buffer.
291         * @return number of values read
292         */
293        unsigned ReadBools(const char * const name, bool * out, 
294                           const unsigned cap) const;
295
296        ///Read an array of bools with given base name. (STL version)
297        /**
298         * Reads values from tags named name1=, name2=, etc. where name is the
299         * given base name for the tags. This version of ReadBools will read
300         * as many elements as there are in the ini file to given vector.
301         * @note Elements read are appended to the given vector.
302         * @param name Base name of the tags to read from.
303         * @param out Reference to the vector to read to.
304         * @return number of values read
305         */
306        #ifndef INI_NO_STL
307        unsigned ReadBools(const std::string & name, 
308                           std::vector<bool> & out) const;
309        #endif
310
311        ///@return number of tags in the section.
312        unsigned GetLength() const
313        {
314            return static_cast<unsigned>(Length);
315        }
316
317
318        struct tagval { 
319          const char*  tag;
320          const char*  val;
321        };
322
323        unsigned GetTags(const char* tags[], unsigned n) const;
324        unsigned GetTags(tagval tags[], unsigned n) const;
325        #ifndef INI_NO_STL
326        void GetTags(std::vector<std::string>& tags) const;
327        void GetTags(std::vector<std::pair<std::string,std::string> >& tags) const;
328        #endif
329         
330           
331    private:
332
333        ///Empty constructor.
334        INISection()
335            :Name(NULL)
336            ,Length(0)
337            ,Tags(NULL)
338            ,Alloc(NULL)
339        {}
340
341        ///Destructor.
342        ~INISection();
343
344        ///Tries to read a tag name from line starting by given character pointer.
345        /**
346         * Updates character pointer and tag size according to data processed.
347         * Tag name is read to static member tagbuf, which is reallocated if needed.
348         * @param currentcharref Reference to pointer to current character in a buffer.
349         * @param tagsize Reference to size of the tag.
350         * @return LT_VAL if this is a valid tag with a value.
351         * Current char ptr is updated to point to the first character after the '='
352         * and tag size is updated to number of characters read to tagbuf.
353         * @return LT_HEADER if this line contains a header. Current char ptr is updated
354         * to point to '[', NOT after it.
355         * @return LT_NAME otherwise. In this case the line contains nothing interesting
356         * and we can ignore it. Current char ptr is updated to point to start of next
357         * line.
358         */
359        static inline miniini_private::LineToken TagName(const miniini_private::c * & currentcharref, 
360                                                         miniini_private::ui & tagsizeref);
361       
362        ///Tries to read a tag value from line starting by given character pointer.
363        /**
364         * Updates character pointer to the start of the next line or end of the buffer,
365         * and tag size according to data processed.
366         * Tag value is read to static member tagbuf, which is reallocated if needed.
367         * @param currentcharref Reference to pointer to current character in a buffer.
368         * @param tagsize Reference to size of the tag.
369         * @return size of tag buffer after value is read.
370         */
371        static inline miniini_private::ui TagValue(const miniini_private::c * & currentcharref, 
372                                                   miniini_private::ui tagsize);
373       
374        ///Determines if the line staring by given character pointer contains a header.
375        /**
376         * @param currentcharref Reference to pointer to current character in a buffer.
377         * @returns true if header is found and not empty.
378         * @returns false otherwise, and updates current char pointer to the next line.
379         */
380        static inline bool Header(const miniini_private::c * & currentcharref);
381
382
383        ///Loads the section from given position in a raw ini file buffer.
384        /*
385         * Loads the section and changes currentcharptr so that the caller can
386         * start with another section.
387         * @param sectionname Name of the section to initialize
388         * @param currentcharptr Start of the section in a raw ini file buffer.
389         * @return true if the section is valid.
390         * @return false if the section is empty.
391         */
392        void Init(const miniini_private::c * const sectionname, 
393                  const miniini_private::c * * const currentcharptr,
394                  miniini_private::Allocator * const alloc);
395
396        ///Allocates/initializes static data
397        static void InitTempData()
398        {
399            assert(!temptags);
400            assert(!tagbuf);
401            temptagscap = 8;
402            temptags = new miniini_private::c * [temptagscap];
403            //MUST be over 6
404            tagcap = 64;
405            tagbuf = new miniini_private::c [tagcap];
406        }
407       
408        ///Destroys static data
409        static void DestroyTempData()
410        {
411            assert(temptags);
412            assert(tagbuf);
413            temptagscap = 0;
414            delete [] temptags;
415            temptags = NULL;
416            tagcap = 0;
417            delete [] tagbuf;
418            tagbuf = NULL;
419        }
420       
421        /// @cond PRIVATE
422
423        ///ReadXXX benchmark. Read every element in the section as given type.
424        #ifndef INI_NO_STL
425        #define BENCH(method, type, stltype)\
426            for(miniini_private::ui tag = 0; tag < Length; ++tag)\
427            {\
428                if(stl)\
429                {\
430                    stltype out;\
431                    method(std::string(Tags[tag]), out);\
432                }\
433                else\
434                {\
435                    type out;\
436                    method(Tags[tag], out);\
437                }\
438            }
439        #else
440        #define BENCH(method, type, stltype)\
441            for(miniini_private::ui tag = 0; tag < Length; ++tag)\
442            {\
443                type out;\
444                method(Tags[tag], out);\
445            }
446        #endif
447
448        void BenchString(bool stl)
449        {
450            BENCH(ReadString, const char *, std::string);
451        }
452
453        void BenchInt(bool stl)
454        {
455            BENCH(ReadInt, int, int);
456        }
457
458        void BenchFloat(bool stl)
459        {
460            BENCH(ReadFloat, float, float);
461        }
462
463        void BenchBool(bool stl)
464        {
465            BENCH(ReadBool, bool, bool);
466        }
467       
468        ///ReadXXXs benchmarks. These require specific inifiles.
469        ///Each section has to contain tags a=, b= , etc.
470        ///that specify lengths of arrays with same base name,
471        ///i.e. a=2 means there's going to be a1= and a2=.
472        #ifndef INI_NO_STL
473        #define BENCHARRAY(method, type, stltype)\
474        for(char tagname [] = "a"; tagname[0] <= 'z'; ++(tagname[0]))\
475        {\
476            if(stl)\
477            {\
478                std::vector<stltype> out;\
479                method(std::string(tagname), out);\
480            }\
481            else\
482            {\
483                int elemcount;\
484                if(!ReadInt(tagname, elemcount))\
485                {\
486                    break;\
487                }\
488                type * out = new type [elemcount];\
489                method(tagname, out, elemcount);\
490                delete [] out;\
491            }\
492        }
493        #else
494        #define BENCHARRAY(method, type, stltype)\
495        for(char tagname [] = "a"; tagname[0] <= 'z'; ++(tagname[0]))\
496        {\
497            int elemcount;\
498            if(!ReadInt(tagname, elemcount))\
499            {\
500                break;\
501            }\
502            type * out = new type [elemcount];\
503            method(tagname, out, elemcount);\
504            delete [] out;\
505        }
506        #endif
507       
508        void BenchStrings(bool stl)
509        {
510            BENCHARRAY(ReadStrings, const char *, std::string);
511        }
512
513        void BenchInts(bool stl)
514        {
515            BENCHARRAY(ReadInts, int, int);
516        }
517
518        void BenchFloats(bool stl)
519        {
520            BENCHARRAY(ReadFloats, float, float);
521        }
522
523        void BenchBools(bool stl)
524        {
525            BENCHARRAY(ReadBools, bool, bool);
526        }
527
528        #undef BENCH
529        #undef BENCHARRAY
530        /// @endcond
531
532        ///No assignment or copyconstruction.
533
534        INISection(const INISection &);
535
536        void operator = (const INISection &);
537};
538
539#endif
Note: See TracBrowser for help on using the repository browser.