Make CGitHash "operator const unsigned char*" explicit
[TortoiseGit.git] / src / Git / GitHash.h
blob693af17e87f8adc7c7b2365b7466840763d1e5ac
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2018 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
21 #define GIT_HASH_SIZE 20
23 /* also see gitdll.c */
24 static_assert(GIT_HASH_SIZE == GIT_OID_RAWSZ, "hash size needs to be the same as in libgit2");
25 static_assert(sizeof(git_oid::id) == GIT_HASH_SIZE, "hash size needs to be the same as in libgit2");
27 #define GIT_REV_ZERO_C "0000000000000000000000000000000000000000"
28 #define GIT_REV_ZERO _T(GIT_REV_ZERO_C)
30 class CGitHash;
31 template<>
32 struct std::hash<CGitHash>;
34 class CGitHash
36 private:
37 unsigned char m_hash[GIT_HASH_SIZE];
38 public:
39 CGitHash()
41 memset(m_hash,0, GIT_HASH_SIZE);
43 CGitHash(const unsigned char* p)
45 memcpy(m_hash,p,GIT_HASH_SIZE);
47 CGitHash(const git_oid* oid)
49 git_oid_cpy((git_oid*)m_hash, oid);
51 CGitHash(const git_oid oid)
53 git_oid_cpy((git_oid*)m_hash, &oid);
55 CGitHash& operator = (const CString& str)
57 CGitHash hash(str);
58 *this = hash;
59 return *this;
61 CGitHash& operator = (const unsigned char *p)
63 memcpy(m_hash, p, GIT_HASH_SIZE);
64 return *this;
66 CGitHash& operator = (const git_oid* oid)
68 git_oid_cpy((git_oid*)m_hash, oid);
69 return *this;
71 CGitHash& operator = (const git_oid oid)
73 git_oid_cpy((git_oid*)m_hash, &oid);
74 return *this;
76 CGitHash(const CString &str)
78 if (!IsValidSHA1(str))
80 #ifdef ASSERT
81 //ASSERT(FALSE); // TODO problematic
82 #endif
83 memset(m_hash, 0, GIT_HASH_SIZE);
84 return;
87 for (int i = 0; i < GIT_HASH_SIZE; ++i)
89 unsigned char a;
90 a=0;
91 for (int j = 2 * i; j <= 2 * i + 1; ++j)
93 a =a<<4;
95 TCHAR ch = str[j];
96 if (ch >= L'0' && ch <= L'9')
97 a |= (ch - L'0') & 0xF;
98 else if (ch >=L'A' && ch <= L'F')
99 a |= ((ch - L'A') & 0xF) + 10 ;
100 else if (ch >=L'a' && ch <= L'f')
101 a |= ((ch - L'a') & 0xF) + 10;
104 m_hash[i]=a;
108 void ConvertFromStrA(const char *str)
110 for (int i = 0; i < GIT_HASH_SIZE; ++i)
112 unsigned char a;
113 a=0;
114 for (int j = 2 * i; j <= 2 * i + 1; ++j)
116 a =a<<4;
118 char ch = str[j];
119 if (ch >= '0' && ch <= '9')
120 a |= (ch - '0') & 0xF;
121 else if (ch >= 'A' && ch <= 'F')
122 a |= ((ch - 'A') & 0xF) + 10 ;
123 else if (ch >= 'a' && ch <= 'f')
124 a |= ((ch - 'a') & 0xF) + 10;
127 m_hash[i]=a;
130 void Empty()
132 memset(m_hash,0, GIT_HASH_SIZE);
134 bool IsEmpty() const
136 for (int i = 0; i < GIT_HASH_SIZE; ++i)
138 if(m_hash[i] != 0)
139 return false;
141 return true;
144 CString ToString() const
146 CString str;
147 str.Preallocate(GIT_HASH_SIZE * 2);
148 for (int i = 0; i < GIT_HASH_SIZE; ++i)
149 str.AppendFormat(L"%02x", m_hash[i]);
150 return str;
153 operator const git_oid*() const
155 return (const git_oid*)m_hash;
158 explicit operator const unsigned char*() const
160 return m_hash;
163 bool operator == (const CGitHash &hash) const
165 return memcmp(m_hash,hash.m_hash,GIT_HASH_SIZE) == 0;
168 static friend bool operator<(const CGitHash& left, const CGitHash& right)
170 return memcmp(left.m_hash,right.m_hash,GIT_HASH_SIZE) < 0;
173 static friend bool operator>(const CGitHash& left, const CGitHash& right)
175 return memcmp(left.m_hash, right.m_hash, GIT_HASH_SIZE) > 0;
178 static friend bool operator != (const CGitHash& left, const CGitHash& right)
180 return memcmp(left.m_hash, right.m_hash, GIT_HASH_SIZE) != 0;
183 bool MatchesPrefix(const CGitHash& hash, const CString& hashString, size_t prefixLen) const
185 if (memcmp(m_hash, hash.m_hash, prefixLen >> 1))
186 return false;
187 return prefixLen == 2 * GIT_HASH_SIZE || wcsncmp(ToString(), hashString, prefixLen) == 0;
190 static bool IsValidSHA1(const CString &possibleSHA1)
192 if (possibleSHA1.GetLength() != 2 * GIT_HASH_SIZE)
193 return false;
194 for (int i = 0; i < possibleSHA1.GetLength(); ++i)
196 if (!((possibleSHA1[i] >= '0' && possibleSHA1[i] <= '9') || (possibleSHA1[i] >= 'a' && possibleSHA1[i] <= 'f') || (possibleSHA1[i] >= 'A' && possibleSHA1[i] <= 'F')))
197 return false;
199 return true;
202 friend struct std::hash<CGitHash>;
205 namespace std
207 template <>
208 struct hash<CGitHash>
210 std::size_t operator()(const CGitHash& k) const
212 return *(size_t*)k.m_hash;