1
0

Addressed Issue #402. cIniFile can now process UTF-8 files that have a

Byte Order Marker, BOM.
This commit is contained in:
narroo 2014-02-15 19:56:36 -05:00
parent a5b8d35845
commit 8c34b2d974
2 changed files with 90 additions and 66 deletions

View File

@ -83,91 +83,97 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
} }
} }
while (getline(f, line)) if (getline(f, line))
{ {
// To be compatible with Win32, check for existence of '\r'. // Removes UTF-8 Byte Order Markers (BOM) if, present.
// Win32 files have the '\r' and Unix files don't at the end of a line. RemoveBom(line);
// Note that the '\r' will be written to INI files from
// Unix so that the created INI file can be read under Win32
// without change.
size_t lineLength = line.length();
if (lineLength == 0)
{
continue;
}
if (line[lineLength - 1] == '\r')
{
line = line.substr(0, lineLength - 1);
}
if (line.length() == 0) do
{ {
continue; // To be compatible with Win32, check for existence of '\r'.
} // Win32 files have the '\r' and Unix files don't at the end of a line.
// Note that the '\r' will be written to INI files from
// Unix so that the created INI file can be read under Win32
// without change.
size_t lineLength = line.length();
if (lineLength == 0)
{
continue;
}
if (line[lineLength - 1] == '\r')
{
line = line.substr(0, lineLength - 1);
}
// Check that the user hasn't opened a binary file by checking the first if (line.length() == 0)
// character of each line! {
if (!isprint(line[0])) continue;
{ }
printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]);
f.close();
return false;
}
if ((pLeft = line.find_first_of(";#[=")) == AString::npos)
{
continue;
}
switch (line[pLeft]) // Check that the user hasn't opened a binary file by checking the first
{ // character of each line!
if (!isprint(line[0]))
{
printf("%s: Binary-check failed on char %d\n", __FUNCTION__, line[0]);
f.close();
return false;
}
if ((pLeft = line.find_first_of(";#[=")) == AString::npos)
{
continue;
}
switch (line[pLeft])
{
case '[': case '[':
{ {
if ( if (
((pRight = line.find_last_of("]")) != AString::npos) && ((pRight = line.find_last_of("]")) != AString::npos) &&
(pRight > pLeft) (pRight > pLeft)
) )
{ {
keyname = line.substr(pLeft + 1, pRight - pLeft - 1); keyname = line.substr(pLeft + 1, pRight - pLeft - 1);
AddKeyName(keyname); AddKeyName(keyname);
} }
break; break;
} }
case '=': case '=':
{ {
valuename = line.substr(0, pLeft); valuename = line.substr(0, pLeft);
value = line.substr(pLeft + 1); value = line.substr(pLeft + 1);
AddValue(keyname, valuename, value); AddValue(keyname, valuename, value);
break; break;
} }
case ';': case ';':
case '#': case '#':
{ {
if (names.size() == 0) if (names.size() == 0)
{ {
AddHeaderComment(line.substr(pLeft + 1)); AddHeaderComment(line.substr(pLeft + 1));
} }
else else
{ {
AddKeyComment(keyname, line.substr(pLeft + 1)); AddKeyComment(keyname, line.substr(pLeft + 1));
} }
break; break;
} }
} // switch (line[pLeft]) } // switch (line[pLeft])
} // while (getline()) } while (getline(f, line)); // do
f.close(); f.close();
if (names.size() == 0) if (names.size() == 0)
{ {
return false; return false;
}
if (IsFromExampleRedirect)
{
WriteFile(FILE_IO_PREFIX + a_FileName);
}
return true;
} }
if (IsFromExampleRedirect)
{
WriteFile(FILE_IO_PREFIX + a_FileName);
}
return true;
} }
@ -824,3 +830,19 @@ AString cIniFile::CheckCase(const AString & s) const
void cIniFile::RemoveBom(AString & a_line) const
{
// The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF ( In Unicode Latin I:  )
static char BOM[] = { 0xEF, 0xBB, 0xBF };
// The BOM sequence, if present, is always the first three characters of the input.
if (a_line.compare(0, 3, BOM) == 0)
{
a_line.erase(0, 3);
}
}

View File

@ -51,6 +51,8 @@ private:
/// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is /// If the object is case-insensitive, returns s as lowercase; otherwise returns s as-is
AString CheckCase(const AString & s) const; AString CheckCase(const AString & s) const;
/// Removes the UTF-8 BOMs (Byte order makers), if present.
void RemoveBom(AString & a_line) const;
public: public:
enum errors enum errors
{ {