-
Notifications
You must be signed in to change notification settings - Fork 0
/
blob.cpp
189 lines (166 loc) · 4.57 KB
/
blob.cpp
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/* B L O B . C P P
* BRL-CAD
*
* Published in 2020 by the United States Government.
* This work is in the public domain.
*
*/
/** @file blob.cpp
*
* Logic for handling git blobs
*
*/
#include "repowork.h"
typedef int (*blobcmd_t)(git_blob_data *, std::ifstream &);
blobcmd_t
blob_find_cmd(std::string &line, std::map<std::string, blobcmd_t> &cmdmap)
{
blobcmd_t cc = NULL;
std::map<std::string, blobcmd_t>::iterator c_it;
for (c_it = cmdmap.begin(); c_it != cmdmap.end(); c_it++) {
if (!ficmp(line, c_it->first)) {
cc = c_it->second;
break;
}
}
return cc;
}
int
blob_parse_blob(git_blob_data *cd, std::ifstream &infile)
{
/* No other information on line - just consume it and continue */
std::string line;
std::getline(infile, line);
return 0;
}
int
blob_parse_data(git_blob_data *cd, std::ifstream &infile)
{
std::string line;
std::getline(infile, line);
line.erase(0, 5); // Remove "data " prefix
cd->length = std::stoi(line);
cd->offset = infile.tellg();
#if 0
// Detect binary blobs (in case we ever want to try post-processing
// of text blobs
int cc = 0;
char c;
bool bfile = false;
while (!infile.eof() && infile >> std::noskipws >> c && cc < 500) {
if (c == '\0') {
bfile = true;
break;
}
cc++;
}
if (bfile) {
std::cout << "Binary blob\n";
}
infile.clear();
#endif
long offset = cd->offset + cd->length;
infile.seekg(offset);
return 0;
}
int
blob_parse_mark(git_blob_data *cd, std::ifstream &infile)
{
std::string line;
std::getline(infile, line);
//std::cout << "mark line: " << line << "\n";
line.erase(0, 5); // Remove "mark " prefix
//std::cout << "mark line: " << line << "\n";
if (line.c_str()[0] != ':') {
std::cerr << "Mark without \":\" character??: " << line << "\n";
return -1;
}
line.erase(0, 1); // Remove ":" prefix
cd->id.mark = cd->s->next_mark(std::stol(line));
//std::cout << "Mark id :" << line << " -> " << cd->id.mark << "\n";
return 0;
}
int
blob_parse_original_oid(git_blob_data *cd, std::ifstream &infile)
{
std::string line;
std::getline(infile, line);
line.erase(0, 13); // Remove "original-oid " prefix
cd->id.sha1 = line;
return 0;
}
int
parse_blob(git_fi_data *fi_data, std::ifstream &infile)
{
//std::cout << "Found command: blob\n";
git_blob_data gbd;
gbd.s = fi_data;
// Tell the blob where it will be in the vector.
gbd.id.index = fi_data->blobs.size();
std::map<std::string, blobcmd_t> cmdmap;
cmdmap[std::string("blob")] = blob_parse_blob;
cmdmap[std::string("data")] = blob_parse_data;
cmdmap[std::string("mark")] = blob_parse_mark;
cmdmap[std::string("original-oid")] = blob_parse_original_oid;
std::string line;
size_t offset = infile.tellg();
int blob_done = 0;
while (!blob_done && std::getline(infile, line)) {
blobcmd_t cc = blob_find_cmd(line, cmdmap);
// If we found a command, process it. Otherwise, we are done
// with the blob and need to clean up.
if (cc) {
//std::cout << "blob line: " << line << "\n";
infile.seekg(offset);
(*cc)(&gbd, infile);
offset = infile.tellg();
} else {
// Whatever was on that line, it's not a blob input.
// Reset input to allow the parent routine to deal with
// it, and return.
infile.seekg(offset);
blob_done = 1;
}
}
gbd.id.mark = fi_data->next_mark(gbd.id.mark);
fi_data->mark_to_index[gbd.id.mark] = gbd.id.index;
// If we have an original-oid sha1, associate it with the mark
if (gbd.id.sha1.length() == 40) {
fi_data->sha1_to_mark[gbd.id.sha1] = gbd.id.mark;
fi_data->mark_to_sha1[gbd.id.mark] = gbd.id.sha1;
}
// Add the blob to the data
fi_data->blobs.push_back(gbd);
return 0;
}
int
write_blob(std::ofstream &outfile, git_blob_data *b, std::ifstream &infile)
{
if (!infile.good()) {
return -1;
}
// Header
outfile << "blob\n";
outfile << "mark :" << b->id.mark << "\n";
if (b->id.sha1.length()) {
outfile << "original-oid " << b->id.sha1 << "\n";
}
outfile << "data " << b->length << "\n";
// Contents
/* TODO - probably don't really need to read this into memory... */
char *buffer = new char [b->length];
infile.seekg(b->offset);
infile.read(buffer, b->length);
outfile.write(buffer, b->length);
delete[] buffer;
outfile << "\n";
return 0;
}
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8