File: | src/text_public.c |
Location: | line 672, column 3 |
Description: | Value stored to 'ret' is never read |
1 | /* |
2 | * |
3 | * |
4 | * Copyright (c) 2003 Johannes Prix |
5 | * Copyright (c) 2004-2010 Arthur Huillet |
6 | * |
7 | * This file is part of Freedroid |
8 | * |
9 | * Freedroid is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or |
12 | * (at your option) any later version. |
13 | * |
14 | * Freedroid is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with Freedroid; see the file COPYING. If not, write to the |
21 | * Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
22 | * MA 02111-1307 USA |
23 | * |
24 | */ |
25 | |
26 | /** |
27 | * This file contains some text code, that is also needed in the |
28 | * dialog editor. |
29 | */ |
30 | |
31 | #define _text_public_c |
32 | |
33 | #include "system.h" |
34 | |
35 | #include "defs.h" |
36 | #include "struct.h" |
37 | #include "proto.h" |
38 | #include "global.h" |
39 | |
40 | #include <zlib.h> |
41 | |
42 | extern int debug_level; |
43 | |
44 | /** |
45 | * This function works a malloc, except that it also checks for |
46 | * success and terminates in case of "out of memory", so we don't |
47 | * need to do this always in the code. |
48 | */ |
49 | void *MyMalloc(long Mamount) |
50 | { |
51 | void *Mptr = NULL((void*)0); |
52 | |
53 | // make Gnu-compatible even if on a broken system: |
54 | if (Mamount == 0) |
55 | Mamount = 1; |
56 | |
57 | if ((Mptr = calloc(1, (size_t) Mamount)) == NULL((void*)0)) { |
58 | fprintf(stderrstderr, " MyMalloc(%ld) did not succeed!\n", Mamount); |
59 | fflush(stderrstderr); |
60 | Terminate(EXIT_FAILURE1); |
61 | } |
62 | |
63 | return Mptr; |
64 | |
65 | }; // void* MyMalloc ( long Mamount ) |
66 | |
67 | /** |
68 | * This function is used for debugging purposes. It writes the |
69 | * given string on the screen, or simply does |
70 | * nothing according to currently set debug level. |
71 | */ |
72 | void DebugPrintf(int db_level, const char *fmt, ...) |
73 | { |
74 | va_list args; |
75 | va_start(args, fmt)__builtin_va_start(args, fmt); |
76 | |
77 | if (db_level <= debug_level) { |
78 | vfprintf(stderrstderr, fmt, args); |
79 | } |
80 | |
81 | va_end(args)__builtin_va_end(args); |
82 | }; // void DebugPrintf ( int db_level, char *fmt, ...) |
83 | |
84 | /** |
85 | * This function should help to simplify and standardize the many error |
86 | * messages possible in FreedroidRPG. |
87 | */ |
88 | void error_message(const char *fn, const char *fmt, int error_type, ...) |
89 | { |
90 | if (error_type & SILENT) |
91 | return; |
92 | |
93 | va_list args; |
94 | va_start(args, error_type)__builtin_va_start(args, error_type); |
95 | |
96 | fprintf(stderrstderr, "\n---------------------------------------------------------------------------------\n" |
97 | "FreedroidRPG %s encountered a problem in function: %s\n", freedroid_version, fn); |
98 | vfprintf(stderrstderr, fmt, args); |
99 | fprintf(stderrstderr, "\n"); |
100 | |
101 | va_end(args)__builtin_va_end(args); |
102 | |
103 | if (error_type & PLEASE_INFORM) { |
104 | fprintf(stderrstderr, "\n\n" |
105 | "If you encounter this message, please inform the FreedroidRPG developers about it!\n" |
106 | "You can\n" |
107 | " send an e-mail to freedroid-discussion AT lists.sourceforge.net\n""" |
108 | " mention it on our IRC channel #freedroid on irc.freenode.net\n" |
109 | " or report the bug on our tracker at http://bugs.freedroid.org/\n" |
110 | "\n" |
111 | "Thank you!\n"); |
112 | } |
113 | |
114 | if (error_type & IS_FATAL) { |
115 | fprintf(stderrstderr, "\nFreedroidRPG will terminate now to draw attention to the problems it could\n" |
116 | "not resolve. We are sorry if that interrupts a major game of yours.\n" |
117 | "---------------------------------------------------------------------------------\n"); |
118 | } else { |
119 | fprintf(stderrstderr, "\nThe problem mentioned above is not fatal, we continue the execution.\n" |
120 | "---------------------------------------------------------------------------------\n"); |
121 | } |
122 | |
123 | if (error_type & IS_FATAL) |
124 | Terminate(EXIT_FAILURE1); |
125 | } |
126 | |
127 | /** |
128 | * This function does something similar to memmem. Indeed, it would be |
129 | * best perhaps if it did exactly the same as memmem, but since we do not |
130 | * use gnu extensions for compatibility reasons, we go this way. |
131 | * |
132 | * Be careful with using this function for searching just one byte!! |
133 | * |
134 | * Be careful with using this function for non-string NEEDLE!! |
135 | * |
136 | * Haystack can of course have ANY form!!! |
137 | * |
138 | */ |
139 | void *MyMemmem(char *haystack, size_t haystacklen, char *needle, size_t needlelen) |
140 | { |
141 | char *NextFoundPointer; |
142 | void *MatchPointer; |
143 | size_t SearchPos = 0; |
144 | |
145 | while (haystacklen - SearchPos > 0) { |
146 | // We search for the first match OF THE FIRST CHARACTER of needle |
147 | // |
148 | NextFoundPointer = memchr(haystack + SearchPos, needle[0], haystacklen - SearchPos); |
149 | |
150 | // if not even that was found, we can immediately return and report our failure to find it |
151 | // |
152 | if (NextFoundPointer == NULL((void*)0)) |
153 | return (NULL((void*)0)); |
154 | |
155 | // Otherwise we see, if also the rest of the strings match this time ASSUMING THEY ARE STRINGS! |
156 | // In case of a match, we can return immediately |
157 | // |
158 | MatchPointer = strstr(NextFoundPointer, needle); |
159 | if (MatchPointer != NULL((void*)0)) |
160 | return (MatchPointer); |
161 | |
162 | // At this point, we know that we had no luck with this one occasion of a first-character-match |
163 | // and must continue after this one occasion with our search |
164 | SearchPos = NextFoundPointer - haystack + 1; |
165 | } |
166 | |
167 | return (NULL((void*)0)); |
168 | }; // void *MyMemmem ( ... ); |
169 | |
170 | /** |
171 | * This function looks for a string begin indicator and takes the string |
172 | * from after there up to a string end indicator and mallocs memory for |
173 | * it, copies it there and returns it. |
174 | * The original source string specified should in no way be modified. |
175 | * Returns 0 if the prefix string is not present |
176 | */ |
177 | char *ReadAndMallocStringFromDataOptional(char *SearchString, const char *StartIndicationString, const char *EndIndicationString) |
178 | { |
179 | char *SearchPointer; |
180 | char *EndOfStringPointer; |
181 | char *ReturnString = NULL((void*)0); |
182 | int StringLength; |
183 | |
184 | SearchPointer = strstr(SearchString, StartIndicationString); |
185 | |
186 | if (!SearchPointer) |
187 | return 0; |
188 | |
189 | // Now we move to the beginning |
190 | SearchPointer += strlen(StartIndicationString); |
191 | |
192 | // Now we move to the end with the end pointer |
193 | EndOfStringPointer = strstr(SearchPointer, EndIndicationString); |
194 | if (!EndOfStringPointer) |
195 | return 0; |
196 | |
197 | // Now we allocate memory and copy the string (even empty string)... |
198 | StringLength = EndOfStringPointer - SearchPointer; |
199 | ReturnString = MyMalloc(StringLength + 1); |
200 | strncpy(ReturnString, SearchPointer, StringLength)__builtin_strncpy (ReturnString, SearchPointer, StringLength); |
201 | ReturnString[StringLength] = 0; |
202 | |
203 | return ReturnString; |
204 | } |
205 | |
206 | /** |
207 | * This function looks for a string begin indicator and takes the string |
208 | * from after there up to a string end indicator and mallocs memory for |
209 | * it, copies it there and returns it. |
210 | * The original source string specified should in no way be modified. |
211 | * The lack of searched string is fatal. |
212 | */ |
213 | char *ReadAndMallocStringFromData(char *SearchString, const char *StartIndicationString, const char *EndIndicationString) |
214 | { |
215 | char *result = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString); |
216 | if (!result) { |
217 | fprintf(stderrstderr, "\n\nStartIndicationString: '%s'\nEndIndicationString: '%s'\n", StartIndicationString, EndIndicationString); |
218 | error_message(__FUNCTION__, "\ |
219 | The string that is supposed to prefix an entry in a text data file\n\ |
220 | of FreedroidRPG was not found within this text data file.\n\ |
221 | This indicates some corruption in the data file in question.", PLEASE_INFORM | IS_FATAL); |
222 | } |
223 | return result; |
224 | }; // char* ReadAndMallocStringFromData ( ... ) |
225 | |
226 | /** |
227 | * This function counts the number of occurences of a string in a given |
228 | * other string. |
229 | */ |
230 | int CountStringOccurences(char *SearchString, const char *TargetString) |
231 | { |
232 | int Counter = 0; |
233 | char *CountPointer; |
234 | |
235 | CountPointer = SearchString; |
236 | |
237 | while ((CountPointer = strstr(CountPointer, TargetString)) != NULL((void*)0)) { |
238 | CountPointer += strlen(TargetString); |
239 | Counter++; |
240 | } |
241 | return (Counter); |
242 | }; // CountStringOccurences ( char* SearchString , char* TargetString ) |
243 | |
244 | /** |
245 | * This function read in a file with the specified name, allocated |
246 | * memory for it of course, looks for the file end string and then |
247 | * terminates the whole read in file with a 0 character, so that it |
248 | * can easily be treated like a common string. |
249 | */ |
250 | char *ReadAndMallocAndTerminateFile(const char *filename, const char *File_End_String) |
251 | { |
252 | FILE *DataFile; |
253 | char *Data; |
254 | char *ReadPointer; |
255 | long MemoryAmount; |
256 | |
257 | // Read the whole theme data to memory. We use binary mode, as we |
258 | // don't want to have to deal with any carriage return/line feed |
259 | // convention mess on win32 or something... |
260 | // |
261 | if ((DataFile = fopen(filename, "rb")) == NULL((void*)0)) { |
262 | fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename); |
263 | |
264 | error_message(__FUNCTION__, "\ |
265 | FreedroidRPG was unable to open a given text file,\n\ |
266 | that should be there and should be accessible.\n\ |
267 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM | IS_FATAL); |
268 | } else { |
269 | DebugPrintf(1, "\nchar* ReadAndMallocAndTerminateFile ( char* filename ) : Opening file succeeded..."); |
270 | } |
271 | |
272 | int filelen = FS_filelength(DataFile); |
273 | MemoryAmount = filelen + 100; |
274 | Data = (char *)MyMalloc(MemoryAmount); |
275 | |
276 | if (fread(Data, 1, MemoryAmount, DataFile) < filelen && ferror(DataFile)) { |
277 | error_message(__FUNCTION__, "\ |
278 | FreedroidRPG was unable to read a given text file, that should be there and\n\ |
279 | should be accessible.\n\ |
280 | Filename: %s", PLEASE_INFORM | IS_FATAL, filename); |
281 | } else { |
282 | DebugPrintf(1, "\n%s(): Reading file succeeded...", __FUNCTION__); |
283 | } |
284 | |
285 | if (fclose(DataFile) == EOF(-1)) { |
286 | fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename); |
287 | error_message(__FUNCTION__, "\ |
288 | FreedroidRPG was unable to close a given text file, that should be there and\n\ |
289 | should be accessible.\n\ |
290 | This indicates a strange bug in this installation of Freedroid, that is\n\ |
291 | very likely a problem with the file/directory permissions of the files\n\ |
292 | belonging to FreedroidRPG.", PLEASE_INFORM | IS_FATAL); |
293 | } else { |
294 | DebugPrintf(1, "\n%s(): file closed successfully...\n", __FUNCTION__); |
295 | } |
296 | |
297 | // NOTE: Since we do not assume to always have pure text files here, we switched to |
298 | // MyMemmem, so that we can handle 0 entries in the middle of the file content as well |
299 | if (File_End_String) { |
300 | if ((ReadPointer = MyMemmem(Data, (size_t) MemoryAmount, (char *)File_End_String, (size_t) strlen(File_End_String))) == NULL((void*)0)) { |
301 | error_message(__FUNCTION__, "FreedroidRPG was unable to find the string, that should indicate the end of\n" |
302 | "the given text file within this file.\n" |
303 | "This indicates a corrupt or outdated data or saved game file." |
304 | " filename: '%s' - File_End_String: '%s'", |
305 | PLEASE_INFORM | IS_FATAL, filename, File_End_String); |
306 | } else { |
307 | ReadPointer[0] = 0; |
308 | } |
309 | } else |
310 | Data[MemoryAmount - 100] = 0; |
311 | |
312 | return (Data); |
313 | } |
314 | |
315 | /** |
316 | * This function tries to locate a string in some given data string. |
317 | * The data string is assumed to be null terminated. Otherwise SEGFAULTS |
318 | * might happen. |
319 | * |
320 | * The return value is a pointer to the first instance where the substring |
321 | * we are searching is found in the main text. |
322 | */ |
323 | char *LocateStringInData(char *SearchBeginPointer, const char *SearchTextPointer) |
324 | { |
325 | char *temp; |
326 | |
327 | if ((temp = strstr(SearchBeginPointer, SearchTextPointer)) == NULL((void*)0)) { |
328 | fprintf(stderrstderr, "\n\nSearchTextPointer: '%s'\n", SearchTextPointer); |
329 | error_message(__FUNCTION__, "\ |
330 | The string that was supposed to be in the text data file could not be found.\n\ |
331 | This indicates a corrupted or seriously outdated game data or saved game file.", PLEASE_INFORM | IS_FATAL); |
332 | } |
333 | |
334 | return (temp); |
335 | |
336 | }; // char* LocateStringInData ( ... ) |
337 | |
338 | /** |
339 | * This function should analyze a given passage of text, locate an |
340 | * indicator for a value, and read in the value. |
341 | */ |
342 | void |
343 | ReadValueFromStringWithDefault(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString, |
344 | const char *DefaultValueString, void *TargetValue, char *EndOfSearchSectionPointer) |
345 | { |
346 | char OldTerminaterCharValue = 0; |
347 | const char *SourceLocation; |
348 | |
349 | // We shortly make a termination char into the string. |
350 | if (EndOfSearchSectionPointer) { |
351 | OldTerminaterCharValue = EndOfSearchSectionPointer[0]; |
352 | EndOfSearchSectionPointer[0] = 0; |
353 | } |
354 | |
355 | // Now we locate the spot, where we finally will find our value |
356 | SourceLocation = strstr(SearchBeginPointer, ValuePreceedText); |
357 | if (SourceLocation) |
358 | SourceLocation += strlen(ValuePreceedText); |
359 | else |
360 | SourceLocation = DefaultValueString; |
361 | |
362 | // Attention!!! |
363 | // Now we try to read in the value!!! |
364 | // |
365 | if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) { |
366 | error_message(__FUNCTION__, "sscanf using a certain format string failed!\n" |
367 | "This indicates a corrupted or seriously outdated game data or saved game file.\n" |
368 | " FormatString: '%s' - ValuePreceedText: '%s'", |
369 | PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText); |
370 | } |
371 | // Now that we are done, we restore the given SearchArea to former glory |
372 | if (EndOfSearchSectionPointer) { |
373 | EndOfSearchSectionPointer[0] = OldTerminaterCharValue; |
374 | } |
375 | } |
376 | |
377 | /** |
378 | * This function should analyze a given passage of text, locate an |
379 | * indicator for a value, and read in the value. |
380 | */ |
381 | void |
382 | ReadValueFromString(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString, void *TargetValue, |
383 | char *EndOfSearchSectionPointer) |
384 | { |
385 | char OldTerminaterCharValue = 0; |
386 | char *SourceLocation; |
387 | |
388 | // We shortly make a termination char into the string if needed |
389 | if (EndOfSearchSectionPointer) { |
390 | OldTerminaterCharValue = EndOfSearchSectionPointer[0]; |
391 | EndOfSearchSectionPointer[0] = 0; |
392 | } |
393 | // Now we locate the spot, where we finally will find our value |
394 | SourceLocation = LocateStringInData(SearchBeginPointer, ValuePreceedText); |
395 | SourceLocation += strlen(ValuePreceedText); |
396 | |
397 | // Attention!!! |
398 | // Now we try to read in the value!!! |
399 | // |
400 | if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) { |
401 | error_message(__FUNCTION__, "sscanf using a certain format string failed!\n" |
402 | "This indicates a corrupted or seriously outdated game data or saved game file.\n" |
403 | " FormatString: '%s' - ValuePreceedText: '%s'", |
404 | PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText); |
405 | } |
406 | |
407 | if (EndOfSearchSectionPointer) { |
408 | // Now that we are done, we restore the given SearchArea to former glory |
409 | EndOfSearchSectionPointer[0] = OldTerminaterCharValue; |
410 | } |
411 | |
412 | }; // void ReadValueFromString( ... ) |
413 | |
414 | /** |
415 | * \deprecated Use get_range_from_string. |
416 | * \brief Read a range of integer values from a string with a default. |
417 | * |
418 | * Read the range between two indications. The function don't accept negative value. |
419 | * |
420 | * \param SearchString The global string to search the range. |
421 | * \param StartIndicationString The start indication. |
422 | * \param EndIndicationString The end indication. |
423 | * \param min,max The result of the conversion. |
424 | * \param default_val The value used as default. |
425 | * \return FALSE if the conversion failed and set min and max to default_val, else return TRUE. |
426 | */ |
427 | int ReadRangeFromString(char *SearchString, const char *StartIndicationString, const char *EndIndicationString, int *min, int *max, int default_val) |
428 | { |
429 | int result; |
430 | |
431 | // First, we have to get the range string. |
432 | char *search_ptr = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString); |
433 | |
434 | result = get_range_from_string(search_ptr, min, max, default_val); |
435 | |
436 | //Handle corrupted values. |
437 | if (*min < 0) { |
438 | error_message(__FUNCTION__, "\ |
439 | The value read in as a minimum (%d) is a negative number.\n\ |
440 | This most likely means corrupted data.\n\ |
441 | Setting both the maximum and minimum to the default value (%d).", NO_REPORT, *min, default_val); |
442 | *min = *max = default_val; |
443 | return FALSE(0); |
444 | } |
445 | |
446 | free(search_ptr); |
447 | |
448 | return result; |
449 | } |
450 | |
451 | /** |
452 | * \brief Read a range of integer values from a string with a default. |
453 | * \param str The constant string to convert. |
454 | * \param min,max The result of the conversion. |
455 | * \param default_value The value used in case of error or NULL. |
456 | * \return FALSE if the conversion failed and set min and max to default_val, else return TRUE. |
457 | */ |
458 | int get_range_from_string(const char *str, int *min, int *max, int default_value) |
459 | { |
460 | char *ptr; |
461 | |
462 | if (!str) { |
463 | // String is NULL, set everything to default value. |
464 | *min = *max = default_value; |
465 | return TRUE(1); |
466 | } |
467 | |
468 | *min = strtol(str, &ptr, 10); |
469 | |
470 | if (str == ptr) { |
471 | goto read_error; |
472 | } |
473 | |
474 | if (*ptr == '\0') { |
475 | // Conversion succeeded and the string contains only one value. |
476 | *max = *min; |
477 | return TRUE(1); |
478 | } |
479 | |
480 | if (*ptr != ':') { |
481 | goto read_error; |
482 | } |
483 | |
484 | // The string contains potentially another value. |
485 | str = ++ptr; |
486 | *max = strtol(str, &ptr, 10); |
487 | |
488 | if (str == ptr) { |
489 | goto read_error; |
490 | } |
491 | // Conversion of max value succeeded |
492 | |
493 | if (*max >= *min) { |
494 | return TRUE(1); // Values are in the good order. |
495 | } |
496 | |
497 | error_message(__FUNCTION__, "The value read in as a maximum (%d) is less than the minimum (%d).\n" |
498 | "This most likely means corrupted data.\n" |
499 | "Setting both the maximum and minimum to the default value (%d).", |
500 | NO_REPORT, *max, *min, default_value); |
501 | *min = *max = default_value; |
502 | return FALSE(0); |
503 | |
504 | read_error: |
505 | // Failed to read the string. |
506 | error_message(__FUNCTION__, "The string (\"%s\") cannot be legaly converted to a range of integers.\n" |
507 | "This most likely means corrupted data.\n" |
508 | "Setting both the maximum and minimum to the default value (%d).", |
509 | NO_REPORT, str, default_value); |
510 | *min = *max = default_value; |
511 | return FALSE(0); |
512 | } |
513 | |
514 | /** |
515 | * This function does the rotation of a given vector by a given angle. |
516 | * The vector is a vector. |
517 | * The angle given is in DEGREE MEASURE, i.e. 0-360 or so, maybe more or |
518 | * less than that, but you get what I mean... |
519 | */ |
520 | void RotateVectorByAngle(moderately_finepoint * vector, float rot_angle) |
521 | { |
522 | moderately_finepoint new_vect; |
523 | float rad_angle; |
524 | |
525 | if (rot_angle == 0) |
526 | return; |
527 | |
528 | rad_angle = rot_angle * (M_PI3.14159265358979323846 / 180.0); |
529 | |
530 | DebugPrintf(2, "\n RAD_ANGLE : %f ", rad_angle); |
531 | new_vect.x = sin(rad_angle) * vector->y + cos(rad_angle) * vector->x; |
532 | new_vect.y = cos(rad_angle) * vector->y - sin(rad_angle) * vector->x; |
533 | vector->x = new_vect.x; |
534 | vector->y = new_vect.y; |
535 | |
536 | }; // void RotateVectorByAngle ( ... ) |
537 | |
538 | /*---------------------------------------------------------------------- |
539 | * Copyright (C) 1997-2001 Id Software, Inc., under GPL |
540 | * |
541 | * FS_filelength().. (taken from quake2) |
542 | * contrary to stat() this fct is nice and portable, |
543 | *----------------------------------------------------------------------*/ |
544 | int FS_filelength(FILE * f) |
545 | { |
546 | int pos; |
547 | int end; |
548 | |
549 | pos = ftell(f); |
550 | fseek(f, 0, SEEK_END2); |
551 | end = ftell(f); |
552 | fseek(f, pos, SEEK_SET0); |
553 | |
554 | // DebugPrintf ( -4 , "\n%s(): file length: %d." , __FUNCTION__ , end ); |
555 | |
556 | return end; |
557 | }; // int FS_filelength (FILE *f) |
558 | |
559 | /*------------------------------------------------------------------------- |
560 | * Inflate a given stream using zlib |
561 | * |
562 | * Takes DataFile file and points DataBuffer to a buffer containing the |
563 | * uncompressed data. Sets '*size' to the size of said uncompressed data, if size |
564 | * is not NULL. |
565 | * |
566 | * Returns nonzero in case of error. |
567 | ***/ |
568 | int inflate_stream(FILE * DataFile, unsigned char **DataBuffer, int *size) |
569 | { |
570 | int filelen = FS_filelength(DataFile); |
571 | unsigned char *src = MyMalloc(filelen + 1); |
572 | int cursz = 1048576; //start with 1MB |
573 | unsigned char *temp_dbuffer = malloc(cursz); |
574 | if (fread(src, filelen, 1, DataFile) != 1) { |
575 | error_message(__FUNCTION__, "Error reading compressed data stream.", PLEASE_INFORM); |
576 | free(temp_dbuffer); |
577 | free(src); |
578 | return -1; |
579 | } |
580 | |
581 | int ret; |
582 | z_stream strm; |
583 | |
584 | /* copy paste of public domain tool "zpipe" */ |
585 | /* big thanks to zlib authors */ |
586 | /* allocate inflate state */ |
587 | strm.zalloc = Z_NULL0; |
588 | strm.zfree = Z_NULL0; |
589 | strm.opaque = Z_NULL0; |
590 | strm.avail_in = filelen; |
591 | strm.next_in = src; |
592 | strm.avail_out = cursz; |
593 | strm.next_out = (Bytef *) temp_dbuffer; |
594 | |
595 | ret = inflateInit2(&strm, 47)inflateInit2_((&strm), (47), "1.2.8", (int)sizeof(z_stream )); |
596 | if (ret != Z_OK0) { |
597 | error_message(__FUNCTION__, "\ |
598 | zlib was unable to start decompressing a stream.\n\ |
599 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM); |
600 | free(temp_dbuffer); |
601 | free(src); |
602 | return -1; |
603 | } |
604 | |
605 | do { |
606 | if (!strm.avail_out) { //out of memory? increase |
607 | temp_dbuffer = realloc(temp_dbuffer, cursz + 1048576); //increase size by 1MB |
608 | strm.next_out = temp_dbuffer + cursz; |
609 | cursz += 1048576; |
610 | strm.avail_out += 1048576; |
611 | } |
612 | ret = inflate(&strm, Z_NO_FLUSH0); |
613 | switch (ret) { |
614 | case Z_OK0: |
615 | break; |
616 | case Z_NEED_DICT2: |
617 | case Z_DATA_ERROR(-3): |
618 | case Z_MEM_ERROR(-4): |
619 | (void)inflateEnd(&strm); |
620 | |
621 | error_message(__FUNCTION__, "\ |
622 | zlib was unable to decompress a stream\n\ |
623 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM); |
624 | free(temp_dbuffer); |
625 | free(src); |
626 | return -1; |
627 | break; |
628 | } |
629 | } while (ret != Z_STREAM_END1); |
630 | |
631 | (*DataBuffer) = (unsigned char *)malloc(strm.total_out + 1); |
632 | memcpy(*DataBuffer, temp_dbuffer, strm.total_out); |
633 | (*DataBuffer)[strm.total_out] = 0; |
634 | |
635 | if (size != NULL((void*)0)) |
636 | *size = strm.total_out; |
637 | |
638 | (void)inflateEnd(&strm); |
639 | free(src); |
640 | free(temp_dbuffer); |
641 | |
642 | return 0; |
643 | } |
644 | |
645 | int deflate_to_stream(unsigned char *source_buffer, int size, FILE *dest) |
646 | { |
647 | int ret; |
648 | unsigned have; |
649 | z_stream strm; |
650 | #define CHUNK16384 16384 |
651 | unsigned char out[CHUNK16384]; |
652 | |
653 | /* allocate deflate state */ |
654 | strm.zalloc = Z_NULL0; |
655 | strm.zfree = Z_NULL0; |
656 | strm.opaque = Z_NULL0; |
657 | strm.avail_in = size; |
658 | strm.next_in = source_buffer; |
659 | |
660 | ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)deflateInit2_((&strm),((-1)),(8),(31),(8), (0), "1.2.8", ( int)sizeof(z_stream)); |
661 | if (ret != Z_OK0) { |
662 | error_message(__FUNCTION__, "\ |
663 | zlib was unable to start compressing a string.", PLEASE_INFORM); |
664 | return -1; |
665 | } |
666 | |
667 | /* run deflate() on input until output buffer not full, finish |
668 | compression if all of source has been read in */ |
669 | do { |
670 | strm.avail_out = CHUNK16384; |
671 | strm.next_out = out; |
672 | ret = deflate(&strm, Z_FINISH4); /* no bad return value */ |
Value stored to 'ret' is never read | |
673 | have = CHUNK16384 - strm.avail_out; |
674 | if (fwrite(out, 1, have, dest) != have || ferror(dest)) { |
675 | (void)deflateEnd(&strm); |
676 | return -1; |
677 | } |
678 | } while (strm.avail_out == 0); |
679 | |
680 | /* clean up and return */ |
681 | (void)deflateEnd(&strm); |
682 | |
683 | return 0; |
684 | } |
685 | |
686 | #undef _text_public_c |