aboutsummaryrefslogtreecommitdiffstats
path: root/src/CacheEntryReader.hpp
blob: 880281617a457915fe9cb9a856b1e2b14709217d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (C) 2019 Joel Rosdahl and other contributors
//
// See doc/AUTHORS.adoc for a complete list of contributors.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the Free Software Foundation, Inc., 51
// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#pragma once

#include "system.hpp"

#include "Checksum.hpp"
#include "Decompressor.hpp"
#include "Util.hpp"

#include <cstdio>
#include <memory>

// This class knows how to read a cache entry with a common header and a
// payload part that is different depending on the cache entry type (result or
// manifest).
class CacheEntryReader
{
public:
  // Constructor.
  //
  // Parameters:
  // - stream: Stream to read header and payload from.
  // - expected_magic: Expected magic bytes (first four bytes of the file).
  // - expected_version: Expected file format version.
  CacheEntryReader(FILE* stream,
                   const uint8_t expected_magic[4],
                   uint8_t expected_version);

  // Dump header information in text format.
  //
  // Parameters:
  // - dump_stream: Stream to write to.
  void dump_header(FILE* dump_stream);

  // Read data into a buffer from the payload.
  //
  // Parameters:
  // - data: Buffer to write data to.
  // - count: How many bytes to write.
  //
  // Throws Error on failure.
  void read(void* data, size_t count);

  // Read an unsigned integer from the payload.
  //
  // Parameters:
  // - value: Variable to write to.
  //
  // Throws Error on failure.
  template<typename T> void read(T& value);

  // Close for reading.
  //
  // This method potentially verifies the end state after reading the cache
  // entry and throws Error if any integrity issues are found.
  void finalize();

  // Get size of the payload,
  uint64_t payload_size() const;

  // Get content magic.
  const uint8_t* magic() const;

  // Get content version.
  uint8_t version() const;

  // Get compression type.
  Compression::Type compression_type() const;

  // Get compression level.
  uint64_t compression_level() const;

  // Get size of the content (header + payload + checksum).
  uint64_t content_size() const;

private:
  std::unique_ptr<Decompressor> m_decompressor;
  Checksum m_checksum;
  uint8_t m_magic[4];
  uint8_t m_version;
  Compression::Type m_compression_type;
  int8_t m_compression_level;
  uint64_t m_content_size;
};

template<typename T>
inline void
CacheEntryReader::read(T& value)
{
  uint8_t buffer[sizeof(T)];
  read(buffer, sizeof(T));
  Util::big_endian_to_int(buffer, value);
}

inline const uint8_t*
CacheEntryReader::magic() const
{
  return m_magic;
}

inline uint8_t
CacheEntryReader::version() const
{
  return m_version;
}

inline Compression::Type
CacheEntryReader::compression_type() const
{
  return m_compression_type;
}

inline uint64_t
CacheEntryReader::compression_level() const
{
  return m_compression_level;
}

inline uint64_t
CacheEntryReader::payload_size() const
{
  return m_content_size - 15 - 8;
}

inline uint64_t
CacheEntryReader::content_size() const
{
  return m_content_size;
}