1 /*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
2  *
3  *  Use of this source code is governed by a zlib-style license that can
4  *  be found in the License.txt file in the root of the source tree.
5  */
6 
7 //---------------------------------------------------------------------------
8 #include "ZenLib/PreComp.h"
9 #ifdef __BORLANDC__
10     #pragma hdrstop
11 #endif
12 //---------------------------------------------------------------------------
13 
14 //---------------------------------------------------------------------------
15 #include "ZenLib/Conf_Internal.h"
16 //---------------------------------------------------------------------------
17 
18 //---------------------------------------------------------------------------
19 #include <algorithm>
20 #include "ZenLib/ZtringListList.h"
21 using namespace std;
22 #if defined(_MSC_VER) && _MSC_VER <= 1200
23     using std::vector; //Visual C++ 6 patch
24 #endif
25 //---------------------------------------------------------------------------
26 
27 
28 namespace ZenLib
29 {
30 
31 //---------------------------------------------------------------------------
32 extern Ztring EmptyZtring;
33 //---------------------------------------------------------------------------
34 
35 //***************************************************************************
36 // Constructors/Destructor
37 //***************************************************************************
38 
39 //---------------------------------------------------------------------------
40 // Constructors
ZtringListList()41 ZtringListList::ZtringListList()
42 : std::vector<ZenLib::ZtringList, std::allocator<ZenLib::ZtringList> > ()
43 {
44     Separator[0]=EOL;
45     Separator[1]=__T(";");
46     Quote=__T("\"");
47     Max[0]=Error;
48     Max[1]=Error;
49 }
50 
ZtringListList(const ZtringListList & Source)51 ZtringListList::ZtringListList(const ZtringListList &Source)
52 : std::vector<ZenLib::ZtringList, std::allocator<ZenLib::ZtringList> > ()
53 {
54     Separator[0]=Source.Separator[0];
55     Separator[1]=Source.Separator[1];
56     Quote=Source.Quote;
57     Max[0]=Source.Max[0];
58     Max[1]=Source.Max[1];
59     reserve(Source.size());
60     for (intu Pos=0; Pos<Source.size(); Pos++)
61         push_back(Source[Pos]);
62 }
63 
ZtringListList(const Ztring & Source)64 ZtringListList::ZtringListList(const Ztring &Source)
65 {
66     Separator[0]=EOL;
67     Separator[1]=__T(";");
68     Quote=__T("\"");
69     Max[0]=Error;
70     Max[1]=Error;
71     Write(Source.c_str());
72 }
73 
ZtringListList(const Char * Source)74 ZtringListList::ZtringListList(const Char *Source)
75 {
76     Separator[0]=EOL;
77     Separator[1]=__T(";");
78     Quote=__T("\"");
79     Max[0]=Error;
80     Max[1]=Error;
81     Write(Source);
82 }
83 
84 #ifdef _UNICODE
ZtringListList(const char * S)85 ZtringListList::ZtringListList (const char* S)
86 {
87     Separator[0]=EOL;
88     Separator[1]=__T(";");
89     Quote=__T("\"");
90     Max[0]=Error;
91     Max[1]=Error;
92     Write(Ztring(S));
93 }
94 #endif
95 
96 //***************************************************************************
97 // Operators
98 //***************************************************************************
99 
100 //---------------------------------------------------------------------------
101 //Operator ==
operator ==(const ZtringListList & Source) const102 bool ZtringListList::operator== (const ZtringListList &Source) const
103 {
104     return (Read()==Source.Read());
105 }
106 
107 //---------------------------------------------------------------------------
108 //Operator !=
operator !=(const ZtringListList & Source) const109 bool ZtringListList::operator!= (const ZtringListList &Source) const
110 {
111     return (!(Read()==Source.Read()));
112 }
113 
114 //---------------------------------------------------------------------------
115 // Operator +=
operator +=(const ZtringListList & Source)116 ZtringListList &ZtringListList::operator+= (const ZtringListList &Source)
117 {
118     reserve(size()+Source.size());
119     for (size_type Pos=0; Pos<Source.size(); Pos++)
120     {
121         push_back(Source[Pos]);
122         operator[](size()-1).Separator_Set(0, Separator[1]);
123         operator[](size()-1).Quote_Set(Quote);
124         operator[](size()-1).Max_Set(0, Max[1]);
125     }
126 
127     return *this;
128 }
129 
130 //---------------------------------------------------------------------------
131 // Operator =
operator =(const ZtringListList & Source)132 ZtringListList &ZtringListList::operator= (const ZtringListList &Source)
133 {
134     if (this == &Source)
135         return *this;
136     clear();
137 
138     reserve(Source.size());
139     for (size_type Pos=0; Pos<Source.size(); Pos++)
140     {
141         push_back(Source[Pos]);
142         operator[](size()-1).Separator_Set(0, Separator[1]);
143         operator[](size()-1).Quote_Set(Quote);
144         operator[](size()-1).Max_Set(0, Max[1]);
145     }
146 
147     return *this;
148 }
149 
150 //---------------------------------------------------------------------------
151 // Operatorr ()
operator ()(size_type Pos0)152 ZtringList &ZtringListList::operator() (size_type Pos0)
153 {
154     //Integrity
155     if (Pos0>=size())
156         Write(Ztring(), Pos0);
157 
158     return operator[](Pos0);
159 }
160 
operator ()(size_type Pos0,size_type Pos1)161 Ztring &ZtringListList::operator() (size_type Pos0, size_type Pos1)
162 {
163     //Integrity
164     if (Pos0>=size())
165         Write(Ztring(), Pos0);
166 
167     return operator[](Pos0).operator()(Pos1);
168 }
169 
operator ()(const Ztring & Pos0,size_type Pos0_1,size_type Pos1)170 Ztring &ZtringListList::operator() (const Ztring &Pos0, size_type Pos0_1, size_type Pos1)
171 {
172     size_type Pos=0;
173     size_t Size=size();
174     for (; Pos<Size; Pos++)
175         if (operator[](Pos).size()>Pos0_1)
176             if (operator[](Pos)[Pos0_1]==Pos0)
177                 break;
178 
179     if (Pos>=Size)
180     {
181         Write(Pos0, Size, Pos0_1);
182         Pos=size()-1;
183     }
184 
185     return operator[](Pos).operator()(Pos1);
186 }
187 
188 //***************************************************************************
189 // In/Out
190 //***************************************************************************
191 
192 //---------------------------------------------------------------------------
193 // Read
Read() const194 Ztring ZtringListList::Read () const
195 {
196     //Integrity
197     if (size()==0)
198         return Ztring();
199 
200     Ztring ToReturn;
201     size_type Size=size()-1;
202     for (size_type Pos0=0; Pos0<Size; Pos0++)
203         ToReturn+=Read(Pos0)+Separator[0];
204     ToReturn+=Read(Size);
205 
206     //Delete all useless separators at the end
207     //if(ToReturn.size()>0 && Separator[0].size() && ToReturn(ToReturn.size()-1)==Separator[0][Separator[0].size()-1]) //Optimize speed
208     //    while (ToReturn.find(Separator[0].c_str(), ToReturn.size()-Separator[0].size())!=std::string::npos)
209     //        ToReturn.resize(ToReturn.size()-Separator[0].size());
210 
211     return ToReturn;
212 }
213 
Read(size_type Pos0) const214 Ztring ZtringListList::Read (size_type Pos0) const
215 {
216     //Integrity
217     if (Pos0>=size())
218         return Ztring();
219 
220     return operator[](Pos0).Read();
221 }
222 
Read(size_type Pos0,size_type Pos1) const223 const Ztring &ZtringListList::Read (size_type Pos0, size_type Pos1) const
224 {
225     //Integrity
226     if (Pos0>=size())
227         return EmptyZtring;
228 
229     return operator[](Pos0).Read(Pos1);
230 }
231 
Read(const Ztring & Pos0,size_type Pos1) const232 const Ztring &ZtringListList::Read (const Ztring &Pos0, size_type Pos1) const
233 {
234     size_type Pos=Find(Pos0);
235     if (Pos==Error)
236         return EmptyZtring;
237 
238     return operator[](Pos).Read(Pos1);
239 }
240 
Read(const Ztring & Pos0,size_type Pos0_1,size_type Pos1) const241 const Ztring &ZtringListList::Read (const Ztring &Pos0, size_type Pos0_1, size_type Pos1) const
242 {
243     size_type Pos=Find(Pos0, Pos0_1);
244     if (Pos==Error)
245         return EmptyZtring;
246 
247     return operator[](Pos).Read(Pos1);
248 }
249 
Read(const Ztring & Pos0,const Ztring & Default,size_type Pos1) const250 const Ztring &ZtringListList::Read (const Ztring &Pos0, const Ztring &Default, size_type Pos1) const
251 {
252     size_type Pos=Find(Pos0);
253     if (Pos==Error)
254         return Default;
255 
256     return operator[](Pos).Read(Pos1);
257 }
258 
Read(const Ztring & Pos0,const Ztring & Default,size_type Pos0_1,size_type Pos1) const259 const Ztring &ZtringListList::Read (const Ztring &Pos0, const Ztring &Default, size_type Pos0_1, size_type Pos1) const //Lecture d'un champs en position 0 avec une option par defaut
260 {
261     size_type Pos=Find(Pos0, Pos0_1);
262     if (Pos==Error)
263         return Default;
264 
265     return operator[](Pos).Read(Pos1);
266 }
267 
Read1(size_type Pos1) const268 Ztring ZtringListList::Read1 (size_type Pos1) const
269 {
270     Ztring ToReturn;
271     size_type Size=size()-1;
272     for (size_type Pos=0; Pos<Size; Pos++)
273         ToReturn+=operator[](Pos).Read(Pos1)+Separator[0];
274     ToReturn+=operator[](Size).Read(Pos1);
275 
276     //Delete all useless separators at the end
277     if(ToReturn(ToReturn.size()-1)==Separator[0][Separator[0].size()-1]) //Optimize speed
278         while (ToReturn.find(Separator[0].c_str(), ToReturn.size()-Separator[0].size())!=std::string::npos)
279             ToReturn.resize(ToReturn.size()-Separator[0].size());
280 
281     return ToReturn;
282 }
283 
284 //---------------------------------------------------------------------------
285 // Write
Write(const Ztring & ToWrite)286 void ZtringListList::Write(const Ztring &ToWrite)
287 {
288     clear();
289 
290     if (ToWrite.empty())
291         return;
292 
293     //Detecting carriage return format
294     Ztring Separator0;
295     if (Separator[0]==EOL)
296     {
297         size_t CarriageReturn_Pos=ToWrite.find_first_of(__T("\r\n"));
298         if (CarriageReturn_Pos!=string::npos)
299         {
300             if (ToWrite[CarriageReturn_Pos]==__T('\r'))
301             {
302                 if (CarriageReturn_Pos+1<ToWrite.size() && ToWrite[CarriageReturn_Pos+1]==__T('\n'))
303                     Separator0=__T("\r\n");
304                 else
305                     Separator0=__T("\r");
306             }
307             else
308                 Separator0=__T("\n");
309         }
310         else
311             Separator0=Separator[0];
312     }
313     else
314         Separator0=Separator[0];
315 
316     size_t l=ToWrite.size();
317     size_t i=0;
318     bool q=false; //In quotes
319     size_t Quote_Size=Quote.size();
320     size_t Separator0_Size=Separator0.size();
321     size_t Separator1_Size=Separator[1].size();
322     size_t x=0, y=0;
323     while (i<l)
324     {
325         //Quote
326         if (Quote_Size && i+Quote_Size<=l)
327         {
328             bool IsQuote=true;
329             for (size_t j=0; j<Quote_Size; j++)
330             {
331                 if (ToWrite[i+j]!=Quote[j])
332                 {
333                     IsQuote=false;
334                     break;
335                 }
336             }
337             if (IsQuote)
338             {
339                 //Double quote
340                 if (i+Quote_Size*2<=l)
341                 {
342                     IsQuote=false;
343                     for (size_t j=0; j<Quote_Size; j++)
344                     {
345                         if (ToWrite[i+Quote_Size+j]!=Quote[j])
346                         {
347                             IsQuote=true;
348                             break;
349                         }
350                     }
351                     if (!IsQuote)
352                         i++; // 2 quote chars transformed to one unique quote
353                 }
354                 if (IsQuote)
355                 {
356                     i+=Quote_Size;
357                     q=!q;
358                     continue;
359                 }
360             }
361         }
362 
363         if (!q)
364         {
365             //Carriage return
366             if (i+Separator0_Size<=l)
367             {
368                 bool IsSeparator0=true;
369                 for (size_t j=0; j<Separator0_Size; j++)
370                 {
371                     if (ToWrite[i+j]!= Separator0[j])
372                     {
373                         IsSeparator0=false;
374                         break;
375                     }
376                 }
377                 if (IsSeparator0)
378                 {
379                     i+=Separator0_Size;
380                     y++;
381                     x=0;
382                     continue;
383                 }
384             }
385 
386             //Carriage return
387             if (i+Separator1_Size<=l)
388             {
389                 bool IsSeparator1=true;
390                 for (size_t j=0; j<Separator1_Size; j++)
391                 {
392                     if (ToWrite[i+j]!= Separator[1][j])
393                     {
394                         IsSeparator1=false;
395                         break;
396                     }
397                 }
398                 if (IsSeparator1)
399                 {
400                     i+=Separator1_Size;
401                     x++;
402                     continue;
403                 }
404             }
405         }
406 
407         if (y>=size())
408         {
409             resize(y+1);
410             for (size_t j=0; j<=y; j++)
411             {
412                 operator[](j).Separator_Set(0, Separator[1]);
413                 operator[](j).Quote_Set(Quote);
414                 operator[](j).Max_Set(0, Max[1]);
415             }
416         }
417         ZtringList& Line=operator[](y);
418         if (x>=Line.size())
419             Line.resize(x+1);
420         Line.operator[](x).push_back(ToWrite[i]);
421 
422         i++;
423     }
424 }
425 
Write(const ZtringList & ToWrite,size_type Pos)426 void ZtringListList::Write(const ZtringList &ToWrite, size_type Pos)
427 {
428     //Integrity
429     if (Pos==Error)
430         return;
431 
432     //Writing
433     if (Pos>=size())
434     {
435         //Reservation de ressources
436         if (!capacity())
437             reserve(1);
438         while (Pos>=capacity())
439             reserve(capacity()*2);
440 
441         while (Pos>size())
442             push_back (Ztring());
443         push_back(ToWrite);
444     }
445     else
446         operator[](Pos)=ToWrite;
447 }
448 
Write(const Ztring & ToWrite,size_type Pos0,size_type Pos1)449 void ZtringListList::Write(const Ztring &ToWrite, size_type Pos0, size_type Pos1)
450 {
451     if (Pos0>=size())
452         Write(Ztring(), Pos0);
453 
454     operator[](Pos0).Write(ToWrite, Pos1);
455 }
456 
push_back(const ZtringList & ToAdd)457 void ZtringListList::push_back (const ZtringList &ToAdd)
458 {
459     vector<ZtringList>::push_back(ToAdd); //Visual C++ 6 patch, should be std::vector
460     operator[](size()-1).Separator_Set(0, Separator[1]);
461     operator[](size()-1).Quote_Set(Quote);
462     operator[](size()-1).Max_Set(0, Max[1]);
463 }
464 
push_back(const Ztring & ToAdd)465 void ZtringListList::push_back (const Ztring &ToAdd)
466 {
467     ZtringList ZL1;
468     ZL1.Separator_Set(0, Separator[1]);
469     ZL1.Quote_Set(Quote);
470     ZL1.Max_Set(0, Max[1]);
471     ZL1.Write(ToAdd);
472     push_back(ZL1);
473 }
474 
475 //---------------------------------------------------------------------------
476 // Insert
Insert1(const Ztring & ToInsert,size_type Pos1)477 void ZtringListList::Insert1 (const Ztring &ToInsert, size_type Pos1)
478 {
479     for (size_type Pos0=0; Pos0<size(); Pos0++)
480         operator[](Pos0).Insert(ToInsert, Pos1);
481 }
482 
483 //---------------------------------------------------------------------------
484 // Delete
Delete(const Ztring & ToFind,size_type Pos1,const Ztring & Comparator,ztring_t Options)485 void ZtringListList::Delete (const Ztring &ToFind, size_type Pos1, const Ztring &Comparator, ztring_t Options)
486 {
487     size_type Pos0=0;
488     while ((Pos0=Find(ToFind, Pos1, Pos0, Comparator, Options))!=Error)
489         operator [] (Pos0).Delete(Pos1);
490 }
491 
Delete1(size_type Pos1)492 void ZtringListList::Delete1 (size_type Pos1)
493 {
494     for (size_type Pos0=0; Pos0<size(); Pos0++)
495         operator [] (Pos0).Delete(Pos1);
496 }
497 
498 //***************************************************************************
499 // Edition
500 //***************************************************************************
501 
502 //---------------------------------------------------------------------------
503 // Swap
Swap(size_type Pos0_A,size_type Pos0_B)504 void ZtringListList::Swap (size_type Pos0_A, size_type Pos0_B)
505 {
506     //Integrity
507     size_type Pos_Max;
508     if (Pos0_A<Pos0_B)
509         Pos_Max=Pos0_B;
510     else
511         Pos_Max=Pos0_A;
512     if (Pos_Max>=size())
513         Write(Ztring(), Pos_Max);
514 
515     operator [] (Pos0_A).swap(operator [] (Pos0_B));
516 }
517 
Swap1(size_type Pos1_A,size_type Pos1_B)518 void ZtringListList::Swap1 (size_type Pos1_A, size_type Pos1_B)
519 {
520     for (size_type Pos0=0; Pos0<size(); Pos0++)
521         operator () (Pos0, Pos1_A).swap(operator () (Pos0, Pos1_B));
522 }
523 
524 //---------------------------------------------------------------------------
525 // Sort
Sort(size_type,ztring_t)526 void ZtringListList::Sort(size_type, ztring_t)
527 {
528     std::stable_sort(begin(), end());
529     return;
530 }
531 
532 //---------------------------------------------------------------------------
533 // Find
Find(const Ztring & ToFind,size_type Pos1,size_type Pos0) const534 Ztring::size_type ZtringListList::Find (const Ztring &ToFind, size_type Pos1, size_type Pos0) const
535 {
536     size_t Size=size();
537     for (; Pos0<Size; Pos0++)
538         if (operator[](Pos0).size()>Pos1)
539             if (operator[](Pos0)[Pos1]==ToFind)
540                 break;
541 
542     if (Pos0>=Size)
543         return Error;
544     return Pos0;
545 }
546 
Find_Filled(size_type Pos1,size_type Pos0) const547 Ztring::size_type ZtringListList::Find_Filled (size_type Pos1, size_type Pos0) const
548 {
549     size_t Size=size();
550     for (; Pos0<Size; Pos0++)
551         if (operator[](Pos0).size()>Pos1)
552             if (!operator[](Pos0)[Pos1].empty())
553                 break;
554 
555     if (Pos0>=Size)
556         return Error;
557     return Pos0;
558 }
559 
Find(const Ztring & ToFind,size_type Pos1,size_type Pos0,const Ztring & Comparator,ztring_t Options) const560 Ztring::size_type ZtringListList::Find (const Ztring &ToFind, size_type Pos1, size_type Pos0, const Ztring &Comparator, ztring_t Options) const
561 {
562     while (    Pos0<size()
563        && (    Pos1>=at(Pos0).size()
564             || !at(Pos0).at(Pos1).Compare(ToFind, Comparator, Options)))
565         Pos0++;
566     if (Pos0>=size())
567         return Error;
568     return Pos0;
569 }
570 
FindValue(const Ztring & ToFind,size_type Pos1Value,size_type Pos1,size_type Pos0Begin,const Ztring & Comparator,ztring_t) const571 Ztring ZtringListList::FindValue (const Ztring &ToFind, size_type Pos1Value, size_type Pos1, size_type Pos0Begin, const Ztring &Comparator, ztring_t) const
572 {
573     size_type Pos0=Find(ToFind, Pos1, Pos0Begin, Comparator);
574     if (Pos0==Error)
575         return Ztring();
576 
577     return Read(Pos0, Pos1Value);
578 }
579 
SubSheet(const Ztring & ToFind,size_type Pos1,size_type Pos0,const Ztring & Comparator,ztring_t) const580 ZtringListList ZtringListList::SubSheet (const Ztring &ToFind, size_type Pos1, size_type Pos0, const Ztring &Comparator, ztring_t) const
581 {
582     ZtringListList ToReturn;
583     ToReturn.Separator[0]=Separator[0];
584     ToReturn.Separator[1]=Separator[1];
585     ToReturn.Quote=Quote;
586 
587     Pos0--;
588     do
589     {
590         Pos0=Find(ToFind, Pos1, Pos0+1, Comparator);
591         ToReturn.push_back(Read(Pos0));
592     }
593     while (Pos0!=Error);
594 
595     return ToReturn;
596 }
597 
598 //***************************************************************************
599 // Configuration
600 //***************************************************************************
601 
602 //---------------------------------------------------------------------------
603 // Separator
Separator_Set(size_type Level,const Ztring & NewSeparator)604 void ZtringListList::Separator_Set (size_type Level, const Ztring &NewSeparator)
605 {
606     if (NewSeparator.empty() || Level>1)
607         return;
608 
609     Separator[Level]=NewSeparator;
610     if (Level==1)
611         for (size_type Pos0=0; Pos0<size(); Pos0++)
612             operator () (Pos0).Separator_Set(0, Separator[1]);
613 }
614 
615 //---------------------------------------------------------------------------
616 // Quote
Quote_Set(const Ztring & NewQuote)617 void ZtringListList::Quote_Set (const Ztring &NewQuote)
618 {
619     Quote=NewQuote;
620     for (size_type Pos0=0; Pos0<size(); Pos0++)
621         operator () (Pos0).Quote_Set(Quote);
622 }
623 
624 //---------------------------------------------------------------------------
625 // Max
Max_Set(size_type Level,size_type NewMax)626 void ZtringListList::Max_Set (size_type Level, size_type NewMax)
627 {
628     if (Level>1 || NewMax==0)
629         return;
630 
631     Max[Level]=NewMax;
632     if (Level==1)
633         for (size_type Pos0=0; Pos0<size(); Pos0++)
634             operator () (Pos0).Max_Set(0, Max[1]);
635 }
636 
637 //***************************************************************************
638 //
639 //***************************************************************************
640 
641 } //namespace
642