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