Classes | Typedefs | Functions
cnpy Namespace Reference

Classes

struct  NpyArray
 

Typedefs

using npz_t = std::map< std::string, NpyArray >
 

Functions

char BigEndianTest ()
 
char map_type (const std::type_info &t)
 
template<typename T >
std::vector< char > create_npy_header (const std::vector< size_t > &shape)
 
void parse_npy_header (FILE *fp, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order)
 
void parse_npy_header (unsigned char *buffer, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order)
 
void parse_zip_footer (FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
 
npz_t npz_load (std::string fname)
 
NpyArray npz_load (std::string fname, std::string varname)
 
NpyArray npy_load (std::string fname)
 
template<typename T >
std::vector< char > & operator+= (std::vector< char > &lhs, const T rhs)
 
template<>
std::vector< char > & operator+= (std::vector< char > &lhs, const std::string rhs)
 
template<>
std::vector< char > & operator+= (std::vector< char > &lhs, const char *rhs)
 
template<typename T >
void npy_save (std::string fname, const T *data, const std::vector< size_t > shape, std::string mode="w")
 
template<typename T >
void npz_save (std::string zipname, std::string fname, const T *data, const std::vector< size_t > &shape, std::string mode="w")
 
template<typename T >
void npy_save (std::string fname, const std::vector< T > data, std::string mode="w")
 
template<typename T >
void npz_save (std::string zipname, std::string fname, const std::vector< T > data, std::string mode="w")
 

Typedef Documentation

using cnpy::npz_t = typedef std::map<std::string, NpyArray>

Definition at line 63 of file cnpy.h.

Function Documentation

char cnpy::BigEndianTest ( )

Definition at line 16 of file cnpy.cxx.

16  {
17  int x = 1;
18  return (((char *)&x)[0]) ? '<' : '>';
19 }
list x
Definition: train.py:276
template<typename T >
std::vector< char > cnpy::create_npy_header ( const std::vector< size_t > &  shape)

Definition at line 240 of file cnpy.h.

240  {
241 
242  std::vector<char> dict;
243  dict += "{'descr': '";
244  dict += BigEndianTest();
245  dict += map_type(typeid(T));
246  dict += std::to_string(sizeof(T));
247  dict += "', 'fortran_order': False, 'shape': (";
248  dict += std::to_string(shape[0]);
249  for(size_t i = 1;i < shape.size();i++) {
250  dict += ", ";
251  dict += std::to_string(shape[i]);
252  }
253  if(shape.size() == 1) dict += ",";
254  dict += "), }";
255  //pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to end with \n
256  int remainder = 16 - (10 + dict.size()) % 16;
257  dict.insert(dict.end(),remainder,' ');
258  dict.back() = '\n';
259 
260  std::vector<char> header;
261  header += (char) 0x93;
262  header += "NUMPY";
263  header += (char) 0x01; //major version of numpy format
264  header += (char) 0x00; //minor version of numpy format
265  header += (uint16_t) dict.size();
266  header.insert(header.end(),dict.begin(),dict.end());
267 
268  return header;
269  }
char map_type(const std::type_info &t)
Definition: cnpy.cxx:21
unsigned short uint16_t
Definition: stdint.h:125
char BigEndianTest()
Definition: cnpy.cxx:16
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
char cnpy::map_type ( const std::type_info &  t)

Definition at line 21 of file cnpy.cxx.

22 {
23  if(t == typeid(float) ) return 'f';
24  if(t == typeid(double) ) return 'f';
25  if(t == typeid(long double) ) return 'f';
26 
27  if(t == typeid(int) ) return 'i';
28  if(t == typeid(char) ) return 'i';
29  if(t == typeid(short) ) return 'i';
30  if(t == typeid(long) ) return 'i';
31  if(t == typeid(long long) ) return 'i';
32 
33  if(t == typeid(unsigned char) ) return 'u';
34  if(t == typeid(unsigned short) ) return 'u';
35  if(t == typeid(unsigned long) ) return 'u';
36  if(t == typeid(unsigned long long) ) return 'u';
37  if(t == typeid(unsigned int) ) return 'u';
38 
39  if(t == typeid(bool) ) return 'b';
40 
41  if(t == typeid(std::complex<float>) ) return 'c';
42  if(t == typeid(std::complex<double>) ) return 'c';
43  if(t == typeid(std::complex<long double>) ) return 'c';
44 
45  else return '?';
46 }
cnpy::NpyArray cnpy::npy_load ( std::string  fname)

Definition at line 343 of file cnpy.cxx.

343  {
344 
345  FILE* fp = fopen(fname.c_str(), "rb");
346 
347  if(!fp) throw std::runtime_error("npy_load: Unable to open file "+fname);
348 
349  NpyArray arr = load_the_npy_file(fp);
350 
351  fclose(fp);
352  return arr;
353 }
cnpy::NpyArray load_the_npy_file(FILE *fp)
Definition: cnpy.cxx:195
template<typename T >
void cnpy::npy_save ( std::string  fname,
const T *  data,
const std::vector< size_t >  shape,
std::string  mode = "w" 
)

Definition at line 88 of file cnpy.h.

88  {
89  FILE* fp = NULL;
90  std::vector<size_t> true_data_shape; //if appending, the shape of existing + new data
91 
92  if(mode == "a") fp = fopen(fname.c_str(),"r+b");
93 
94  if(fp) {
95  //file exists. we need to append to it. read the header, modify the array size
96  size_t word_size;
97  bool fortran_order;
98  parse_npy_header(fp,word_size,true_data_shape,fortran_order);
99  if (fortran_order) {
100  throw std::runtime_error("npy_save: unexpected fortran order");
101  }
102 
103  if(word_size != sizeof(T)) {
104  std::cerr<<"libnpy error: "<<fname<<" has word size "<<word_size<<" but npy_save appending data sized "<<sizeof(T)<<"\n";
105  if( word_size != sizeof(T) ) {
106  throw std::runtime_error("npy_save: illegal word size");
107  }
108  }
109  if(true_data_shape.size() != shape.size()) {
110  std::cerr<<"libnpy error: npy_save attempting to append misdimensioned data to "<<fname<<"\n";
111  throw std::runtime_error("npy_save: misdimensioned data");
112  // original assert() had a bug, I think.
113  }
114 
115  for(size_t i = 1; i < shape.size(); i++) {
116  if(shape[i] != true_data_shape[i]) {
117  std::cerr<<"libnpy error: npy_save attempting to append misshaped data to "<<fname<<"\n";
118  throw std::runtime_error("npy_save: misdimensioned data");
119  }
120  }
121  true_data_shape[0] += shape[0];
122  }
123  else {
124  fp = fopen(fname.c_str(),"wb");
125  true_data_shape = shape;
126  }
127 
128  std::vector<char> header = create_npy_header<T>(true_data_shape);
129  size_t nels = std::accumulate(shape.begin(),shape.end(),1,std::multiplies<size_t>());
130 
131  fseek(fp,0,SEEK_SET);
132  fwrite(&header[0],sizeof(char),header.size(),fp);
133  fseek(fp,0,SEEK_END);
134  fwrite(data,sizeof(T),nels,fp);
135  fclose(fp);
136  }
basic_data data
Definition: format.h:764
void parse_npy_header(unsigned char *buffer, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order)
Definition: cnpy.cxx:63
template<typename T >
void cnpy::npy_save ( std::string  fname,
const std::vector< T >  data,
std::string  mode = "w" 
)

Definition at line 228 of file cnpy.h.

228  {
229  std::vector<size_t> shape;
230  shape.push_back(data.size());
231  npy_save(fname, &data[0], shape, mode);
232  }
void npy_save(std::string fname, const std::vector< T > data, std::string mode="w")
Definition: cnpy.h:228
cnpy::npz_t cnpy::npz_load ( std::string  fname)

Definition at line 246 of file cnpy.cxx.

246  {
247  FILE* fp = fopen(fname.c_str(),"rb");
248 
249  if(!fp) {
250  throw std::runtime_error("npz_load: Error! Unable to open file "+fname+"!");
251  }
252 
253  cnpy::npz_t arrays;
254 
255  while(1) {
256  std::vector<char> local_header(30);
257  size_t headerres = fread(&local_header[0],sizeof(char),30,fp);
258  if(headerres != 30)
259  throw std::runtime_error("npz_load: failed fread");
260 
261  //if we've reached the global header, stop reading
262  if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
263 
264  //read in the variable name
265  uint16_t name_len = *(uint16_t*) &local_header[26];
266  std::string varname(name_len,' ');
267  size_t vname_res = fread(&varname[0],sizeof(char),name_len,fp);
268  if(vname_res != name_len)
269  throw std::runtime_error("npz_load: failed fread");
270 
271  //erase the lagging .npy
272  varname.erase(varname.end()-4,varname.end());
273 
274  //read in the extra field
275  uint16_t extra_field_len = *(uint16_t*) &local_header[28];
276  if(extra_field_len > 0) {
277  std::vector<char> buff(extra_field_len);
278  size_t efield_res = fread(&buff[0],sizeof(char),extra_field_len,fp);
279  if(efield_res != extra_field_len)
280  throw std::runtime_error("npz_load: failed fread");
281  }
282 
283  uint16_t compr_method = *reinterpret_cast<uint16_t*>(&local_header[0]+8);
284  uint32_t compr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+18);
285  uint32_t uncompr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+22);
286 
287  if(compr_method == 0) {arrays[varname] = load_the_npy_file(fp);}
288  else {arrays[varname] = load_the_npz_array(fp,compr_bytes,uncompr_bytes);}
289  }
290 
291  fclose(fp);
292  return arrays;
293 }
std::string string
Definition: nybbler.cc:12
cnpy::NpyArray load_the_npy_file(FILE *fp)
Definition: cnpy.cxx:195
cnpy::NpyArray load_the_npz_array(FILE *fp, uint32_t compr_bytes, uint32_t uncompr_bytes)
Definition: cnpy.cxx:208
unsigned short uint16_t
Definition: stdint.h:125
std::map< std::string, NpyArray > npz_t
Definition: cnpy.h:63
unsigned int uint32_t
Definition: stdint.h:126
cnpy::NpyArray cnpy::npz_load ( std::string  fname,
std::string  varname 
)

