Imported Upstream version 4.0
[platform/upstream/ccache.git] / src / Hash.hpp
1 // Copyright (C) 2020 Joel Rosdahl and other contributors
2 //
3 // See doc/AUTHORS.adoc for a complete list of contributors.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3 of the License, or (at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 // more details.
14 //
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Software Foundation, Inc., 51
17 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19 #pragma once
20
21 #include "system.hpp"
22
23 #include "Digest.hpp"
24
25 #include "third_party/blake3/blake3.h"
26 #include "third_party/nonstd/string_view.hpp"
27
28 // This class represents a hash state.
29 class Hash
30 {
31 public:
32   enum class HashType { binary, text };
33
34   Hash();
35   Hash(const Hash& other) = default;
36
37   Hash& operator=(const Hash& other) = default;
38
39   // Enable debug logging of the hashed input to a binary and a text file.
40   void enable_debug(nonstd::string_view section_name,
41                     FILE* debug_binary,
42                     FILE* debug_text);
43
44   // Retrieve the digest.
45   Digest digest() const;
46
47   // Hash some data that is unlikely to occur in the input. The idea is twofold:
48   //
49   // - Delimit things like arguments from each other (e.g., so that -I -O2 and
50   //   -I-O2 hash differently).
51   // - Tag different types of hashed information so that it's possible to do
52   //   conditional hashing of information in a safe way (e.g., if we want to
53   //   hash information X if CCACHE_A is set and information Y if CCACHE_B is
54   //   set, there should never be a hash collision risk).
55   Hash& hash_delimiter(nonstd::string_view type);
56
57   // Add bytes to the hash.
58   //
59   // If hash debugging is enabled:
60   //
61   // - If `hash_type` is `HashType::binary`, the buffer content is written in
62   //   hex format to the text input file.
63   // - If `hash_type` is `HashType::text`, the buffer content is written
64   //   verbatim to the text input file.
65   //
66   // In both cases a newline character is added as well.
67   Hash&
68   hash(const void* data, size_t size, HashType hash_type = HashType::text);
69
70   // Add a string to the hash.
71   //
72   // If hash debugging is enabled, the string is written to the text input file
73   // followed by a newline.
74   Hash& hash(nonstd::string_view data);
75
76   // Add an integer to the hash.
77   //
78   // If hash debugging is enabled, the integer is written in text form to the
79   // text input file followed by a newline.
80   Hash& hash(int64_t x);
81
82   // Add contents read from an open file descriptor to the hash.
83   //
84   // If hash debugging is enabled, the data is written verbatim to the text
85   // input file.
86   //
87   // Returns true on success, otherwise false.
88   bool hash_fd(int fd);
89
90   // Add file contents to the hash.
91   //
92   // If hash debugging is enabled, the data is written verbatim to the text
93   // input file.
94   //
95   // Returns true on success, otherwise false.
96   bool hash_file(const std::string& path);
97
98 private:
99   blake3_hasher m_hasher;
100   FILE* m_debug_binary = nullptr;
101   FILE* m_debug_text = nullptr;
102
103   void hash_buffer(nonstd::string_view buffer);
104   void add_debug_text(nonstd::string_view text);
105 };