OSDN Git Service

Allow NUL and \\.\NUL in paths specified as command line arguments (#2056)
[winmerge-jp/winmerge-jp.git] / Src / LineFiltersList.cpp
1 /** 
2  * @file  LineFiltersList.cpp
3  *
4  * @brief Implementation for LineFiltersList class.
5  */
6
7 #include "pch.h"
8 #include "LineFiltersList.h"
9 #include "FilterList.h"
10 #include <vector>
11 #include <cassert>
12 #include "OptionsMgr.h"
13 #include "UnicodeString.h"
14
15 using std::vector;
16
17 /** @brief Registry key for saving linefilters. */
18 static const tchar_t LineFiltersRegPath[] = _T("LineFilters");
19
20 /**
21  * @brief Default constructor.
22  */
23 LineFiltersList::LineFiltersList()
24 : m_pOptionsMgr(nullptr)
25 {
26 }
27
28 /**
29  * @brief Destructor, empties the list.
30  */
31 LineFiltersList::~LineFiltersList() = default;
32
33 /**
34  * @brief Add new filter to the list.
35  * @param [in] filter Filter string to add.
36  * @param [in] enabled Is filter enabled?
37  */
38 void LineFiltersList::AddFilter(const String& filter, bool enabled)
39 {
40         auto item = std::make_shared<LineFilterItem>(LineFilterItem());
41         item->enabled = enabled;
42         item->filterStr = filter;
43         m_items.push_back(item);
44 }
45
46 /**
47  * @brief Return filter from given index.
48  * @param [in] ind Index of filter.
49  * @return Filter item from the index. If the index is beyond table limit,
50  *  return the last item in the list.
51  */
52 const LineFilterItem & LineFiltersList::GetAt(size_t ind) const
53 {
54         if (ind < m_items.size())
55                 return *m_items[ind];
56         else
57                 return *m_items.back();
58 }
59
60 /**
61  * @brief Clone filter list from another list.
62  * This function clones filter list from another list. Current items in the
63  * list are removed and new items added from the given list.
64  * @param [in] list List to clone.
65  */
66 void LineFiltersList::CloneFrom(const LineFiltersList *list)
67 {
68         Empty();
69         size_t count = list->GetCount();
70
71         for (size_t i = 0; i < count; i++)
72         {
73                 const LineFilterItem &item = list->GetAt(i);
74                 AddFilter(item.filterStr, item.enabled);
75         }
76 }
77
78 /**
79  * @brief Compare filter lists.
80  * @param [in] list List to compare.
81  * @return true if lists are identical, false otherwise.
82  */
83 bool LineFiltersList::Compare(const LineFiltersList *list) const
84 {
85         if (list->GetCount() != GetCount())
86                 return false;
87
88         for (size_t i = 0; i < GetCount(); i++)
89         {
90                 const LineFilterItem &item1 = list->GetAt(i);
91                 const LineFilterItem &item2 = GetAt(i);
92
93                 if (item1.enabled != item2.enabled)
94                         return false;
95
96                 if (item1.filterStr != item2.filterStr)
97                         return false;
98         }
99         return true;
100 }
101
102 /**
103  * @brief Read filter list from the options system.
104  * @param [in] pOptionsMgr Pointer to options system.
105  */
106 void LineFiltersList::Initialize(COptionsMgr *pOptionsMgr)
107 {
108         assert(pOptionsMgr != nullptr);
109         String valuename(LineFiltersRegPath);
110
111         m_pOptionsMgr = pOptionsMgr;
112
113         Empty();
114
115         valuename += _T("/Values");
116         m_pOptionsMgr->InitOption(valuename, 0);
117         size_t count = m_pOptionsMgr->GetInt(valuename);
118
119         for (unsigned i = 0; i < count; i++)
120         {
121                 String name = strutils::format(_T("%s/Filter%02u"), LineFiltersRegPath, i);
122                 m_pOptionsMgr->InitOption(name, _T(""));
123                 String filter = m_pOptionsMgr->GetString(name);
124
125                 name = strutils::format(_T("%s/Enabled%02u"), LineFiltersRegPath, i);
126                 m_pOptionsMgr->InitOption(name, (int)true);
127                 int enabled = m_pOptionsMgr->GetInt(name);
128                 bool bEnabled = enabled ? true : false;
129
130                 AddFilter(filter, bEnabled);
131         }
132 }
133
134 /**
135  * @brief Save linefilters to options system.
136  */
137 void LineFiltersList::SaveFilters()
138 {
139         assert(m_pOptionsMgr != nullptr);
140         String valuename(LineFiltersRegPath);
141
142         size_t count = m_items.size();
143         valuename += _T("/Values");
144         m_pOptionsMgr->SaveOption(valuename, static_cast<int>(count));
145
146         for (size_t i = 0; i < count; i++)
147         {
148                 const LineFilterItemPtr& item = m_items[i];
149
150                 String name = strutils::format(_T("%s/Filter%02u"), LineFiltersRegPath, i);
151                 m_pOptionsMgr->InitOption(name, _T(""));
152                 m_pOptionsMgr->SaveOption(name, item->filterStr);
153
154                 name = strutils::format(_T("%s/Enabled%02u"), LineFiltersRegPath, i);
155                 m_pOptionsMgr->InitOption(name, 0);
156                 m_pOptionsMgr->SaveOption(name, (int)item->enabled);
157         }
158
159         // Remove options we don't need anymore
160         // We could have earlier 10 pcs but now we only need 5
161         String filter = strutils::format(_T("%s/Filter%02u"), LineFiltersRegPath, count);
162         int retval1 = m_pOptionsMgr->RemoveOption(filter);
163
164         filter = strutils::format(_T("%s/Enabled%02u"), LineFiltersRegPath, count);
165         int retval2 = m_pOptionsMgr->RemoveOption(filter);
166         
167         while (retval1 == COption::OPT_OK || retval2 == COption::OPT_OK)
168         {
169                 ++count;
170                 filter = strutils::format(_T("%s/Filter%02u"), LineFiltersRegPath, count);
171                 retval1 = m_pOptionsMgr->RemoveOption(filter);
172                 filter = strutils::format(_T("%s/Enabled%02u"), LineFiltersRegPath, count);
173                 retval2 = m_pOptionsMgr->RemoveOption(filter);
174         }
175 }
176
177 std::shared_ptr<FilterList> LineFiltersList::MakeFilterList(bool throwIfInvalid)
178 {
179         int i = 0;
180         std::shared_ptr<FilterList> plist(new FilterList);
181         for (auto& item : m_items)
182         {
183                 if (item->enabled && !item->filterStr.empty())
184                 {
185                         try
186                         {
187                                 plist->AddRegExp(ucr::toUTF8(item->filterStr), false, throwIfInvalid);
188                         }
189                         catch (const std::runtime_error& e)
190                         {
191                                 if (throwIfInvalid)
192                                 {
193                                         plist.reset();
194                                         const String msg = strutils::format(_T("#%d: %S"), i + 1, e.what());
195                                         throw std::runtime_error(ucr::toUTF8(msg).c_str());
196                                 }
197                         }
198                 }
199                 i++;
200         }
201         return plist;
202 }