-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakeHeader.cpp
More file actions
132 lines (109 loc) · 3.96 KB
/
makeHeader.cpp
File metadata and controls
132 lines (109 loc) · 3.96 KB
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
//----------------------------------------------------------------------
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <cstdlib>
#include <tuple>
#include <stdexcept>
#include <filesystem>
//----------------------------------------------------------------------
class success_exception : public std::runtime_error {
public:
success_exception(const std::string& message) : std::runtime_error(message) {}
};
//----------------------------------------------------------------------
std::vector<unsigned char> readBytes(const std::string& filename) {
std::vector<unsigned char> bytes;
// Open the file
std::ifstream file(filename, std::ios::binary);
if (!file) {
throw std::runtime_error("Failed to open file");
}
// Get the file size
file.seekg(0, std::ios::end);
std::streampos fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// Check for errors
if (fileSize <= 0) {
throw std::runtime_error("Failed to get file size");
}
// Allocate space
bytes.resize(fileSize);
// Read the file
file.read(reinterpret_cast<char*>(bytes.data()), fileSize);
return bytes;
}
//----------------------------------------------------------------------
void writeHeader(const std::string& name, const std::string& filename, const std::vector<unsigned char>& bytes) {
// Open the file
std::ofstream file(filename, std::ios::trunc);
if (!file) {
throw std::runtime_error("Failed to open file");
}
// Write the header
file << "#pragma once\n";
file << "#include <cstddef>\n";
// Write the data
file << "const unsigned char " << name << "_data[] = {\n";
for (size_t i = 0; i < bytes.size(); ++i) {
file << "0x" << std::hex << static_cast<int>(bytes[i]);
if (i != bytes.size() - 1) {
file << ",";
}
if ( (i + 1) % 16 == 0) {
file << "\n";
}
}
file << "\n};\n";
// Write the size
file << std::dec;
file << "const size_t " << name << "_size = " << bytes.size() << ";\n";
}
//----------------------------------------------------------------------
void checkTimestamps(const std::string& input, const std::string& output) {
// If either file doesn't exist, we need to update
if (!std::filesystem::exists(input) || !std::filesystem::exists(output)) {
return;
}
// If the input file is newer than the output file, we need to update
const auto inputTime = std::filesystem::last_write_time(input);
const auto outputTime = std::filesystem::last_write_time(output);
if (inputTime > outputTime) {
return;
}
// If the output file is newer than the input file, we don't need to update
throw success_exception("Skipping " + output + " because it is up to date");
}
//----------------------------------------------------------------------
std::tuple<std::string, std::string, std::string> processArgs(int argc, char* argv[]) {
// Check for the right number of arguments
if (argc != 4) {
throw std::runtime_error("Usage: makeHeader <name> <input> <output>");
}
// Return the arguments
return {argv[1], argv[2], argv[3]};
}
//----------------------------------------------------------------------
int main(int argc, char* argv[]) {
try {
// Process the arguments
const auto [name, input, output] = processArgs(argc, argv);
// Check if we need to update
checkTimestamps(input, output);
// Read the bytes
const auto bytes = readBytes(input);
// Write the header
writeHeader(name, output, bytes);
throw success_exception("Updated " + std::to_string(bytes.size()) + " bytes, " + output);
}
catch(const success_exception& e) {
std::cout << e.what() << '\n';
return EXIT_SUCCESS;
}
catch(const std::exception& e) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}