p7zip-rar/CPP/7zip/UI/FileManager/TextPairs.cpp
2017-10-11 12:40:22 +02:00

191 lines
3.9 KiB
C++

// TextPairs.cpp
#include "StdAfx.h"
#include "TextPairs.h"
static const wchar_t kNewLineChar = '\n';
static const wchar_t kQuoteChar = '\"';
static const wchar_t kBOM = (wchar_t)0xFEFF;
static bool IsSeparatorChar(wchar_t c)
{
return (c == ' ' || c == '\t');
}
static void RemoveCr(UString &s)
{
s.RemoveChar(L'\x0D');
}
static UString GetIDString(const wchar_t *srcString, unsigned &finishPos)
{
UString result;
bool quotes = false;
for (finishPos = 0;;)
{
wchar_t c = srcString[finishPos];
if (c == 0)
break;
finishPos++;
bool isSeparatorChar = IsSeparatorChar(c);
if (c == kNewLineChar || (isSeparatorChar && !quotes)
|| (c == kQuoteChar && quotes))
break;
else if (c == kQuoteChar)
quotes = true;
else
result += c;
}
result.Trim();
RemoveCr(result);
return result;
}
static UString GetValueString(const wchar_t *srcString, unsigned &finishPos)
{
UString result;
for (finishPos = 0;;)
{
wchar_t c = srcString[finishPos];
if (c == 0)
break;
finishPos++;
if (c == kNewLineChar)
break;
result += c;
}
result.Trim();
RemoveCr(result);
return result;
}
static bool GetTextPairs(const UString &srcString, CObjectVector<CTextPair> &pairs)
{
pairs.Clear();
unsigned pos = 0;
if (srcString.Len() > 0)
{
if (srcString[0] == kBOM)
pos++;
}
while (pos < srcString.Len())
{
unsigned finishPos;
UString id = GetIDString((const wchar_t *)srcString + pos, finishPos);
pos += finishPos;
if (id.IsEmpty())
continue;
UString value = GetValueString((const wchar_t *)srcString + pos, finishPos);
pos += finishPos;
if (!id.IsEmpty())
{
CTextPair pair;
pair.ID = id;
pair.Value = value;
pairs.Add(pair);
}
}
return true;
}
static int ComparePairIDs(const UString &s1, const UString &s2)
{ return MyStringCompareNoCase(s1, s2); }
static int ComparePairItems(const CTextPair &p1, const CTextPair &p2)
{ return ComparePairIDs(p1.ID, p2.ID); }
static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */)
{ return ComparePairItems(**(const CTextPair **)a1, **(const CTextPair **)a2); }
void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, 0); }
int CPairsStorage::FindID(const UString &id, int &insertPos) const
{
int left = 0, right = Pairs.Size();
while (left != right)
{
int mid = (left + right) / 2;
int compResult = ComparePairIDs(id, Pairs[mid].ID);
if (compResult == 0)
return mid;
if (compResult < 0)
right = mid;
else
left = mid + 1;
}
insertPos = left;
return -1;
}
int CPairsStorage::FindID(const UString &id) const
{
int pos;
return FindID(id, pos);
}
void CPairsStorage::AddPair(const CTextPair &pair)
{
int insertPos;
int pos = FindID(pair.ID, insertPos);
if (pos >= 0)
Pairs[pos] = pair;
else
Pairs.Insert(insertPos, pair);
}
void CPairsStorage::DeletePair(const UString &id)
{
int pos = FindID(id);
if (pos >= 0)
Pairs.Delete(pos);
}
bool CPairsStorage::GetValue(const UString &id, UString &value) const
{
value.Empty();
int pos = FindID(id);
if (pos < 0)
return false;
value = Pairs[pos].Value;
return true;
}
UString CPairsStorage::GetValue(const UString &id) const
{
int pos = FindID(id);
if (pos < 0)
return UString();
return Pairs[pos].Value;
}
bool CPairsStorage::ReadFromString(const UString &text)
{
bool result = ::GetTextPairs(text, Pairs);
if (result)
Sort();
else
Pairs.Clear();
return result;
}
void CPairsStorage::SaveToString(UString &text) const
{
FOR_VECTOR (i, Pairs)
{
const CTextPair &pair = Pairs[i];
bool multiWord = (pair.ID.Find(L' ') >= 0);
if (multiWord)
text += L'\"';
text += pair.ID;
if (multiWord)
text += L'\"';
text += L' ';
text += pair.Value;
text += L'\x0D';
text.Add_LF();
}
}