1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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/. */
10 #include "readstrings.h"
14 # define NS_tfopen _wfopen
15 # define OPEN_MODE L"rb"
17 # define NS_tfopen fopen
18 # define OPEN_MODE "r"
21 // stack based FILE wrapper to ensure that fclose is called.
24 explicit AutoFILE(FILE *fp
) : fp_(fp
) {}
25 ~AutoFILE() { if (fp_
) fclose(fp_
); }
26 operator FILE *() { return fp_
; }
33 explicit AutoCharArray(size_t len
) { ptr_
= new char[len
]; }
34 ~AutoCharArray() { delete[] ptr_
; }
35 operator char *() { return ptr_
; }
40 static const char kNL
[] = "\r\n";
41 static const char kEquals
[] = "=";
42 static const char kWhitespace
[] = " \t";
43 static const char kRBracket
[] = "]";
46 NS_strspnp(const char *delims
, const char *str
)
50 for (d
= delims
; *d
!= '\0'; ++d
) {
62 NS_strtok(const char *delims
, char **str
)
67 char *ret
= (char*) NS_strspnp(delims
, *str
);
76 for (const char *d
= delims
; *d
!= '\0'; ++d
) {
91 * Find a key in a keyList containing zero-delimited keys ending with "\0\0".
92 * Returns a zero-based index of the key in the list, or -1 if the key is not found.
95 find_key(const char *keyList
, char* key
)
101 const char *p
= keyList
;
104 if (strcmp(key
, p
) == 0)
111 // The key was not found if we came here
116 * A very basic parser for updater.ini taken mostly from nsINIParser.cpp
117 * that can be used by standalone apps.
119 * @param path Path to the .ini file to read
120 * @param keyList List of zero-delimited keys ending with two zero characters
121 * @param numStrings Number of strings to read into results buffer - must be equal to the number of keys
122 * @param results Two-dimensional array of strings to be filled in the same order as the keys provided
123 * @param section Optional name of the section to read; defaults to "Strings"
126 ReadStrings(const NS_tchar
*path
,
128 unsigned int numStrings
,
129 char results
[][MAX_TEXT_LEN
],
132 AutoFILE
fp(NS_tfopen(path
, OPEN_MODE
));
138 if (fseek(fp
, 0, SEEK_END
) != 0)
141 long len
= ftell(fp
);
145 size_t flen
= size_t(len
);
146 AutoCharArray
fileContents(flen
+ 1);
148 return READ_STRINGS_MEM_ERROR
;
150 /* read the file in one swoop */
151 if (fseek(fp
, 0, SEEK_SET
) != 0)
154 size_t rd
= fread(fileContents
, sizeof(char), flen
, fp
);
158 fileContents
[flen
] = '\0';
160 char *buffer
= fileContents
;
161 bool inStringsSection
= false;
163 unsigned int read
= 0;
165 while (char *token
= NS_strtok(kNL
, &buffer
)) {
166 if (token
[0] == '#' || token
[0] == ';') // it's a comment
169 token
= (char*) NS_strspnp(kWhitespace
, token
);
170 if (!*token
) // empty line
173 if (token
[0] == '[') { // section header!
175 char const * currSection
= token
;
177 char *rb
= NS_strtok(kRBracket
, &token
);
178 if (!rb
|| NS_strtok(kWhitespace
, &token
)) {
179 // there's either an unclosed [Section or a [Section]Moretext!
180 // we could frankly decide that this INI file is malformed right
181 // here and stop, but we won't... keep going, looking for
182 // a well-formed [section] to continue working with
183 inStringsSection
= false;
187 inStringsSection
= strcmp(currSection
, section
) == 0;
189 inStringsSection
= strcmp(currSection
, "Strings") == 0;
195 if (!inStringsSection
) {
196 // If we haven't found a section header (or we found a malformed
197 // section header), or this isn't the [Strings] section don't bother
198 // parsing this line.
203 char *e
= NS_strtok(kEquals
, &token
);
207 int keyIndex
= find_key(keyList
, key
);
208 if (keyIndex
>= 0 && (unsigned int)keyIndex
< numStrings
)
210 strncpy(results
[keyIndex
], token
, MAX_TEXT_LEN
- 1);
211 results
[keyIndex
][MAX_TEXT_LEN
- 1] = '\0';
216 return (read
== numStrings
) ? OK
: PARSE_ERROR
;
219 // A wrapper function to read strings for the updater.
220 // Added for compatibility with the original code.
222 ReadStrings(const NS_tchar
*path
, StringTable
*results
)
224 const unsigned int kNumStrings
= 2;
225 const char *kUpdaterKeys
= "Title\0Info\0";
226 char updater_strings
[kNumStrings
][MAX_TEXT_LEN
];
228 int result
= ReadStrings(path
, kUpdaterKeys
, kNumStrings
, updater_strings
);
230 strncpy(results
->title
, updater_strings
[0], MAX_TEXT_LEN
- 1);
231 results
->title
[MAX_TEXT_LEN
- 1] = '\0';
232 strncpy(results
->info
, updater_strings
[1], MAX_TEXT_LEN
- 1);
233 results
->info
[MAX_TEXT_LEN
- 1] = '\0';