1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 //
15 // IniFile class defines contents of the configuration file.
16 // It serves as a INI parser and plain enumerator of all the sections and items
17 // found in file, or, oppositely, as INI file constructor.
18 // But is not much suitable for regular key/value lookup. It is suggested to
19 // create a proper map to store items, from IniFile contents.
20 //
21 //=============================================================================
22 #ifndef __AGS_CN_UTIL__INIFILE_H
23 #define __AGS_CN_UTIL__INIFILE_H
24 
25 #include <list>
26 #include "util/string.h"
27 
28 namespace AGS
29 {
30 namespace Common
31 {
32 
33 class IniFile
34 {
35 public:
36     // Position of a string in the line of text:
37     // is defined by a pair of first and next-after-last character indices
38     typedef std::pair<int, int> StrPos;
39     // Location of section in the array of text lines:
40     // is defined by a pair of first and next-after-last line indices
41     typedef std::pair<int, int> SectionPos;
42 
43     // Item definition
44     // Valid key indicates a key-value line; no key means unparsed
45     // line of text, e.g. comment or incorrectly formatted item.
46     class ItemDef
47     {
48     public:
49         ItemDef(const String &key, const String &value);
50         ItemDef(const String &line, const StrPos &key, const StrPos &value, int sep_at);
GetLine()51         String GetLine()  const { return Line; }
GetKey()52         String GetKey()   const { return SubString(Line, Key); }
GetValue()53         String GetValue() const { return SubString(Line, Value); }
IsKeyValue()54         bool   IsKeyValue() const { return Key.second - Key.first > 0; }
55         void SetKey(const String &key);
56         void SetValue(const String &value);
57 
58     private:
59         String  Line;  // actual text
60         StrPos  Key;   // position of item key
61         int     SepAt; // position of the separator (assignment) symbol
62         StrPos  Value; // position of item value
63     };
64     // Linked list of items
65     typedef std::list<ItemDef> LItems;
66     typedef LItems::iterator          ItemIterator;
67     typedef LItems::const_iterator    ConstItemIterator;
68 
69     // Section definition
70     class SectionDef
71     {
72     public:
73         SectionDef(const String &name);
74         SectionDef(const String &line, const StrPos &name);
GetLine()75         String GetLine() const { return Header; }
GetName()76         String GetName() const { return SubString(Header, Name); }
GetItemCount()77         size_t GetItemCount() const { return Items.size(); }
IsGlobal()78         bool   IsGlobal() const { return Name.second - Name.first <= 0; }
Begin()79         ItemIterator Begin() { return Items.begin(); }
End()80         ItemIterator End()   { return Items.end(); }
CBegin()81         ConstItemIterator CBegin() const { return Items.begin(); }
CEnd()82         ConstItemIterator CEnd()   const { return Items.end(); }
83         void SetName(const String &sec_name);
84         void Clear();
85         ItemIterator InsertItem(ItemIterator item, const ItemDef &itemdef);
86         void EraseItem(ItemIterator item);
87 
88     private:
89         String      Header;// section's heading line
90         StrPos      Name;  // location of section name in the header line
91         LItems      Items; // linked list of items belonging to the section
92     };
93     // Linked list of sections
94     typedef std::list<SectionDef>     LSections;
95     typedef LSections::iterator       SectionIterator;
96     typedef LSections::const_iterator ConstSectionIterator;
97 
98 private:
SubString(const String & line,const StrPos & pos)99     inline static String SubString(const String &line, const StrPos &pos)
100     {
101         return line.Mid(pos.first, pos.second - pos.first);
102     }
103 
104 public:
105     IniFile();
106 
Begin()107     SectionIterator Begin() { return _sections.begin(); }
End()108     SectionIterator End()   { return _sections.end(); }
CBegin()109     ConstSectionIterator CBegin() const { return _sections.begin(); }
CEnd()110     ConstSectionIterator CEnd()   const { return _sections.end(); }
111 
112     void Read(Stream *in);
113     void Write(Stream *out) const;
114 
115     // Return number of sections
GetSectionCount()116     size_t GetSectionCount() const { return _sections.size(); }
117     // Insert new item *before* existing item
118     ItemIterator InsertItem(SectionIterator sec, ItemIterator item, const String &key, const String &value);
119     // Insert new section *before* existing section
120     SectionIterator InsertSection(SectionIterator sec, const String &name);
121     // Remove a single item
122     void RemoveItem(SectionIterator sec, ItemIterator item);
123     // Completely remove whole section; this removes all lines between section
124     // header and the last item found in that section (inclusive).
125     void RemoveSection(SectionIterator sec);
126 
127 private:
128     void MakeItemDef(const String &key, const String &value, ItemDef &itemdef);
129 
130     LSections _sections;
131 };
132 
133 } // namespace Common
134 } // namespace AGS
135 
136 #endif // __AGS_CN_UTIL__INIFILE_H
137