1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // This file was shamelessly copied from mozilla/xpinstall/wizard/unix/src2
8 
9 #ifndef nsINIParser_h__
10 #define nsINIParser_h__
11 
12 #ifdef MOZILLA_INTERNAL_API
13 #  define nsINIParser nsINIParser_internal
14 #endif
15 
16 #include "nscore.h"
17 #include "nsClassHashtable.h"
18 #include "mozilla/UniquePtr.h"
19 
20 #include <stdio.h>
21 
22 class nsIFile;
23 
24 class nsINIParser {
25  public:
nsINIParser()26   nsINIParser() {}
27   ~nsINIParser() = default;
28 
29   /**
30    * Initialize the INIParser with a nsIFile. If this method fails, no
31    * other methods should be called. This method reads and parses the file,
32    * the class does not hold a file handle open. An instance must only be
33    * initialized once.
34    */
35   nsresult Init(nsIFile* aFile);
36 
37   /**
38    * Callback for GetSections
39    * @return false to stop enumeration, or true to continue.
40    */
41   typedef bool (*INISectionCallback)(const char* aSection, void* aClosure);
42 
43   /**
44    * Enumerate the sections within the INI file.
45    */
46   nsresult GetSections(INISectionCallback aCB, void* aClosure);
47 
48   /**
49    * Callback for GetStrings
50    * @return false to stop enumeration, or true to continue
51    */
52   typedef bool (*INIStringCallback)(const char* aString, const char* aValue,
53                                     void* aClosure);
54 
55   /**
56    * Enumerate the strings within a section. If the section does
57    * not exist, this function will silently return.
58    */
59   nsresult GetStrings(const char* aSection, INIStringCallback aCB,
60                       void* aClosure);
61 
62   /**
63    * Get the value of the specified key in the specified section
64    * of the INI file represented by this instance.
65    *
66    * @param aSection      section name
67    * @param aKey          key name
68    * @param aResult       the value found
69    * @throws NS_ERROR_FAILURE if the specified section/key could not be
70    *                          found.
71    */
72   nsresult GetString(const char* aSection, const char* aKey,
73                      nsACString& aResult);
74 
75   /**
76    * Alternate signature of GetString that uses a pre-allocated buffer
77    * instead of a nsACString (for use in the standalone glue before
78    * the glue is initialized).
79    *
80    * @throws NS_ERROR_LOSS_OF_SIGNIFICANT_DATA if the aResult buffer is not
81    *         large enough for the data. aResult will be filled with as
82    *         much data as possible.
83    *
84    * @see GetString [1]
85    */
86   nsresult GetString(const char* aSection, const char* aKey, char* aResult,
87                      uint32_t aResultLen);
88 
89   /**
90    * Sets the value of the specified key in the specified section. The section
91    * is created if it does not already exist.
92    *
93    * @oaram aSection      section name
94    * @param aKey          key name
95    * @param aValue        the value to set
96    */
97   nsresult SetString(const char* aSection, const char* aKey,
98                      const char* aValue);
99 
100   /**
101    * Deletes the value of the specified key in the specified section.
102    *
103    * @param aSection      section name
104    * @param aKey          key name
105    *
106    * @throws NS_ERROR_FAILURE if the string was not set.
107    */
108   nsresult DeleteString(const char* aSection, const char* aKey);
109 
110   /**
111    * Deletes the specified section.
112    *
113    * @param aSection      section name
114    *
115    * @throws NS_ERROR_FAILURE if the section did not exist.
116    */
117   nsresult DeleteSection(const char* aSection);
118 
119   /**
120    * Renames the specified section.
121    *
122    * @param aSection      section name
123    * @param aNewName      new section name
124    *
125    * @throws NS_ERROR_FAILURE if the section did not exist.
126    * @throws NS_ERROR_ILLEGAL_VALUE if the new section name already exists.
127    */
128   nsresult RenameSection(const char* aSection, const char* aNewName);
129 
130   /**
131    * Writes the ini data to disk.
132    * @param aFile         the file to write to
133    * @throws NS_ERROR_FAILURE on failure.
134    */
135   nsresult WriteToFile(nsIFile* aFile);
136 
137  private:
138   struct INIValue {
INIValueINIValue139     INIValue(const char* aKey, const char* aValue)
140         : key(strdup(aKey)), value(strdup(aValue)) {}
141 
~INIValueINIValue142     ~INIValue() {
143       delete key;
144       delete value;
145     }
146 
SetValueINIValue147     void SetValue(const char* aValue) {
148       delete value;
149       value = strdup(aValue);
150     }
151 
152     const char* key;
153     const char* value;
154     mozilla::UniquePtr<INIValue> next;
155   };
156 
157   nsClassHashtable<nsCharPtrHashKey, INIValue> mSections;
158 
159   nsresult InitFromString(const nsCString& aStr);
160 
161   bool IsValidSection(const char* aSection);
162   bool IsValidKey(const char* aKey);
163   bool IsValidValue(const char* aValue);
164 };
165 
166 #endif /* nsINIParser_h__ */
167