From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_archive_8cpp_source.html | 709 +++++++++++++++++++++++++++++ 1 file changed, 709 insertions(+) create mode 100644 Doc/doxygen/html/_archive_8cpp_source.html (limited to 'Doc/doxygen/html/_archive_8cpp_source.html') diff --git a/Doc/doxygen/html/_archive_8cpp_source.html b/Doc/doxygen/html/_archive_8cpp_source.html new file mode 100644 index 0000000..9c1c739 --- /dev/null +++ b/Doc/doxygen/html/_archive_8cpp_source.html @@ -0,0 +1,709 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/nGenEx/Archive.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
Archive.cpp
+
+
+Go to the documentation of this file.
1 /* Project nGenEx
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: nGenEx.lib
+
6  FILE: Archive.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 */
+
10 
+
11 #include "MemDebug.h"
+
12 #include "Types.h"
+
13 #include "Archive.h"
+
14 
+
15 #include <fcntl.h>
+
16 #include <sys/types.h>
+
17 #include <sys/stat.h>
+
18 #include <io.h>
+
19 #include <stdio.h>
+
20 #include <time.h>
+
21 
+
22 #include "zlib.h"
+
23 
+
24 // +--------------------------------------------------------------------+
+
25 
+
26 void Print(const char* fmt, ...);
+
27 
+
28 int verbose = 1;
+
29 int err;
+
30 
+
31 #define CHECK_ERR(err, msg) { \
+
32  if (err != Z_OK) { \
+
33  fprintf(stderr, "%s error: %d\n", msg, err); \
+
34  exit(1); \
+
35  } \
+
36  }
+
37 
+
38 // +--------------------------------------------------------------------+
+
39 
+
40 DataArchive::DataArchive(const char* name)
+
41 {
+
42  ZeroMemory(this, sizeof(DataArchive));
+
43 
+
44  if (name)
+
45  LoadDatafile(name);
+
46 }
+
47 
+ +
49 {
+
50  delete [] block_map;
+
51  delete [] directory;
+
52 }
+
53 
+
54 // +--------------------------------------------------------------------+
+
55 
+
56 void DataArchive::WriteEntry(int index, BYTE* buf)
+
57 {
+
58  int f = _open(datafile, _O_RDWR|_O_CREAT|_O_BINARY, _S_IREAD|_S_IWRITE);
+
59 
+
60  if (f != -1) {
+
61  header.dir_size_comp = DirBlocks() * BLOCK_SIZE;
+
62  dirbuf = new(__FILE__,__LINE__) BYTE[header.dir_size_comp];
+
63 
+
64  if (!dirbuf) {
+
65  err = Z_MEM_ERROR;
+
66  }
+
67 
+
68  else {
+
69  err = compress(dirbuf, &header.dir_size_comp,
+
70  (BYTE*) directory, header.nfiles * sizeof(DataEntry));
+
71  CHECK_ERR(err, "compress");
+
72 
+
73  header.dir_blocks = Blocks(header.dir_size_comp) * BLOCK_SIZE;
+
74 
+
75  _lseek(f, 0, SEEK_SET);
+
76  _write(f, &header, sizeof(DataHeader));
+
77  _lseek(f, sizeof(DataHeader) + header.dir_offset, SEEK_SET);
+
78  _write(f, dirbuf, header.dir_blocks);
+
79 
+
80  delete [] dirbuf;
+
81  dirbuf = 0;
+
82  }
+
83 
+
84  if (buf && directory && directory[index].size_comp) {
+
85  _lseek(f, sizeof(DataHeader) + directory[index].offset, SEEK_SET);
+
86  _write(f, buf, directory[index].size_comp);
+
87  }
+
88  _close(f);
+
89  }
+
90  else
+
91  perror("WriteEntry");
+
92 }
+
93 
+
94 // +--------------------------------------------------------------------+
+
95 
+
96 DWORD DataArchive::Blocks(DWORD raw_size)
+
97 {
+
98  int full_blocks = raw_size / BLOCK_SIZE;
+
99  int part_blocks = (raw_size % BLOCK_SIZE) > 0;
+
100 
+
101  return full_blocks + part_blocks;
+
102 }
+
103 
+ +
105 {
+
106  DWORD result = Blocks(header.nfiles * sizeof(DataEntry));
+
107  if (result == 0) result = 1;
+
108  return result;
+
109 }
+
110 
+
111 DWORD DataArchive::FileBlocks(int index)
+
112 {
+
113  if (index >= 0 && index < (int) header.nfiles && directory)
+
114  return Blocks(directory[index].size_comp);
+
115 
+
116  return 0;
+
117 }
+
118 
+
119 // +--------------------------------------------------------------------+
+
120 
+ +
122 {
+
123  delete [] block_map;
+
124  block_map = 0;
+
125 
+
126  if (header.nfiles == 0) return;
+
127 
+
128  DWORD i,j;
+
129  DWORD dir_usage = header.dir_offset + DirBlocks() * BLOCK_SIZE;
+
130  DWORD max_usage = dir_usage;
+
131 
+
132  for (i = 0; i < header.nfiles; i++) {
+
133  DWORD last_block = directory[i].offset + FileBlocks(i) * BLOCK_SIZE;
+
134  if (last_block > max_usage)
+
135  max_usage = last_block;
+
136  }
+
137 
+
138  nblocks = max_usage/BLOCK_SIZE;
+
139  block_map = new(__FILE__,__LINE__) DWORD[nblocks];
+
140 
+
141  if (!block_map) {
+
142  nblocks = 0;
+
143  }
+
144 
+
145  else {
+
146  ZeroMemory(block_map, nblocks*sizeof(DWORD));
+
147 
+
148  DWORD first_block = header.dir_offset/BLOCK_SIZE +
+
149  (header.dir_offset%BLOCK_SIZE > 0);
+
150 
+
151  for (j = 0; j < DirBlocks(); j++)
+
152  block_map[first_block+j] = 1;
+
153 
+
154  for (i = 0; i < header.nfiles; i++) {
+
155  DWORD first_block = directory[i].offset/BLOCK_SIZE +
+
156  (directory[i].offset%BLOCK_SIZE > 0);
+
157 
+
158  for (j = 0; j < FileBlocks(i); j++)
+
159  block_map[first_block+j] = i+2;
+
160  }
+
161  }
+
162 }
+
163 
+
164 // +--------------------------------------------------------------------+
+
165 
+ +
167 {
+
168  if ((int) (nblocks)-need > 0) {
+
169  DWORD start;
+
170  int i;
+
171 
+
172  for (start = 0; start < nblocks-need; start++) {
+
173  for (i = 0; block_map[start+i] == 0 && i < need; i++);
+
174 
+
175  if (i == need) return start*BLOCK_SIZE;
+
176 
+
177  start += i;
+
178  }
+
179  }
+
180 
+
181  return nblocks*BLOCK_SIZE;
+
182 }
+
183 
+
184 // +--------------------------------------------------------------------+
+
185 
+
186 void DataArchive::LoadDatafile(const char* name)
+
187 {
+
188  if (!name) return;
+
189 
+
190  delete [] directory;
+
191  delete [] block_map;
+
192 
+
193  ZeroMemory(this, sizeof(DataArchive));
+
194  strncpy_s(datafile, name, NAMELEN-1);
+
195 
+
196  FILE* f;
+
197  fopen_s(&f, datafile, "rb");
+
198  if (f) {
+
199  fread(&header, sizeof(DataHeader), 1, f);
+
200 
+
201  if (header.version != VERSION) {
+
202  Print("ERROR: datafile '%s' invalid version '%d'\n",
+
203  datafile, header.version);
+
204  fclose(f);
+
205  ZeroMemory(&header, sizeof(header));
+
206  return;
+
207  }
+
208 
+
209  DWORD len = DirBlocks() * BLOCK_SIZE;
+
210  DWORD dirsize = header.nfiles + 64;
+
211 
+
212  dirbuf = new(__FILE__,__LINE__) BYTE[len];
+
213  directory = new(__FILE__,__LINE__) DataEntry[dirsize];
+
214 
+
215  if (!dirbuf || !directory) {
+
216  err = Z_MEM_ERROR;
+
217  }
+
218 
+
219  else {
+
220  ZeroMemory(directory, sizeof(DataEntry) * dirsize);
+
221 
+
222  fseek(f, sizeof(DataHeader) + header.dir_offset, SEEK_SET);
+
223  fread(dirbuf, header.dir_size_comp, 1, f);
+
224 
+
225  int err = uncompress((BYTE*) directory, &len,
+
226 #pragma warning(suppress: 6029)
+
227  dirbuf, header.dir_size_comp);
+
228  if (err != Z_OK)
+
229  ZeroMemory(directory, sizeof(DataEntry) * dirsize);
+
230 
+
231  delete [] dirbuf;
+
232  dirbuf = 0;
+
233 
+
234  CreateBlockMap();
+
235  }
+
236  }
+
237  else {
+
238  Print("Creating Archive '%s'...\n", datafile);
+
239 
+
240  header.version = VERSION;
+
241  header.nfiles = 0;
+
242  header.dir_blocks = 0;
+
243  header.dir_size_comp = 0;
+
244  header.dir_offset = 0;
+
245 
+
246  nblocks = DirBlocks();
+
247 
+
248  delete [] block_map;
+
249  block_map = 0;
+
250  }
+
251 }
+
252 
+
253 // +--------------------------------------------------------------------+
+
254 
+
255 int DataArchive::FindEntry(const char* req_name)
+
256 {
+
257  int entry = -1;
+
258 
+
259  if (req_name && *req_name && directory) {
+
260  char path[256];
+
261  int len = strlen(req_name);
+
262 
+
263  ZeroMemory(path, sizeof(path));
+
264 
+
265  for (int c = 0; c < len; c++) {
+
266  if (req_name[c] == '\\')
+
267  path[c] = '/';
+
268  else
+
269  path[c] = req_name[c];
+
270  }
+
271 
+
272  for (DWORD i = 0; i < header.nfiles; i++) {
+
273  if (!_stricmp(directory[i].name, path))
+
274  return i;
+
275  }
+
276  }
+
277 
+
278  return entry;
+
279 }
+
280 
+
281 // +--------------------------------------------------------------------+
+
282 
+ +
284 {
+
285  if (directory && i >= 0 && i < (int) header.nfiles) {
+
286  char* name = directory[i].name;
+
287 
+
288  FILE* f;
+
289  fopen_s(&f, name, "rb");
+
290 
+
291  if (f) {
+
292  fseek(f, 0, SEEK_END);
+
293  DWORD len = ftell(f);
+
294  fseek(f, 0, SEEK_SET);
+
295 
+
296  BYTE* buf = new(__FILE__,__LINE__) BYTE[len];
+
297 
+
298  if (!buf) {
+
299  err = Z_MEM_ERROR;
+
300  }
+
301 
+
302  else {
+
303  fread(buf, len, 1, f);
+
304  fclose(f);
+
305 
+
306  directory[i].size_orig = len;
+
307 
+
308  directory[i].size_comp = (int) (len * 1.1);
+
309  BYTE* cbuf = new(__FILE__,__LINE__) BYTE[directory[i].size_comp];
+
310 
+
311  if (!cbuf) {
+
312  err = Z_MEM_ERROR;
+
313  }
+
314  else {
+
315  err = compress(cbuf, &directory[i].size_comp, buf, len);
+
316  CHECK_ERR(err, "compress");
+
317  }
+
318 
+
319  delete [] buf;
+
320  return cbuf;
+
321  }
+
322  }
+
323  }
+
324 
+
325  return 0;
+
326 }
+
327 
+
328 // +--------------------------------------------------------------------+
+
329 
+
330 int DataArchive::ExpandEntry(int i, BYTE*& buf, bool null_terminate)
+
331 {
+
332  DWORD len = 0;
+
333 
+
334  if (directory && i >= 0 && i < (int) header.nfiles) {
+
335  FILE* f;
+
336  fopen_s(&f, datafile, "rb");
+
337 
+
338  if (f) {
+
339  DWORD clen = directory[i].size_comp;
+
340  BYTE* cbuf = new(__FILE__,__LINE__) BYTE[clen];
+
341 
+
342  if (!cbuf) {
+
343  err = Z_MEM_ERROR;
+
344  }
+
345 
+
346  else {
+
347  fseek(f, sizeof(DataHeader) + directory[i].offset, SEEK_SET);
+
348  fread(cbuf, clen, 1, f);
+
349 
+
350  len = directory[i].size_orig;
+
351 
+
352  if (null_terminate) {
+
353  buf = new(__FILE__,__LINE__) BYTE[len+1];
+
354  if (buf) buf[len] = 0;
+
355  }
+
356 
+
357  else {
+
358  buf = new(__FILE__,__LINE__) BYTE[len];
+
359  }
+
360 
+
361  if (!buf) {
+
362  err = Z_MEM_ERROR;
+
363  }
+
364 
+
365  else {
+
366  err = uncompress(buf, &len, cbuf, clen);
+
367  if (err != Z_OK) {
+
368  delete [] buf;
+
369  buf = 0;
+
370  }
+
371  }
+
372 
+
373  delete [] cbuf;
+
374  fclose(f);
+
375  }
+
376  }
+
377  }
+
378 
+
379  return len;
+
380 }
+
381 
+
382 // +--------------------------------------------------------------------+
+
383 
+
384 int DataArchive::InsertEntry(const char* name)
+
385 {
+
386  if (name && *name) {
+
387  char path[256];
+
388  DWORD len = strlen(name);
+
389 
+
390  ZeroMemory(path, sizeof(path));
+
391 
+
392  for (DWORD c = 0; c < len; c++) {
+
393  if (name[c] == '\\')
+
394  path[c] = '/';
+
395  else
+
396  path[c] = name[c];
+
397  }
+
398 
+
399  int dirsize = header.nfiles + 64;
+
400 
+
401  if (directory && dirsize) {
+
402  for (int i = 0; i < dirsize; i++) {
+
403  if (directory[i].size_orig == 0) {
+
404  ZeroMemory(directory[i].name, NAMELEN);
+
405  strncpy_s(directory[i].name, path, NAMELEN);
+
406  directory[i].name[NAMELEN-1] = '\0';
+
407  directory[i].size_orig = 1;
+
408 
+
409  return i;
+
410  }
+
411  }
+
412  }
+
413 
+
414  DataEntry* dir = new(__FILE__,__LINE__) DataEntry[dirsize + 64];
+
415 
+
416  if (directory && dirsize) {
+
417  ZeroMemory(dir, (dirsize + 64) * sizeof(DataEntry));
+
418  CopyMemory(dir, directory, dirsize * sizeof(DataEntry));
+
419  }
+
420 
+
421  delete [] directory;
+
422 
+
423  header.nfiles = dirsize + 64;
+
424  directory = dir;
+
425 
+
426  ZeroMemory(directory[dirsize].name, NAMELEN);
+
427  strncpy_s(directory[dirsize].name, path, NAMELEN);
+
428  directory[dirsize].name[NAMELEN-1] = '\0';
+
429  directory[dirsize].size_orig = 1;
+
430 
+
431  return dirsize;
+
432  }
+
433 
+
434  return -1;
+
435 }
+
436 
+
437 // +--------------------------------------------------------------------+
+
438 
+ +
440 {
+
441  if (directory && index >= 0 && index < (int) header.nfiles)
+
442  ZeroMemory(&directory[index], sizeof(DataEntry));
+
443 }
+
444 
+
445 // +--------------------------------------------------------------------+
+
446 
+
447 void DataArchive::Insert(const char* name)
+
448 {
+
449  DWORD old_blocks = 0, old_offset = 0, new_blocks = 0;
+
450  DWORD old_dir_blocks = 0, old_dir_offset = 0, new_dir_blocks = 0;
+
451  int added = 0;
+
452 
+
453  int index = FindEntry(name);
+
454 
+
455  if (index < 0) {
+
456  old_dir_blocks = DirBlocks();
+
457  old_dir_offset = header.dir_offset;
+
458 
+
459  index = InsertEntry(name);
+
460 
+
461  if (index >= (int) header.nfiles) {
+
462  header.nfiles = index+1;
+
463  added = 1;
+
464  }
+
465 
+
466  new_dir_blocks = DirBlocks();
+
467 
+
468  if (new_dir_blocks > old_dir_blocks) {
+
469  header.dir_offset = FindDataBlocks(new_dir_blocks);
+
470  CreateBlockMap();
+
471  }
+
472  }
+
473  else {
+
474  old_blocks = FileBlocks(index);
+
475  old_offset = directory[index].offset;
+
476  }
+
477 
+
478  if (index >= 0) {
+
479  DataEntry& e = directory[index];
+
480 
+
481  if (verbose) Print(" Inserting: %-16s ", e.name);
+
482 
+
483  BYTE* buf = CompressEntry(index);
+
484 
+
485  if (!buf) {
+
486  // this is (almost) unrecoverable,
+
487  // so we quit before screwing things up:
+
488  Print("ERROR: Could not compress %d:%s\n", index, directory[index].name);
+
489  exit(1);
+
490  }
+
491 
+
492  new_blocks = FileBlocks(index);
+
493 
+
494  // the file is new, or got bigger,
+
495  // need to find room for the data:
+
496  if (new_blocks > old_blocks) {
+
497  directory[index].offset = FindDataBlocks(new_blocks);
+
498  CreateBlockMap();
+
499  }
+
500 
+
501  WriteEntry(index, buf);
+
502  delete [] buf;
+
503 
+
504  if (verbose) {
+
505  int ratio = (int) (100.0 * (double) e.size_comp / (double) e.size_orig);
+
506  Print("%9d => %9d (%2d%%)\n", e.size_orig, e.size_comp, ratio);
+
507  }
+
508  }
+
509  else if (added)
+
510  header.nfiles--;
+
511 }
+
512 
+
513 // +--------------------------------------------------------------------+
+
514 
+
515 void DataArchive::Extract(const char* name)
+
516 {
+
517  int index = FindEntry(name);
+
518 
+
519  if (!directory || index < 0 || index >= (int) header.nfiles) {
+
520  Print("Could not extract '%s', not found\n", name);
+
521  return;
+
522  }
+
523 
+
524  BYTE* buf;
+
525  ExpandEntry(index, buf);
+
526 
+
527  FILE* f;
+
528  fopen_s(&f, directory[index].name, "wb");
+
529  if (f) {
+
530  fwrite(buf, directory[index].size_orig, 1, f);
+
531  fclose(f);
+
532  }
+
533  else
+
534  Print("Could not extract '%s', could not open file for writing\n", name);
+
535 
+
536  delete [] buf;
+
537 
+
538  if (verbose) Print(" Extracted: %s\n", name);
+
539 }
+
540 
+
541 // +--------------------------------------------------------------------+
+
542 
+
543 void DataArchive::Remove(const char* name)
+
544 {
+
545  int index = FindEntry(name);
+
546 
+
547  if (!directory || index < 0 || index >= (int) header.nfiles) {
+
548  Print("Could not remove '%s', not found\n", name);
+
549  return;
+
550  }
+
551 
+
552  RemoveEntry(index);
+
553  WriteEntry(index, 0);
+
554 
+
555  if (verbose) Print(" Removed: %s\n", name);
+
556 }
+
557 
+
558 // +--------------------------------------------------------------------+
+
559 
+ +
561 {
+
562  int total_orig = 0;
+
563  int total_comp = 0;
+
564 
+
565  printf("DATAFILE: %s\n", datafile);
+
566  printf("Files: %d\n", header.nfiles);
+
567  printf("\n");
+
568 
+
569  if (directory && header.nfiles) {
+
570  printf("Index Orig Size Comp Size Ratio Name\n");
+
571  printf("----- --------- --------- ----- ----------------\n");
+
572 
+
573  for (DWORD i = 0; i < header.nfiles; i++) {
+
574  DataEntry& e = directory[i];
+
575  int ratio = (int) (100.0 * (double) e.size_comp / (double) e.size_orig);
+
576 
+
577  printf("%5d %9d %9d %2d%% %s\n", i+1, e.size_orig, e.size_comp, ratio, e.name);
+
578 
+
579  total_orig += e.size_orig;
+
580  total_comp += e.size_comp;
+
581  }
+
582 
+
583  int total_ratio = (int) (100.0 * (double) total_comp / (double) total_orig);
+
584 
+
585  printf("----- --------- --------- -----\n");
+
586  printf("TOTAL %9d %9d %2d%%\n\n", total_orig, total_comp, total_ratio);
+
587  }
+
588 }
+
589 
+
590 
+
591 // +--------------------------------------------------------------------+
+
592 
+
+
+ + + + -- cgit v1.1