OSDN Git Service

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