Definition at line 295 of file cnpy.cxx.

295  {
296  FILE* fp = fopen(fname.c_str(),"rb");
297 
298  if(!fp) throw std::runtime_error("npz_load: Unable to open file "+fname);
299 
300  while(1) {
301  std::vector<char> local_header(30);
302  size_t header_res = fread(&local_header[0],sizeof(char),30,fp);
303  if(header_res != 30)
304  throw std::runtime_error("npz_load: failed fread");
305 
306  //if we've reached the global header, stop reading
307  if(local_header[2] != 0x03 || local_header[3] != 0x04) break;
308 
309  //read in the variable name
310  uint16_t name_len = *(uint16_t*) &local_header[26];
311  std::string vname(name_len,' ');
312  size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp);
313  if(vname_res != name_len)
314  throw std::runtime_error("npz_load: failed fread");
315  vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy
316 
317  //read in the extra field
318  uint16_t extra_field_len = *(uint16_t*) &local_header[28];
319  fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field
320 
321  uint16_t compr_method = *reinterpret_cast<uint16_t*>(&local_header[0]+8);
322  uint32_t compr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+18);
323  uint32_t uncompr_bytes = *reinterpret_cast<uint32_t*>(&local_header[0]+22);
324 
325  if(vname == varname) {
326  NpyArray array = (compr_method == 0) ? load_the_npy_file(fp) : load_the_npz_array(fp,compr_bytes,uncompr_bytes);
327  fclose(fp);
328  return array;
329  }
330  else {
331  //skip past the data
332  uint32_t size = *(uint32_t*) &local_header[22];
333  fseek(fp,size,SEEK_CUR);
334  }
335  }
336 
337  fclose(fp);
338 
339  //if we get here, we haven't found the variable in the file
340  throw std::runtime_error("npz_load: Variable name "+varname+" not found in "+fname);
341 }
std::string string
Definition: nybbler.cc:12
cnpy::NpyArray load_the_npy_file(FILE *fp)
Definition: cnpy.cxx:195
cnpy::NpyArray load_the_npz_array(FILE *fp, uint32_t compr_bytes, uint32_t uncompr_bytes)
Definition: cnpy.cxx:208
unsigned short uint16_t
Definition: stdint.h:125
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:87
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
unsigned int uint32_t
Definition: stdint.h:126
template<typename T >
void cnpy::npz_save ( std::string  zipname,
std::string  fname,
const T *  data,
const std::vector< size_t > &  shape,
std::string  mode = "w" 
)

