1*f6dc9357SAndroid Build Coastguard Worker // TextPairs.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "TextPairs.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker static const wchar_t kNewLineChar = '\n';
8*f6dc9357SAndroid Build Coastguard Worker static const wchar_t kQuoteChar = '\"';
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker static const wchar_t kBOM = (wchar_t)0xFEFF;
11*f6dc9357SAndroid Build Coastguard Worker
IsSeparatorChar(wchar_t c)12*f6dc9357SAndroid Build Coastguard Worker static bool IsSeparatorChar(wchar_t c)
13*f6dc9357SAndroid Build Coastguard Worker {
14*f6dc9357SAndroid Build Coastguard Worker return (c == ' ' || c == '\t');
15*f6dc9357SAndroid Build Coastguard Worker }
16*f6dc9357SAndroid Build Coastguard Worker
RemoveCr(UString & s)17*f6dc9357SAndroid Build Coastguard Worker static void RemoveCr(UString &s)
18*f6dc9357SAndroid Build Coastguard Worker {
19*f6dc9357SAndroid Build Coastguard Worker s.RemoveChar(L'\x0D');
20*f6dc9357SAndroid Build Coastguard Worker }
21*f6dc9357SAndroid Build Coastguard Worker
GetIDString(const wchar_t * srcString,unsigned & finishPos)22*f6dc9357SAndroid Build Coastguard Worker static UString GetIDString(const wchar_t *srcString, unsigned &finishPos)
23*f6dc9357SAndroid Build Coastguard Worker {
24*f6dc9357SAndroid Build Coastguard Worker UString result;
25*f6dc9357SAndroid Build Coastguard Worker bool quotes = false;
26*f6dc9357SAndroid Build Coastguard Worker for (finishPos = 0;;)
27*f6dc9357SAndroid Build Coastguard Worker {
28*f6dc9357SAndroid Build Coastguard Worker wchar_t c = srcString[finishPos];
29*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
30*f6dc9357SAndroid Build Coastguard Worker break;
31*f6dc9357SAndroid Build Coastguard Worker finishPos++;
32*f6dc9357SAndroid Build Coastguard Worker bool isSeparatorChar = IsSeparatorChar(c);
33*f6dc9357SAndroid Build Coastguard Worker if (c == kNewLineChar || (isSeparatorChar && !quotes)
34*f6dc9357SAndroid Build Coastguard Worker || (c == kQuoteChar && quotes))
35*f6dc9357SAndroid Build Coastguard Worker break;
36*f6dc9357SAndroid Build Coastguard Worker else if (c == kQuoteChar)
37*f6dc9357SAndroid Build Coastguard Worker quotes = true;
38*f6dc9357SAndroid Build Coastguard Worker else
39*f6dc9357SAndroid Build Coastguard Worker result += c;
40*f6dc9357SAndroid Build Coastguard Worker }
41*f6dc9357SAndroid Build Coastguard Worker result.Trim();
42*f6dc9357SAndroid Build Coastguard Worker RemoveCr(result);
43*f6dc9357SAndroid Build Coastguard Worker return result;
44*f6dc9357SAndroid Build Coastguard Worker }
45*f6dc9357SAndroid Build Coastguard Worker
GetValueString(const wchar_t * srcString,unsigned & finishPos)46*f6dc9357SAndroid Build Coastguard Worker static UString GetValueString(const wchar_t *srcString, unsigned &finishPos)
47*f6dc9357SAndroid Build Coastguard Worker {
48*f6dc9357SAndroid Build Coastguard Worker UString result;
49*f6dc9357SAndroid Build Coastguard Worker for (finishPos = 0;;)
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker wchar_t c = srcString[finishPos];
52*f6dc9357SAndroid Build Coastguard Worker if (c == 0)
53*f6dc9357SAndroid Build Coastguard Worker break;
54*f6dc9357SAndroid Build Coastguard Worker finishPos++;
55*f6dc9357SAndroid Build Coastguard Worker if (c == kNewLineChar)
56*f6dc9357SAndroid Build Coastguard Worker break;
57*f6dc9357SAndroid Build Coastguard Worker result += c;
58*f6dc9357SAndroid Build Coastguard Worker }
59*f6dc9357SAndroid Build Coastguard Worker result.Trim();
60*f6dc9357SAndroid Build Coastguard Worker RemoveCr(result);
61*f6dc9357SAndroid Build Coastguard Worker return result;
62*f6dc9357SAndroid Build Coastguard Worker }
63*f6dc9357SAndroid Build Coastguard Worker
GetTextPairs(const UString & srcString,CObjectVector<CTextPair> & pairs)64*f6dc9357SAndroid Build Coastguard Worker static bool GetTextPairs(const UString &srcString, CObjectVector<CTextPair> &pairs)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker pairs.Clear();
67*f6dc9357SAndroid Build Coastguard Worker unsigned pos = 0;
68*f6dc9357SAndroid Build Coastguard Worker
69*f6dc9357SAndroid Build Coastguard Worker if (srcString.Len() > 0)
70*f6dc9357SAndroid Build Coastguard Worker {
71*f6dc9357SAndroid Build Coastguard Worker if (srcString[0] == kBOM)
72*f6dc9357SAndroid Build Coastguard Worker pos++;
73*f6dc9357SAndroid Build Coastguard Worker }
74*f6dc9357SAndroid Build Coastguard Worker while (pos < srcString.Len())
75*f6dc9357SAndroid Build Coastguard Worker {
76*f6dc9357SAndroid Build Coastguard Worker unsigned finishPos;
77*f6dc9357SAndroid Build Coastguard Worker UString id = GetIDString((const wchar_t *)srcString + pos, finishPos);
78*f6dc9357SAndroid Build Coastguard Worker pos += finishPos;
79*f6dc9357SAndroid Build Coastguard Worker if (id.IsEmpty())
80*f6dc9357SAndroid Build Coastguard Worker continue;
81*f6dc9357SAndroid Build Coastguard Worker UString value = GetValueString((const wchar_t *)srcString + pos, finishPos);
82*f6dc9357SAndroid Build Coastguard Worker pos += finishPos;
83*f6dc9357SAndroid Build Coastguard Worker if (!id.IsEmpty())
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker CTextPair pair;
86*f6dc9357SAndroid Build Coastguard Worker pair.ID = id;
87*f6dc9357SAndroid Build Coastguard Worker pair.Value = value;
88*f6dc9357SAndroid Build Coastguard Worker pairs.Add(pair);
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker }
91*f6dc9357SAndroid Build Coastguard Worker return true;
92*f6dc9357SAndroid Build Coastguard Worker }
93*f6dc9357SAndroid Build Coastguard Worker
ComparePairIDs(const UString & s1,const UString & s2)94*f6dc9357SAndroid Build Coastguard Worker static int ComparePairIDs(const UString &s1, const UString &s2)
95*f6dc9357SAndroid Build Coastguard Worker { return MyStringCompareNoCase(s1, s2); }
96*f6dc9357SAndroid Build Coastguard Worker
ComparePairItems(const CTextPair & p1,const CTextPair & p2)97*f6dc9357SAndroid Build Coastguard Worker static int ComparePairItems(const CTextPair &p1, const CTextPair &p2)
98*f6dc9357SAndroid Build Coastguard Worker { return ComparePairIDs(p1.ID, p2.ID); }
99*f6dc9357SAndroid Build Coastguard Worker
ComparePairItems(void * const * a1,void * const * a2,void *)100*f6dc9357SAndroid Build Coastguard Worker static int ComparePairItems(void *const *a1, void *const *a2, void * /* param */)
101*f6dc9357SAndroid Build Coastguard Worker { return ComparePairItems(**(const CTextPair *const *)a1, **(const CTextPair *const *)a2); }
102*f6dc9357SAndroid Build Coastguard Worker
Sort()103*f6dc9357SAndroid Build Coastguard Worker void CPairsStorage::Sort() { Pairs.Sort(ComparePairItems, NULL); }
104*f6dc9357SAndroid Build Coastguard Worker
FindID(const UString & id,unsigned & insertPos) const105*f6dc9357SAndroid Build Coastguard Worker int CPairsStorage::FindID(const UString &id, unsigned &insertPos) const
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker unsigned left = 0, right = Pairs.Size();
108*f6dc9357SAndroid Build Coastguard Worker while (left != right)
109*f6dc9357SAndroid Build Coastguard Worker {
110*f6dc9357SAndroid Build Coastguard Worker const unsigned mid = (left + right) / 2;
111*f6dc9357SAndroid Build Coastguard Worker const int compResult = ComparePairIDs(id, Pairs[mid].ID);
112*f6dc9357SAndroid Build Coastguard Worker if (compResult == 0)
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker insertPos = mid; // to disable GCC warning
115*f6dc9357SAndroid Build Coastguard Worker return (int)mid;
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker if (compResult < 0)
118*f6dc9357SAndroid Build Coastguard Worker right = mid;
119*f6dc9357SAndroid Build Coastguard Worker else
120*f6dc9357SAndroid Build Coastguard Worker left = mid + 1;
121*f6dc9357SAndroid Build Coastguard Worker }
122*f6dc9357SAndroid Build Coastguard Worker insertPos = left;
123*f6dc9357SAndroid Build Coastguard Worker return -1;
124*f6dc9357SAndroid Build Coastguard Worker }
125*f6dc9357SAndroid Build Coastguard Worker
FindID(const UString & id) const126*f6dc9357SAndroid Build Coastguard Worker int CPairsStorage::FindID(const UString &id) const
127*f6dc9357SAndroid Build Coastguard Worker {
128*f6dc9357SAndroid Build Coastguard Worker unsigned pos;
129*f6dc9357SAndroid Build Coastguard Worker return FindID(id, pos);
130*f6dc9357SAndroid Build Coastguard Worker }
131*f6dc9357SAndroid Build Coastguard Worker
AddPair(const CTextPair & pair)132*f6dc9357SAndroid Build Coastguard Worker void CPairsStorage::AddPair(const CTextPair &pair)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker unsigned insertPos;
135*f6dc9357SAndroid Build Coastguard Worker const int pos = FindID(pair.ID, insertPos);
136*f6dc9357SAndroid Build Coastguard Worker if (pos >= 0)
137*f6dc9357SAndroid Build Coastguard Worker Pairs[pos] = pair;
138*f6dc9357SAndroid Build Coastguard Worker else
139*f6dc9357SAndroid Build Coastguard Worker Pairs.Insert(insertPos, pair);
140*f6dc9357SAndroid Build Coastguard Worker }
141*f6dc9357SAndroid Build Coastguard Worker
DeletePair(const UString & id)142*f6dc9357SAndroid Build Coastguard Worker void CPairsStorage::DeletePair(const UString &id)
143*f6dc9357SAndroid Build Coastguard Worker {
144*f6dc9357SAndroid Build Coastguard Worker const int pos = FindID(id);
145*f6dc9357SAndroid Build Coastguard Worker if (pos >= 0)
146*f6dc9357SAndroid Build Coastguard Worker Pairs.Delete((unsigned)pos);
147*f6dc9357SAndroid Build Coastguard Worker }
148*f6dc9357SAndroid Build Coastguard Worker
GetValue(const UString & id,UString & value) const149*f6dc9357SAndroid Build Coastguard Worker bool CPairsStorage::GetValue(const UString &id, UString &value) const
150*f6dc9357SAndroid Build Coastguard Worker {
151*f6dc9357SAndroid Build Coastguard Worker value.Empty();
152*f6dc9357SAndroid Build Coastguard Worker const int pos = FindID(id);
153*f6dc9357SAndroid Build Coastguard Worker if (pos < 0)
154*f6dc9357SAndroid Build Coastguard Worker return false;
155*f6dc9357SAndroid Build Coastguard Worker value = Pairs[pos].Value;
156*f6dc9357SAndroid Build Coastguard Worker return true;
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker
GetValue(const UString & id) const159*f6dc9357SAndroid Build Coastguard Worker UString CPairsStorage::GetValue(const UString &id) const
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker const int pos = FindID(id);
162*f6dc9357SAndroid Build Coastguard Worker if (pos < 0)
163*f6dc9357SAndroid Build Coastguard Worker return UString();
164*f6dc9357SAndroid Build Coastguard Worker return Pairs[pos].Value;
165*f6dc9357SAndroid Build Coastguard Worker }
166*f6dc9357SAndroid Build Coastguard Worker
ReadFromString(const UString & text)167*f6dc9357SAndroid Build Coastguard Worker bool CPairsStorage::ReadFromString(const UString &text)
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker bool result = ::GetTextPairs(text, Pairs);
170*f6dc9357SAndroid Build Coastguard Worker if (result)
171*f6dc9357SAndroid Build Coastguard Worker Sort();
172*f6dc9357SAndroid Build Coastguard Worker else
173*f6dc9357SAndroid Build Coastguard Worker Pairs.Clear();
174*f6dc9357SAndroid Build Coastguard Worker return result;
175*f6dc9357SAndroid Build Coastguard Worker }
176*f6dc9357SAndroid Build Coastguard Worker
SaveToString(UString & text) const177*f6dc9357SAndroid Build Coastguard Worker void CPairsStorage::SaveToString(UString &text) const
178*f6dc9357SAndroid Build Coastguard Worker {
179*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, Pairs)
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker const CTextPair &pair = Pairs[i];
182*f6dc9357SAndroid Build Coastguard Worker bool multiWord = (pair.ID.Find(L' ') >= 0);
183*f6dc9357SAndroid Build Coastguard Worker if (multiWord)
184*f6dc9357SAndroid Build Coastguard Worker text.Add_Char('\"');
185*f6dc9357SAndroid Build Coastguard Worker text += pair.ID;
186*f6dc9357SAndroid Build Coastguard Worker if (multiWord)
187*f6dc9357SAndroid Build Coastguard Worker text.Add_Char('\"');
188*f6dc9357SAndroid Build Coastguard Worker text.Add_Space();
189*f6dc9357SAndroid Build Coastguard Worker text += pair.Value;
190*f6dc9357SAndroid Build Coastguard Worker text.Add_Char('\x0D');
191*f6dc9357SAndroid Build Coastguard Worker text.Add_LF();
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker }
194