Skip to content
Snippets Groups Projects
Commit cd5a17e8 authored by Ben Hearsum's avatar Ben Hearsum
Browse files

Bug 1787121: add support for formatting INI files to nsINIParser r=xpcom-reviewers,kmag

This allows callers to re-encode the data (eg: to UTF-16) and write or otherwise do with the formatted data as they wish.

I ended up adding/exposing additional init methods in part because I thought it made sense to support initialization from a string since we can now write to one, but also to make testing easier.

Differential Revision: https://phabricator.services.mozilla.com/D157377
parent 386adfe3
No related branches found
No related tags found
No related merge requests found
......@@ -294,15 +294,7 @@ nsresult nsINIParser::RenameSection(const char* aSection,
nsresult nsINIParser::WriteToFile(nsIFile* aFile) {
nsCString buffer;
for (const auto& entry : mSections) {
buffer.AppendPrintf("[%s]\n", entry.GetKey());
INIValue* val = entry.GetWeak();
while (val) {
buffer.AppendPrintf("%s=%s\n", val->key, val->value);
val = val->next.get();
}
buffer.AppendLiteral("\n");
}
WriteToString(buffer);
FILE* writeFile;
nsresult rv = aFile->OpenANSIFileDesc("w", &writeFile);
......@@ -318,3 +310,15 @@ nsresult nsINIParser::WriteToFile(nsIFile* aFile) {
fclose(writeFile);
return NS_OK;
}
void nsINIParser::WriteToString(nsACString& aOutput) {
for (const auto& entry : mSections) {
aOutput.AppendPrintf("[%s]\n", entry.GetKey());
INIValue* val = entry.GetWeak();
while (val) {
aOutput.AppendPrintf("%s=%s\n", val->key, val->value);
val = val->next.get();
}
aOutput.AppendLiteral("\n");
}
}
......@@ -34,6 +34,8 @@ class nsINIParser {
*/
nsresult Init(nsIFile* aFile);
nsresult InitFromString(const nsCString& aStr);
/**
* Callback for GetSections
* @return false to stop enumeration, or true to continue.
......@@ -134,6 +136,8 @@ class nsINIParser {
*/
nsresult WriteToFile(nsIFile* aFile);
void WriteToString(nsACString& aOutput);
private:
struct INIValue {
INIValue(const char* aKey, const char* aValue)
......@@ -156,8 +160,6 @@ class nsINIParser {
nsClassHashtable<nsCharPtrHashKey, INIValue> mSections;
nsresult InitFromString(const nsCString& aStr);
bool IsValidSection(const char* aSection);
bool IsValidKey(const char* aKey);
bool IsValidValue(const char* aValue);
......
......@@ -10,6 +10,11 @@ interface nsIFile;
[scriptable, uuid(7eb955f6-3e78-4d39-b72f-c1bf12a94bce)]
interface nsIINIParser : nsISupports
{
/**
* Initializes an INI file from string data
*/
void initFromString(in AUTF8String aData);
/**
* Enumerates the [section]s available in the INI file.
*/
......@@ -29,6 +34,7 @@ interface nsIINIParser : nsISupports
[scriptable, uuid(b67bb24b-31a3-4a6a-a5d9-0485c9af5a04)]
interface nsIINIParserWriter : nsISupports
{
/**
* Set the value of a string for a particular section and key.
*/
......@@ -38,6 +44,11 @@ interface nsIINIParserWriter : nsISupports
* Write to the INI file.
*/
void writeFile(in nsIFile aINIFile);
/**
* Return the formatted INI file contents
*/
AUTF8String writeToString();
};
[scriptable, uuid(ccae7ea5-1218-4b51-aecb-c2d8ecd46af9)]
......
......@@ -112,6 +112,11 @@ nsINIParserImpl::GetString(const nsACString& aSection, const nsACString& aKey,
PromiseFlatCString(aKey).get(), aResult);
}
NS_IMETHODIMP
nsINIParserImpl::InitFromString(const nsACString& aData) {
return mParser.InitFromString(nsCString(aData));
}
NS_IMETHODIMP
nsINIParserImpl::SetString(const nsACString& aSection, const nsACString& aKey,
const nsACString& aValue) {
......@@ -128,3 +133,11 @@ NS_IMETHODIMP
nsINIParserImpl::WriteFile(nsIFile* aINIFile) {
return mParser.WriteToFile(aINIFile);
}
NS_IMETHODIMP
nsINIParserImpl::WriteToString(nsACString& aOutput) {
aOutput.Truncate();
mParser.WriteToString(aOutput);
return NS_OK;
}
......@@ -257,8 +257,8 @@ function run_test() {
);
Assert.ok(!!factory);
// Test reading from a variety of files. While we're at it, write out each one
// and read it back to ensure that nothing changed.
// Test reading from a variety of files and strings. While we're at it,
// write out each one and read it back to ensure that nothing changed.
while (testnum < testdata.length) {
dump("\nINFO | test #" + ++testnum);
let filename = testdata[testnum - 1].filename;
......@@ -279,6 +279,15 @@ function run_test() {
checkParserOutput(parser, testdata[testnum - 1].reference);
// cleanup after the test
newfile.remove(false);
// ensure that `writeString` works correctly
Assert.ok(parser instanceof Ci.nsIINIParserWriter);
let formatted = parser.writeToString();
parser = factory.createINIParser(null);
// re-parsing the formatted string is the easiest
// way to verify correctness...
parser.initFromString(formatted);
checkParserOutput(parser, testdata[testnum - 1].reference);
}
dump("INFO | test #" + ++testnum + "\n");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment