FS2_Open
Open source remastering of the Freespace 2 engine
cfilelist.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <string>
16 #include <algorithm>
17 
18 #ifdef _WIN32
19 #include <io.h>
20 #include <direct.h>
21 #include <windows.h>
22 #include <winbase.h> /* needed for memory mapping of file functions */
23 #endif
24 
25 #include "cfile/cfile.h"
26 #include "globalincs/pstypes.h"
27 
28 
30 {
31  // NOTE: This really needs to be updated to C++ style sorting at some point
32 
33  int i, j, incr;
34  SCP_string t;
35  file_list_info tt;
36 
37  int n = (int)list.size();
38 
39  if (sort == CF_SORT_NAME) {
40  incr = n / 2;
41  while (incr > 0) {
42  for (i=incr; i<n; i++) {
43  j = i - incr;
44  while (j >= 0) {
45  if (stricmp(list[j].c_str(), list[j + incr].c_str()) > 0) {
46  t = list[j];
47  list[j] = list[j + incr];
48  list[j + incr] = t;
49 
50  if (info) {
51  tt = (*info)[j];
52  (*info)[j] = (*info)[j + incr];
53  (*info)[j + incr] = tt;
54  }
55 
56  j -= incr;
57 
58  } else
59  break;
60  }
61  }
62 
63  incr /= 2;
64  }
65 
66  return;
67 
68  } else if (sort == CF_SORT_TIME) {
69  Assert(info);
70  incr = n / 2;
71  while (incr > 0) {
72  for (i=incr; i<n; i++) {
73  j = i - incr;
74  while (j >= 0) {
75  if ( (*info)[j].write_time < (*info)[j + incr].write_time ) {
76  t = list[j];
77  list[j] = list[j + incr];
78  list[j + incr] = t;
79 
80  tt = (*info)[j];
81  (*info)[j] = (*info)[j + incr];
82  (*info)[j + incr] = tt;
83  j -= incr;
84 
85  } else
86  break;
87  }
88  }
89 
90  incr /= 2;
91  }
92 
93  return;
94 
95  } else if (sort == CF_SORT_REVERSE) {
96  std::reverse( list.begin(), list.end() );
97 
98  if (info) {
99  std::reverse( info->begin(), info->end() );
100  }
101 
102  return;
103  }
104 
105  nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
106 }
107 
108 // Sorts a list of filenames using the specified sorting method (CF_SORT_*).
109 // n = number of filenames in list to sort
110 // list = list of filenames to be sorted
111 // sort = sorting method to use (one of the CF_SORT_* defines)
112 // info = extra info for each file. Only required if sorting by time, however if you
113 // have extra file info, you should pass it as well to get it sorted too (so an
114 // index into list is the same index for info for that file
115 void cf_sort_filenames( int n, char **list, int sort, file_list_info *info )
116 {
117  int i, j, incr;
118  char *t;
119  file_list_info tt;
120 
121  if (sort == CF_SORT_NAME) {
122  incr = n / 2;
123  while (incr > 0) {
124  for (i=incr; i<n; i++) {
125  j = i - incr;
126  while (j >= 0) {
127  if (stricmp(list[j], list[j + incr]) > 0) {
128  t = list[j];
129  list[j] = list[j + incr];
130  list[j + incr] = t;
131 
132  if (info) {
133  tt = info[j];
134  info[j] = info[j + incr];
135  info[j + incr] = tt;
136  }
137 
138  j -= incr;
139 
140  } else
141  break;
142  }
143  }
144 
145  incr /= 2;
146  }
147 
148  return;
149 
150  } else if (sort == CF_SORT_TIME) {
151  Assert(info);
152  incr = n / 2;
153  while (incr > 0) {
154  for (i=incr; i<n; i++) {
155  j = i - incr;
156  while (j >= 0) {
157  if (info[j].write_time < info[j + incr].write_time) {
158  t = list[j];
159  list[j] = list[j + incr];
160  list[j + incr] = t;
161 
162  tt = info[j];
163  info[j] = info[j + incr];
164  info[j + incr] = tt;
165  j -= incr;
166 
167  } else
168  break;
169  }
170  }
171 
172  incr /= 2;
173  }
174 
175  return;
176 
177  } else if (sort == CF_SORT_REVERSE) {
178  incr = n / 2;
179  char buffer[MAX_FILENAME_LEN];
180  file_list_info tt_tmp;
181 
182  for (i = 0; i < incr; i++) {
183  t = list[n - 1 - i];
184 
185  if (list[i] != t) {
186  strcpy_s(buffer, list[i]);
187  strcpy(list[i], t);
188  strcpy(t, buffer);
189 
190  if (info) {
191  tt = info[n - 1 - i];
192  tt_tmp = info[i];
193  info[i] = tt;
194  tt = tt_tmp;
195  }
196  }
197  }
198 
199  return;
200  }
201 
202  nprintf(("Error", "Unknown sorting method %d passed to cf_sort_filenames()\n", sort));
203 }
204 
205 
206 #if (0) // these aren't used anywhere now
207 
208 // cf_compress - Do Run Length Compression on a block of data. Targa format.
209 //
210 // Usage:
211 // out Buffer to write it out to
212 // in Buffer to compress
213 // bytecount Number of bytes input
214 int cf_compress(char *out, char *in, int bytecount )
215 {
216  int pixcount; // number of pixels in the current packet
217  char *inputpixel=NULL; // current input pixel position
218  char *matchpixel=NULL; // pixel value to match for a run
219  char *flagbyte=NULL; // location of last flag byte to set
220  int rlcount; // current count in r.l. string
221  int rlthresh; // minimum valid run length
222  char *copyloc; // location to begin copying at
223 
224  // set the threshold -- the minimum valid run length
225  rlthresh = 2; // Require a 2 pixel span before rle'ing
226 
227  // set the first pixel up
228 
229  flagbyte = out; // place to put next flag if run
230  inputpixel = in;
231  pixcount = 1;
232  rlcount = 0;
233  copyloc = (char *)0;
234 
235  // loop till data processing complete
236  do {
237 
238  // if we have accumulated a 128-byte packet, process it
239  if ( pixcount == 129 ) {
240  *flagbyte = 127;
241 
242  // set the run flag if this is a run
243 
244  if ( rlcount >= rlthresh ) {
245  *flagbyte |= 0x80;
246  pixcount = 2;
247  }
248 
249  // copy the data into place
250  ++flagbyte;
251  memmove( flagbyte, copyloc, pixcount-1 );
252  flagbyte += pixcount-1;
253  pixcount = 1;
254 
255  // set up for next packet
256  continue;
257  }
258 
259  // if zeroth byte, handle as special case
260  if ( pixcount == 1 ) {
261  rlcount = 0;
262  copyloc = inputpixel; /* point to 1st guy in packet */
263  matchpixel = inputpixel; /* set pointer to pix to match */
264  pixcount = 2;
265  inputpixel += 1;
266  continue;
267  }
268 
269  // assembling a packet -- look at next pixel
270 
271  // current pixel == match pixel?
272  if ( *inputpixel == *matchpixel ) {
273 
274  // establishing a run of enough length to
275  // save space by doing it
276  // -- write the non-run length packet
277  // -- start run-length packet
278 
279  if ( ++rlcount == rlthresh ) {
280 
281  // close a non-run packet
282 
283  if ( pixcount > (rlcount+1) ) {
284  // write out length and do not set run flag
285 
286  *flagbyte++ = (char)(pixcount - 2 - rlthresh);
287 
288  memmove(flagbyte, copyloc, (pixcount-1-rlcount) );
289  flagbyte += (pixcount-1-rlcount);
290 
291  copyloc = inputpixel;
292  pixcount = rlcount + 1;
293  }
294  }
295  } else {
296 
297  // no match -- either break a run or continue without one
298  // if a run exists break it:
299  // write the bytes in the string (1+1)
300  // start the next string
301 
302  if ( rlcount >= rlthresh ) {
303 
304  *flagbyte++ = (char)(0x80 | rlcount);
305  memmove(flagbyte, copyloc, 1 );
306  flagbyte += 1;
307  pixcount = 1;
308  continue;
309  } else {
310 
311  // not a match and currently not a run
312  // - save the current pixel
313  // - reset the run-length flag
314  rlcount = 0;
315  matchpixel = inputpixel;
316  }
317  }
318  pixcount++;
319  inputpixel += 1;
320  } while ( inputpixel < (in + bytecount));
321 
322  // quit this buffer without loosing any data
323  if ( --pixcount >= 1 ) {
324  *flagbyte = (char)(pixcount - 1);
325  if ( rlcount >= rlthresh ) {
326  *flagbyte |= 0x80;
327  pixcount = 1;
328  }
329 
330  // copy the data into place
331  ++flagbyte;
332  memmove(flagbyte, copyloc, pixcount );
333  flagbyte += pixcount;
334  }
335  return(flagbyte-out);
336 }
337 
338 
339 // cf_decompress - Do Decompression on a run-length encoded block of data. Targa format.
340 //
341 // Usage:
342 // out Buffer to write it out to
343 // in Buffer to compress
344 // bytecount Number of bytes input
345 int cf_decompress(char *out, char *in )
346 {
347  int count;
348 
349  char *param_out = out;
350 
351  while(1) {
352 
353  count = int(*in++);
354  int run_span = count & 0x80;
355 
356  count &= (~0x80);
357 
358  if ( count > 0 ) {
359  if ( run_span ) {
360  // RLE'd data
361  ubyte c = *in++;
362 
363  memset( out, c, count );
364  out += count;
365  } else {
366  memmove( out, in, count );
367  in += count;
368  out += count;
369  }
370  }
371  }
372 
373  return out - param_out;
374 
375 }
376 
377 #endif // 0
378 
379 
380 // cfread() reads from a file and decompresses it
381 //
382 // returns: returns the number of full elements read
383 //
384 //
385 int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
386 {
387  char *out = (char *)buf;
388 
389  while(1) {
390 
391  ubyte count;
392 
393  if ( cfread( &count, 1, 1, cfile ) != 1 ) {
394  break;
395  }
396 
397  int run_span = count & 0x80;
398  count &= (~0x80);
399  count++;
400 
401  if ( count > 0 ) {
402  if ( run_span ) {
403  // RLE'd data
404  ubyte c;
405  if ( cfread( &c, 1, 1, cfile ) != 1 ) {
406  break;
407  }
408  memset( out, c, count );
409  } else {
410  if ( cfread( out, 1, count, cfile ) != count ) {
411  break;
412  }
413  }
414  out += count;
415  if ( out >= (char *)buf + (elsize*nelem)) {
416  break;
417  }
418  } else {
419  break;
420  }
421  }
422 
423  return (out - (char *)buf)/elsize;
424 }
425 
426 int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
427 {
428  char *in = (char *)param_buf;
429  int bytecount = (param_elsize * param_nelem );
430 
431  int pixcount; // number of pixels in the current packet
432  char *inputpixel=NULL; // current input pixel position
433  char *matchpixel=NULL; // pixel value to match for a run
434  int rlcount; // current count in r.l. string
435  int rlthresh; // minimum valid run length
436  char *copyloc; // location to begin copying at
437 
438  // set the threshold -- the minimum valid run length
439  rlthresh = 2; // Require a 2 pixel span before rle'ing
440 
441  // set the first pixel up
442 
443  inputpixel = in;
444  pixcount = 1;
445  rlcount = 0;
446  copyloc = (char *)0;
447 
448  // loop till data processing complete
449  do {
450 
451  // if we have accumulated a 128-byte packet, process it
452  if ( pixcount == 129 ) {
453  ubyte code = 127;
454 
455  // set the run flag if this is a run
456 
457  if ( rlcount >= rlthresh ) {
458  code |= 0x80;
459  pixcount = 2;
460  }
461 
462  cfwrite( &code, 1, 1, cfile );
463 
464  // copy the data into place
465  cfwrite( copyloc, 1, pixcount-1, cfile );
466  pixcount = 1;
467 
468  // set up for next packet
469  continue;
470  }
471 
472  // if zeroth byte, handle as special case
473  if ( pixcount == 1 ) {
474  rlcount = 0;
475  copyloc = inputpixel; /* point to 1st guy in packet */
476  matchpixel = inputpixel; /* set pointer to pix to match */
477  pixcount = 2;
478  inputpixel += 1;
479  continue;
480  }
481 
482  // assembling a packet -- look at next pixel
483 
484  // current pixel == match pixel?
485  if ( *inputpixel == *matchpixel ) {
486 
487  // establishing a run of enough length to
488  // save space by doing it
489  // -- write the non-run length packet
490  // -- start run-length packet
491 
492  if ( ++rlcount == rlthresh ) {
493 
494  // close a non-run packet
495 
496  if ( pixcount > (rlcount+1) ) {
497  // write out length and do not set run flag
498 
499  ubyte code = (ubyte)(pixcount - 2 - rlthresh);
500  cfwrite( &code, 1, 1, cfile );
501 
502  cfwrite( copyloc, 1, (pixcount-1-rlcount), cfile );
503  copyloc = inputpixel;
504  pixcount = rlcount + 1;
505  }
506  }
507  } else {
508 
509  // no match -- either break a run or continue without one
510  // if a run exists break it:
511  // write the bytes in the string (1+1)
512  // start the next string
513 
514  if ( rlcount >= rlthresh ) {
515 
516  ubyte code = (ubyte)(0x80 | rlcount);
517  cfwrite( &code, 1, 1, cfile );
518  cfwrite( copyloc, 1, 1, cfile );
519  pixcount = 1;
520  continue;
521  } else {
522 
523  // not a match and currently not a run
524  // - save the current pixel
525  // - reset the run-length flag
526  rlcount = 0;
527  matchpixel = inputpixel;
528  }
529  }
530  pixcount++;
531  inputpixel += 1;
532  } while ( inputpixel < (in + bytecount));
533 
534  // quit this buffer without loosing any data
535  if ( --pixcount >= 1 ) {
536  ubyte code = ubyte(pixcount - 1);
537 
538  // set the run flag if this is a run
539 
540  if ( rlcount >= rlthresh ) {
541  code |= 0x80;
542  pixcount = 1;
543  }
544 
545  cfwrite( &code, 1, 1, cfile );
546 
547  // copy the data into place
548  cfwrite( copyloc, 1, pixcount, cfile );
549  }
550 
551  return param_nelem;
552 }
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
int i
Definition: multi_pxo.cpp:466
int cfread(void *buf, int elsize, int nelem, CFILE *fp)
Assert(pm!=NULL)
Definition: cfile.h:28
#define CF_SORT_REVERSE
Definition: cfile.h:95
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
GLuint in
Definition: Glext.h:9087
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
HWND DWORD code
Definition: vddraw.h:425
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define nprintf(args)
Definition: pstypes.h:239
#define CF_SORT_TIME
Definition: cfile.h:94
GLuint buffer
Definition: Glext.h:5492
int cfwrite(const void *buf, int elsize, int nelem, CFILE *cfile)
Definition: cfile.cpp:1414
Definition: cfile.h:354
GLdouble GLdouble t
Definition: Glext.h:5329
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
int cfread_compressed(void *buf, int elsize, int nelem, CFILE *cfile)
Definition: cfilelist.cpp:385
#define CF_SORT_NAME
Definition: cfile.h:93
GLint GLsizei count
Definition: Gl.h:1491
int cfwrite_compressed(void *param_buf, int param_elsize, int param_nelem, CFILE *cfile)
Definition: cfilelist.cpp:426
#define stricmp(s1, s2)
Definition: config.h:271
void cf_sort_filenames(SCP_vector< SCP_string > &list, int sort, SCP_vector< file_list_info > *info)
Definition: cfilelist.cpp:29
const GLubyte * c
Definition: Glext.h:8376
#define strcpy_s(...)
Definition: safe_strings.h:67