Definition at line 138 of file cnpy.h.

139  {
140  //first, append a .npy to the fname
141  fname += ".npy";
142 
143  //now, on with the show
144  FILE* fp = NULL;
145  uint16_t nrecs = 0;
146  size_t global_header_offset = 0;
147  std::vector<char> global_header;
148 
149  if(mode == "a") fp = fopen(zipname.c_str(),"r+b");
150 
151  if(fp) {
152  //zip file exists. we need to add a new npy file to it.
153  //first read the footer. this gives us the offset and size of the global header
154  //then read and store the global header.
155  //below, we will write the the new data at the start of the global header then append the global header and footer below it
156  size_t global_header_size;
157  parse_zip_footer(fp,nrecs,global_header_size,global_header_offset);
158  fseek(fp,global_header_offset,SEEK_SET);
159  global_header.resize(global_header_size);
160  size_t res = fread(&global_header[0],sizeof(char),global_header_size,fp);
161  if(res != global_header_size){
162  throw std::runtime_error("npz_save: header read error while adding to existing zip");
163  }
164  fseek(fp,global_header_offset,SEEK_SET);
165  }
166  else {
167  fp = fopen(zipname.c_str(),"wb");
168  }
169 
170  std::vector<char> npy_header = create_npy_header<T>(shape);
171 
172  size_t nels = std::accumulate(shape.begin(),shape.end(),1,std::multiplies<size_t>());
173  size_t nbytes = nels*sizeof(T) + npy_header.size();
174 
175  //get the CRC of the data to be added
176  uint32_t crc = crc32(0L,(uint8_t*)&npy_header[0],npy_header.size());
177  crc = crc32(crc,(uint8_t*)data,nels*sizeof(T));
178 
179  //build the local header
180  std::vector<char> local_header;
181  local_header += "PK"; //first part of sig
182  local_header += (uint16_t) 0x0403; //second part of sig
183  local_header += (uint16_t) 20; //min version to extract
184  local_header += (uint16_t) 0; //general purpose bit flag
185  local_header += (uint16_t) 0; //compression method
186  local_header += (uint16_t) 0; //file last mod time
187  local_header += (uint16_t) 0; //file last mod date
188  local_header += (uint32_t) crc; //crc
189  local_header += (uint32_t) nbytes; //compressed size
190  local_header += (uint32_t) nbytes; //uncompressed size
191  local_header += (uint16_t) fname.size(); //fname length
192  local_header += (uint16_t) 0; //extra field length
193  local_header += fname;
194 
195  //build global header
196  global_header += "PK"; //first part of sig
197  global_header += (uint16_t) 0x0201; //second part of sig
198  global_header += (uint16_t) 20; //version made by
199  global_header.insert(global_header.end(),local_header.begin()+4,local_header.begin()+30);
200  global_header += (uint16_t) 0; //file comment length
201  global_header += (uint16_t) 0; //disk number where file starts
202  global_header += (uint16_t) 0; //internal file attributes
203  global_header += (uint32_t) 0; //external file attributes
204  global_header += (uint32_t) global_header_offset; //relative offset of local file header, since it begins where the global header used to begin
205  global_header += fname;
206 
207  //build footer
208  std::vector<char> footer;
209  footer += "PK"; //first part of sig
210  footer += (uint16_t) 0x0605; //second part of sig
211  footer += (uint16_t) 0; //number of this disk
212  footer += (uint16_t) 0; //disk where footer starts
213  footer += (uint16_t) (nrecs+1); //number of records on this disk
214  footer += (uint16_t) (nrecs+1); //total number of records
215  footer += (uint32_t) global_header.size(); //nbytes of global headers
216  footer += (uint32_t) (global_header_offset + nbytes + local_header.size()); //offset of start of global headers, since global header now starts after newly written array
217  footer += (uint16_t) 0; //zip file comment length
218 
219  //write everything
220  fwrite(&local_header[0],sizeof(char),local_header.size(),fp);
221  fwrite(&npy_header[0],sizeof(char),npy_header.size(),fp);
222  fwrite(data,sizeof(T),nels,fp);
223  fwrite(&global_header[0],sizeof(char),global_header.size(),fp);
224  fwrite(&footer[0],sizeof(char),footer.size(),fp);
225  fclose(fp);
226  }
void parse_zip_footer(FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
Definition: cnpy.cxx:162
unsigned short uint16_t
Definition: stdint.h:125
basic_data data
Definition: format.h:764
unsigned char uint8_t
Definition: stdint.h:124
unsigned int uint32_t
Definition: stdint.h:126
template<typename T >
void cnpy::npz_save ( std::string  zipname,
std::string  fname,
const std::vector< T >  data,
std::string  mode = "w" 
)

Definition at line 234 of file cnpy.h.

234  {
235  std::vector<size_t> shape;
236  shape.push_back(data.size());
237  npz_save(zipname, fname, &data[0], shape, mode);
238  }
void npz_save(std::string zipname, std::string fname, const std::vector< T > data, std::string mode="w")
Definition: cnpy.h:234
template<typename T >
std::vector<char>& cnpy::operator+= ( std::vector< char > &  lhs,
const T  rhs 
)

Definition at line 75 of file cnpy.h.

75  {
76  //write in little endian
77  for(size_t byte = 0; byte < sizeof(T); byte++) {
78  char val = *((char*)&rhs+byte);
79  lhs.push_back(val);
80  }
81  return lhs;
82  }
byte_as<> byte
Type of data size stored in bytes, in long long precision.
Definition: datasize.h:98
template<>
std::vector< char > & cnpy::operator+= ( std::vector< char > &  lhs,
const std::string  rhs 
)

Definition at line 48 of file cnpy.cxx.

48  {
49  lhs.insert(lhs.end(),rhs.begin(),rhs.end());
50  return lhs;
51 }
template<>
std::vector< char > & cnpy::operator+= ( std::vector< char > &  lhs,
const char *  rhs 
)

Definition at line 53 of file cnpy.cxx.

53  {
54  //write in little endian
55  size_t len = strlen(rhs);
56  lhs.reserve(len);
57  for(size_t byte = 0; byte < len; byte++) {
58  lhs.push_back(rhs[byte]);
59  }
60  return lhs;
61 }
byte_as<> byte
Type of data size stored in bytes, in long long precision.
Definition: datasize.h:98
void cnpy::parse_npy_header ( FILE *  fp,
size_t &  word_size,
std::vector< size_t > &  shape,
bool fortran_order 
)

Definition at line 107 of file cnpy.cxx.

107  {
108  char buffer[256];
109  size_t res = fread(buffer,sizeof(char),11,fp);
110  if(res != 11)
111  throw std::runtime_error("parse_npy_header: failed fread");
112  std::string header = fgets(buffer,256,fp);
113  if (header[header.size()-1] != '\n') {
114  throw std::runtime_error("parse_npy_header: header is not newline terminated");
115  }
116 
117  size_t loc1, loc2;
118 
119  //fortran order
120  loc1 = header.find("fortran_order");
121  if (loc1 == std::string::npos)
122  throw std::runtime_error("parse_npy_header: failed to find header keyword: 'fortran_order'");
123  loc1 += 16;
124  fortran_order = (header.substr(loc1,4) == "True" ? true : false);
125 
126  //shape
127  loc1 = header.find("(");
128  loc2 = header.find(")");
129  if (loc1 == std::string::npos || loc2 == std::string::npos)
130  throw std::runtime_error("parse_npy_header: failed to find header keyword: '(' or ')'");
131 
132  std::regex num_regex("[0-9][0-9]*");
133  std::smatch sm;
134  shape.clear();
135 
136  std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
137  while(std::regex_search(str_shape, sm, num_regex)) {
138  shape.push_back(std::stoi(sm[0].str()));
139  str_shape = sm.suffix().str();
140  }
141 
142  //endian, word size, data type
143  //byte order code | stands for not applicable.
144  //not sure when this applies except for byte array
145  loc1 = header.find("descr");
146  if (loc1 == std::string::npos)
147  throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'");
148  loc1 += 9;
149  bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
150  if (!littleEndian) {
151  throw std::runtime_error("parse_npy_header: header is not little endian");
152  }
153 
154  //char type = header[loc1+1];
155  //assert(type == map_type(T));
156 
157  std::string str_ws = header.substr(loc1+2);
158  loc2 = str_ws.find("'");
159  word_size = atoi(str_ws.substr(0,loc2).c_str());
160 }
std::string string
Definition: nybbler.cc:12
std::string str(const std::pair< Type, Type > &tt)
Definition: test_pimpos.cxx:12
void cnpy::parse_npy_header ( unsigned char *  buffer,
size_t &  word_size,
std::vector< size_t > &  shape,
bool fortran_order 
)

Definition at line 63 of file cnpy.cxx.

63  {
64  //std::string magic_string(buffer,6);
65  //uint8_t major_version = *reinterpret_cast<uint8_t*>(buffer+6);
66  //uint8_t minor_version = *reinterpret_cast<uint8_t*>(buffer+7);
67  uint16_t header_len = *reinterpret_cast<uint16_t*>(buffer+8);
68  std::string header(reinterpret_cast<char*>(buffer+9),header_len);
69 
70  size_t loc1, loc2;
71 
72  //fortran order
73  loc1 = header.find("fortran_order")+16;
74  fortran_order = (header.substr(loc1,4) == "True" ? true : false);
75 
76  //shape
77  loc1 = header.find("(");
78  loc2 = header.find(")");
79 
80  std::regex num_regex("[0-9][0-9]*");
81  std::smatch sm;
82  shape.clear();
83 
84  std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
85  while(std::regex_search(str_shape, sm, num_regex)) {
86  shape.push_back(std::stoi(sm[0].str()));
87  str_shape = sm.suffix().str();
88  }
89 
90  //endian, word size, data type
91  //byte order code | stands for not applicable.
92  //not sure when this applies except for byte array
93  loc1 = header.find("descr")+9;
94  bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
95  if (!littleEndian) {
96  throw std::runtime_error("parse_npy_header: header is not little endian");
97  }
98 
99  //char type = header[loc1+1];
100  //assert(type == map_type(T));
101 
102  std::string str_ws = header.substr(loc1+2);
103  loc2 = str_ws.find("'");
104  word_size = atoi(str_ws.substr(0,loc2).c_str());
105 }
std::string string
Definition: nybbler.cc:12
unsigned short uint16_t
Definition: stdint.h:125
std::string str(const std::pair< Type, Type > &tt)
Definition: test_pimpos.cxx:12
void cnpy::parse_zip_footer ( FILE *  fp,
uint16_t nrecs,
size_t &  global_header_size,
size_t &  global_header_offset 
)

Definition at line 162 of file cnpy.cxx.

163 {
164  std::vector<char> footer(22);
165  fseek(fp,-22,SEEK_END);
166  size_t res = fread(&footer[0],sizeof(char),22,fp);
167  if(res != 22)
168  throw std::runtime_error("parse_zip_footer: failed fread");
169 
170  uint16_t disk_no, disk_start, nrecs_on_disk, comment_len;
171  disk_no = *(uint16_t*) &footer[4];
172  disk_start = *(uint16_t*) &footer[6];
173  nrecs_on_disk = *(uint16_t*) &footer[8];
174  nrecs = *(uint16_t*) &footer[10];
175  global_header_size = *(uint32_t*) &footer[12];
176  global_header_offset = *(uint32_t*) &footer[16];
177  comment_len = *(uint16_t*) &footer[20];
178 
179  if (disk_no != 0) {
180  throw std::runtime_error("parse_zip_footer: non-zero disk number");
181  }
182 
183  if (disk_start != 0) {
184  throw std::runtime_error("parse_zip_footer: non-zero disk start");
185  }
186 
187  if (nrecs_on_disk != nrecs) {
188  throw std::runtime_error("parse_zip_footer: number of recrods do not match");
189  }
190  if (comment_len != 0) {
191  throw std::runtime_error("parse_zip_footer: unexepcted comment");
192  }
193 }
unsigned short uint16_t
Definition: stdint.h:125
unsigned int uint32_t
Definition: stdint.h:126