OSDN Git Service

Fix an issue where items with different case are not displayed correctly in the folde...
[winmerge-jp/winmerge-jp.git] / Src / CompareStats.cpp
1 /** 
2  * @file  CompareStats.cpp
3  *
4  * @brief Implementation of CompareStats class.
5  */
6
7 #include "pch.h"
8 #include "CompareStats.h"
9 #include <cassert>
10 #include <cstring>
11 #include <atomic>
12 #include "DiffItem.h"
13
14 /** 
15  * @brief Constructor, initializes critical section.
16  */
17 CompareStats::CompareStats(int nDirs)
18 : m_nTotalItems(0)
19 , m_nComparedItems(0)
20 , m_state(STATE_IDLE)
21 , m_bCompareDone(false)
22 , m_nDirs(nDirs)
23 , m_counts()
24 {
25 }
26
27 /** 
28  * @brief Destructor, deletes critical section.
29  */
30 CompareStats::~CompareStats() = default;
31
32 /** 
33  * @brief Add compared item.
34  * @param [in] code Resultcode to add.
35  */
36 void CompareStats::AddItem(int code)
37 {
38         if (code != -1)
39         {
40                 RESULT res = GetResultFromCode(code);
41                 int index = static_cast<int>(res);
42                 m_counts[index] += 1;
43         }
44         ++m_nComparedItems;
45         assert(m_nComparedItems <= m_nTotalItems);
46 }
47
48 /**
49 * @brief Return item taking most time among current items.
50 */
51 const DIFFITEM *CompareStats::GetCurDiffItem()
52 {
53         int nHitCountMax = 0;
54         const DIFFITEM *cdi = m_rgThreadState.front().m_pDiffItem;
55         std::vector<ThreadState>::iterator it = m_rgThreadState.begin();
56         while (it != m_rgThreadState.end())
57         {
58                 const DIFFITEM *di = it->m_pDiffItem;
59                 if (di != nullptr && (di->diffcode.diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::NOCMP)
60                 {
61                         int nHitCount = it->m_nHitCount++;
62                         if (nHitCountMax < nHitCount)
63                         {
64                                 nHitCountMax = nHitCount;
65                                 cdi = di;
66                         }
67                 }
68                 ++it;
69         }
70         return cdi;
71 }
72
73 /** 
74  * @brief Reset comparestats.
75  * Use this function to reset stats before new compare.
76  */
77 void CompareStats::Reset()
78 {
79         std::fill(std::begin(m_counts), std::end(m_counts), 0);
80         SetCompareState(STATE_IDLE);
81         m_nTotalItems = 0;
82         m_nComparedItems = 0;
83         m_bCompareDone = false;
84 }
85
86 /** 
87  * @brief Change compare state.
88  * @param [in] state New compare state.
89  */
90 void CompareStats::SetCompareState(CompareStats::CMP_STATE state)
91 {
92         // New compare starting so reset ready status
93         if (state == STATE_START)
94                 m_bCompareDone = false;
95         // Compare ready
96         if (state == STATE_IDLE && m_state == STATE_COMPARE)
97                 m_bCompareDone = true;
98
99         m_state = state;
100 }
101
102 /** 
103  * @brief Convert diffcode to compare-result.
104  * @param [in] diffcode DIFFITEM.diffcode to convert.
105  * @return Compare result.
106  */
107 CompareStats::RESULT CompareStats::GetResultFromCode(unsigned diffcode) const
108 {
109         DIFFCODE di(diffcode);
110         
111         // Test first for skipped so we pick all skipped items as such 
112         if (di.isResultFiltered())
113         {
114                 // skipped
115                 return di.isDirectory() ? RESULT_DIRSKIP : RESULT_SKIP;
116         }
117         else if (di.isSideFirstOnly())
118         {
119                 // left-only
120                 return di.isDirectory() ? RESULT_LDIRUNIQUE : RESULT_LUNIQUE;
121         }
122         else if (di.isSideSecondOnly())
123         {
124                 // right-only
125                 if (di.isDirectory())
126                         return (m_nDirs < 3) ? RESULT_RDIRUNIQUE : RESULT_MDIRUNIQUE;
127                 else
128                         return (m_nDirs < 3) ? RESULT_RUNIQUE : RESULT_MUNIQUE;
129         }
130         else if (di.isSideThirdOnly())
131         {
132                 // right-only
133                 return di.isDirectory() ? RESULT_RDIRUNIQUE : RESULT_RUNIQUE;
134         }
135         else if (m_nDirs > 2 && !di.exists(0) && di.exists(1) && di.exists(2))
136                 return di.isDirectory() ? RESULT_LDIRMISSING : RESULT_LMISSING;
137         else if (m_nDirs > 2 && di.exists(0) && !di.exists(1) && di.exists(2))
138                 return di.isDirectory() ? RESULT_MDIRMISSING : RESULT_MMISSING;
139         else if (m_nDirs > 2 && di.exists(0) && di.exists(1) && !di.exists(2))
140                 return di.isDirectory() ? RESULT_RDIRMISSING : RESULT_RMISSING;
141         else if (di.isResultError())
142         {
143                 // could be directory error ?
144                 return RESULT_ERROR;
145         }
146         // Now we know it was on both sides & compared!
147         else if (di.isResultSame())
148         {
149                 // same
150                 if (di.isDirectory())
151                 {
152                         return RESULT_DIRSAME;
153                 }
154                 else
155                 {
156                         return di.isBin() ? RESULT_BINSAME : RESULT_SAME;
157                 }
158         }
159         else
160         {
161                 if (di.isDirectory())
162                 {
163                         return RESULT_DIRDIFF;
164                 }
165                 else
166                 {
167                         // presumably it is different
168                         return di.isBin() ? RESULT_BINDIFF : RESULT_DIFF;
169                 }
170         }
171 }
172
173 void CompareStats::Swap(int idx1, int idx2)
174 {
175         idx2 = m_nDirs < 3 ? idx2 + 1 : idx2;
176         m_counts[RESULT_LUNIQUE     + idx2] = m_counts[RESULT_LUNIQUE     + idx1].exchange(m_counts[RESULT_LUNIQUE     + idx2]);
177         m_counts[RESULT_LMISSING    + idx2] = m_counts[RESULT_LMISSING    + idx1].exchange(m_counts[RESULT_LMISSING    + idx2]);
178         m_counts[RESULT_LDIRUNIQUE  + idx2] = m_counts[RESULT_LDIRUNIQUE  + idx1].exchange(m_counts[RESULT_LDIRUNIQUE  + idx2]);
179         m_counts[RESULT_LDIRMISSING + idx2] = m_counts[RESULT_LDIRMISSING + idx1].exchange(m_counts[RESULT_LDIRMISSING + idx2]);
180 }