diff options
author | Strangerke | 2012-10-10 08:26:41 +0200 |
---|---|---|
committer | Strangerke | 2012-10-10 08:26:41 +0200 |
commit | b164cbb571fc4e0f2a6f002760a851d8ac592540 (patch) | |
tree | 4d25f2e1f8241f6f3352fd9fb1135f5faa36dfd4 /engines/wintermute/utils | |
parent | b2f2f8d7b08b40e43702e8db325f8136066f10be (diff) | |
parent | 1e200620d673af4acdd2d128ed6e390df001aacf (diff) | |
download | scummvm-rg350-b164cbb571fc4e0f2a6f002760a851d8ac592540.tar.gz scummvm-rg350-b164cbb571fc4e0f2a6f002760a851d8ac592540.tar.bz2 scummvm-rg350-b164cbb571fc4e0f2a6f002760a851d8ac592540.zip |
Merge branch 'master' of github.com:scummvm/scummvm into mortevielle
Conflicts:
base/plugins.cpp
configure
Diffstat (limited to 'engines/wintermute/utils')
-rw-r--r-- | engines/wintermute/utils/convert_utf.cpp | 615 | ||||
-rw-r--r-- | engines/wintermute/utils/convert_utf.h | 148 | ||||
-rw-r--r-- | engines/wintermute/utils/crc.cpp | 237 | ||||
-rw-r--r-- | engines/wintermute/utils/crc.h | 85 | ||||
-rw-r--r-- | engines/wintermute/utils/path_util.cpp | 101 | ||||
-rw-r--r-- | engines/wintermute/utils/path_util.h | 49 | ||||
-rw-r--r-- | engines/wintermute/utils/string_util.cpp | 232 | ||||
-rw-r--r-- | engines/wintermute/utils/string_util.h | 56 | ||||
-rw-r--r-- | engines/wintermute/utils/utils.cpp | 261 | ||||
-rw-r--r-- | engines/wintermute/utils/utils.h | 64 |
10 files changed, 1848 insertions, 0 deletions
diff --git a/engines/wintermute/utils/convert_utf.cpp b/engines/wintermute/utils/convert_utf.cpp new file mode 100644 index 0000000000..7ebc011d01 --- /dev/null +++ b/engines/wintermute/utils/convert_utf.cpp @@ -0,0 +1,615 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Source code file. + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Sept 2001: fixed const & error conditions per + mods suggested by S. Parent & A. Lillich. + June 2002: Tim Dodd added detection and handling of incomplete + source sequences, enhanced error detection, added casts + to eliminate compiler warnings. + July 2003: slight mods to back out aggressive FFFE detection. + Jan 2004: updated switches in from-UTF8 conversions. + Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. + + See the header file "ConvertUTF.h" for complete documentation. + +------------------------------------------------------------------------ */ + + +#include "engines/wintermute/utils/convert_utf.h" +#ifdef CVTUTF_DEBUG +#include "common/textconsole.h" +#endif + +namespace Wintermute { + +static const int halfShift = 10; /* used for shifting by 10 bits */ + +static const UTF32 halfBase = 0x0010000UL; +static const UTF32 halfMask = 0x3FFUL; + +#define UNI_SUR_HIGH_START (UTF32)0xD800 +#define UNI_SUR_HIGH_END (UTF32)0xDBFF +#define UNI_SUR_LOW_START (UTF32)0xDC00 +#define UNI_SUR_LOW_END (UTF32)0xDFFF +#define false 0 +#define true 1 + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + if (target >= targetEnd) { + result = targetExhausted; + break; + } + ch = *source++; + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_LEGAL_UTF32) { + if (flags == strictConversion) { + result = sourceIllegal; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + --source; /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF32 *target = *targetStart; + UTF32 ch, ch2; + while (source < sourceEnd) { + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + if (target >= targetEnd) { + source = oldSource; /* Back up source pointer! */ + result = targetExhausted; + break; + } + *target++ = ch; + } + *sourceStart = source; + *targetStart = target; +#ifdef CVTUTF_DEBUG + if (result == sourceIllegal) { + warning("ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); + } +#endif + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is + * left as-is for anyone who may want to do such conversion, which was + * allowed in earlier algorithms. + */ +static const char trailingBytesForUTF8[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 +}; + +/* + * Magic values subtracted from a buffer value during UTF8 conversion. + * This table contains as many values as there might be trailing bytes + * in a UTF-8 sequence. + */ +static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL + }; + +/* + * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed + * into the first byte, depending on how many bytes follow. There are + * as many entries in this table as there are UTF-8 sequence types. + * (I.e., one byte sequence, two byte... etc.). Remember that sequencs + * for *legal* UTF-8 will be 4 or fewer bytes total. + */ +static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +/* --------------------------------------------------------------------- */ + +/* The interface converts a whole buffer to avoid function-call overhead. + * Constants have been gathered. Loops & conditionals have been removed as + * much as possible for efficiency, in favor of drop-through switches. + * (See "Note A" at the bottom of the file for equivalent code.) + * If your compiler supports it, the "isLegalUTF8" call can be turned + * into an inline function. + */ + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF16 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + const UTF16 *oldSource = source; /* In case we have to back up because of target overflow. */ + ch = *source++; + /* If we have a surrogate pair, convert to UTF32 first. */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { + /* If the 16 bits following the high surrogate are in the source buffer... */ + if (source < sourceEnd) { + UTF32 ch2 = *source; + /* If it's a low surrogate, convert to UTF32. */ + if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { + ch = ((ch - UNI_SUR_HIGH_START) << halfShift) + + (ch2 - UNI_SUR_LOW_START) + halfBase; + ++source; + } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } else { /* We don't have the 16 bits following the high surrogate. */ + --source; /* return to the high surrogate */ + result = sourceExhausted; + break; + } + } else if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* Figure out how many bytes the result will require */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch < (UTF32)0x110000) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + } + + target += bytesToWrite; + if (target > targetEnd) { + source = oldSource; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * If not calling this from ConvertUTF8to*, then the length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns false. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ + +static Boolean isLegalUTF8(const UTF8 *source, int length) { + UTF8 a; + const UTF8 *srcptr = source + length; + switch (length) { + default: + return false; + /* Everything else falls through when "true"... */ + case 4: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 3: + if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; + case 2: + if ((a = (*--srcptr)) > 0xBF) return false; + + switch (*source) { + /* no fall-through in this inner switch */ + case 0xE0: + if (a < 0xA0) return false; + break; + case 0xED: + if (a > 0x9F) return false; + break; + case 0xF0: + if (a < 0x90) return false; + break; + case 0xF4: + if (a > 0x8F) return false; + break; + default: + if (a < 0x80) return false; + } + + case 1: + if (*source >= 0x80 && *source < 0xC2) return false; + } + if (*source > 0xF4) return false; + return true; +} + +/* --------------------------------------------------------------------- */ + +/* + * Exported function to return whether a UTF-8 sequence is legal or not. + * This is not used here; it's just exported. + */ +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { + int length = trailingBytesForUTF8[*source] + 1; + if (source + length > sourceEnd) { + return false; + } + return isLegalUTF8(source, length); +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF16 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 4: + ch += *source++; + ch <<= 6; /* remember, illegal UTF-8 */ + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = (UTF16)ch; /* normal case */ + } + } else if (ch > UNI_MAX_UTF16) { + if (flags == strictConversion) { + result = sourceIllegal; + source -= (extraBytesToRead + 1); /* return to the start */ + break; /* Bail out; shouldn't continue */ + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + /* target is a character in range 0xFFFF - 0x10FFFF. */ + if (target + 1 >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up source pointer! */ + result = targetExhausted; + break; + } + ch -= halfBase; + *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); + *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF32 *source = *sourceStart; + UTF8 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch; + unsigned short bytesToWrite = 0; + const UTF32 byteMask = 0xBF; + const UTF32 byteMark = 0x80; + ch = *source++; + if (flags == strictConversion) { + /* UTF-16 surrogate values are illegal in UTF-32 */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + --source; /* return to the illegal value itself */ + result = sourceIllegal; + break; + } + } + /* + * Figure out how many bytes the result will require. Turn any + * illegally large UTF32 things (> Plane 17) into replacement chars. + */ + if (ch < (UTF32)0x80) { + bytesToWrite = 1; + } else if (ch < (UTF32)0x800) { + bytesToWrite = 2; + } else if (ch < (UTF32)0x10000) { + bytesToWrite = 3; + } else if (ch <= UNI_MAX_LEGAL_UTF32) { + bytesToWrite = 4; + } else { + bytesToWrite = 3; + ch = UNI_REPLACEMENT_CHAR; + result = sourceIllegal; + } + + target += bytesToWrite; + if (target > targetEnd) { + --source; /* Back up source pointer! */ + target -= bytesToWrite; + result = targetExhausted; + break; + } + switch (bytesToWrite) { /* note: everything falls through. */ + case 4: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 3: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 2: + *--target = (UTF8)((ch | byteMark) & byteMask); + ch >>= 6; + case 1: + *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); + } + target += bytesToWrite; + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- */ + +ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags) { + ConversionResult result = conversionOK; + const UTF8 *source = *sourceStart; + UTF32 *target = *targetStart; + while (source < sourceEnd) { + UTF32 ch = 0; + unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; + if (source + extraBytesToRead >= sourceEnd) { + result = sourceExhausted; + break; + } + /* Do this check whether lenient or strict */ + if (! isLegalUTF8(source, extraBytesToRead + 1)) { + result = sourceIllegal; + break; + } + /* + * The cases all fall through. See "Note A" below. + */ + switch (extraBytesToRead) { + case 5: + ch += *source++; + ch <<= 6; + case 4: + ch += *source++; + ch <<= 6; + case 3: + ch += *source++; + ch <<= 6; + case 2: + ch += *source++; + ch <<= 6; + case 1: + ch += *source++; + ch <<= 6; + case 0: + ch += *source++; + } + ch -= offsetsFromUTF8[extraBytesToRead]; + + if (target >= targetEnd) { + source -= (extraBytesToRead + 1); /* Back up the source pointer! */ + result = targetExhausted; + break; + } + if (ch <= UNI_MAX_LEGAL_UTF32) { + /* + * UTF-16 surrogate values are illegal in UTF-32, and anything + * over Plane 17 (> 0x10FFFF) is illegal. + */ + if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { + if (flags == strictConversion) { + source -= (extraBytesToRead + 1); /* return to the illegal value itself */ + result = sourceIllegal; + break; + } else { + *target++ = UNI_REPLACEMENT_CHAR; + } + } else { + *target++ = ch; + } + } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ + result = sourceIllegal; + *target++ = UNI_REPLACEMENT_CHAR; + } + } + *sourceStart = source; + *targetStart = target; + return result; +} + +/* --------------------------------------------------------------------- + + Note A. + The fall-through switches in UTF-8 reading code save a + temp variable, some decrements & conditionals. The switches + are equivalent to the following loop: + { + int tmpBytesToRead = extraBytesToRead+1; + do { + ch += *source++; + --tmpBytesToRead; + if (tmpBytesToRead) ch <<= 6; + } while (tmpBytesToRead > 0); + } + In UTF-8 writing code, the switches on "bytesToWrite" are + similarly unrolled loops. + + --------------------------------------------------------------------- */ + +} // End of namespace Wintermute diff --git a/engines/wintermute/utils/convert_utf.h b/engines/wintermute/utils/convert_utf.h new file mode 100644 index 0000000000..a5f34456f5 --- /dev/null +++ b/engines/wintermute/utils/convert_utf.h @@ -0,0 +1,148 @@ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +// NOTE: Modifications have been made to the code for inclusion +// into ScummVM. + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ +#include "common/system.h" + +namespace Wintermute { + +typedef uint32 UTF32; /* at least 32 bits */ +typedef uint16 UTF16; /* at least 16 bits */ +typedef uint8 UTF8; /* typically 8 bits */ +typedef uint8 Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +ConversionResult ConvertUTF8toUTF16( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32( + const UTF8 **sourceStart, const UTF8 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF8 **targetStart, UTF8 *targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32( + const UTF16 **sourceStart, const UTF16 *sourceEnd, + UTF32 **targetStart, UTF32 *targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16( + const UTF32 **sourceStart, const UTF32 *sourceEnd, + UTF16 **targetStart, UTF16 *targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +} // End of namespace Wintermute + +/* --------------------------------------------------------------------- */ diff --git a/engines/wintermute/utils/crc.cpp b/engines/wintermute/utils/crc.cpp new file mode 100644 index 0000000000..e7ec45511b --- /dev/null +++ b/engines/wintermute/utils/crc.cpp @@ -0,0 +1,237 @@ +/********************************************************************** + * + * Filename: crc.c + * + * Description: Slow and fast implementations of the CRC standards. + * + * Notes: The parameters for each supported CRC standard are + * defined in the header file crc.h. The implementations + * here should stand up to further additions to that list. + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#include "engines/wintermute/utils/crc.h" + +namespace Wintermute { + +/* + * Derive parameters from the standard-specific parameters in crc.h. + */ +#define WIDTH (8 * sizeof(crc)) +#define TOPBIT (1 << (WIDTH - 1)) + +#if (REFLECT_DATA == TRUE) +#undef REFLECT_DATA +#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) +#else +#undef REFLECT_DATA +#define REFLECT_DATA(X) (X) +#endif + +#if (REFLECT_REMAINDER == TRUE) +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) +#else +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) (X) +#endif + + +/********************************************************************* + * + * Function: reflect() + * + * Description: Reorder the bits of a binary sequence, by reflecting + * them about the middle position. + * + * Notes: No checking is done that nBits <= 32. + * + * Returns: The reflection of the original data. + * + *********************************************************************/ +static unsigned long +reflect(unsigned long data, unsigned char nBits) { + unsigned long reflection = 0x00000000; + unsigned char bit; + + /* + * Reflect the data about the center bit. + */ + for (bit = 0; bit < nBits; ++bit) { + /* + * If the LSB bit is set, set the reflection of it. + */ + if (data & 0x01) { + reflection |= (1 << ((nBits - 1) - bit)); + } + + data = (data >> 1); + } + + return (reflection); + +} /* reflect() */ + + +/********************************************************************* + * + * Function: crcSlow() + * + * Description: Compute the CRC of a given message. + * + * Notes: + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcSlow(unsigned char const message[], int nBytes) { + crc remainder = INITIAL_REMAINDER; + int byte; + unsigned char bit; + + + /* + * Perform modulo-2 division, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) { + /* + * Bring the next byte into the remainder. + */ + remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) { + remainder = (remainder << 1) ^ POLYNOMIAL; + } else { + remainder = (remainder << 1); + } + } + } + + /* + * The final remainder is the CRC result. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcSlow() */ + + +crc crcTable[256]; + + +/********************************************************************* + * + * Function: crcInit() + * + * Description: Populate the partial CRC lookup table. + * + * Notes: This function must be rerun any time the CRC standard + * is changed. If desired, it can be run "offline" and + * the table results stored in an embedded system's ROM. + * + * Returns: None defined. + * + *********************************************************************/ +void +crcInit(void) { + crc remainder; + int dividend; + unsigned char bit; + + + /* + * Compute the remainder of each possible dividend. + */ + for (dividend = 0; dividend < 256; ++dividend) { + /* + * Start with the dividend followed by zeros. + */ + remainder = dividend << (WIDTH - 8); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) { + remainder = (remainder << 1) ^ POLYNOMIAL; + } else { + remainder = (remainder << 1); + } + } + + /* + * Store the result into the table. + */ + crcTable[dividend] = remainder; + } + +} /* crcInit() */ + + +/********************************************************************* + * + * Function: crcFast() + * + * Description: Compute the CRC of a given message. + * + * Notes: crcInit() must be called first. + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcFast(unsigned char const message[], int nBytes) { + crc remainder = INITIAL_REMAINDER; + unsigned char data; + int byte; + + + /* + * Divide the message by the polynomial, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) { + data = (unsigned char)(REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8))); + remainder = crcTable[data] ^ (remainder << 8); + } + + /* + * The final remainder is the CRC. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcFast() */ + + + +crc crc_initialize(void) { + crcInit(); + return INITIAL_REMAINDER; +} + +crc crc_process_byte(unsigned char byteVal, crc remainder) { + unsigned char data; + data = (unsigned char)(REFLECT_DATA(byteVal) ^ (remainder >> (WIDTH - 8))); + remainder = crcTable[data] ^ (remainder << 8); + return remainder; +} + +crc crc_finalize(crc remainder) { + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/crc.h b/engines/wintermute/utils/crc.h new file mode 100644 index 0000000000..77c2ea267f --- /dev/null +++ b/engines/wintermute/utils/crc.h @@ -0,0 +1,85 @@ +/********************************************************************** + * + * Filename: crc.h + * + * Description: A header file describing the various CRC standards. + * + * Notes: + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#ifndef _crc_h +#define _crc_h + +#include "common/system.h" // For types. + +namespace Wintermute { + +#ifndef TRUE +#define FALSE 0 +#define TRUE !FALSE +#endif + +/* + * Select the CRC standard from the list that follows. + */ +#define CRC32 + +#if defined(CRC_CCITT) + +typedef uint16 crc; + +#define CRC_NAME "CRC-CCITT" +#define POLYNOMIAL 0x1021 +#define INITIAL_REMAINDER 0xFFFF +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA FALSE +#define REFLECT_REMAINDER FALSE +#define CHECK_VALUE 0x29B1 + +#elif defined(CRC16) + +typedef uint16 crc; + +#define CRC_NAME "CRC-16" +#define POLYNOMIAL 0x8005 +#define INITIAL_REMAINDER 0x0000 +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xBB3D + +#elif defined(CRC32) + +typedef uint32 crc; + +#define CRC_NAME "CRC-32" +#define POLYNOMIAL 0x04C11DB7 +#define INITIAL_REMAINDER 0xFFFFFFFF +#define FINAL_XOR_VALUE 0xFFFFFFFF +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xCBF43926 + +#else + +#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd." + +#endif + +void crcInit(void); +crc crcSlow(unsigned char const message[], int nBytes); +crc crcFast(unsigned char const message[], int nBytes); + +extern "C" crc crc_initialize(void); +extern "C" crc crc_process_byte(unsigned char byteVal, crc remainder); +extern "C" crc crc_finalize(crc remainder); + +} // End of namespace Wintermute + +#endif /* _crc_h */ diff --git a/engines/wintermute/utils/path_util.cpp b/engines/wintermute/utils/path_util.cpp new file mode 100644 index 0000000000..298f0c268f --- /dev/null +++ b/engines/wintermute/utils/path_util.cpp @@ -0,0 +1,101 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "common/file.h" +#include "engines/wintermute/utils/path_util.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::unifySeparators(const AnsiString &path) { + AnsiString newPath = path; + + for (uint32 i = 0; i < newPath.size(); i++) { + if (newPath[i] == '\\') { + newPath.setChar('/', i); + } + } + + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::normalizeFileName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + newPath.toLowercase(); + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::combine(const AnsiString &path1, const AnsiString &path2) { + AnsiString newPath1 = unifySeparators(path1); + AnsiString newPath2 = unifySeparators(path2); + + if (!newPath1.hasSuffix("/") && !newPath2.hasPrefix("/")) { + newPath1 += "/"; + } + + return newPath1 + newPath2; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getDirectoryName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + Common::String filename = getFileName(path); + return Common::String(path.c_str(), path.size() - filename.size()); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + Common::String lastPart = Common::lastPathComponent(newPath, '/'); + if (lastPart[lastPart.size() - 1 ] != '/') { + return lastPart; + } else { + return path; + } +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileNameWithoutExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + // TODO: Prettify this. + AnsiString extension = Common::lastPathComponent(fileName, '.'); + for (uint32 i = 0; i < extension.size() + 1; i++) { + fileName.deleteLastChar(); + } + return fileName; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + return Common::lastPathComponent(path, '.'); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/path_util.h b/engines/wintermute/utils/path_util.h new file mode 100644 index 0000000000..7358c2aba0 --- /dev/null +++ b/engines/wintermute/utils/path_util.h @@ -0,0 +1,49 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_PATHUTILS_H +#define WINTERMUTE_PATHUTILS_H + +#include "engines/wintermute/dctypes.h" + +namespace Wintermute { + +class PathUtil { +public: + static AnsiString unifySeparators(const AnsiString &path); + static AnsiString normalizeFileName(const AnsiString &path); + static AnsiString combine(const AnsiString &path1, const AnsiString &path2); + static AnsiString getDirectoryName(const AnsiString &path); + static AnsiString getFileName(const AnsiString &path); + static AnsiString getFileNameWithoutExtension(const AnsiString &path); + static AnsiString getExtension(const AnsiString &path); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp new file mode 100644 index 0000000000..2c3be8c2f5 --- /dev/null +++ b/engines/wintermute/utils/string_util.cpp @@ -0,0 +1,232 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "common/tokenizer.h" +#include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/utils/convert_utf.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) { + return (str1.compareToIgnoreCase(str2) == 0); +} + +////////////////////////////////////////////////////////////////////////// +/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) { + WideString str1lc = str1; + WideString str2lc = str2; + + ToLowerCase(str1lc); + ToLowerCase(str2lc); + + return (str1lc == str2lc); +}*/ + +////////////////////////////////////////////////////////////////////////// +WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) { + error("StringUtil::Utf8ToWide - WideString not supported yet"); + /* size_t WideSize = Utf8Str.size(); + + if (sizeof(wchar_t) == 2) { + wchar_t *WideStringNative = new wchar_t[WideSize + 1]; + + const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str()); + const UTF8 *SourceEnd = SourceStart + WideSize; + + UTF16 *TargetStart = reinterpret_cast<UTF16 *>(WideStringNative); + UTF16 *TargetEnd = TargetStart + WideSize + 1; + + ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] WideStringNative; + return L""; + } + *TargetStart = 0; + WideString ResultString(WideStringNative); + delete[] WideStringNative; + + return ResultString; + } else if (sizeof(wchar_t) == 4) { + wchar_t *WideStringNative = new wchar_t[WideSize + 1]; + + const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(Utf8Str.c_str()); + const UTF8 *SourceEnd = SourceStart + WideSize; + + UTF32 *TargetStart = reinterpret_cast<UTF32 *>(WideStringNative); + UTF32 *TargetEnd = TargetStart + WideSize; + + ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] WideStringNative; + return L""; + } + *TargetStart = 0; + WideString ResultString(WideStringNative); + delete[] WideStringNative; + + return ResultString; + } else { + return L""; + }*/ + return ""; +} + +////////////////////////////////////////////////////////////////////////// +Utf8String StringUtil::wideToUtf8(const WideString &WideStr) { + error("StringUtil::wideToUtf8 - Widestring not supported yet"); + /* size_t WideSize = WideStr.length(); + + if (sizeof(wchar_t) == 2) { + size_t utf8Size = 3 * WideSize + 1; + char *utf8StringNative = new char[Utf8Size]; + + const UTF16 *SourceStart = reinterpret_cast<const UTF16 *>(WideStr.c_str()); + const UTF16 *SourceEnd = SourceStart + WideSize; + + UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative); + UTF8 *TargetEnd = TargetStart + Utf8Size; + + ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] Utf8StringNative; + return (Utf8String)""; + } + *TargetStart = 0; + Utf8String ResultString(Utf8StringNative); + delete[] Utf8StringNative; + return ResultString; + } else if (sizeof(wchar_t) == 4) { + size_t utf8Size = 4 * WideSize + 1; + char *utf8StringNative = new char[Utf8Size]; + + const UTF32 *SourceStart = reinterpret_cast<const UTF32 *>(WideStr.c_str()); + const UTF32 *SourceEnd = SourceStart + WideSize; + + UTF8 *TargetStart = reinterpret_cast<UTF8 *>(Utf8StringNative); + UTF8 *TargetEnd = TargetStart + Utf8Size; + + ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] Utf8StringNative; + return (Utf8String)""; + } + *TargetStart = 0; + Utf8String ResultString(Utf8StringNative); + delete[] Utf8StringNative; + return ResultString; + } else { + return (Utf8String)""; + }*/ + return ""; +} + +// Currently this only does Ansi->ISO 8859, and only for carets. +char simpleAnsiToWide(const AnsiString &str, uint32 &offset) { + char c = str[offset]; + + if (c == 92) { + offset++; + return '\''; + } else { + offset++; + return c; + } +} + +////////////////////////////////////////////////////////////////////////// +WideString StringUtil::ansiToWide(const AnsiString &str) { + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + /*Common::String converted = ""; + uint32 index = 0; + while (index != str.size()) { + converted += simpleAnsiToWide(str, index); + }*/ + // using default os locale! + + /* setlocale(LC_CTYPE, ""); + size_t wideSize = mbstowcs(NULL, str.c_str(), 0) + 1; + wchar_t *wstr = new wchar_t[WideSize]; + mbstowcs(wstr, str.c_str(), WideSize); + WideString ResultString(wstr); + delete[] wstr; + return ResultString;*/ + return WideString(str); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::wideToAnsi(const WideString &wstr) { + // using default os locale! + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + /* setlocale(LC_CTYPE, ""); + size_t wideSize = wcstombs(NULL, wstr.c_str(), 0) + 1; + char *str = new char[WideSize]; + wcstombs(str, wstr.c_str(), WideSize); + AnsiString ResultString(str); + delete[] str; + return ResultString;*/ + return AnsiString(wstr); +} + +////////////////////////////////////////////////////////////////////////// +bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) { + if (bufferSize > 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) { + return true; + } else { + return false; + } +} + +////////////////////////////////////////////////////////////////////////// +int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { + const char *index = strstr(str.c_str(), toFind.c_str()); + if (index == NULL) { + return -1; + } else { + return index - str.c_str(); + } +} + +Common::String StringUtil::encodeSetting(const Common::String &str) { + if (str.contains('=')) { + error("Setting contains '='"); + } + return str; +} + +Common::String StringUtil::decodeSetting(const Common::String &str) { + return str; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(int val) { + return Common::String::format("%d", val); +} + + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h new file mode 100644 index 0000000000..e419e2bca8 --- /dev/null +++ b/engines/wintermute/utils/string_util.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_STRINGUTIL_H +#define WINTERMUTE_STRINGUTIL_H + +#include "engines/wintermute/dctypes.h" + +namespace Wintermute { + +class StringUtil { +public: + static bool compareNoCase(const AnsiString &str1, const AnsiString &str2); + //static bool compareNoCase(const WideString &str1, const WideString &str2); + static WideString utf8ToWide(const Utf8String &Utf8Str); + static Utf8String wideToUtf8(const WideString &WideStr); + static WideString ansiToWide(const AnsiString &str); + static AnsiString wideToAnsi(const WideString &str); + + static bool isUtf8BOM(const byte *buffer, uint32 bufferSize); + static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom); + + static Common::String encodeSetting(const Common::String &str); + static Common::String decodeSetting(const Common::String &str); + + static AnsiString toString(int val); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp new file mode 100644 index 0000000000..824b16ccdb --- /dev/null +++ b/engines/wintermute/utils/utils.cpp @@ -0,0 +1,261 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/wintermute.h" +#include "engines/wintermute/base/base_engine.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +static inline unsigned Sqr(int x) { + return (x * x); +} + +////////////////////////////////////////////////////////////////////////////////// +// Swap - swaps two integers +////////////////////////////////////////////////////////////////////////////////// +void BaseUtils::swap(int *a, int *b) { + int temp = *a; + *a = *b; + *b = temp; +} + + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::normalizeAngle(float angle) { + while (angle > 360) { + angle -= 360; + } + while (angle < 0) { + angle += 360; + } + + return angle; +} + + +//////////////////////////////////////////////////////////////////////////////// +void BaseUtils::createPath(const char *path, bool pathOnly) { + /* AnsiString pathStr; + + if (!pathOnly) pathStr = PathUtil::getDirectoryName(path); + else pathStr = path; + */ +// try { + warning("BaseUtils::CreatePath - not implemented: %s", path); +// boost::filesystem::create_directories(path); +// } catch (...) { + return; +// } +} + + +////////////////////////////////////////////////////////////////////////// +void BaseUtils::debugMessage(const char *text) { + //MessageBox(hWnd, Text, "WME", MB_OK|MB_ICONINFORMATION); +} + + +////////////////////////////////////////////////////////////////////////// +char *BaseUtils::setString(char **string, const char *value) { + delete[] *string; + *string = new char[strlen(value) + 1]; + if (*string) { + strcpy(*string, value); + } + return *string; +} + +////////////////////////////////////////////////////////////////////////// +char *BaseUtils::strEntry(int entry, const char *str, const char delim) { + int numEntries = 0; + + const char *start = NULL; + int len = 0; + + for (uint32 i = 0; i <= strlen(str); i++) { + if (numEntries == entry) { + if (!start) { + start = str + i; + } else { + len++; + } + } + if (str[i] == delim || str[i] == '\0') { + numEntries++; + if (start) { + char *ret = new char[len + 1]; + memset(ret, 0, len + 1); + Common::strlcpy(ret, start, len + 1); + return ret; + } + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +int BaseUtils::randomInt(int from, int to) { + if (to < from) { + int i = to; + to = from; + from = i; + } + return BaseEngine::instance().randInt(from, to); +// return (rand() % (to - from + 1)) + from; +} + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::randomFloat(float from, float to) { + const uint32 randMax = RAND_MAX; + float randNum = (float)BaseEngine::instance().randInt(0, randMax) / (float)randMax; + return from + (to - from) * randNum; +} + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::randomAngle(float from, float to) { + while (to < from) { + to += 360; + } + return normalizeAngle(randomFloat(from, to)); +} + +////////////////////////////////////////////////////////////////////////// +void BaseUtils::RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL) { + float varR = (RGBCOLGetR(rgbColor) / 255.0f); + float varG = (RGBCOLGetG(rgbColor) / 255.0f); + float varB = (RGBCOLGetB(rgbColor) / 255.0f); + + //Min. value of RGB + float varMin = MIN(varR, varG); + varMin = MIN(varMin, varB); + + //Max. value of RGB + float varMax = MAX(varR, varG); + varMax = MAX(varMax, varB); + + //Delta RGB value + float delMax = varMax - varMin; + + float H = 0.0f, S = 0.0f, L = 0.0f; + + L = (varMax + varMin) / 2.0f; + + //This is a gray, no chroma... + if (delMax == 0) { + H = 0; + S = 0; + } + //Chromatic data... + else { + if (L < 0.5f) { + S = delMax / (varMax + varMin); + } else { + S = delMax / (2.0f - varMax - varMin); + } + + float delR = (((varMax - varR) / 6.0f) + (delMax / 2.0f)) / delMax; + float delG = (((varMax - varG) / 6.0f) + (delMax / 2.0f)) / delMax; + float delB = (((varMax - varB) / 6.0f) + (delMax / 2.0f)) / delMax; + + if (varR == varMax) { + H = delB - delG; + } else if (varG == varMax) { + H = (1.0f / 3.0f) + delR - delB; + } else if (varB == varMax) { + H = (2.0f / 3.0f) + delG - delR; + } + + if (H < 0) { + H += 1; + } + if (H > 1) { + H -= 1; + } + } + + *outH = (byte)(H * 255); + *outS = (byte)(S * 255); + *outL = (byte)(L * 255); +} + + +////////////////////////////////////////////////////////////////////////// +uint32 BaseUtils::HSLtoRGB(byte InH, byte InS, byte InL) { + float H = InH / 255.0f; + float S = InS / 255.0f; + float L = InL / 255.0f; + + byte R, G, B; + + + if (S == 0) { + R = (byte)(L * 255); + G = (byte)(L * 255); + B = (byte)(L * 255); + } else { + float var1, var2; + + if (L < 0.5) { + var2 = L * (1.0 + S); + } else { + var2 = (L + S) - (S * L); + } + + var1 = 2.0f * L - var2; + + R = (byte)(255 * Hue2RGB(var1, var2, H + (1.0f / 3.0f))); + G = (byte)(255 * Hue2RGB(var1, var2, H)); + B = (byte)(255 * Hue2RGB(var1, var2, H - (1.0f / 3.0f))); + } + return BYTETORGBA(255, R, G, B); +} + + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::Hue2RGB(float v1, float v2, float vH) { + if (vH < 0.0f) { + vH += 1.0f; + } + if (vH > 1.0f) { + vH -= 1.0f; + } + if ((6.0f * vH) < 1.0f) { + return (v1 + (v2 - v1) * 6.0f * vH); + } + if ((2.0f * vH) < 1.0f) { + return (v2); + } + if ((3.0f * vH) < 2.0f) { + return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f); + } + return (v1); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h new file mode 100644 index 0000000000..d6a603ec72 --- /dev/null +++ b/engines/wintermute/utils/utils.h @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UTILS_H +#define WINTERMUTE_UTILS_H + +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/math/rect32.h" + +namespace Wintermute { + +class BaseGame; + +class BaseUtils { +public: + static void swap(int *a, int *b); + static float normalizeAngle(float angle); + + static void createPath(const char *path, bool pathOnly = false); + + static void debugMessage(const char *text); + static char *setString(char **string, const char *value); + + static char *strEntry(int entry, const char *str, const char delim = ','); + + static int randomInt(int from, int to); + static float randomFloat(float from, float to); + static float randomAngle(float from, float to); + + static void RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL); + static uint32 HSLtoRGB(byte H, byte S, byte L); + +private: + static float Hue2RGB(float v1, float v2, float vH); +}; + +} // end of namespace Wintermute + +#endif |