OSDN Git Service

Avoid an assertion failure when loading settings from winmerge.ini
[winmerge-jp/winmerge-jp.git] / Src / DiffItemList.cpp
1 /**
2  *  @file DiffItemList.cpp
3  *
4  *  @brief Implementation of DiffItemList
5  */ 
6
7 #include "pch.h"
8 #include "DiffItemList.h"
9 #include <cassert>
10 #include "DebugNew.h"
11
12 /**
13  * @brief Constructor
14  */
15 DiffItemList::DiffItemList() : m_pRoot(nullptr)
16 {
17 }
18
19 /**
20  * @brief Destructor
21  */
22 DiffItemList::~DiffItemList()
23 {
24         RemoveAll();
25 }
26
27 /**
28  * @brief Add new diffitem to structured DIFFITEM tree.
29  * @param [in] par Parent item, or `nullptr` if no parent.
30  * @return Pointer to the added item.
31  */
32 DIFFITEM *DiffItemList::AddNewDiff(DIFFITEM *par)
33 {
34         DIFFITEM *p = new DIFFITEM;
35         if (par == nullptr)
36         {
37                 // if there is no `parent`, this item becomes a child of `m_pRoot`
38                 assert(m_pRoot != nullptr);
39                 m_pRoot->AddChildToParent(p);
40         }
41         else
42                 par->AddChildToParent(p);
43
44         return p;
45 }
46
47 /**
48  * @brief Empty structured DIFFITEM tree
49  */
50 void DiffItemList::RemoveAll()
51 {
52         delete m_pRoot;
53         m_pRoot = nullptr;
54 }
55
56 void DiffItemList::InitDiffItemList()
57 {
58         assert(m_pRoot == nullptr);
59         m_pRoot = new DIFFITEM;
60 }
61
62 /**
63  * @brief Get position of first item in structured DIFFITEM tree
64  */
65 DIFFITEM *DiffItemList::GetFirstDiffPosition() const
66 {
67         return GetFirstChildDiffPosition(m_pRoot);
68 }
69
70 /**
71  * @brief Get position of first child item in structured DIFFITEM tree
72  * @param  [in] par Position of parent diff item (maybe `nullptr`)
73  * @return Position of first child item (or `nullptr` if no children)
74  */
75 DIFFITEM *DiffItemList::GetFirstChildDiffPosition(const DIFFITEM *par) const
76 {
77         if (par == nullptr)
78         {
79                 assert(m_pRoot != nullptr);
80                 return m_pRoot->GetFirstChild();
81         }
82         else
83                 return par->GetFirstChild();
84 }
85
86 /**
87  * @brief Get position of next item in structured DIFFITEM tree
88  * @param [in,out] diffpos Position of current item, updated to next item position
89  * @return Diff Item (by reference) in current position
90  */
91 const DIFFITEM &DiffItemList::GetNextDiffPosition(DIFFITEM *&diffpos) const
92 {
93         DIFFITEM *p = diffpos;
94         if (diffpos->HasChildren())
95         {
96                 diffpos = GetFirstChildDiffPosition(diffpos);
97         }
98         else
99         {
100                 DIFFITEM *cur = diffpos;
101                 do
102                 {
103                         diffpos = cur->GetFwdSiblingLink();
104                         cur = cur->GetParentLink();
105                         assert(cur != nullptr);
106                 } while (diffpos == nullptr && cur->HasParent());
107         }
108         return *p;
109 }
110
111 /**
112  * @brief Get position of next item in structured DIFFITEM tree
113  * @param [in,out] diffpos Position of current item, updated to next item position
114  * @return Diff Item (by reference) in current position
115  */
116 DIFFITEM &DiffItemList::GetNextDiffRefPosition(DIFFITEM *&diffpos)
117 {
118         return (DIFFITEM &)GetNextDiffPosition(diffpos);
119 }
120
121 /**
122  * @brief Get position of next sibling item in structured DIFFITEM tree
123  * @param [in,out] diffpos Position of current item, updated to next sibling item position
124  * @return Diff Item (by reference) in current position
125  */
126 const DIFFITEM &DiffItemList::GetNextSiblingDiffPosition(DIFFITEM *&diffpos) const
127 {
128         DIFFITEM *p = diffpos;
129         diffpos = p->GetFwdSiblingLink();
130         assert(p==nullptr || diffpos==nullptr || p->GetParentLink() == diffpos->GetParentLink());
131         assert(p==nullptr || p->HasParent());
132         return *p;
133 }
134
135 /**
136  * @brief Get position of next sibling item in structured DIFFITEM tree
137  * @param [in,out] diffpos Position of current item, updated to next sibling item position
138  * @return Diff Item (by reference) in current position
139  */
140 DIFFITEM &DiffItemList::GetNextSiblingDiffRefPosition(DIFFITEM *&diffpos)
141 {
142         return (DIFFITEM &)GetNextSiblingDiffPosition(diffpos);
143 }
144
145 /**
146  * @brief Alter some bit flags of the diffcode.
147  *
148  * Examples:
149  *  SetDiffStatusCode(pos, DIFFCODE::SAME, DIFFCODE::COMPAREFLAGS)
150  *   changes the comparison result to be the same.
151  * 
152  *  SetDiffStatusCode(pos, DIFFCODE::BOTH, DIFFCODE::SIDEFLAG)
153  *   changes the side status to be both (sides).
154  *
155  * SetDiffStatusCode(pos, DIFFCODE::SAME+DIFFCODE::BOTH, DIFFCODE::COMPAREFLAGS+DIFFCODE::SIDEFLAG);
156  *  changes the comparison result to be the same and the side status to be both
157  */
158 void DiffItemList::SetDiffStatusCode(DIFFITEM *diffpos, unsigned diffcode, unsigned mask)
159 {
160         assert(diffpos != nullptr);
161         DIFFITEM &di = GetDiffRefAt(diffpos);
162         assert( ((~mask) & diffcode) == 0 ); // make sure they only set flags in their mask
163         di.diffcode.diffcode &= (~mask); // remove current data
164         di.diffcode.diffcode |= diffcode; // add new data
165 }
166
167 /**
168  * @brief Update difference counts.
169  */
170 void DiffItemList::SetDiffCounts(DIFFITEM *diffpos, unsigned diffs, unsigned ignored)
171 {
172         assert(diffpos != nullptr);
173         DIFFITEM &di = GetDiffRefAt(diffpos);
174         di.nidiffs = ignored; // see StoreDiffResult() in DirScan.cpp
175         di.nsdiffs = diffs;
176 }
177
178 /**
179  * @brief Returns item's custom (user) flags.
180  * @param [in] diffpos Position of item.
181  * @return Custom flags from item.
182  */
183 unsigned DiffItemList::GetCustomFlags1(DIFFITEM *diffpos) const
184 {
185         assert(diffpos != nullptr);
186         const DIFFITEM &di = GetDiffAt(diffpos);
187         return di.customFlags;
188 }
189
190 /**
191  * @brief Sets item's custom (user) flags.
192  * @param [in] diffpos Position of item.
193  * @param [in] flag Value of flag to set.
194  */
195 void DiffItemList::SetCustomFlags1(DIFFITEM *diffpos, unsigned flag)
196 {
197         assert(diffpos != nullptr);
198         DIFFITEM &di = GetDiffRefAt(diffpos);
199         di.customFlags = flag;
200 }
201
202 void DiffItemList::Swap(int idx1, int idx2)
203 {
204         assert(m_pRoot != nullptr);
205         for (DIFFITEM *p = GetFirstDiffPosition(); p != nullptr; p = p->GetFwdSiblingLink())
206                 p->Swap(idx1, idx2);
207 }