From 348199501d33b06c80704eabc82c5cc5d55d406d Mon Sep 17 00:00:00 2001 From: d07RiV Date: Wed, 9 Mar 2016 11:42:26 +0300 Subject: [PATCH] initial release --- libs/zlib/vc100.pdb | Bin 0 -> 77824 bytes libs/zlib/zconf.h | 511 ++++++++++ libs/zlib/zlib.h | 1768 +++++++++++++++++++++++++++++++++ libs/zlib/zlib32d.lib | Bin 0 -> 242152 bytes libs/zlib/zlib32r.lib | Bin 0 -> 233248 bytes libs/zlib/zlib64d.lib | Bin 0 -> 275630 bytes libs/zlib/zlib64r.lib | Bin 0 -> 263836 bytes libs/zlib/zutil.h | 253 +++++ src/app.cpp | 36 + src/app.h | 28 + src/base/checksum.cpp | 223 +++++ src/base/checksum.h | 33 + src/base/common.cpp | 127 +++ src/base/common.h | 78 ++ src/base/error.cpp | 16 + src/base/error.h | 31 + src/base/file.cpp | 399 ++++++++ src/base/file.h | 251 +++++ src/base/functor.h | 77 ++ src/base/http.cpp | 216 ++++ src/base/http.h | 38 + src/base/json.cpp | 989 ++++++++++++++++++ src/base/json.h | 381 +++++++ src/base/path.cpp | 91 ++ src/base/path.h | 17 + src/base/pool.cpp | 100 ++ src/base/pool.h | 55 + src/base/regexp.cpp | 837 ++++++++++++++++ src/base/regexp.h | 163 +++ src/base/string.cpp | 165 +++ src/base/string.h | 77 ++ src/base/thread.cpp | 56 ++ src/base/thread.h | 102 ++ src/base/types.h | 60 ++ src/base/utf8.cpp | 1176 ++++++++++++++++++++++ src/base/utf8.h | 18 + src/data.cpp | 597 +++++++++++ src/data.h | 126 +++ src/frameui/controlframes.cpp | 650 ++++++++++++ src/frameui/controlframes.h | 216 ++++ src/frameui/fontsys.cpp | 171 ++++ src/frameui/fontsys.h | 64 ++ src/frameui/frame.cpp | 436 ++++++++ src/frameui/frame.h | 158 +++ src/frameui/framewnd.cpp | 209 ++++ src/frameui/framewnd.h | 40 + src/frameui/listctrl.cpp | 39 + src/frameui/listctrl.h | 24 + src/frameui/searchlist.cpp | 474 +++++++++ src/frameui/searchlist.h | 19 + src/frameui/window.cpp | 335 +++++++ src/frameui/window.h | 77 ++ src/main.cpp | 23 + src/ngdp.cpp | 457 +++++++++ src/ngdp.h | 182 ++++ src/pages/build.cpp | 119 +++ src/pages/build.h | 19 + src/pages/download.cpp | 178 ++++ src/pages/download.h | 28 + src/pages/program.cpp | 115 +++ src/pages/program.h | 20 + src/pages/tags.cpp | 153 +++ src/pages/tags.h | 25 + src/wizard.cpp | 80 ++ src/wizard.h | 55 + vc13/Battle_130.ico | Bin 0 -> 95399 bytes vc13/BlizzGet.rc | Bin 0 -> 3938 bytes vc13/BlizzGet.sln | 22 + vc13/BlizzGet.vcxproj | 155 +++ vc13/BlizzGet.vcxproj.filters | 226 +++++ vc13/resource.h | Bin 0 -> 994 bytes 71 files changed, 13864 insertions(+) create mode 100644 libs/zlib/vc100.pdb create mode 100644 libs/zlib/zconf.h create mode 100644 libs/zlib/zlib.h create mode 100644 libs/zlib/zlib32d.lib create mode 100644 libs/zlib/zlib32r.lib create mode 100644 libs/zlib/zlib64d.lib create mode 100644 libs/zlib/zlib64r.lib create mode 100644 libs/zlib/zutil.h create mode 100644 src/app.cpp create mode 100644 src/app.h create mode 100644 src/base/checksum.cpp create mode 100644 src/base/checksum.h create mode 100644 src/base/common.cpp create mode 100644 src/base/common.h create mode 100644 src/base/error.cpp create mode 100644 src/base/error.h create mode 100644 src/base/file.cpp create mode 100644 src/base/file.h create mode 100644 src/base/functor.h create mode 100644 src/base/http.cpp create mode 100644 src/base/http.h create mode 100644 src/base/json.cpp create mode 100644 src/base/json.h create mode 100644 src/base/path.cpp create mode 100644 src/base/path.h create mode 100644 src/base/pool.cpp create mode 100644 src/base/pool.h create mode 100644 src/base/regexp.cpp create mode 100644 src/base/regexp.h create mode 100644 src/base/string.cpp create mode 100644 src/base/string.h create mode 100644 src/base/thread.cpp create mode 100644 src/base/thread.h create mode 100644 src/base/types.h create mode 100644 src/base/utf8.cpp create mode 100644 src/base/utf8.h create mode 100644 src/data.cpp create mode 100644 src/data.h create mode 100644 src/frameui/controlframes.cpp create mode 100644 src/frameui/controlframes.h create mode 100644 src/frameui/fontsys.cpp create mode 100644 src/frameui/fontsys.h create mode 100644 src/frameui/frame.cpp create mode 100644 src/frameui/frame.h create mode 100644 src/frameui/framewnd.cpp create mode 100644 src/frameui/framewnd.h create mode 100644 src/frameui/listctrl.cpp create mode 100644 src/frameui/listctrl.h create mode 100644 src/frameui/searchlist.cpp create mode 100644 src/frameui/searchlist.h create mode 100644 src/frameui/window.cpp create mode 100644 src/frameui/window.h create mode 100644 src/main.cpp create mode 100644 src/ngdp.cpp create mode 100644 src/ngdp.h create mode 100644 src/pages/build.cpp create mode 100644 src/pages/build.h create mode 100644 src/pages/download.cpp create mode 100644 src/pages/download.h create mode 100644 src/pages/program.cpp create mode 100644 src/pages/program.h create mode 100644 src/pages/tags.cpp create mode 100644 src/pages/tags.h create mode 100644 src/wizard.cpp create mode 100644 src/wizard.h create mode 100644 vc13/Battle_130.ico create mode 100644 vc13/BlizzGet.rc create mode 100644 vc13/BlizzGet.sln create mode 100644 vc13/BlizzGet.vcxproj create mode 100644 vc13/BlizzGet.vcxproj.filters create mode 100644 vc13/resource.h diff --git a/libs/zlib/vc100.pdb b/libs/zlib/vc100.pdb new file mode 100644 index 0000000000000000000000000000000000000000..d9c401e0f1d2cf80d3c70b9d33c3328e0dc33b49 GIT binary patch literal 77824 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 K6oLOA2>cHU7?%M6 literal 0 HcmV?d00001 diff --git a/libs/zlib/zconf.h b/libs/zlib/zconf.h new file mode 100644 index 0000000..9987a77 --- /dev/null +++ b/libs/zlib/zconf.h @@ -0,0 +1,511 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/libs/zlib/zlib.h b/libs/zlib/zlib.h new file mode 100644 index 0000000..3e0c767 --- /dev/null +++ b/libs/zlib/zlib.h @@ -0,0 +1,1768 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.8, April 28th, 2013 + + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 8 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/libs/zlib/zlib32d.lib b/libs/zlib/zlib32d.lib new file mode 100644 index 0000000000000000000000000000000000000000..c6bdd2e22e6978348671ab6e0e36bb13a0b87702 GIT binary patch literal 242152 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
QT<@GVm2X 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
+#m2;~rmQ1fa)r-1iga6Er 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%0A`eMomi7)b5DV=r#cj|u2}QODKVi; zteISE?H~64$Jt9JRaZ^5K4mW{3uG_ZLeo}1lN-ujQc7*)xFJqJcoUmN9sVjqJA-;~ zeGz-f-q4SW)A);=>m&IXjA@skF6zT>r+O`B2U(4uROnAxEq1cOgZTN2Jb#qMaoItZ zlTP)~*+Ih7c23v~5`3U?;d1T=bR+d}=?1xG##@cm(gTOM9_1RJxAs>U`FUJj(5Z)@ z#GMGFRiKyRBjQ*EYWZD`=rS%7!Ysd)e6iCFwEU02L)Vbk*l3~dt|XAPgxK|CD$>T3 z$LTyD&(#^q8>nLC`$p*H(3_yu(3_!?p|?P1KxaamptGR!ptGTip>v?^&@Vx?CdW@| zBNRPm(7-tqC-qm{-vL#*{VDXP&}QhX(0R}|pe@i}LjMff51kJkgx(4LZ)hu2Ye3RW zod;b4y%gF8mFBw(dM5R>3@Vg9+EMCL&=t@L(7U16K*?+BS}5g|ngP8Bs^2wNK~>LR zh5iZUbT4!o^gieeD7N}k3v@N~9%vVI4U~6It%a_EZi1%x`#y9XRBd5B^aJughRZos zvz#hePU-R&lya$kZQ{yD1y&gOxrl3oZ%M9wIYacvnA<#tHj$WiR?VC-ds2fD6*;Tn zeS%bRIj8)nEh$g#-Tsbu)&1W?mCq-Jc=t=FE4{aS1--j|A9L^iJbXUly28lMInWXp z(DyC(?iNGal_}n%j!t%LFRwY1IjBNCO&v=w3=n&b>6!w>rUeDLpN9BL4hzX`n(*|(tTdk;hDhruII`ddIesoSC7fi8f47pm0%61o9O z|4KarWz;oD*WZKwJNMs*9)xa%oM< zBVE9Pdihwa>f@{!bNEJqjZAsUZ%SWO<2Hfeu*sL`B z2mOu}oUoZQCm-WMG+&?q;OsVB!K~>0smmIxqb&n<(_vzidM6a{7q*T+wJTn-vdJ88uRTxNn3pISDH~e(+OG0LcxsOkdb~J&_1Ksh$>*qiBixlS4>`|0 zv-Vx{RQopAY!Hv}UFjvft=YI(v7M3+1}e>cJl?T@&os%F|7y3p>u}JS#7xJ2Lu^(i z3BN-jV=|H%d}YY2G-PV`>`=iy%XZaxED`>t;J5}Hq1 zIg!Qgqika{h!QTXa4Cl`XNseDKi^67v@&kqSYP7W?3g!VZ&|dgcykj+W`|z4Z8tks ziUu{`HuKb#bADKCjYY%i^Y7wWZhMZc6h&k1eVct-JRSOV+nzgXn6PcTD~8QgY}lAF zd=|}B+wQZ6jrp8mV;(hh%t*U?9d%@Ii6hRQ>5@V^u(?H2yy}n}I-$rHLv(s87-lu-Q4@-E~l! zN-cS`Rgkn>yARrH#lcsGZ(&|Ry6pkzYZ5r7eYoB4Rq}bhtp4aSOEMzSkNZ2yyI=Zf z;4M_ql3WyR{B+~tk&Q=)Ysi7Z2^m^4;n2c}a%4X{*4t4QN7fFAHKC6v zHiS(_+%Ti;8C9R@?yHRaOrkm)mf5U3s^2jpwpoTmZ1A$qD%a)PcaF1hMb8v3 z4cspP^8FNLla(-d2K}Lg=@9M;{Ug4tpQ|M?&c$Hq)$ literal 0 HcmV?d00001 diff --git a/libs/zlib/zlib32r.lib b/libs/zlib/zlib32r.lib new file mode 100644 index 0000000000000000000000000000000000000000..7c096659b1a4d8467595f953e3557d8f86d44fdf GIT binary patch literal 233248 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

Z)sW)m-BG^2XmcUvG- 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 literal 0 HcmV?d00001 diff --git a/libs/zlib/zutil.h b/libs/zlib/zutil.h new file mode 100644 index 0000000..24ab06b --- /dev/null +++ b/libs/zlib/zutil.h @@ -0,0 +1,253 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2013 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/src/app.cpp b/src/app.cpp new file mode 100644 index 0000000..b5ac77e --- /dev/null +++ b/src/app.cpp @@ -0,0 +1,36 @@ +#include "app.h" +#include +#include "wizard.h" +#include "pages/program.h" + +Application::Application(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) + : wizard_(nullptr) + , data_(this) +{ + INITCOMMONCONTROLSEX iccex; + iccex.dwSize = sizeof iccex; + iccex.dwICC = ICC_STANDARD_CLASSES | ICC_PROGRESS_CLASS | + ICC_BAR_CLASSES | ICC_TREEVIEW_CLASSES | ICC_LISTVIEW_CLASSES | + ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_DATE_CLASSES; + InitCommonControlsEx(&iccex); + OleInitialize(NULL); + + wizard_ = new Wizard(this); + wizard_->setPage(new ProgramPage(wizard_)); +} + +Application::~Application() { + delete wizard_; + + OleFlushClipboard(); + OleUninitialize(); +} + +int Application::run() { + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; +} diff --git a/src/app.h b/src/app.h new file mode 100644 index 0000000..9b53e63 --- /dev/null +++ b/src/app.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include "frameui/window.h" +#include "ngdp.h" +#include "data.h" + +class Wizard; + +class Application { +public: + Application(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); + ~Application(); + + int run(); + + ProgramData& data() { + return data_; + } + Wizard* wizard() { + return wizard_; + } + +private: + ProgramData data_; + Wizard* wizard_; +}; diff --git a/src/base/checksum.cpp b/src/base/checksum.cpp new file mode 100644 index 0000000..520ddfc --- /dev/null +++ b/src/base/checksum.cpp @@ -0,0 +1,223 @@ +#include "checksum.h" + +uint32 update_crc(uint32 crc, void const* vbuf, uint32 length) { + static uint32 crc_table[256]; + static bool table_computed = false; + uint8 const* buf = (uint8*)vbuf; + if (!table_computed) { + for (uint32 i = 0; i < 256; i++) { + uint32 c = i; + for (int k = 0; k < 8; k++) { + if (c & 1) { + c = 0xEDB88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[i] = c; + } + table_computed = true; + } + for (uint32 i = 0; i < length; i++) { + crc = crc_table[(crc ^ buf[i]) & 0xFF] ^ (crc >> 8); + } + return crc; +} +uint32 crc32(void const* buf, uint32 length) { + return ~update_crc(0xFFFFFFFF, buf, length); +} +uint32 crc32(std::string const& str) { + return ~update_crc(0xFFFFFFFF, str.c_str(), str.length()); +} + +////////////////////////////////////////////////////////////////// + +static const uint32 MD5_R[64] = { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 +}; +static uint32 MD5_K[64] = { + 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, + 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, + 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, + 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, + 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, + 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, + 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, + 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, + 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, + 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, + 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, + 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, + 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, + 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, + 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, + 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391, +}; + +MD5::MD5() { + digest[0] = 0x67452301; + digest[1] = 0xEFCDAB89; + digest[2] = 0x98BADCFE; + digest[3] = 0x10325476; + length = 0; + bufSize = 0; +} +void MD5::process(void const* _buf, uint32 size) { + uint8 const* buf = (uint8*)_buf; + while (size) { + uint32 cur = 64 - bufSize; + if (cur > size) cur = size; + memcpy(buffer + bufSize, buf, cur); + bufSize += cur; + length += cur; + size -= cur; + buf += cur; + if (bufSize == 64) run(); + } +} +void MD5::finish(void* _digest) { + buffer[bufSize++] = 0x80; + if (bufSize > 56) { + if (bufSize < 64) memset(buffer + bufSize, 0, 64 - bufSize); + run(); + } + if (bufSize < 56) memset(buffer + bufSize, 0, 56 - bufSize); + *(uint64*)(buffer + 56) = uint64(length) * 8; + run(); + memcpy(_digest, digest, sizeof digest); +} +std::string MD5::format(void const* digest) +{ + std::string result(32, ' '); + uint8 const* d = (uint8*)digest; + for (int i = 0; i < DIGEST_SIZE; i++) { + sprintf(&result[i * 2], "%02x", d[i]); + } + return result; +} +static inline uint32 rot(uint32 x, int k) { + return (x << k) | (x >> (32 - k)); +} +void MD5::run() { + uint32* m = (uint32*)buffer; + uint32 a = digest[0]; + uint32 b = digest[1]; + uint32 c = digest[2]; + uint32 d = digest[3]; + for (int i = 0; i < 64; i++) { + uint32 f, g; + if (i < 16) f = (b & c) | ((~b) & d), g = i; + else if (i < 32) f = (d & b) | ((~d) & c), g = (i * 5 + 1) & 0x0F; + else if (i < 48) f = b ^ c ^ d, g = (i * 3 + 5) & 0x0F; + else f = c ^ (b | (~d)), g = (i * 7) & 0x0F; + uint32 temp = d; + d = c; + c = b; + b += rot(a + f + MD5_K[i] + m[g], MD5_R[i]); + a = temp; + } + digest[0] += a; + digest[1] += b; + digest[2] += c; + digest[3] += d; + bufSize = 0; +} + +uint64 jenkins(void const* buf, uint32 length) { + uint32 a, b, c; + a = b = c = 0xDEADBEEF + length + 2; + c += 1; + + uint32* k = (uint32*)buf; + while (length > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + + a -= c; a ^= rot(c, 4); c += b; + b -= a; b ^= rot(a, 6); a += c; + c -= b; c ^= rot(b, 8); b += a; + a -= c; a ^= rot(c, 16); c += b; + b -= a; b ^= rot(a, 19); a += c; + c -= b; c ^= rot(b, 4); b += a; + + length -= 12; + k += 3; + } + + switch (length) { + case 12: c += k[2]; b += k[1]; a += k[0]; break; + case 11: c += k[2] & 0xFFFFFF; b += k[1]; a += k[0]; break; + case 10: c += k[2] & 0xFFFF; b += k[1]; a += k[0]; break; + case 9: c += k[2] & 0xFF; b += k[1]; a += k[0]; break; + case 8: b += k[1]; a += k[0]; break; + case 7: b += k[1] & 0xFFFFFF; a += k[0]; break; + case 6: b += k[1] & 0xFFFF; a += k[0]; break; + case 5: b += k[1] & 0xFF; a += k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0] & 0xFFFFFF; break; + case 2: a += k[0] & 0xFFFF; break; + case 1: a += k[0] & 0xFF; break; + case 0: return (uint64(b) << 32) | uint64(c); + } + + c ^= b; c -= rot(b, 14); + a ^= c; a -= rot(c, 11); + b ^= a; b -= rot(a, 25); + c ^= b; c -= rot(b, 16); + a ^= c; a -= rot(c, 4); + b ^= a; b -= rot(a, 14); + c ^= b; c -= rot(b, 24); + + return (uint64(b) << 32) | uint64(c); +} +uint32 hashlittle(void const* buf, uint32 length, uint32 initval) { + uint32 a, b, c; + a = b = c = 0xDEADBEEF + length + initval; + + uint32* k = (uint32*)buf; + while (length > 12) { + a += k[0]; + b += k[1]; + c += k[2]; + + a -= c; a ^= rot(c, 4); c += b; + b -= a; b ^= rot(a, 6); a += c; + c -= b; c ^= rot(b, 8); b += a; + a -= c; a ^= rot(c, 16); c += b; + b -= a; b ^= rot(a, 19); a += c; + c -= b; c ^= rot(b, 4); b += a; + + length -= 12; + k += 3; + } + + switch (length) { + case 12: c += k[2]; b += k[1]; a += k[0]; break; + case 11: c += k[2] & 0xFFFFFF; b += k[1]; a += k[0]; break; + case 10: c += k[2] & 0xFFFF; b += k[1]; a += k[0]; break; + case 9: c += k[2] & 0xFF; b += k[1]; a += k[0]; break; + case 8: b += k[1]; a += k[0]; break; + case 7: b += k[1] & 0xFFFFFF; a += k[0]; break; + case 6: b += k[1] & 0xFFFF; a += k[0]; break; + case 5: b += k[1] & 0xFF; a += k[0]; break; + case 4: a += k[0]; break; + case 3: a += k[0] & 0xFFFFFF; break; + case 2: a += k[0] & 0xFFFF; break; + case 1: a += k[0] & 0xFF; break; + case 0: return c; + } + + c ^= b; c -= rot(b, 14); + a ^= c; a -= rot(c, 11); + b ^= a; b -= rot(a, 25); + c ^= b; c -= rot(b, 16); + a ^= c; a -= rot(c, 4); + b ^= a; b -= rot(a, 14); + c ^= b; c -= rot(b, 24); + + return c; +} diff --git a/src/base/checksum.h b/src/base/checksum.h new file mode 100644 index 0000000..d7db8e4 --- /dev/null +++ b/src/base/checksum.h @@ -0,0 +1,33 @@ +#pragma once + +#include "base/types.h" +#include + +uint32 update_crc(uint32 crc, void const* vbuf, uint32 length); +uint32 crc32(void const* buf, uint32 length); +uint32 crc32(std::string const& str); + +class MD5 { + uint8 buffer[64]; + uint32 digest[4]; + uint64 length; + uint32 bufSize; + void run(); +public: + enum { DIGEST_SIZE = 16 }; + + MD5(); + void process(void const* buf, uint32 size); + void finish(void* digest); + + static std::string format(void const* digest); + + static void checksum(void const* buf, uint32 size, void* digest) { + MD5 md5; + md5.process(buf, size); + md5.finish(digest); + } +}; + +uint64 jenkins(void const* buf, uint32 length); +uint32 hashlittle(void const* buf, uint32 length, uint32 initval); diff --git a/src/base/common.cpp b/src/base/common.cpp new file mode 100644 index 0000000..ddf1384 --- /dev/null +++ b/src/base/common.cpp @@ -0,0 +1,127 @@ +#include +#include "common.h" + +uint32 RefCounted::addref() { + return InterlockedIncrement(&ref_); +} +uint32 RefCounted::release() { + if (!this) { + return 0; + } + uint32 result = InterlockedDecrement(&ref_); + if (!result) { + delete this; + } + return result; +} + +void _qmemset(uint32* mem, uint32 fill, uint32 count) { + while (count--) { + *mem++ = fill; + } +} + +#include "zlib/zlib.h" +#ifdef _WIN64 + #ifdef _DEBUG + #pragma comment(lib, "zlib/zlib64d.lib") + #else + #pragma comment(lib, "zlib/zlib64r.lib") + #endif +#else + #ifdef _DEBUG + #pragma comment(lib, "zlib/zlib32d.lib") + #else + #pragma comment(lib, "zlib/zlib32r.lib") + #endif +#endif + +uint32 gzdeflate(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size) { + z_stream z; + memset(&z, 0, sizeof z); + z.next_in = const_cast(in); + z.avail_in = in_size; + z.total_in = in_size; + z.next_out = out; + z.avail_out = *out_size; + z.total_out = 0; + + memset(out, 0, *out_size); + + int result = deflateInit(&z, Z_DEFAULT_COMPRESSION); + if (result == Z_OK) { + result = deflate(&z, Z_FINISH); + *out_size = z.total_out; + deflateEnd(&z); + } + return (result == Z_STREAM_END ? 0 : -1); +} +uint32 gzencode(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size) { + z_stream z; + memset(&z, 0, sizeof z); + z.next_in = const_cast(in); + z.avail_in = in_size; + z.total_in = in_size; + z.next_out = out; + z.avail_out = *out_size; + z.total_out = 0; + + int result = deflateInit2(&z, 6, Z_DEFLATED, 16 + MAX_WBITS, 8, Z_DEFAULT_STRATEGY); + if (result == Z_OK) { + result = deflate(&z, Z_FINISH); + *out_size = z.total_out; + deflateEnd(&z); + } + return ((result == Z_OK || result == Z_STREAM_END) ? 0 : 1); +} +uint32 gzinflate(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size) { + z_stream z; + memset(&z, 0, sizeof z); + z.next_in = const_cast(in); + z.avail_in = in_size; + z.total_in = in_size; + z.next_out = out; + z.avail_out = *out_size; + z.total_out = 0; + + memset(out, 0, *out_size); + + int result = inflateInit(&z); + if (result == Z_OK) { + result = inflate(&z, Z_FINISH); + *out_size = z.total_out; + inflateEnd(&z); + } + return (z.avail_out == 0 ? 0 : -1); +} +uint32 gzdecode(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size) { + z_stream z; + memset(&z, 0, sizeof z); + z.next_in = const_cast(in); + z.avail_in = in_size; + z.total_in = in_size; + z.next_out = out; + z.avail_out = *out_size; + z.total_out = 0; + + int result = inflateInit2(&z, 16 + MAX_WBITS); + if (result == Z_OK) { + result = inflate(&z, Z_FINISH); + *out_size = z.total_out; + deflateEnd(&z); + } + return (z.avail_out == 0 ? 0 : 1); +} + +std::string formatSize(uint64 usize) { + double size = static_cast(usize); + if (size < 100 * 1024) { + return fmtstring("%u B", static_cast(size)); + } else if (size < 10.0 * 1024 * 1024) { + return fmtstring("%u K", static_cast(size / 1024)); + } else if (size < 10.0 * 1024 * 1024 * 1024) { + return fmtstring("%.1f M", size / 1024 / 1024); + } else { + return fmtstring("%.1f G", size / 1024 / 1024 / 1024); + } +} diff --git a/src/base/common.h b/src/base/common.h new file mode 100644 index 0000000..d27c098 --- /dev/null +++ b/src/base/common.h @@ -0,0 +1,78 @@ +#pragma once + +#include "types.h" +#include +#include +#include +#include +#include +#define NOMINMAX +#include + +#include "string.h" + +class RefCounted { + uint32 ref_; +public: + RefCounted() : ref_(1) {} + virtual ~RefCounted() {} + + bool unique() const { + return ref_ == 1; + } + uint32 addref(); + uint32 release(); +}; + +void _qmemset(uint32* mem, uint32 fill, uint32 count); + +template +using Map = std::map; +typedef Map Dictionary; + +template +typename MapType::mapped_type* getptr(MapType& map, Key const& key) { + auto it = map.find(key); + return (it == map.end() ? nullptr : &it->second); +} +template +typename MapType::mapped_type const* getptr(MapType const& map, Key const& key) { + auto it = map.find(key); + return (it == map.end() ? nullptr : &it->second); +} + +uint32 gzdeflate(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size); +uint32 gzencode(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size); +uint32 gzinflate(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size); +uint32 gzdecode(uint8 const* in, uint32 in_size, uint8* out, uint32* out_size); + +template +struct FlipTraits {}; + +template<> struct FlipTraits<1> { + typedef unsigned char T; + static T flip(T x) { return x; } +}; + +template<> struct FlipTraits<2> { + typedef unsigned short T; + static T flip(T x) { return _byteswap_ushort(x); } +}; + +template<> struct FlipTraits<4> { + typedef unsigned long T; + static T flip(T x) { return _byteswap_ulong(x); } +}; + +template<> struct FlipTraits<8> { + typedef unsigned long long T; + static T flip(T x) { return _byteswap_uint64(x); } +}; + +template +void flip(T& x) { + typedef FlipTraits Flip; + x = static_cast(Flip::flip(static_cast(x))); +} + +std::string formatSize(uint64 size); diff --git a/src/base/error.cpp b/src/base/error.cpp new file mode 100644 index 0000000..0f47450 --- /dev/null +++ b/src/base/error.cpp @@ -0,0 +1,16 @@ +#include "error.h" +#include "types.h" +#include + +Exception::Exception(char const* fmt, ...) { + va_list ap; + va_start(ap, fmt); + + uint32 len = _vscprintf(fmt, ap); + std::string dst; + dst.resize(len + 1); + vsprintf(&dst[0], fmt, ap); + dst.resize(len); + + buf_.str(dst); +} diff --git a/src/base/error.h b/src/base/error.h new file mode 100644 index 0000000..cc32977 --- /dev/null +++ b/src/base/error.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +class Exception { +public: + Exception(char const* fmt, ...); + Exception(Exception const& e) + : buf_(e.buf_.str()) + {} + + virtual char const* what() const throw() { + str_ = buf_.str(); + return str_.c_str(); + } + + template + inline void append(T const& t) { + buf_ << t; + } +private: + mutable std::string str_; + std::stringstream buf_; +}; + +template +static inline Exception&& operator<<(Exception&& e, T const& t) { + e.append(t); + return std::forward(e); +} diff --git a/src/base/file.cpp b/src/base/file.cpp new file mode 100644 index 0000000..77bbc6b --- /dev/null +++ b/src/base/file.cpp @@ -0,0 +1,399 @@ +#include "file.h" +#include +#include +#include + +class StdFileBuffer : public FileBuffer { + FILE* file_; +public: + StdFileBuffer(FILE* file) + : file_(file) + {} + ~StdFileBuffer() { + fclose(file_); + } + + int getc() { + return fgetc(file_); + } + void putc(int chr) { + fputc(chr, file_); + } + + uint64 tell() const { + return _ftelli64(file_); + } + void seek(int64 pos, int mode) { + _fseeki64(file_, pos, mode); + } + + size_t read(void* ptr, size_t size) { + return fread(ptr, 1, size, file_); + } + size_t write(void const* ptr, size_t size) { + return fwrite(ptr, 1, size, file_); + } +}; + +File::File(char const* name, uint32 mode) + : file_(nullptr) +{ + FILE* file = nullptr; + if (mode == READ) { + file = fopen(name, "rb"); + } else if (mode == MODIFY) { + file = fopen(name, "rb+"); + if (!file) { + mode = REWRITE; + } + } + if (mode == REWRITE) { + file = fopen(name, "wb+"); + if (!file) { + path::create(path::path(name)); + file = fopen(name, "wb+"); + } + } + if (file) { + file_ = new StdFileBuffer(file); + } +} + +void File::printf(char const* fmt, ...) { + static char buf[1024]; + + va_list ap; + va_start(ap, fmt); + + int len = _vscprintf(fmt, ap); + char* dst; + if (len < 1024) { + dst = buf; + } else { + dst = new char[len + 1]; + } + vsprintf(dst, fmt, ap); + file_->write(dst, len); + if (dst != buf) { + delete[] dst; + } +} +bool File::getline(std::string& out) { + out.clear(); + int chr; + while ((chr = file_->getc()) != EOF) { + if (chr == '\r') { + char next = file_->getc(); + if (next != '\n') { + file_->seek(-1, SEEK_CUR); + } + return true; + } + if (chr == '\n') { + return true; + } + out.push_back(chr); + } + return !out.empty(); +} +File::LineIterator File::begin() { + return LineIterator(*this); +} +File::LineIterator File::end() { + return LineIterator(); +} + +class MemFileBuffer : public FileBuffer { + uint8 const* ptr_; + uint8* clone_; + size_t pos_; + size_t size_; +public: + MemFileBuffer(uint8 const* ptr, size_t size, bool clone) + : ptr_(ptr) + , pos_(0) + , size_(size) + , clone_(nullptr) + { + if (clone) { + clone_ = new uint8[size]; + memcpy(clone_, ptr, size); + ptr_ = clone_; + } + } + ~MemFileBuffer() { + delete[] clone_; + } + + int getc() { + return (pos_ < size_ ? ptr_[pos_++] : EOF); + } + void putc(int chr) {} + + uint64 tell() const { + return pos_; + } + void seek(int64 pos, int mode) { + switch (mode) { + case SEEK_CUR: + pos += pos_; + break; + case SEEK_END: + pos += size_; + break; + } + if (pos < 0) pos = 0; + if (pos > size_) pos = size_; + pos_ = pos; + } + uint64 size() { + return size_; + } + + size_t read(void* ptr, size_t size) { + if (size + pos_ > size_) { + size = size_ - pos_; + } + if (size) { + memcpy(ptr, ptr_ + pos_, size); + pos_ += size; + } + return size; + } + size_t write(void const* ptr, size_t size) { + return 0; + } +}; + +File File::memfile(void const* ptr, size_t size, bool clone) { + return File(new MemFileBuffer((uint8*)ptr, size, clone)); +} + +class SubFileBuffer : public FileBuffer { + File file_; + uint64 start_; + uint64 end_; + uint64 pos_; +public: + SubFileBuffer(File& file, uint64 offset, uint64 size) + : file_(file) + , start_(offset) + , end_(offset + size) + , pos_(offset) + { + file.seek(offset); + } + + int getc() { + if (pos_ >= end_) return EOF; + ++pos_; + return file_.getc(); + } + void putc(int chr) {} + + uint64 tell() const { + return pos_ - start_; + } + void seek(int64 pos, int mode) { + switch (mode) { + case SEEK_SET: + pos += start_; + break; + case SEEK_CUR: + pos += pos_; + break; + case SEEK_END: + pos += end_; + break; + } + if (pos < start_) pos = start_; + if (pos > end_) pos = end_; + pos_ = pos; + file_.seek(pos_); + } + uint64 size() { + return end_ - start_; + } + + size_t read(void* ptr, size_t size) { + if (size + pos_ > end_) { + size = end_ - pos_; + } + if (size) { + size = file_.read(ptr, size); + pos_ += size; + } + return size; + } + size_t write(void const* ptr, size_t size) { + return 0; + } +}; + +File File::subfile(uint64 offset, uint64 size) { + return File(new SubFileBuffer(*this, offset, size)); +} + +class MemoryBuffer : public FileBuffer { + size_t pos_; + uint8* data_; + size_t size_; + size_t alloc_; + size_t grow_; +public: + MemoryBuffer(size_t size, size_t grow) + : alloc_(size) + , grow_(grow) + , size_(0) + , pos_(0) + { + data_ = new uint8[size]; + } + ~MemoryBuffer() { + delete[] data_; + } + + int getc() { + if (pos_ < size_) return data_[pos_++]; + return EOF; + } + + uint64 tell() const { + return pos_; + } + void seek(int64 pos, int mode) { + switch (mode) { + case SEEK_CUR: + pos += pos_; + break; + case SEEK_END: + pos += size_; + break; + } + if (pos < 0) pos = 0; + if (pos > size_) pos = size_; + pos_ = pos; + } + uint64 size() { + return size_; + } + + size_t read(void* ptr, size_t size) { + if (size + pos_ > size_) { + size = size_ - pos_; + } + if (size) { + memcpy(ptr, data_ + pos_, size); + pos_ += size; + } + return size; + } + + size_t write(void const* ptr, size_t size) { + memcpy(reserve(size), ptr, size); + return size; + } + + uint8 const* data() const { + return data_; + } + uint8* reserve(uint32 size) { + if (pos_ + size > alloc_) { + while (alloc_ < pos_ + size) { + if (alloc_ < grow_) alloc_ *= 2; + else alloc_ += grow_; + } + uint8* temp = new uint8[alloc_]; + memcpy(temp, data_, size_); + delete[] data_; + data_ = temp; + } + uint8* res = data_ + pos_; + pos_ += size; + if (pos_ > size_) size_ = pos_; + return res; + } + void resize(uint32 size) { + size_ = size; + if (pos_ > size) pos_ = size; + } +}; + +MemoryFile::MemoryFile(size_t initial, size_t grow) + : File(new MemoryBuffer(initial, grow)) +{} +uint8 const* MemoryFile::data() const { + MemoryBuffer* buffer = dynamic_cast(file_); + return (buffer ? buffer->data() : nullptr); +} +uint8* MemoryFile::reserve(uint32 size) { + MemoryBuffer* buffer = dynamic_cast(file_); + return (buffer ? buffer->reserve(size) : nullptr); +} +void MemoryFile::resize(uint32 size) { + MemoryBuffer* buffer = dynamic_cast(file_); + if (buffer) buffer->resize(size); +} +size_t MemoryFile::csize() const { + MemoryBuffer* buffer = dynamic_cast(file_); + return (buffer ? buffer->size() : 0); +} + +void File::copy(File& src, uint64 size) { + auto mem = dynamic_cast(src.file_); + if (mem) { + uint64 pos = mem->tell(); + size = std::min(size, mem->size() - pos); + write(mem->data() + pos, size); + mem->seek(size, SEEK_CUR); + } else { + uint8 buf[65536]; + while (size_t count = src.read(buf, std::min(sizeof buf, size))) { + write(buf, count); + size -= count; + } + } +} +#include "checksum.h" +void File::md5(void* digest) { + auto mem = dynamic_cast(file_); + if (mem) { + MD5::checksum(mem->data(), mem->size(), digest); + } else { + uint64 pos = tell(); + seek(0, SEEK_SET); + uint8 buf[65536]; + MD5 checksum; + while (size_t count = read(buf, sizeof buf)) { + checksum.process(buf, count); + } + checksum.finish(digest); + seek(pos, SEEK_SET); + } +} +std::string File::md5() { + uint8 digest[MD5::DIGEST_SIZE]; + md5(digest); + return MD5::format(digest); +} + +bool File::exists(char const* path) { + return GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES; +} + +FileLoader::SearchResults FileLoader::search(char const* mask) { + WIN32_FIND_DATA fdata; + HANDLE hFind = FindFirstFile((root / mask).c_str(), &fdata); + SearchResults results; + if (hFind == INVALID_HANDLE_VALUE) return results; + do { + if (!strcmp(fdata.cFileName, ".") || !strcmp(fdata.cFileName, "..")) continue; + if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + results.folders.push_back(fdata.cFileName); + } else { + results.files.push_back(fdata.cFileName); + } + } while (FindNextFile(hFind, &fdata)); + FindClose(hFind); + return results; +} diff --git a/src/base/file.h b/src/base/file.h new file mode 100644 index 0000000..f17e2ea --- /dev/null +++ b/src/base/file.h @@ -0,0 +1,251 @@ +#pragma once + +#include +#include "common.h" +#include "path.h" +#include +#include + +class FileBuffer : public RefCounted { +public: + virtual ~FileBuffer() {} + + virtual int getc() { + uint8 chr; + if (read(&chr, 1) != 1) { + return EOF; + } + return chr; + } + virtual void putc(int chr) { + write(&chr, 1); + } + + virtual uint64 tell() const = 0; + virtual void seek(int64 pos, int mode) = 0; + virtual uint64 size() { + uint64 pos = tell(); + seek(0, SEEK_END); + uint64 res = tell(); + seek(pos, SEEK_SET); + return res; + } + + virtual size_t read(void* ptr, size_t size) = 0; + virtual size_t write(void const* ptr, size_t size) = 0; +}; + +class File { +protected: + FileBuffer* file_; +public: + File() + : file_(nullptr) + {} + File(FileBuffer* file) + : file_(file) + {} + File(File const& file) + : file_(file.file_) + { + if (file_) file_->addref(); + } + File(File&& file) + : file_(file.file_) + { + file.file_ = nullptr; + } + + enum { + READ = 0, + REWRITE = 1, + MODIFY = 2, + }; + + File(char const* name, uint32 mode = READ); + File(std::string const& name, uint32 mode = READ) + : File(name.c_str(), mode) + {} + ~File() { + file_->release(); + } + void release() { + file_->release(); + file_ = nullptr; + } + + File& operator=(File const& file) { + if (file_ == file.file_) { + return *this; + } + file_->release(); + file_ = file.file_; + if (file_) file_->addref(); + return *this; + } + File& operator=(File&& file) { + if (file_ == file.file_) { + return *this; + } + file_->release(); + file_ = file.file_; + file.file_ = nullptr; + return *this; + } + + operator bool() const { + return file_ != nullptr; + } + + int getc() { + return file_->getc(); + } + void putc(int chr) { + file_->putc(chr); + } + + void seek(int64 pos, int mode = SEEK_SET) { + file_->seek(pos, mode); + } + uint64 tell() const { + return file_->tell(); + } + uint64 size() { + return file_->size(); + } + + size_t read(void* dst, size_t size) { + return file_->read(dst, size); + } + template + T read() { + T x; + file_->read(&x, sizeof(T)); + return x; + } + uint8 read8() { + uint8 x; + file_->read(&x, 1); + return x; + } + uint16 read16(bool big = false) { + uint16 x; + file_->read(&x, 2); + if (big) x = _byteswap_ushort(x); + return x; + } + uint32 read32(bool big = false) { + uint32 x; + file_->read(&x, 4); + if (big) x = _byteswap_ulong(x); + return x; + } + uint64 read64(bool big = false) { + uint64 x; + file_->read(&x, 8); + if (big) x = _byteswap_uint64(x); + return x; + } + + size_t write(void const* ptr, size_t size) { + return file_->write(ptr, size); + } + template + bool write(T const& x) { + return file_->write(&x, sizeof(T)) == sizeof(T); + } + bool write8(uint8 x) { + return file_->write(&x, 1) == 1; + } + bool write16(uint16 x, bool big = false) { + if (big) x = _byteswap_ushort(x); + return file_->write(&x, 2) == 2; + } + bool write32(uint32 x, bool big = false) { + if (big) x = _byteswap_ulong(x); + return file_->write(&x, 4) == 4; + } + bool write64(uint64 x, bool big = false) { + if (big) x = _byteswap_uint64(x); + return file_->write(&x, 8) == 8; + } + + void printf(char const* fmt, ...); + + bool getline(std::string& line); + + class LineIterator; + LineIterator begin(); + LineIterator end(); + + static File memfile(void const* ptr, size_t size, bool clone = false); + File subfile(uint64 offset, uint64 size); + + void copy(File& src, uint64 size = max_uint64); + void md5(void* digest); + std::string md5(); + + static bool exists(char const* path); + static bool exists(std::string const& path) { + return exists(path.c_str()); + } +}; + +class MemoryFile : public File { +public: + MemoryFile(size_t initial = 16384, size_t grow = (1 << 20)); + uint8 const* data() const; + size_t csize() const; + uint8* reserve(uint32 size); + void resize(uint32 size); +}; + +class File::LineIterator { + friend class File; + File file_; + std::string line_; + LineIterator(File& file) { + if (file.getline(line_)) { + file_ = file; + } + } +public: + LineIterator() {} + + std::string const& operator*() { + return line_; + } + std::string const* operator->() { + return &line_; + } + + bool operator!=(LineIterator const& it) const { + return file_ != it.file_; + } + + LineIterator& operator++() { + if (!file_.getline(line_)) { + file_.release(); + } + return *this; + } +}; + +class FileLoader { + std::string root; +public: + FileLoader(std::string const& root = path::root()) + : root(root) + { + } + + struct SearchResults { + std::vector files; + std::vector folders; + }; + + File load(char const* name) { + return File(root / name); + } + SearchResults search(char const* mask); +}; diff --git a/src/base/functor.h b/src/base/functor.h new file mode 100644 index 0000000..987d368 --- /dev/null +++ b/src/base/functor.h @@ -0,0 +1,77 @@ +#pragma once + +template +class Functor { + class FunctionBase { + public: + virtual ~FunctionBase() {} + virtual Ret run(Args... args) const = 0; + }; + template + class Function : public FunctionBase { + F const& func_; + public: + Function(F const& f) + : func_(f) + {} + Ret run(Args... args) const { + return func_(args...); + } + }; + FunctionBase* func_; +public: + template + Functor(F const& f) + : func_(new Function(f)) + {} + Functor(Functor const& f) = delete; + ~Functor() { + delete func_; + } + Functor(Functor&& f) + : func_(f.func_) + { + f.func_ = nullptr; + } + Ret operator()(Args... args) const { + return func_->run(args...); + } +}; + +template +class FunctorNoRet { + class FunctionBase { + public: + virtual ~FunctionBase() {} + virtual void run(Args... args) const = 0; + }; + template + class Function : public FunctionBase { + F const& func_; + public: + Function(F const& f) + : func_(f) + {} + void run(Args... args) const { + return func_(args...); + } + }; + FunctionBase* func_; +public: + template + FunctorNoRet(F const& f) + : func_(new Function(f)) + {} + FunctorNoRet(FunctorNoRet const& f) = delete; + ~FunctorNoRet() { + delete func_; + } + FunctorNoRet(FunctorNoRet&& f) + : func_(f.func_) + { + f.func_ = nullptr; + } + void operator()(Args... args) const { + func_->run(args...); + } +}; diff --git a/src/base/http.cpp b/src/base/http.cpp new file mode 100644 index 0000000..3aedeed --- /dev/null +++ b/src/base/http.cpp @@ -0,0 +1,216 @@ +#define NOMINMAX +#include "http.h" +#include "common.h" +#include "types.h" +#include +#pragma comment(lib, "winhttp.lib") + +HttpRequest::SessionHolder::~SessionHolder() { + if (request) WinHttpCloseHandle(request); + if (connect) WinHttpCloseHandle(connect); + if (session) WinHttpCloseHandle(session); +} + +HttpRequest::HttpRequest(std::string const& url, RequestType type) + : type_(type) + , handles_(new SessionHolder) +{ + std::wstring url16 = utf8_to_utf16(url); + URL_COMPONENTS urlComp; + memset(&urlComp, 0, sizeof urlComp); + urlComp.dwStructSize = sizeof urlComp; + urlComp.dwSchemeLength = -1; + urlComp.dwHostNameLength = -1; + urlComp.dwUrlPathLength = -1; + urlComp.dwExtraInfoLength = -1; + + if (!WinHttpCrackUrl(url16.c_str(), url.size(), 0, &urlComp)) { + return; + } + + std::wstring host(urlComp.lpszHostName, urlComp.dwHostNameLength); + std::wstring path(urlComp.lpszUrlPath, urlComp.dwUrlPathLength); + + handles_->session = WinHttpOpen(L"ShrineTips", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0); + if (!handles_->session) return; + handles_->connect = WinHttpConnect(handles_->session, host.c_str(), urlComp.nPort, 0); + if (!handles_->connect) return; + handles_->request = WinHttpOpenRequest( + handles_->connect, + type == GET ? L"GET" : L"POST", + path.c_str(), + L"HTTP/1.1", + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + (urlComp.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0) | WINHTTP_FLAG_BYPASS_PROXY_CACHE); +} + +void HttpRequest::addHeader(std::string const& header) { + headers_.append(utf8_to_utf16(header)); + headers_.append(L"\r\n"); +} + +void HttpRequest::addHeader(std::string const& name, std::string const& value) { + addHeader(name + ": " + value); +} + +static std::string urlencode(std::string const& str) { + std::string dst; + for (unsigned char c : str) { + if (isalnum(c)) { + dst.push_back(c); + } else if (c == ' ') { + dst.push_back('+'); + } else { + char hex[4]; + sprintf_s(hex, sizeof hex, "%%%02X", c); + dst.append(hex); + } + } + return dst; +} + +void HttpRequest::addData(std::string const& key, std::string const& value) { + if (!post_.empty()) post_.push_back('&'); + post_.append(urlencode(key)); + post_.push_back('='); + post_.append(urlencode(value)); +} + +bool HttpRequest::send() { + if (!handles_->request) return false; + if (!WinHttpSendRequest(handles_->request, + headers_.empty() ? nullptr : headers_.c_str(), headers_.size(), + post_.empty() ? nullptr : &post_[0], post_.size(), post_.size(), 0)) { + return false; + } + return WinHttpReceiveResponse(handles_->request, NULL); +} + +uint32 HttpRequest::status() { + if (!handles_->request) return 0; + + DWORD statusCode = 0; + uint32 size = sizeof statusCode; + WinHttpQueryHeaders(handles_->request, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, + &statusCode, &size, WINHTTP_NO_HEADER_INDEX); + return statusCode; +} + + +class HttpBuffer : public FileBuffer { + std::shared_ptr handles_; + size_t size_; + uint8* data_; + size_t pos_; + size_t loaded_; +public: + HttpBuffer(std::shared_ptr const& handles, size_t size) + : handles_(handles) + , size_(size) + , pos_(0) + , loaded_(0) + { + data_ = new uint8[size]; + } + ~HttpBuffer() { + delete[] data_; + } + + int getc() { + if (pos_ < loaded_) { + return data_[pos_++]; + } else if (pos_ >= size_) { + return EOF; + } else { + uint8 chr; + read(&chr, 1); + return chr; + } + } + + uint64 tell() const { + return pos_; + } + void seek(int64 pos, int mode) { + switch (mode) { + case SEEK_CUR: + pos += pos_; + break; + case SEEK_END: + pos += size_; + break; + } + if (pos < 0) pos = 0; + if (pos > size_) pos = size_; + pos_ = pos; + } + uint64 size() { + return size_; + } + + size_t read(void* ptr, size_t size) { + if (size + pos_ > size_) { + size = size_ - pos_; + } + while (pos_ + size > loaded_) { + DWORD nsize = 0, nread; + if (!WinHttpQueryDataAvailable(handles_->request, &nsize) || !nsize) break; + WinHttpReadData(handles_->request, data_ + loaded_, std::min(nsize, size_ - loaded_), &nread); + loaded_ += nread; + } + if (size + pos_ > loaded_) { + size = loaded_ - pos_; + } + if (size) { + memcpy(ptr, data_ + pos_, size); + pos_ += size; + } + return size; + } + + size_t write(void const* ptr, size_t size) { + return 0; + } +}; + +File HttpRequest::response() { + if (!handles_->request) return File(); + + DWORD contentLength = 0; + DWORD size = (sizeof contentLength); + WinHttpQueryHeaders(handles_->request, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, + &contentLength, &size, WINHTTP_NO_HEADER_INDEX); + + return File(new HttpBuffer(handles_, contentLength)); +} + +File HttpRequest::get(std::string const& url) { + HttpRequest request(url); + if (!request.send() || request.status() != 200) return File(); + return request.response(); +} + +std::map HttpRequest::headers() { + std::map result; + if (!handles_->request) return result; + DWORD size; + WinHttpQueryHeaders(handles_->request, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, nullptr, &size, WINHTTP_NO_HEADER_INDEX); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return result; + std::vector raw((size + 1) / sizeof(wchar_t)); + WinHttpQueryHeaders(handles_->request, WINHTTP_QUERY_RAW_HEADERS, WINHTTP_HEADER_NAME_BY_INDEX, &raw[0], &size, WINHTTP_NO_HEADER_INDEX); + std::wstring cur; + for (wchar_t wc : raw) { + if (wc) { + cur.push_back(wc); + } else if (!cur.empty()) { + std::string line = utf16_to_utf8(cur); + cur.clear(); + + size_t colon = line.find(':'); + if (colon == std::string::npos) continue; + result.emplace(trim(line.substr(0, colon)), trim(line.substr(colon + 1))); + } + } + return result; +} diff --git a/src/base/http.h b/src/base/http.h new file mode 100644 index 0000000..ad60e55 --- /dev/null +++ b/src/base/http.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include "file.h" + +class HttpRequest { +public: + enum RequestType {GET, POST}; + + HttpRequest(std::string const& url, RequestType type = GET); + + void addHeader(std::string const& name, std::string const& value); + void addHeader(std::string const& header); + void addData(std::string const& key, std::string const& value); + + bool send(); + uint32 status(); + std::map headers(); + File response(); + + static File get(std::string const& url); + +private: + struct SessionHolder { + HINTERNET session = nullptr; + HINTERNET connect = nullptr; + HINTERNET request = nullptr; + ~SessionHolder(); + }; + friend class HttpBuffer; + std::shared_ptr handles_; + RequestType type_; + std::wstring headers_; + std::string post_; +}; diff --git a/src/base/json.cpp b/src/base/json.cpp new file mode 100644 index 0000000..dcbee7d --- /dev/null +++ b/src/base/json.cpp @@ -0,0 +1,989 @@ +#include "json.h" +#include + +namespace json { + +template +struct Defaults { + static T value_; +}; +template +T Defaults::value_; + +Value::Value(Type type) + : type_(tUndefined) +{ + setType(type); +} +Value::Value(bool val) + : type_(tUndefined) +{ + setType(tBoolean); + bool_ = val; +} +Value::Value(int val) + : type_(tUndefined) +{ + setType(tInteger); + int_ = val; +} +Value::Value(unsigned int val) + : type_(tUndefined) +{ + if (val > 0x7FFFFFFF) { + setType(tNumber); + number_ = static_cast(val); + } else { + setType(tInteger); + int_ = static_cast(val); + } +} +Value::Value(sint32 val) + : type_(tUndefined) +{ + setType(tInteger); + int_ = static_cast(val); +} +Value::Value(uint32 val) + : type_(tUndefined) +{ + if (val > 0x7FFFFFFF) { + setType(tNumber); + number_ = static_cast(val); + } else { + setType(tInteger); + int_ = static_cast(val); + } +} +Value::Value(sint64 val) + : type_(tUndefined) +{ + if (val > 0x7FFFFFFFLL || val < -0x80000000LL) { + setType(tNumber); + number_ = static_cast(val); + } else { + setType(tInteger); + int_ = static_cast(val); + } +} +Value::Value(uint64 val) + : type_(tUndefined) +{ + if (val > 0x7FFFFFFFULL) { + setType(tNumber); + number_ = static_cast(val); + } else { + setType(tInteger); + int_ = static_cast(val); + } +} +Value::Value(double val) + : type_(tUndefined) +{ + setType(tNumber); + number_ = val; +} +Value::Value(std::string const& val) + : type_(tUndefined) +{ + setType(tString); + *string_ = val; +} +Value::Value(char const* val) + : type_(tUndefined) +{ + setType(tString); + *string_ = val; +} +Value::Value(Value const& rhs) +: type_(rhs.type_) +{ + switch (type_) { + case tString: + string_ = new std::string(*rhs.string_); + break; + case tObject: + map_ = new Map(*rhs.map_); + break; + case tArray: + array_ = new Array(*rhs.array_); + break; + case tInteger: + int_ = rhs.int_; + break; + case tNumber: + number_ = rhs.number_; + break; + case tBoolean: + bool_ = rhs.bool_; + break; + } +} + +Value& Value::operator=(Value const& rhs) { + clear(); + type_ = rhs.type_; + switch (type_) { + case tString: + string_ = new std::string(*rhs.string_); + break; + case tObject: + map_ = new Map(*rhs.map_); + break; + case tArray: + array_ = new Array(*rhs.array_); + break; + case tInteger: + int_ = rhs.int_; + break; + case tNumber: + number_ = rhs.number_; + break; + case tBoolean: + bool_ = rhs.bool_; + break; + } + return *this; +} + +void Value::clear() { + switch (type_) { + case tString: + delete string_; + break; + case tObject: + delete map_; + break; + case tArray: + delete array_; + break; + } + type_ = tUndefined; +} +Value& Value::setType(Type type) { + if (type == type_) return *this; + clear(); + type_ = type; + switch (type_) { + case tString: + string_ = new std::string(); + break; + case tObject: + map_ = new Map(); + break; + case tArray: + array_ = new Array(); + break; + } + return *this; +} + +// tBoolean +bool Value::getBoolean() const { + return (type_ == tBoolean ? bool_ : false); +} +Value& Value::setBoolean(bool data) { + setType(tBoolean); + bool_ = data; + return *this; +} + +std::string const& Value::getString() const { + return (type_ == tString ? *string_ : Defaults::value_); +} +Value& Value::setString(char const* data) { + setType(tString); + *string_ = data; + return *this; +} +Value& Value::setString(std::string const& data) { + setType(tString); + *string_ = data; + return *this; +} + +// tNumber +bool Value::isInteger() const { + switch (type_) { + case tInteger: return true; + case tNumber: return (int)number_ == number_; + default: return false; + } +} +int Value::getInteger() const { + if (!isInteger()) return 0; + switch (type_) { + case tInteger: return int_; + case tNumber: return static_cast(number_); + default: return 0; + } +} +double Value::getNumber() const { + switch (type_) { + case tInteger: return static_cast(int_); + case tNumber: return number_; + default: return 0; + } +} +Value& Value::setInteger(int data) { + setType(tInteger); + int_ = data; + return *this; +} +Value& Value::setNumber(double data) { + setType(tNumber); + number_ = data; + return *this; +} + +// tObject +Value::Map const& Value::getMap() const { + return (type_ == tObject ? *map_ : Defaults::value_); +} +bool Value::has(std::string const& name) const { + if (type_ != tObject) return false; + return map_->find(name) != map_->end(); +} +bool Value::has(char const* name) const { + if (type_ != tObject) return false; + return map_->find(name) != map_->end(); +} +Value const* Value::get(std::string const& name) const { + if (type_ != tObject) return nullptr; + auto it = map_->find(name); + return (it != map_->end() ? &it->second : nullptr); +} +Value* Value::get(std::string const& name) { + if (type_ != tObject) return nullptr; + auto it = map_->find(name); + return (it != map_->end() ? &it->second : nullptr); +} +Value const* Value::get(char const* name) const { + if (type_ != tObject) return nullptr; + auto it = map_->find(name); + return (it != map_->end() ? &it->second : nullptr); +} +Value* Value::get(char const* name) { + if (type_ != tObject) return nullptr; + auto it = map_->find(name); + return (it != map_->end() ? &it->second : nullptr); +} +Value& Value::insert(std::string const& name, Value const& data) { + setType(tObject); + return (*map_)[name] = data; +} +Value& Value::insert(char const* name, Value const& data) { + setType(tObject); + return (*map_)[name] = data; +} +void Value::remove(std::string const& name) { + if (type_ == tObject) map_->erase(name); +} +void Value::remove(char const* name) { + if (type_ == tObject) map_->erase(name); +} +Value const& Value::operator[](std::string const& name) const { + Value const* ptr = get(name); + return (ptr ? *ptr : Defaults::value_); +} +Value const& Value::operator[](char const* name) const { + Value const* ptr = get(name); + return (ptr ? *ptr : Defaults::value_); +} +Value& Value::operator[](std::string const& name) { + setType(tObject); + return (*map_)[name]; +} +Value& Value::operator[](char const* name) { + setType(tObject); + return (*map_)[name]; +} + +// tArray +Value::Array const& Value::getArray() const { + return (type_ == tArray ? *array_ : Defaults::value_); +} +uint32 Value::length() const { + return (type_ == tArray ? array_->size() : 0); +} +Value const* Value::at(uint32 i) const { + if (type_ != tArray || i >= array_->size()) return nullptr; + return &(*array_)[i]; +} +Value* Value::at(uint32 i) { + if (type_ != tArray || i >= array_->size()) return nullptr; + return &(*array_)[i]; +} +Value& Value::insert(uint32 i, Value const& data) { + setType(tArray); + return *array_->insert(array_->begin() + std::min(i, array_->size()), data); +} +Value& Value::append(Value const& data) { + setType(tArray); + array_->push_back(data); + return array_->back(); +} +void Value::remove(uint32 i) { + if (type_ != tArray || i >= array_->size()) return; + array_->erase(array_->begin() + i); +} +Value const& Value::operator[](int i) const { + if (type_ != tArray || i < 0 || i >= array_->size()) return Defaults::value_; + return (*array_)[i]; +} +Value& Value::operator[](int i) { + setType(tArray); + if (i < 0) i = 0; + if (array_->size() <= i) { + array_->resize(i + 1); + } + return (*array_)[i]; +} + +Value::Iterator Value::begin() { + switch (type_) { + case tObject: + return Iterator(map_->begin()); + case tArray: + return Iterator(array_->begin()); + default: + return Iterator(); + } +} +Value::Iterator Value::end() { + switch (type_) { + case tObject: + return Iterator(map_->end()); + case tArray: + return Iterator(array_->end()); + default: + return Iterator(); + } +} +Value::ConstIterator Value::begin() const { + switch (type_) { + case tObject: + return ConstIterator(map_->begin()); + case tArray: + return ConstIterator(array_->begin()); + default: + return ConstIterator(); + } +} +Value::ConstIterator Value::end() const { + switch (type_) { + case tObject: + return ConstIterator(map_->end()); + case tArray: + return ConstIterator(array_->end()); + default: + return ConstIterator(); + } +} + +class Tokenizer { + File* file; + bool strict; +public: + uint32 line; + uint32 col; + int chr; + int move() { + int old = chr; + chr = file->getc(); + if (chr == '\n') ++line; + if (chr == '\r' || chr == '\n') col = 0; + else ++col; + return old; + } + + enum State {tEnd, tSymbol, tInteger, tNumber, tString, tIdentifier, tError = -1}; + State state; + + int valInteger; + double valNumber; + std::string value; + + Tokenizer(File* file, bool strict) + : file(file) + , chr(file->getc()) + , strict(strict) + , line(0) + , col(0) + {} + + State next(); +}; + +Tokenizer::State Tokenizer::next() { + while (chr != EOF && isspace(chr)) { + move(); + } + if (chr == EOF) { + return state = tEnd; + } + value.clear(); + if (chr == '"' || (!strict && chr == '\'')) { + char init = chr; + state = tString; + move(); + while (chr != init && chr != EOF) { + if (chr == '\\') { + move(); + switch (chr) { + case '\'': + case '"': + case '\\': + case '/': + value.push_back(move()); + break; + case 'b': + value.push_back('\b'); + move(); + break; + case 'f': + value.push_back('\f'); + move(); + break; + case 'n': + value.push_back('\n'); + move(); + break; + case 'r': + value.push_back('\r'); + move(); + break; + case 't': + value.push_back('\t'); + move(); + break; + case 'u': { + move(); + uint32 cp = 0; + for (int i = 0; i < 4; ++i) { + if (chr >= '0' && chr <= '9') { + cp = cp * 16 + (move() - '0'); + } else if (chr >= 'a' && chr <= 'f') { + cp = cp * 16 + (move() - 'a') + 10; + } else if (chr >= 'A' && chr <= 'F') { + cp = cp * 16 + (move() - 'A') + 10; + } else { + value = "invalid hex digit"; + return state = tError; + } + } + if (cp <= 0x7F) { + value.push_back(cp); + } else if (cp <= 0x7FF) { + value.push_back(0xC0 | ((cp >> 6) & 0x1F)); + value.push_back(0x80 | (cp & 0x3F)); + } else { + value.push_back(0xE0 | ((cp >> 12) & 0x0F)); + value.push_back(0x80 | ((cp >> 6) & 0x3F)); + value.push_back(0x80 | (cp & 0x3F)); + } + break; + } + default: + value = "invalid escape sequence"; + return state = tError; + } + } else { + value.push_back(move()); + } + } + move(); + } else if (chr == '-' || (chr >= '0' && chr <= '9') || (!strict && (chr == '.' || chr == '+'))) { + state = tInteger; + if (chr == '-' || (!strict && chr == '+')) { + value.push_back(move()); + } + if (chr == '0') { + value.push_back(move()); + } else if (chr >= '1' && chr <= '9') { + while (chr >= '0' && chr <= '9') { + value.push_back(move()); + } + } else if (strict || chr != '.') { + value = "invalid number"; + return state = tError; + } + if (chr == '.') { + state = tNumber; + value.push_back(move()); + if ((chr < '0' || chr > '9') && strict) { + value = "invalid number"; + return state = tError; + } + while (chr >= '0' && chr <= '9') { + value.push_back(move()); + } + } + if (chr == 'e' || chr == 'E') { + state = tNumber; + value.push_back(move()); + if (chr == '-' || chr == '+') { + value.push_back(move()); + } + if (chr < '0' || chr > '9') { + value = "invalid number"; + return state = tError; + } + while (chr >= '0' && chr <= '9') { + value.push_back(move()); + } + } + valNumber = atof(value.c_str()); + if (state == tInteger) { + valInteger = int(valNumber); + if (double(valInteger) != valNumber) { + state = tNumber; + } + } + } else if (chr == '{' || chr == '}' || chr == '[' || chr == ']' || chr == ':' || chr == ',' || chr == '(' || chr == ')') { + state = tSymbol; + value.push_back(move()); + } else if ((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || chr == '_') { + state = tIdentifier; + while ((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr == '_') { + value.push_back(move()); + } + } else if (chr == '/') { + move(); + if (chr == '/') { + while (chr != '\n' && chr != EOF) { + move(); + } + return next(); + } else if (chr == '*') { + move(); + bool star = false; + while (chr != EOF && (!star || chr != '/')) { + star = (chr == '*'); + move(); + } + if (chr == EOF) { + value = "unterminated comment"; + return state = tError; + } + move(); + return next(); + } else { + value = "unexpected symbol '/'"; + return state = tError; + } + } else { + value = "unexpected symbol '"; + value.push_back(chr); + value.push_back('\''); + return state = tError; + } + return state; +} + +bool parse(File& file, Visitor* visitor, int mode, std::string* func) { + enum State{sValue, sKey, sColon, sNext, sEnd} state = sValue; + std::vector objStack; + bool topEmpty = true; + Tokenizer tok(&file, mode == mJSON); + if (mode == mJSCall) { + if (func) func->clear(); + while (tok.chr != EOF && tok.chr != '(') { + if (func) func->push_back(tok.chr); + tok.move(); + } + if (tok.chr != '(') { + visitor->onError(tok.line, tok.col, "expected '('"); + return false; + } + tok.move(); + } + tok.next(); + while (state != sEnd) { + if (tok.state == Tokenizer::tError) { + visitor->onError(tok.line, tok.col, tok.value); + return false; + } + bool advance = true; + switch (state) { + case sValue: + if (tok.state == Tokenizer::tInteger) { + if (!visitor->onInteger(tok.valInteger)) return false; + } else if (tok.state == Tokenizer::tNumber) { + if (!visitor->onNumber(tok.valNumber)) return false; + } else if (tok.state == Tokenizer::tString) { + if (!visitor->onString(tok.value)) return false; + } else if (tok.state == Tokenizer::tIdentifier) { + if (tok.value == "null") { + if (!visitor->onNull()) return false; + } else if (tok.value == "true") { + if (!visitor->onBoolean(true)) return false; + } else if (tok.value == "false") { + if (!visitor->onBoolean(false)) return false; + } else { + visitor->onError(tok.line, tok.col, "unexpected identifier " + tok.value); + return false; + } + } else if (tok.state == Tokenizer::tSymbol) { + if (tok.value == "{") { + if (!visitor->onOpenMap()) return false; + objStack.push_back(Value::tObject); + topEmpty = true; + state = sKey; + break; + } else if (tok.value == "[") { + if (!visitor->onOpenArray()) return false; + objStack.push_back(Value::tArray); + topEmpty = true; + state = sValue; + break; + } else if ((mode != mJSON || topEmpty) && tok.value == "]" && !objStack.empty() && objStack.back() == Value::tArray) { + state = sNext; + advance = false; + break; + } else { + visitor->onError(tok.line, tok.col, "unexpected symbol '" + tok.value + "'"); + return false; + } + } else { + visitor->onError(tok.line, tok.col, "value expected"); + return false; + } + topEmpty = false; + if (objStack.empty()) { + state = sEnd; + } else { + state = sNext; + } + break; + case sKey: + if (tok.state == Tokenizer::tString) { + if (!visitor->onMapKey(tok.value)) return false; + state = sColon; + } else if (mode != mJSON && tok.state == Tokenizer::tIdentifier) { + if (!visitor->onMapKey(tok.value)) return false; + state = sColon; + } else if (mode != mJSON && (tok.state == Tokenizer::tNumber || tok.state == Tokenizer::tInteger)) { + if (!visitor->onMapKey(tok.value)) return false; + state = sColon; + } else if ((mode != mJSON || topEmpty) && tok.state == Tokenizer::tSymbol && tok.value == "}") { + state = sNext; + advance = false; + } else { + visitor->onError(tok.line, tok.col, "object key expected"); + return false; + } + break; + case sColon: + if (tok.state == Tokenizer::tSymbol && tok.value == ":") { + state = sValue; + } else { + visitor->onError(tok.line, tok.col, "':' expected"); + return false; + } + break; + case sNext: + if (tok.state == Tokenizer::tSymbol) { + if (tok.value == ",") { + if (objStack.back() == Value::tObject) { + state = sKey; + } else { + state = sValue; + } + } else if (tok.value == "}") { + if (objStack.back() != Value::tObject) { + visitor->onError(tok.line, tok.col, "mismatched '}'"); + return false; + } + if (!visitor->onCloseMap()) return false; + } else if (tok.value == "]") { + if (objStack.back() != Value::tArray) { + visitor->onError(tok.line, tok.col, "mismatched ']'"); + return false; + } + if (!visitor->onCloseArray()) return false; + } else { + visitor->onError(tok.line, tok.col, "unexpected symbol '" + tok.value + "'"); + return false; + } + if (state == sNext) { + objStack.pop_back(); + topEmpty = false; + if (objStack.empty()) { + advance = false; + state = sEnd; + } else { + state = sNext; + } + } + } else { + if (objStack.back() == Value::tObject) { + visitor->onError(tok.line, tok.col, "'}' or ',' expected"); + } else { + visitor->onError(tok.line, tok.col, "']' or ',' expected"); + } + return false; + } + break; + default: + visitor->onError(tok.line, tok.col, "internal error"); + return false; + } + if (advance) { + tok.next(); + } + } + if (mode == mJSCall) { + if (tok.next() != Tokenizer::tSymbol || tok.value != ")") { + visitor->onError(tok.line, tok.col, "expected ')'"); + return false; + } + tok.move(); + if (tok.chr == ';') tok.move(); + //while (tok.chr != EOF && isspace(tok.chr)) tok.move(); + //if (tok.chr != EOF) { + // visitor->onError(tok.line, tok.col, fmtstring("unexpected symbol '%c'", (char)tok.chr)); + // return false; + //} + } else { + //if (tok.next() != Tokenizer::tEnd) { + // visitor->onError(tok.line, tok.col, fmtstring("unexpected symbol '%c'", (char)tok.chr)); + // return false; + //} + } + file.seek(-1, SEEK_CUR); + return visitor->onEnd(); +} + +BuilderVisitor::BuilderVisitor(Value& value, bool throwExceptions) + : Visitor(throwExceptions) + , value_(value) + , state_(sStart) +{} + +bool BuilderVisitor::openComplexValue(Value::Type type) { + switch (state_) { + case sStart: + stack_.push_back(&value_.setType(type)); + break; + case sArrayValue: + stack_.push_back(&stack_.back()->append(type)); + break; + case sMapValue: + stack_.push_back(&stack_.back()->insert(key_, type)); + state_ = sMapKey; + break; + default: + return false; + } + return true; +} + +bool BuilderVisitor::closeComplexValue() { + stack_.pop_back(); + if (!stack_.empty()) { + switch (stack_.back()->type()) { + case Value::tObject: + state_ = sMapKey; + break; + case Value::tArray: + state_ = sArrayValue; + break; + default: + return false; + } + } else { + state_ = sFinish; + } + return true; +} + +bool parse(File& file, Value& value, int mode, std::string* func, bool throwExceptions) { + BuilderVisitor builder(value, throwExceptions); + value.clear(); + return parse(file, &builder, mode, func); +} + +bool Value::walk(Visitor* visitor) const { + switch (type_) { + case tUndefined: + case tNull: + return visitor->onNull(); + case tBoolean: + return visitor->onBoolean(bool_); + case tString: + return visitor->onString(*string_); + case tInteger: + return visitor->onInteger(int_); + case tNumber: + return visitor->onNumber(number_); + case tObject: + if (!visitor->onOpenMap()) return false; + for (auto it = map_->begin(); it != map_->end(); ++it) { + if (!visitor->onMapKey(it->first)) return false; + if (!it->second.walk(visitor)) return false; + } + return visitor->onCloseMap(); + case tArray: + if (!visitor->onOpenArray()) return false; + for (auto it = array_->begin(); it != array_->end(); ++it) { + if (!it->walk(visitor)) return false; + } + return visitor->onCloseArray(); + default: + return false; + } +} + +WriterVisitor::WriterVisitor(File& file, int mode, char const* func) + : file_(file) + , mode_(mode) + , escape_(false) + , empty_(true) + , object_(false) +{ + if (mode == mJSCall) { + file.printf("%s(", func ? func : ""); + } +} + +void WriterVisitor::onValue() { + if (!object_ && !empty_) { + file_.putc(','); + } + if (!object_ && !curIndent_.empty()) { + file_.printf("\n%s", curIndent_.c_str()); + } + empty_ = false; + object_ = false; +} + +void WriterVisitor::openValue(char chr) { + onValue(); + empty_ = true; + file_.putc(chr); + curIndent_.append(indent_); +} +void WriterVisitor::closeValue(char chr) { + curIndent_.resize(curIndent_.size() - indent_.size()); + if (!empty_ && !indent_.empty()) { + if (mode_ != mJSON) file_.putc(','); + file_.printf("\n%s", curIndent_.c_str()); + } + file_.putc(chr); + empty_ = false; +} + +void WriterVisitor::writeString(std::string const& str) { + file_.putc('"'); + for (uint32 pos = 0; pos < str.length(); ++pos) { + uint8 chr = static_cast(str[pos]); + switch (chr) { + case '"': + file_.printf("\\\""); + break; + case '\\': + file_.printf("\\\\"); + break; + case '\b': + file_.printf("\\b"); + break; + case '\f': + file_.printf("\\f"); + break; + case '\n': + file_.printf("\\n"); + break; + case '\r': + file_.printf("\\r"); + break; + case '\t': + file_.printf("\\t"); + break; + default: + if (chr < 32) { + file_.printf("\\u%04X", (int)chr); + } else if (chr <= 0x7F || !escape_) { + file_.putc(chr); + } else { + uint8 hdr = chr; + uint32 mask = 0x3F; + uint32 cp = chr; + while ((hdr & 0xC0) == 0xC0 && pos < str.length() - 1) { + chr = str[++pos]; + cp = (cp << 6) | (chr & 0x3F); + mask = (mask << 5) | 0x1F; + hdr <<= 1; + } + cp &= mask; + file_.printf("\\u%04X", cp & 0xFFFF); + } + } + } + file_.putc('"'); +} + +bool WriterVisitor::onNull() { + onValue(); + file_.printf("null"); + return true; +} +bool WriterVisitor::onBoolean(bool val) { + onValue(); + file_.printf(val ? "true" : "false"); + return true; +} +bool WriterVisitor::onInteger(int val) { + onValue(); + file_.printf("%d", val); + return true; +} +bool WriterVisitor::onNumber(double val) { + onValue(); + file_.printf("%.14g", val); + return true; +} +bool WriterVisitor::onString(std::string const& val) { + onValue(); + writeString(val); + return true; +} +bool WriterVisitor::onMapKey(std::string const& key) { + onValue(); + object_ = true; + bool safe = (mode_ != mJSON) && + (!key.empty() && ((key[0] >= 'a' && key[0] <= 'z') + || (key[0] >= 'A' && key[0] <= 'Z') + || key[0] == '_')); + for (uint32 pos = 1; pos < key.length() && safe; ++pos) { + if ((key[pos] < 'a' || key[pos] > 'z') && + (key[pos] < 'A' || key[pos] > 'Z') && + (key[pos] < '0' || key[pos] > '9') && key[pos] != '_') { + safe = false; + } + } + if (safe) { + file_.printf("%s", key.c_str()); + } else { + writeString(key); + } + file_.putc(':'); + if (!indent_.empty()) file_.putc(' '); + return true; +} +bool WriterVisitor::onEnd() { + if (mode_ == mJSCall) file_.printf(");"); + if (!indent_.empty()) file_.putc('\n'); + return true; +} + +bool write(File& file, Value const& value, int mode, char const* func) { + WriterVisitor writer(file, mode, func); + writer.setIndent(2); + if (!value.walk(&writer)) return false; + return writer.onEnd(); +} + +bool Visitor::printExStrings = true; + +} diff --git a/src/base/json.h b/src/base/json.h new file mode 100644 index 0000000..74f94ac --- /dev/null +++ b/src/base/json.h @@ -0,0 +1,381 @@ +#pragma once + +#include "types.h" +#include "file.h" +#include "error.h" +#include +#include + +namespace json { + +class Visitor; + +class Value { +public: + typedef std::map Map; + typedef std::vector Array; + enum Type { tUndefined, tNull, tString, tInteger, tNumber, tObject, tArray, tBoolean }; + +private: + Type type_; + union { + int int_; + double number_; + std::string* string_; + Map* map_; + Array* array_; + bool bool_; + }; +public: + typedef std::map Map; + typedef std::vector Array; + + Value(Type type = tUndefined); + ~Value() { + clear(); + } + + Value(bool val); + Value(int val); + Value(unsigned int val); + Value(sint32 val); + Value(uint32 val); + Value(sint64 val); + Value(uint64 val); + Value(double val); + Value(std::string const& val); + Value(char const* val); + Value(Value const& val); + + Value& operator=(Value const& rhs); + Value& setValue(Value const& rhs) { + return *this = rhs; + } + + void clear(); + Type type() const { + return type_; + } + Value& setType(Type type); + + // tBoolean + bool getBoolean() const; + Value& setBoolean(bool data); + + // tString + std::string const& getString() const; + Value& setString(std::string const& data); + Value& setString(char const* data); + + // tNumber + bool isInteger() const; + int getInteger() const; + double getNumber() const; + Value& setInteger(int data); + Value& setNumber(double data); + + // tObject + Map const& getMap() const; + bool has(std::string const& name) const; + bool has(char const* name) const; + Value const* get(std::string const& name) const; + Value* get(std::string const& name); + Value const* get(char const* name) const; + Value* get(char const* name); + Value& insert(std::string const& name, Value const& data); + void remove(std::string const& name); + Value& insert(char const* name, Value const& data); + void remove(char const* name); + Value const& operator[](std::string const& name) const; + Value& operator[](std::string const& name); + Value const& operator[](char const* name) const; + Value& operator[](char const* name); + + bool hasProperty(char const* name, uint8 type) const { + Value const* prop = get(name); + return prop && prop->type() == type; + } + + // tArray + Array const& getArray() const; + uint32 length() const; + Value const* at(uint32 i) const; + Value* at(uint32 i); + Value& insert(uint32 i, Value const& data); + Value& append(Value const& data); + void remove(uint32 i); + Value const& operator[](int i) const; + Value& operator[](int i); + + class Iterator { + Type type_; + Map::iterator map_; + Array::iterator array_; + friend class Value; + Iterator(Map::iterator map) : map_(map), type_(tObject) {} + Iterator(Array::iterator array) : array_(array), type_(tArray) {} + public: + Iterator() : type_(tUndefined) {} + + Iterator& operator=(Iterator const& it) { + type_ = it.type_; + if (type_ == tObject) map_ = it.map_; + if (type_ == tArray) array_ = it.array_; + return *this; + } + Iterator& operator++() { + if (type_ == tObject) ++map_; + if (type_ == tArray) ++array_; + return *this; + } + bool operator==(Iterator const& it) { + if (type_ != it.type_) return false; + if (type_ == tObject) return map_ == it.map_; + if (type_ == tArray) return array_ == it.array_; + return true; + } + bool operator!=(Iterator const& it) { + if (type_ != it.type_) return true; + if (type_ == tObject) return map_ != it.map_; + if (type_ == tArray) return array_ != it.array_; + return false; + } + + Value& operator*() const { + if (type_ == tObject) return map_->second; + return *array_; + } + Value* operator->() const { + if (type_ == tObject) return &map_->second; + return &*array_; + } + std::string const& key() const { + return map_->first; + } + }; + + class ConstIterator { + Type type_; + Map::const_iterator map_; + Array::const_iterator array_; + friend class Value; + ConstIterator(Map::const_iterator map) : map_(map), type_(tObject) {} + ConstIterator(Array::const_iterator array) : array_(array), type_(tArray) {} + public: + ConstIterator() : type_(tUndefined) {} + + ConstIterator& operator=(ConstIterator const& it) { + type_ = it.type_; + if (type_ == tObject) map_ = it.map_; + if (type_ == tArray) array_ = it.array_; + return *this; + } + ConstIterator& operator++() { + if (type_ == tObject) ++map_; + if (type_ == tArray) ++array_; + return *this; + } + bool operator==(ConstIterator const& it) { + if (type_ != it.type_) return false; + if (type_ == tObject) return map_ == it.map_; + if (type_ == tArray) return array_ == it.array_; + return true; + } + bool operator!=(ConstIterator const& it) { + if (type_ != it.type_) return true; + if (type_ == tObject) return map_ != it.map_; + if (type_ == tArray) return array_ != it.array_; + return false; + } + + Value const& operator*() const { + if (type_ == tObject) return map_->second; + return *array_; + } + Value const* operator->() const { + if (type_ == tObject) return &map_->second; + return &*array_; + } + std::string const& key() const { + return map_->first; + } + }; + + Iterator begin(); + Iterator end(); + ConstIterator begin() const; + ConstIterator end() const; + + bool walk(Visitor* visitor) const; +}; + +class Visitor { +public: + explicit Visitor(bool throwExceptions = false) + : throw_(throwExceptions) + {} + + static bool printExStrings; + + virtual ~Visitor() {} + virtual bool onNull() { return true; } + virtual bool onBoolean(bool val) { return true; } + virtual bool onInteger(int val) { return true; } + virtual bool onNumber(double val) { return true; } + virtual bool onString(std::string const& val) { return true; } + virtual bool onOpenMap() { return true; } + virtual bool onMapKey(std::string const& key) { return true; } + virtual bool onCloseMap() { return true; } + virtual bool onOpenArray() { return true; } + virtual bool onCloseArray() { return true; } + virtual bool onIntegerEx(int val, std::string const& alt) { + if (printExStrings) { + return onString(alt); + } else { + return onInteger(val); + } + } + + virtual bool onEnd() { return true; } + virtual void onError(uint32 line, uint32 col, std::string const& reason) { + if (throw_) throw Exception("JSON error at (%d:%d): %s", line + 1, col + 1, reason.c_str()); + } +private: + bool throw_; +}; + +class BuilderVisitor : public Visitor { +public: + BuilderVisitor(Value& value, bool throwExceptions = false); + bool onNull() { + return setValue(Value::tNull); + } + bool onBoolean(bool val) { + return setValue(val); + } + bool onInteger(int val) { + return setValue(val); + } + bool onNumber(double val) { + return setValue(val); + } + bool onString(std::string const& val) { + return setValue(val); + } + bool onOpenMap() { + bool res = openComplexValue(Value::tObject); + if (res) state_ = sMapKey; + return res; + } + bool onMapKey(std::string const& key) { + if (state_ != sMapKey) return false; + key_ = key; + state_ = sMapValue; + return true; + } + bool onCloseMap() { + return closeComplexValue(); + } + bool onOpenArray() { + bool res = openComplexValue(Value::tArray); + if (res) state_ = sArrayValue; + return res; + } + bool onCloseArray() { + return closeComplexValue(); + } +protected: + Value& value_; + std::string key_; + std::vector stack_; + enum { + sStart, + sMapValue, + sMapKey, + sArrayValue, + sFinish, + } state_; + + template + bool setValue(T const& value) { + switch (state_) { + case sStart: + value_.setValue(value); + break; + case sMapValue: + stack_.back()->insert(key_, value); + state_ = sMapKey; + break; + case sArrayValue: + stack_.back()->append(value); + break; + default: + return false; + } + return true; + } + + bool openComplexValue(Value::Type type); + bool closeComplexValue(); +}; + +enum {mJSON, mJS, mJSCall}; + +bool parse(File& file, Visitor* visitor, int mode = mJSON, std::string* func = nullptr); +bool parse(File& file, Value& value, int mode = mJSON, std::string* func = nullptr, bool throwExceptions = false); + +class WriterVisitor : public Visitor { +public: + WriterVisitor(File& file, int mode = mJSON, char const* func = nullptr); + + void setIndent(std::string indent) { + indent_ = indent; + } + void setIndent(int indent) { + indent_.assign(indent, ' '); + } + void escapeUnicode(bool escape) { + escape_ = escape; + } + + bool onNull(); + bool onBoolean(bool val); + bool onInteger(int val); + bool onNumber(double val); + bool onString(std::string const& val); + bool onOpenMap() { + openValue('{'); + return true; + } + bool onMapKey(std::string const& key); + bool onCloseMap() { + closeValue('}'); + return true; + } + bool onOpenArray() { + openValue('['); + return true; + } + bool onCloseArray() { + closeValue(']'); + return true; + } + bool onEnd(); + +protected: + File& file_; + int mode_; + bool escape_; + bool empty_; + bool object_; + std::string indent_; + std::string curIndent_; + void onValue(); + void openValue(char chr); + void closeValue(char chr); + void writeString(std::string const& str); +}; + +bool write(File& file, Value const& value, int mode = mJSON, char const* func = nullptr); + +} diff --git a/src/base/path.cpp b/src/base/path.cpp new file mode 100644 index 0000000..a8f14eb --- /dev/null +++ b/src/base/path.cpp @@ -0,0 +1,91 @@ +#include "path.h" +#include +using namespace std; + +string path::name(string const& path) { + int pos = path.length(); + while (pos > 0 && path[pos - 1] != '/' && path[pos - 1] != '\\') { + --pos; + } + return path.substr(pos); +} +string path::title(string const& path) { + int pos = path.length(); + int dot = path.length(); + while (pos > 0 && path[pos - 1] != '/' && path[pos - 1] != '\\') { + --pos; + if (path[pos] == '.' && dot == path.length()) { + dot = pos; + } + } + if (dot == pos) { + return path.substr(pos); + } else { + return path.substr(pos, dot - pos); + } +} +string path::path(string const& path) { + int pos = path.length(); + while (pos > 0 && path[pos - 1] != '/' && path[pos - 1] != '\\') { + --pos; + } + return path.substr(0, pos ? pos - 1 : 0); +} +string path::ext(string const& path) { + int pos = path.length(); + int dot = path.length(); + while (pos > 0 && path[pos - 1] != '/' && path[pos - 1] != '\\') { + --pos; + if (path[pos] == '.' && dot == path.length()) { + dot = pos; + } + } + if (dot == pos) { + return ""; + } else { + return path.substr(dot); + } +} + +void path::create(std::string const& path) { + std::string buf; + for (char chr : path) { + if (chr == '/' || chr == '\\') chr = sep; + buf.push_back(chr); + if (chr == sep) { + CreateDirectory(buf.c_str(), nullptr); + } + } + if (!buf.empty() && buf.back() != sep) { + CreateDirectory(buf.c_str(), nullptr); + } +} + +#include +std::string path::root() { + static std::string root_; + if (root_.empty()) { + char buffer[512]; + GetModuleFileName(GetModuleHandle(NULL), buffer, sizeof buffer); + root_ = path(buffer); + } + return root_; + //char buffer[512]; + //GetCurrentDirectory(sizeof buffer, buffer); + //return buffer; +} + +string operator / (string const& lhs, string const& rhs) { + if (lhs.empty() || rhs.empty()) return lhs + rhs; + bool left = (lhs.back() == '\\' || lhs.back() == '/'); + bool right = (rhs.front() == '\\' || rhs.front() == '/'); + if (left && right) { + string res = lhs; + res.pop_back(); + return res + rhs; + } else if (!left && !right) { + return lhs + path::sep + rhs; + } else { + return lhs + rhs; + } +} diff --git a/src/base/path.h b/src/base/path.h new file mode 100644 index 0000000..1fa883d --- /dev/null +++ b/src/base/path.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace path { + std::string name(std::string const& path); + std::string title(std::string const& path); + std::string path(std::string const& path); + std::string ext(std::string const& path); + void create(std::string const& path); + + std::string root(); + + static const char sep = '\\'; +} + +std::string operator / (std::string const& lhs, std::string const& rhs); diff --git a/src/base/pool.cpp b/src/base/pool.cpp new file mode 100644 index 0000000..6c2636d --- /dev/null +++ b/src/base/pool.cpp @@ -0,0 +1,100 @@ +#include "pool.h" + +struct FixedMemoryPool::MemoryChunk { + MemoryChunk* next; + MemoryChunk* nextFree; + + uint8* begin; + uint8* end; + uint8* firstFree; + uint8* firstUnused; + uint32 itemSize; + + MemoryChunk(uint32 size, uint32 count); + ~MemoryChunk(); + + bool hasSpace() { + return firstFree || firstUnused < end; + } + bool contains(uint8* ptr) { + return ptr >= begin && ptr < end; + } + uint8* alloc(); + void free(uint8* ptr); +}; + +FixedMemoryPool::MemoryChunk::MemoryChunk(uint32 size, uint32 count) + : next(nullptr) + , nextFree(nullptr) + , itemSize(size) + , firstFree(nullptr) +{ + begin = new uint8[size * count]; + end = begin + size * count; + firstUnused = begin; +} +FixedMemoryPool::MemoryChunk::~MemoryChunk() { + delete[] begin; +} + +uint8* FixedMemoryPool::MemoryChunk::alloc() { + if (firstFree) { + uint8* result = firstFree; + firstFree = *(uint8**)firstFree; + return result; + } else if (firstUnused < end) { + uint8* result = firstUnused; + firstUnused += itemSize; + return result; + } else { + return nullptr; + } +} +void FixedMemoryPool::MemoryChunk::free(uint8* ptr) { + *(uint8**)ptr = firstFree; + firstFree = ptr; +} + +FixedMemoryPool::FixedMemoryPool(uint32 itemSize, uint32 poolGrow) + : itemSize(itemSize) + , chunkSize(poolGrow / itemSize) + , chunks(nullptr) + , freeChunks(nullptr) +{ +} +FixedMemoryPool::~FixedMemoryPool() { + clear(); +} + +void* FixedMemoryPool::alloc() { + if (freeChunks == nullptr) { + freeChunks = new MemoryChunk(itemSize, chunkSize); + freeChunks->next = chunks; + chunks = freeChunks; + } + void* ptr = freeChunks->alloc(); + if (!freeChunks->hasSpace()) { + freeChunks = freeChunks->nextFree; + } + return ptr; +} +void FixedMemoryPool::free(void* ptr) { + for (MemoryChunk* chunk = chunks; chunk; chunk = chunk->next) { + if (chunk->contains((uint8*)ptr)) { + if (!chunk->hasSpace()) { + chunk->nextFree = freeChunks; + freeChunks = chunk; + } + chunk->free((uint8*)ptr); + return; + } + } +} +void FixedMemoryPool::clear() { + while (chunks) { + MemoryChunk* next = chunks->next; + delete chunks; + chunks = next; + } + freeChunks = nullptr; +} diff --git a/src/base/pool.h b/src/base/pool.h new file mode 100644 index 0000000..8c3f2c9 --- /dev/null +++ b/src/base/pool.h @@ -0,0 +1,55 @@ +#pragma once + +#include "types.h" + +class FixedMemoryPool { +public: + FixedMemoryPool(uint32 itemSize, uint32 poolGrow = 65536); + FixedMemoryPool(FixedMemoryPool&& src) + : itemSize(src.itemSize) + , chunkSize(src.chunkSize) + , chunks(src.chunks) + , freeChunks(src.freeChunks) + { + src.chunks = nullptr; + src.freeChunks = nullptr; + } + FixedMemoryPool(FixedMemoryPool const& src) = delete; + ~FixedMemoryPool(); + + void* alloc(); + void free(void* ptr); + + void clear(); + +private: + struct MemoryChunk; + uint32 itemSize; + uint32 chunkSize; + MemoryChunk* chunks; + MemoryChunk* freeChunks; +}; +template +class TypedMemoryPool : private FixedMemoryPool +{ +public: + TypedMemoryPool(uint32 poolGrow = 65536) + : FixedMemoryPool(sizeof(T), poolGrow) + { + } + TypedMemoryPool(TypedMemoryPool&& src) + : FixedMemoryPool(std::move(src)) + { + } + TypedMemoryPool(TypedMemoryPool const& src) = delete; + + T* alloc() { + T* ptr = (T*)FixedMemoryPool::alloc(); + new(ptr)T(); + return ptr; + } + void free(T* ptr) { + ptr->~T(); + FixedMemoryPool::free(ptr); + } +}; diff --git a/src/base/regexp.cpp b/src/base/regexp.cpp new file mode 100644 index 0000000..1c9e41a --- /dev/null +++ b/src/base/regexp.cpp @@ -0,0 +1,837 @@ +#include +#include + +#include "regexp.h" +#include "utf8.h" +#include "path.h" + +namespace re { + +static uint32 unescape(uint8_const_ptr& chr) { + uint32 cp = 0; + switch (*chr) { + case 'a': chr++; return '\a'; + case 'b': chr++; return '\b'; + case 'f': chr++; return '\f'; + case 'n': chr++; return '\n'; + case 'r': chr++; return '\r'; + case 't': chr++; return '\t'; + case 'v': chr++; return '\v'; + case 'u': + chr++; + for (int z = 0; z < 4 && isxdigit(*chr); z++) { + cp *= 16; + if (*chr >= '0' && *chr <= '9') cp += int(*chr - '0'); + else if (*chr >= 'a' && *chr <= 'f') cp += 10 + int(*chr - 'a'); + else if (*chr >= 'A' && *chr <= 'F') cp += 10 + int(*chr - 'A'); + chr++; + } + return cp; + default: + if (isdigit(*chr)) { + for (int z = 0; z < 3 && isdigit(*chr); z++) + cp = cp * 10 + int((*chr++) - '0'); + return cp; + } else { + return utf8::parse(utf8::transform(&chr, NULL)); + } + } +} +static uint32 getchar(uint8_const_ptr& chr, uint32* table = NULL) { + if (*chr == '\\') return unescape(++chr); + return utf8::parse(utf8::transform(&chr, table)); +} + +void CharacterClass::sort() { + std::sort(data.begin(), data.end()); + uint32 shift = 0; + for (uint32 i = 0; i < data.size(); i++) { + if (data[i].end < data[i].begin || (i - shift > 0 && data[i].end <= data[i - shift - 1].end)) { + shift++; + } else if (i - shift > 0 && data[i].begin <= data[i - shift - 1].end + 1) { + data[i - shift - 1].end = data[i].end; + shift++; + } else if (shift) { + data[i - shift] = data[i]; + } + } + data.resize(data.size() - shift); +} + +static void _addchar(std::string& res, char chr) { + if (chr == ']' || chr == '-' || chr == '\\' || chr == '^' || chr == '[') { + res.push_back('\\'); + } + res.push_back(chr); +} + +std::string CharacterClass::format() const { + bool chrmap[256]; + int has = 0, not = 0; + for (uint32 cp = 32; cp <= 126; ++cp) { + chrmap[cp] = match(cp); + has += (chrmap[cp] == true); + not += (chrmap[cp] == false); + } + if (!not) return "."; + std::string res("["); + if (has > not) { + res.push_back('^'); + for (uint32 cp = 32; cp <= 126; ++cp) { + chrmap[cp] = !chrmap[cp]; + } + } + for (uint32 cp = 32; cp <= 126; ++cp) { + if (chrmap[cp]) { + uint32 start = cp; + while (cp < 126 && chrmap[cp + 1]) { + ++cp; + } + if (cp > start + 2) { + _addchar(res, start); + res.push_back('-'); + _addchar(res, cp); + } else { + for (uint32 i = start; i <= cp; ++i) { + _addchar(res, i); + } + } + } + } + res.push_back(']'); + return res; +} + +void CharacterClass::addClass(CharacterClass const& cls) { + funcs.insert(funcs.end(), cls.funcs.begin(), cls.funcs.end()); + if (cls.invert) { + if (cls.data.size() == 0) { + addRange(0, 0xFFFFFFFF); + } else { + if (cls.data[0].begin > 0) { + addRange(0, cls.data[0].begin - 1); + } + for (int i = 1; i < cls.data.size(); i++) { + addRange(cls.data[i - 1].end + 1, cls.data[i].begin - 1); + } + if (cls.data[cls.data.size() - 1].end < 0xFFFFFFFF) { + addRange(cls.data[cls.data.size() - 1].end + 1, 0xFFFFFFFF); + } + } + } else { + data.insert(data.end(), cls.data.begin(), cls.data.end()); + } +} +uint8_const_ptr CharacterClass::init(char const* src, int flags) { + invert = (*src == '^'); + if (invert) src++; + uint8_const_ptr pos = (uint8_const_ptr)src; + uint32* table = ((flags & Prog::CaseInsensitive) ? utf8::tf_lower : NULL); + while (*pos && (pos == (uint8_const_ptr)src || *pos != ']')) { + uint32 cp = -1; + if (*pos == '\\') { + pos++; + CharacterClass* cls = getDefault(*pos, flags); + if (cls) { + pos++; + addClass(*cls); + } else { + cp = unescape(pos); + if (flags & Prog::CaseInsensitive) cp = towlower(cp); + } + } else { + cp = utf8::parse(utf8::transform(&pos, table)); + } + if (cp != -1) { + if (*pos == '-' && pos[1] && pos[1] != ']') { + pos++; + addRange(cp, getchar(pos, table)); + } else { + addRange(cp, cp); + } + } + } + sort(); + return pos; +} +bool CharacterClass::match(uint32 c) const { + int left = 0; + int right = data.size() - 1; + while (left <= right) { + int mid = (left + right) / 2; + if (c >= data[mid].begin && c <= data[mid].end) { + return !invert; + } + if (c < data[mid].begin) { + right = mid - 1; + } else { + left = mid + 1; + } + } + for (int i = 0; i < funcs.size(); i++) { + if (funcs[i](c)) return !invert; + } + return invert; +} + +static CharacterClass uClsNormal[] = { + CharacterClass("a-zA-Z0-9_"), + CharacterClass("^a-zA-Z0-9_"), + CharacterClass("0-9"), + CharacterClass("a-fA-F0-9"), + CharacterClass("^0-9"), + CharacterClass(" \t\n\r\f\v"), + CharacterClass("^ \t\n\r\f\v"), + CharacterClass("^\n"), + CharacterClass("^"), +}; + +static bool u_word(uint32 cp) { + return cp == '_' || (cp >= '0' && cp <= '9') || iswalnum(cp); +} +static bool u_notword(uint32 cp) { + return !(cp == '_' || (cp >= '0' && cp <= '9') || iswalnum(cp)); +} +static bool u_space(uint32 cp) { + return iswspace(cp); +} +static bool u_notspace(uint32 cp) { + return !iswspace(cp); +} +static CharacterClass uClsUnicode[] = { + CharacterClass(u_word), + CharacterClass(u_notword), + CharacterClass(u_space), + CharacterClass(u_notspace), +}; + +CharacterClass* CharacterClass::getDefault(char ch, int flags) { + switch (ch) { + case 'w': return (flags & Prog::Unicode ? &uClsUnicode[0] : &uClsNormal[0]); + case 'W': return (flags & Prog::Unicode ? &uClsUnicode[1] : &uClsNormal[1]); + case 'd': return &uClsNormal[2]; + case 'x': return &uClsNormal[3]; + case 'D': return &uClsNormal[4]; + case 's': return (flags & Prog::Unicode ? &uClsUnicode[2] : &uClsNormal[5]); + case 'S': return (flags & Prog::Unicode ? &uClsUnicode[3] : &uClsNormal[6]); + case '.': return (flags & Prog::DotAll ? &uClsNormal[8] : &uClsNormal[7]); + default: return NULL; + } +} + +///////////////////////////////////// + +struct State { + enum Type { + NONE = 0, + START = 1, + RBRA, + RBRANC, + LBRA, + LBRANC, + OR, + CAT, + STAR, + PLUS, + QUEST, + NOP, + OPERAND, + BOL, + EOL, + CHAR, + CCLASS, + END + }; + Type type; + union { + CharacterClass const* mask; + uint32 chr; + int subid; + State* left; + }; + union { + State* right; + State* next; + }; + int list; +}; +struct Operand { + State* first; + State* last; +}; +struct Operator { + State::Type type; + int subid; +}; +#define MAXSTACK 32 +struct Compiler { + State* states; + int maxStates; + int numStates; + + Operand andstack[MAXSTACK]; + int andsize; + Operator atorstack[MAXSTACK]; + int atorsize; + + bool lastand; + int brackets; + int cursub; + + int optsize; + + void init(char const* expr, int len); + State* operand(State::Type type); + void pushand(State* first, State* last); + void pushator(State::Type type); + void evaluntil(int pri); + int optimize(State* state); + void floatstart(); +}; +void Compiler::init(char const* expr, int length) { + maxStates = length * 6 + 6; + states = new State[maxStates]; + memset(states, 0, sizeof(State)* maxStates); + numStates = 0; + + andsize = 0; + atorstack[0].type = State::NONE; + atorstack[0].subid = 0; + atorsize = 1; + lastand = false; + brackets = 0; + cursub = 0; + + optsize = 0; +} +State* Compiler::operand(State::Type type) { + if (lastand) pushator(State::CAT); + State* s = &states[numStates++]; + s->type = type; + s->mask = NULL; + s->next = NULL; + pushand(s, s); + lastand = true; + return s; +} +void Compiler::pushand(State* first, State* last) { + andstack[andsize].first = first; + andstack[andsize].last = last; + andsize++; +} +void Compiler::pushator(State::Type type) { + if (type == State::RBRA || type == State::RBRANC) { + brackets--; + } + if (type == State::LBRA || type == State::LBRANC) { + if (type == State::LBRA) cursub++; + brackets++; + if (lastand) pushator(State::CAT); + } else { + evaluntil(type); + } + if (type != State::RBRA && type != State::RBRANC) { + atorstack[atorsize].type = type; + atorstack[atorsize].subid = cursub; + atorsize++; + } + lastand = (type == State::STAR || type == State::PLUS || + type == State::QUEST || type == State::RBRA || type == State::RBRANC); +} +void Compiler::evaluntil(int pri) { + State* s1; + State* s2; + while (pri == State::RBRA || pri == State::RBRANC || atorstack[atorsize - 1].type >= pri) { + atorsize--; + switch (atorstack[atorsize].type) { + case State::LBRA: + s1 = &states[numStates++]; + s2 = &states[numStates++]; + s1->type = State::LBRA; + s1->subid = atorstack[atorsize].subid; + s2->type = State::RBRA; + s2->subid = atorstack[atorsize].subid; + + s1->next = andstack[andsize - 1].first; + andstack[andsize - 1].first = s1; + andstack[andsize - 1].last->next = s2; + andstack[andsize - 1].last = s2; + s2->next = NULL; + return; + case State::LBRANC: + return; + case State::OR: + andsize--; + s1 = &states[numStates++]; + s2 = &states[numStates++]; + s1->type = State::OR; + s1->left = andstack[andsize - 1].first; + s1->right = andstack[andsize].first; + s2->type = State::NOP; + s2->mask = NULL; + s2->next = NULL; + andstack[andsize - 1].last->next = s2; + andstack[andsize].last->next = s2; + andstack[andsize - 1].first = s1; + andstack[andsize - 1].last = s2; + break; + case State::CAT: + andsize--; + andstack[andsize - 1].last->next = andstack[andsize].first; + andstack[andsize - 1].last = andstack[andsize].last; + break; + case State::STAR: + s1 = &states[numStates++]; + s1->type = State::OR; + s1->left = andstack[andsize - 1].first; + s1->right = NULL; + andstack[andsize - 1].last->next = s1; + andstack[andsize - 1].first = s1; + andstack[andsize - 1].last = s1; + break; + case State::PLUS: + s1 = &states[numStates++]; + s1->type = State::OR; + s1->left = andstack[andsize - 1].first; + s1->right = NULL; + andstack[andsize - 1].last->next = s1; + andstack[andsize - 1].last = s1; + break; + case State::QUEST: + s1 = &states[numStates++]; + s2 = &states[numStates++]; + s1->type = State::OR; + s1->left = andstack[andsize - 1].first; + s1->right = s2; + s2->type = State::NOP; + s2->mask = NULL; + s2->next = NULL; + andstack[andsize - 1].last->next = s2; + andstack[andsize - 1].first = s1; + andstack[andsize - 1].last = s2; + break; + } + } +} +int Compiler::optimize(State* state) { + if (state->list >= 0) return state->list; + if (state->type == State::NOP) { + state->list = optimize(state->next); + } else { + state->list = optsize++; + if (state->next) + optimize(state->next); + if (state->type == State::OR) + optimize(state->left); + } + return state->list; +} + +struct Thread { + State* state; + Match match; +}; + +Prog::Prog(char const* expr, int length, uint32 f) { + flags = f; + Compiler comp; + if (length < 0) length = strlen(expr); + comp.init(expr, length); + + uint32* ut_table = (flags & CaseInsensitive ? utf8::tf_lower : NULL); + + uint8_const_ptr pos = (uint8_const_ptr)expr; + uint8_const_ptr end = pos + length; + while (pos < end) { + State::Type type = State::CHAR; + CharacterClass const* mask = NULL; + uint32 cp = -1; + switch (*pos) { + case '\\': + pos++; + if (*pos != '.' && (mask = CharacterClass::getDefault(*pos, flags))) { + type = State::CCLASS; + } else { + cp = unescape(pos); + if (flags & CaseInsensitive) cp = towlower(cp); + pos--; + } + break; + case '*': + type = State::STAR; + break; + case '+': + type = State::PLUS; + break; + case '?': + type = State::QUEST; + break; + case '|': + type = State::OR; + break; + case '(': + type = State::LBRA; + break; + case ')': + type = State::RBRA; + break; + case '{': + type = State::LBRANC; + break; + case '}': + type = State::RBRANC; + break; + case '^': + type = State::BOL; + break; + case '$': + type = State::EOL; + break; + case '.': + type = State::CCLASS; + mask = CharacterClass::getDefault('.', flags); + break; + case '[': { + type = State::CCLASS; + CharacterClass* cls = new CharacterClass(); + masks.push_back(cls); + pos = cls->init((char*)pos + 1, flags); + mask = cls; + break; + } + } + if (cp == -1) { + cp = utf8::parse(utf8::transform(&pos, ut_table)); + } else { + pos++; + } + if (type < State::OPERAND) { + comp.pushator(type); + } else { + State* s = comp.operand(type); + if (type == State::CHAR) { + s->chr = cp; + } else if (type == State::CCLASS) { + s->mask = mask; + } + } + } + comp.evaluntil(State::START); + comp.operand(State::END); + comp.evaluntil(State::START); + + for (int i = 0; i < comp.numStates; i++) { + comp.states[i].list = -1; + } + int startpos = comp.optimize(comp.andstack[0].first); + states = new State[comp.optsize]; + for (int i = 0; i < comp.numStates; i++) { + int p = comp.states[i].list; + if (p >= 0 && comp.states[i].type != State::NOP) { + states[p].type = comp.states[i].type; + states[p].next = comp.states[i].next ? &states[comp.states[i].next->list] : NULL; + if (states[p].type == State::CHAR) { + states[p].chr = comp.states[i].chr; + } else if (states[p].type == State::CCLASS) { + states[p].mask = comp.states[i].mask; + } else if (states[p].type == State::OR) { + states[p].left = comp.states[i].left ? &states[comp.states[i].left->list] : NULL; + } else { + states[p].subid = comp.states[i].subid; + } + } + } + delete[] comp.states; + numStates = comp.optsize; + start = &states[startpos]; + + numCaptures = comp.cursub; + maxThreads = 32; + threads = new Thread[maxThreads * 2]; +} +Prog::~Prog() { + delete[] states; + for (int i = 0; i < masks.size(); i++) { + delete masks[i]; + } + delete[] threads; +} +void Prog::addthread(State* state, Match const& match) { + if (state->list < 0) { + if (numThreads[1 - cur] >= maxThreads) { + Thread* newthreads = new Thread[maxThreads * 4]; + memcpy(newthreads, threads, sizeof(Thread)* numThreads[0]); + memcpy(newthreads + maxThreads * 2, threads + maxThreads, sizeof(Thread)* numThreads[1]); + delete[] threads; + threads = newthreads; + maxThreads *= 2; + } + Thread* thread = &threads[(1 - cur) * maxThreads + numThreads[1 - cur]]; + state->list = numThreads[1 - cur]; + numThreads[1 - cur]++; + thread->state = state; + memcpy(&thread->match, &match, sizeof match); + } +} +void Prog::advance(State* state, Match const& match, uint32 cp, char const* ref) { + if (state->type == State::OR) { + advance(state->left, match, cp, ref); + advance(state->right, match, cp, ref); + } else if (state->type == State::LBRA) { + Match m2; + memcpy(&m2, &match, sizeof m2); + m2.start[state->subid] = ref; + advance(state->next, m2, cp, ref); + } else if (state->type == State::RBRA) { + Match m2; + memcpy(&m2, &match, sizeof m2); + m2.end[state->subid] = ref; + advance(state->next, m2, cp, ref); + } else if (state->type == State::BOL) { + if (flags & MultiLine) { + if (ref == matchText || ref[-1] == '\n') { + advance(state->next, match, 0xFFFFFFFF, ref); + } + } else { + if (ref == matchText) { + advance(state->next, match, 0xFFFFFFFF, ref); + } + } + } else if (state->type == State::EOL) { + if (flags & MultiLine) { + if (*ref == 0 || *ref == '\r' || *ref == '\n') { + advance(state->next, match, 0xFFFFFFFF, ref); + } + } else { + if (*ref == 0) { + advance(state->next, match, 0xFFFFFFFF, ref); + } + } + } else { + if (cp == 0xFFFFFFFF) { + addthread(state, match); + } + else if (cp && ((state->type == State::CHAR && cp == state->chr) || + (state->type == State::CCLASS && state->mask->match(cp)))) { + advance(state->next, match, 0xFFFFFFFF, (char*)utf8::next((uint8_const_ptr)ref)); + } + } +} +int Prog::run(char const* text, int length, bool exact, + bool(*callback) (Match const& match, void* arg), void* arg) { + cur = 0; + numThreads[0] = 0; + numThreads[1] = 0; + int pos = 0; + if (length < 0) length = strlen(text); + matchText = text; + int count = 0; + uint32* ut_table = (flags & CaseInsensitive ? utf8::tf_lower : NULL); + + while (true) { + for (int i = 0; i < numStates; i++) { + if (pos > 0 && states[i].type == State::END && states[i].list >= 0 && + (!exact || pos == length)) { + Thread* thread = &threads[cur * maxThreads + states[i].list]; + thread->match.end[0] = text + pos; + count++; + if (callback) { + if (!callback(thread->match, arg)) return count; + } + } + states[i].list = -1; + } + numThreads[1 - cur] = 0; + uint8_const_ptr next = (uint8_const_ptr)(text + pos); + uint32 cp = utf8::parse(utf8::transform(&next, ut_table)); + if (cp == '\r' && *next == '\n') next++; + for (int i = 0; i < numThreads[cur]; i++) { + advance(threads[cur * maxThreads + i].state, threads[cur * maxThreads + i].match, cp, text + pos); + } + if (pos == 0 || !exact) { + Match match; + memset(&match, 0, sizeof match); + match.start[0] = text + pos; + advance(start, match, cp, text + pos); + } + cur = 1 - cur; + if (pos >= length) break; + pos = (char*)next - text; + } + for (int i = 0; i < numStates; i++) { + if (states[i].type == State::END && states[i].list >= 0) { + Thread* thread = &threads[cur * maxThreads + states[i].list]; + thread->match.end[0] = text + pos; + count++; + if (callback) { + if (!callback(thread->match, arg)) return count; + } + } + } + return count; +} + +static bool matcher(Match const& match, void* arg) { + if (arg) { + auto sub = static_cast*>(arg); + sub->clear(); + for (int i = 0; i < sizeof(match.start) / sizeof(match.start[0]) && match.start[i]; i++) { + sub->emplace_back(match.start[i], match.end[i] - match.start[i]); + } + } + return true; +} +bool Prog::match(char const* text, std::vector* sub) { + int res = run(text, -1, true, matcher, sub); + if (res) { + if (sub) { + while (sub->size() <= numCaptures) { + sub->emplace_back(""); + } + } + return true; + } else { + return false; + } +} +static bool finder(Match const& match, void* arg) { + memcpy(arg, &match, sizeof match); + return false; +} +int Prog::find(char const* text, int start, std::vector* sub) +{ + Match match; + if (run(text + start, -1, false, finder, &match)) { + if (sub) { + sub->clear(); + for (int i = 0; i < sizeof(match.start) / sizeof(match.start[0]) && match.start[i]; i++) { + sub->emplace_back(match.start[i], match.end[i] - match.start[i]); + } + while (sub->size() <= numCaptures) { + sub->emplace_back(""); + } + } + return match.start[0] - text; + } else { + return -1; + } +} + +bool operator < (Match const& lhs, Match const& rhs) { + if (lhs.start[0] != rhs.start[0]) return lhs.start[0] < rhs.start[0]; + return lhs.end[0] > rhs.end[0]; +} + +struct FindStruct { + std::vector matches; + std::vector* result = nullptr; + Prog::FindFunc* func = nullptr; + char const* text; + + FindStruct(char const* text) + : text(text) + {} + static bool callback(Match const& match, void* arg); + void finish(); +}; +bool FindStruct::callback(Match const& match, void* arg) { + FindStruct& rs = *(FindStruct*)arg; + rs.matches.push_back(match); + return true; +} +void FindStruct::finish() { + std::sort(matches.begin(), matches.end()); + char const* end = text; + for (auto& m : matches) { + if (m.start[0] >= end) { + if (func) { + func->call(m); + } else { + result->emplace_back(m.start[0], m.end[0] - m.start[0]); + } + end = m.end[0]; + } + } +} +std::vector Prog::findAll(char const* text) { + std::vector result; + FindStruct rs(text); + rs.result = &result; + run(text, -1, false, FindStruct::callback, &rs); + rs.finish(); + return result; +} +void Prog::findAll_(char const* text, FindFunc* func) { + FindStruct rs(text); + rs.func = func; + run(text, -1, false, FindStruct::callback, &rs); + rs.finish(); +} + +struct ReplaceStruct { + std::vector matches; + Prog::ReplaceFunc* func = nullptr; + char const* with = nullptr; + char const* text; + + ReplaceStruct(char const* text) + : text(text) + {} + static bool callback(Match const& match, void* arg); + std::string finish(); +}; +static void addreplace(std::string& result, char const* with, Match const& match) { + for (int i = 0; with[i]; i++) { + if (with[i] == '\\') { + i++; + if (with[i] >= '0' && with[i] <= '9') { + int m = int(with[i] - '0'); + if (match.start[m] && match.end[m]) { + result.append(match.start[m], match.end[m] - match.start[m]); + } + } else { + result.push_back(with[i]); + } + } else { + result.push_back(with[i]); + } + } +} +bool ReplaceStruct::callback(Match const& match, void* arg) { + ReplaceStruct& rs = *(ReplaceStruct*)arg; + rs.matches.push_back(match); + return true; +} +std::string ReplaceStruct::finish() { + std::string result; + std::sort(matches.begin(), matches.end()); + char const* end = text; + for (auto& m : matches) { + if (m.start[0] >= end) { + result.append(end, m.start[0] - end); + if (func) { + result.append(func->call(m)); + } else { + addreplace(result, with, m); + } + end = m.end[0]; + } + } + result.append(end); + return result; +} + +std::string Prog::replace(char const* text, char const* with) { + ReplaceStruct rs(text); + rs.with = with; + run(text, -1, false, ReplaceStruct::callback, &rs); + return rs.finish(); +} +std::string Prog::replace_(char const* text, ReplaceFunc* with) { + ReplaceStruct rs(text); + rs.func = with; + run(text, -1, false, ReplaceStruct::callback, &rs); + return rs.finish(); +} + +} diff --git a/src/base/regexp.h b/src/base/regexp.h new file mode 100644 index 0000000..1b46d87 --- /dev/null +++ b/src/base/regexp.h @@ -0,0 +1,163 @@ +#pragma once + +#include "types.h" +#include +#include + +namespace re { + +typedef bool(*CharTraitFunc)(uint32); +class CharacterClass { + bool invert; + std::vector funcs; + struct Range { + uint32 begin; + uint32 end; + Range(uint32 a = 0, uint32 b = 0) + : begin(a), end(b) + {} + }; + friend bool operator < (Range const& lhs, Range const& rhs) { + return lhs.begin < rhs.begin; + } + std::vector data; + void addRange(uint32 a, uint32 b) { + data.emplace_back(a, b); + } + void addClass(CharacterClass const& cls); + void sort(); +public: + CharacterClass() + : invert(false) + {} + CharacterClass(CharTraitFunc func, bool inv = false) + : invert(inv) + { + funcs.push_back(func); + } + CharacterClass(char const* src, int flags = 0) { + init(src, flags); + } + + uint8_const_ptr init(char const* src, int flags = 0); + + std::string format() const; + + bool match(uint32 c) const; + + static CharacterClass* getDefault(char ch, int flags = 0); +}; + +struct Match { + char const* start[32]; + char const* end[32]; + std::string group(int index) const { + return std::string(start[index], end[index] - start[index]); + } +}; +struct Thread; +struct State; + +class Prog { + uint32 flags; + State* start; + State* states; + int numStates; + std::vector masks; + int numCaptures; + + int maxThreads; + Thread* threads; + int cur; + int numThreads[2]; + char const* matchText; + void addthread(State* state, Match const& match); + void advance(State* state, Match const& match, uint32 cp, char const* ref); + + friend struct FindStruct; + struct FindFunc { + virtual void call(Match const& match) = 0; + }; + template + class FindFuncHolder : public FindFunc { + public: + FindFuncHolder(Func const& func) : func_(func) {} + void call(Match const& match) { func_(match); } + private: + Func const& func_; + }; + + friend struct ReplaceStruct; + struct ReplaceFunc { + virtual std::string call(Match const& match) = 0; + }; + template + class ReplaceFuncHolder : public ReplaceFunc { + public: + ReplaceFuncHolder(Func const& func) : func_(func) {} + std::string call(Match const& match) { return func_(match); } + private: + Func const& func_; + }; + + void findAll_(char const* text, FindFunc* func); + std::string replace_(char const* text, ReplaceFunc* func); +public: + Prog(char const* expr, int length = -1, uint32 flags = 0); + Prog(std::string const& expr, int length = -1, uint32 flags = 0) + : Prog(expr.c_str(), length, flags) + {} + ~Prog(); + + enum { + CaseInsensitive = 0x01, + DotAll = 0x02, + MultiLine = 0x04, + Unicode = 0x08, + }; + + bool match(char const* text, std::vector* sub = NULL); + int find(char const* text, int start = 0, std::vector* sub = NULL); + + bool match(std::string const& text, std::vector* sub = NULL) { + return match(text.c_str(), sub); + } + int find(std::string const& text, int start = 0, std::vector* sub = NULL) { + return find(text.c_str(), start, sub); + } + + std::vector findAll(char const* text); + template + void findAll(char const* text, Func const& func) { + findAll_(text, &FindFuncHolder(func)); + } + + std::vector findAll(std::string const& text) { + return findAll(text.c_str()); + } + template + void findAll(std::string const& text, Func const& func) { + findAll_(text.c_str(), &FindFuncHolder(func)); + } + + template + std::string replace(char const* text, Func const& func) { + return replace_(text, &ReplaceFuncHolder(func)); + } + std::string replace(char const* text, char const* with); + + template + std::string replace(std::string const& text, Func const& func) { + return replace_(text.c_str(), &ReplaceFuncHolder(func)); + } + std::string replace(std::string const& text, char const* with) { + return replace(text.c_str(), with); + } + + int captures() const { + return numCaptures; + } + int run(char const* text, int length, bool exact, bool(*callback) (Match const& match, void* arg), void* arg); +}; + +} diff --git a/src/base/string.cpp b/src/base/string.cpp new file mode 100644 index 0000000..3dc1c4b --- /dev/null +++ b/src/base/string.cpp @@ -0,0 +1,165 @@ +#include "string.h" + +#include +#include +#include +#include "types.h" +#include "error.h" + +std::string strlower(std::string const& str) { + std::string dest(str.size(), ' '); + std::transform(str.begin(), str.end(), dest.begin(), std::tolower); + return dest; +} + +std::vector split(std::string const& str, char sep) { + std::vector res; + std::string cur; + for (char c : str) { + if (c == sep) { + res.push_back(cur); + cur.clear(); + } else { + cur.push_back(c); + } + } + res.push_back(cur); + return res; +} + +std::vector split_multiple(std::string const& str, char const* sep) { + std::vector res; + std::string cur; + for (char c : str) { + if (strchr(sep, c)) { + res.push_back(cur); + cur.clear(); + } else { + cur.push_back(c); + } + } + res.push_back(cur); + return res; +} + +std::vector split(std::string const& str, char const* sep) { + size_t sep_length = strlen(sep); + std::vector res; + size_t pos = 0, next; + while ((next = str.find(sep, pos)) != std::string::npos) { + res.push_back(str.substr(pos, next - pos)); + pos = next + sep_length; + } + res.push_back(str.substr(pos)); + return res; +} + +std::string join(std::vector const& list, char sep) { + std::string res; + for (auto& str : list) { + if (!res.empty()) res.push_back(' '); + res.append(str); + } + return res; +} +std::string join(std::vector const& list, std::string const& sep) { + std::string res; + for (auto& str : list) { + if (!res.empty()) res.append(sep); + res.append(str); + } + return res; +} +std::string fmtstring(char const* fmt, ...) { + va_list ap; + va_start(ap, fmt); + std::string res = varfmtstring(fmt, ap); + va_end(ap); + return res; +} +std::string varfmtstring(char const* fmt, va_list list) { + uint32 len = _vscprintf(fmt, list); + std::string dst; + dst.resize(len + 1); + vsprintf(&dst[0], fmt, list); + dst.resize(len); + return dst; +} + +std::wstring utf8_to_utf16(std::string const& str) { + std::wstring dst; + for (size_t i = 0; i < str.size();) { + uint32 cp = (unsigned char) str[i++]; + size_t next = 0; + if (cp <= 0x7F) { + // do nothing + } else if (cp <= 0xBF) { + throw Exception("not a valid utf-8 string"); + } else if (cp <= 0xDF) { + cp &= 0x1F; + next = 1; + } else if (cp <= 0xEF) { + cp &= 0x0F; + next = 2; + } else if (cp <= 0xF7) { + cp &= 0x07; + next = 3; + } else { + throw Exception("not a valid utf-8 string"); + } + while (next--) { + if (i >= str.size() || str[i] < 0x80 || str[i] > 0xBF) { + throw Exception("not a valid utf-8 string"); + } + cp = (cp << 6) | (str[i++] & 0x3F); + } + if ((cp >= 0xD800 && cp <= 0xDFFF) || cp > 0x10FFFF) { + throw Exception("not a valid utf-8 string"); + } + + if (cp <= 0xFFFF) { + dst.push_back(cp); + } else { + cp -= 0x10000; + dst.push_back((cp >> 10) + 0xD800); + dst.push_back((cp & 0x3FF) + 0xDC00); + } + } + return dst; +} + +std::string utf16_to_utf8(std::wstring const& str) { + std::string dst; + for (size_t i = 0; i < str.size();) { + uint32 cp = str[i++]; + if (cp >= 0xD800 && cp <= 0xDFFF) { + if (cp >= 0xDC00) throw Exception("not a valid utf-16 string"); + if (i >= str.size() || str[i] < 0xDC00 || str[i] > 0xDFFF) throw Exception("not a valid utf-16 string"); + cp = 0x10000 + ((cp - 0xD800) << 10) + (str[i++] - 0xDC00); + } + if (cp >= 0x10FFFF) throw Exception("not a valid utf-16 string"); + if (cp <= 0x7F) { + dst.push_back(cp); + } else if (cp <= 0x7FF) { + dst.push_back((cp >> 6) | 0xC0); + dst.push_back((cp & 0x3F) | 0x80); + } else if (cp <= 0xFFFF) { + dst.push_back((cp >> 12) | 0xE0); + dst.push_back(((cp >> 6) & 0x3F) | 0x80); + dst.push_back((cp & 0x3F) | 0x80); + } else { + dst.push_back((cp >> 18) | 0xF0); + dst.push_back(((cp >> 12) & 0x3F) | 0x80); + dst.push_back(((cp >> 6) & 0x3F) | 0x80); + dst.push_back((cp & 0x3F) | 0x80); + } + } + return dst; +} + +std::string trim(std::string const& str) { + size_t left = 0, right = str.size(); + while (left < str.length() && isspace((unsigned char) str[left])) ++left; + while (right > left && isspace((unsigned char) str[right - 1])) --right; + return str.substr(left, right - left); +} diff --git a/src/base/string.h b/src/base/string.h new file mode 100644 index 0000000..158dfff --- /dev/null +++ b/src/base/string.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include + +struct ci_char_traits : public std::char_traits < char > { + static bool eq(char c1, char c2) { return std::toupper(c1) == std::toupper(c2); } + static bool ne(char c1, char c2) { return std::toupper(c1) != std::toupper(c2); } + static bool lt(char c1, char c2) { return std::toupper(c1) < std::toupper(c2); } + static int compare(char const* s1, char const* s2, size_t n) { + while (n--) { + char c1 = std::toupper(*s1++); + char c2 = std::toupper(*s2++); + if (c1 != c2) return (c1 < c2 ? -1 : 1); + } + return 0; + } + static char const* find(char const* s, int n, char a) { + a = std::toupper(a); + while (n-- && std::toupper(*s) != a) { + ++s; + } + return (n >= 0 ? s : nullptr); + } +}; + +class istring : public std::basic_string { +public: + typedef std::basic_string _Base; + istring() {} + istring(istring const& str) : _Base(str) {} + istring(std::string const& str) : _Base(str.c_str()) {} + istring(char const* str) : _Base(str) {} + istring(istring&& str) : _Base(str) {} + istring(char const* str, size_t n) : _Base(str) {} + template + istring(Iter begin, Iter end) : _Base(begin, end) {} + + istring& operator=(std::string const& str) { + assign(str.c_str()); + return *this; + } + operator std::string() const { + return std::string(c_str()); + } +}; +std::string strlower(std::string const& src); + +template +inline int basic_compare(T const& lhs, T const& rhs) { + if (lhs < rhs) return -1; + if (lhs > rhs) return 1; + return 0; +} + +std::vector split(std::string const& str, char sep = ' '); +std::vector split(std::string const& str, char const* sep); +std::vector split_multiple(std::string const& str, char const* sep); +std::string join(std::vector const& list, char sep = ' '); +std::string join(std::vector const& list, std::string const& sep); +template +inline std::string join(Iter left, Iter right) { + std::string res; + while (left != right) { + if (!res.empty()) res.push_back(' '); + res.append(*left++); + } + return res; +} + +std::string fmtstring(char const* fmt, ...); +std::string varfmtstring(char const* fmt, va_list list); + +std::wstring utf8_to_utf16(std::string const& str); +std::string utf16_to_utf8(std::wstring const& str); +std::string trim(std::string const& str); diff --git a/src/base/thread.cpp b/src/base/thread.cpp new file mode 100644 index 0000000..3a4c7dd --- /dev/null +++ b/src/base/thread.cpp @@ -0,0 +1,56 @@ +#include "thread.h" +#include + +namespace thread { + + Waitable::~Waitable() { + CloseHandle(handle); + } + bool Waitable::wait(unsigned long timeout) { + return WaitForSingleObject(handle, timeout) == WAIT_OBJECT_0; + } + + Lock::Lock() { + CRITICAL_SECTION* cs = new CRITICAL_SECTION; + InitializeCriticalSection(cs); + impl = cs; + } + Lock::~Lock() { + DeleteCriticalSection((CRITICAL_SECTION*)impl); + } + void Lock::acquire() { + EnterCriticalSection((CRITICAL_SECTION*)impl); + } + void Lock::release() { + LeaveCriticalSection((CRITICAL_SECTION*)impl); + } + + Event::Event(bool initial) + : Waitable(CreateEvent(NULL, TRUE, initial ? TRUE : FALSE, NULL)) + { + } + void Event::set() { + SetEvent(handle); + } + void Event::reset() { + ResetEvent(handle); + } + + Counter::Counter() + : Waitable(CreateEvent(NULL, TRUE, TRUE, NULL)) + , count(0) + { + } + + long Counter::increment() { + long result = InterlockedIncrement(&count); + if (result > 0) ResetEvent(handle); + return result; + } + long Counter::decrement() { + long result = InterlockedDecrement(&count); + if (result <= 0) SetEvent(handle); + return result; + } + +} diff --git a/src/base/thread.h b/src/base/thread.h new file mode 100644 index 0000000..f87b551 --- /dev/null +++ b/src/base/thread.h @@ -0,0 +1,102 @@ +#pragma once + +#include + +namespace thread { + + class Waitable { + protected: + void* handle; + Waitable(void* h) + : handle(h) + { + } + public: + ~Waitable(); + + bool wait(unsigned long timeout = 0xFFFFFFFF); + }; + + class Lock { + void* impl; + public: + Lock(); + ~Lock(); + void acquire(); + void release(); + + class Holder { + Lock* lock; + public: + Holder(Lock* l) + : lock(l) + { + if (lock) lock->acquire(); + } + ~Holder() { + if (lock) lock->release(); + } + }; + }; + class Event : public Waitable { + public: + Event(bool initial = true); + + void set(); + void reset(); + }; + class Counter : public Waitable { + long volatile count; + public: + Counter(); + + operator long() const { + return count; + } + + long increment(); + long decrement(); + }; + + template + struct ThreadArg { + T* ptr; + int (T::*func)(); + }; + template + DWORD WINAPI ThreadProc(LPVOID arg) { + ThreadArg* ta = (ThreadArg*) arg; + int result = (ta->ptr->*(ta->func))(); + delete ta; + return result; + } + template + HANDLE create(T* ptr, int (T::*func)(), unsigned long* id = nullptr) { + ThreadArg* ta = new ThreadArg; + ta->ptr = ptr; + ta->func = func; + return CreateThread(NULL, 0, ThreadProc, ta, 0, id); + } + template + struct ThreadArg1 { + T* ptr; + int (T::*func)(A); + A arg; + }; + template + DWORD WINAPI ThreadProc1(LPVOID arg) { + ThreadArg1* ta = (ThreadArg1*) arg; + int result = (ta->ptr->*(ta->func))(ta->arg); + delete ta; + return result; + } + template + HANDLE create(T* ptr, int (T::*func)(A), A arg, unsigned long* id = nullptr) { + ThreadArg1* ta = new ThreadArg1; + ta->ptr = ptr; + ta->func = func; + ta->arg = arg; + return CreateThread(NULL, 0, ThreadProc1, ta, 0, id); + } + +} diff --git a/src/base/types.h b/src/base/types.h new file mode 100644 index 0000000..cb4a0ee --- /dev/null +++ b/src/base/types.h @@ -0,0 +1,60 @@ +#pragma once + +typedef unsigned char uint8; +typedef signed char sint8; +typedef char int8; +typedef unsigned short uint16; +typedef signed short sint16; +typedef short int16; +typedef unsigned long uint32; +typedef signed long sint32; +typedef long int32; +typedef unsigned __int64 uint64; +typedef signed __int64 sint64; +typedef __int64 int64; + +typedef unsigned char* uint8_ptr; +typedef signed char* sint8_ptr; +typedef char* int8_ptr; +typedef unsigned short* uint16_ptr; +typedef signed short* sint16_ptr; +typedef short* int16_ptr; +typedef unsigned long* uint32_ptr; +typedef signed long* sint32_ptr; +typedef long* int32_ptr; +typedef unsigned __int64* uint64_ptr; +typedef signed __int64* sint64_ptr; +typedef __int64* int64_ptr; + +typedef unsigned char const* uint8_const_ptr; +typedef signed char const* sint8_const_ptr; +typedef char const* int8_const_ptr; +typedef unsigned short const* uint16_const_ptr; +typedef signed short const* sint16_const_ptr; +typedef short const* int16_const_ptr; +typedef unsigned long const* uint32_const_ptr; +typedef signed long const* sint32_const_ptr; +typedef long const* int32_const_ptr; +typedef unsigned __int64 const* uint64_const_ptr; +typedef signed __int64 const* sint64_const_ptr; +typedef __int64 const* int64_const_ptr; + +const uint8 max_uint8 = 0xFFU; +const sint8 min_int8 = sint8(0x80); +const sint8 max_int8 = 0x7F; +const uint16 max_uint16 = 0xFFFFU; +const sint16 min_int16 = sint16(0x8000); +const sint16 max_int16 = 0x7FFF; +const uint32 max_uint32 = 0xFFFFFFFFU; +const sint32 min_int32 = 0x80000000; +const sint32 max_int32 = 0x7FFFFFFF; +const uint64 max_uint64 = 0xFFFFFFFFFFFFFFFFULL; +const sint64 min_int64 = 0x8000000000000000LL; +const sint64 max_int64 = 0x7FFFFFFFFFFFFFFFLL; + +template struct UIntTraits {}; +template<> struct UIntTraits<8> { typedef uint8 Type; }; +template<> struct UIntTraits<16> { typedef uint16 Type; }; +template<> struct UIntTraits<32> { typedef uint32 Type; }; +template<> struct UIntTraits<64> { typedef uint64 Type; }; +template using UInt = typename UIntTraits::Type; diff --git a/src/base/utf8.cpp b/src/base/utf8.cpp new file mode 100644 index 0000000..13a8ee6 --- /dev/null +++ b/src/base/utf8.cpp @@ -0,0 +1,1176 @@ +#include "utf8.h" + +namespace utf8 { + + uint32 UTF8LC3[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, + 0xA0C3, 0xA1C3, 0xA2C3, 0xA3C3, 0xA4C3, 0xA5C3, 0xA6C3, 0xA7C3, 0xA8C3, 0xA9C3, 0xAAC3, 0xABC3, 0xACC3, 0xADC3, 0xAEC3, 0xAFC3, + 0xB0C3, 0xB1C3, 0xB2C3, 0xB3C3, 0xB4C3, 0xB5C3, 0xB6C3, 0, 0xB8C3, 0xB9C3, 0xBAC3, 0xBBC3, 0xBCC3, 0xBDC3, 0xBEC3, 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, + }; + uint32 UTF8LC4[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, + 0x81C4, 0, 0x83C4, 0, 0x85C4, 0, 0x87C4, 0, 0x89C4, 0, 0x8BC4, 0, 0x8DC4, 0, 0x8FC4, 0, + 0x91C4, 0, 0x93C4, 0, 0x95C4, 0, 0x97C4, 0, 0x99C4, 0, 0x9BC4, 0, 0x9DC4, 0, 0x9FC4, 0, + 0xA1C4, 0, 0xA3C4, 0, 0xA5C4, 0, 0xA7C4, 0, 0xA9C4, 0, 0xABC4, 0, 0xADC4, 0, 0xAFC4, 0, + 0x69, 0, 0xB3C4, 0, 0xB5C4, 0, 0xB7C4, 0, 0, 0xBAC4, 0, 0xBCC4, 0, 0xBEC4, 0, 0x80C5, + 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, + }; + uint32 UTF8LC5[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, 0x82C5, 0, 0x84C5, 0, 0x86C5, 0, 0x88C5, 0, 0, 0x8BC5, 0, 0x8DC5, 0, 0x8FC5, 0, + 0x91C5, 0, 0x93C5, 0, 0x95C5, 0, 0x97C5, 0, 0x99C5, 0, 0x9BC5, 0, 0x9DC5, 0, 0x9FC5, 0, + 0xA1C5, 0, 0xA3C5, 0, 0xA5C5, 0, 0xA7C5, 0, 0xA9C5, 0, 0xABC5, 0, 0xADC5, 0, 0xAFC5, 0, + 0xB1C5, 0, 0xB3C5, 0, 0xB5C5, 0, 0xB7C5, 0, 0xBFC3, 0xBAC5, 0, 0xBCC5, 0, 0xBEC5, 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, + }; + uint32 UTF8LC6[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, 0x93C9, 0x83C6, 0, 0x85C6, 0, 0x94C9, 0x88C6, 0, 0, 0x97C9, 0x8CC6, 0, 0, 0x98C9, 0x99C9, + 0x9BC9, 0x92C6, 0, 0xA0C9, 0xA3C9, 0, 0xA9C9, 0xA8C9, 0x99C6, 0, 0, 0, 0xAFC9, 0xB2C9, 0, 0xB5C9, + 0xA1C6, 0, 0xA3C6, 0, 0xA5C6, 0, 0, 0xA8C6, 0, 0x83CA, 0, 0, 0xADC6, 0, 0x88CA, 0xB0C6, + 0, 0x8ACA, 0x8BCA, 0xB4C6, 0, 0xB6C6, 0, 0x92CA, 0xB9C6, 0, 0, 0, 0xBDC6, 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, + }; + uint32 UTF8LC7[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, 0x86C7, 0x86C7, 0, 0x89C7, 0x89C7, 0, 0x8CC7, 0x8CC7, 0, 0x8EC7, 0, 0x90C7, + 0, 0x92C7, 0, 0x94C7, 0, 0x96C7, 0, 0x98C7, 0, 0x9AC7, 0, 0x9CC7, 0, 0, 0x9FC7, 0, + 0xA1C7, 0, 0xA3C7, 0, 0xA5C7, 0, 0xA7C7, 0, 0xA9C7, 0, 0xABC7, 0, 0xADC7, 0, 0xAFC7, 0, + 0, 0xB3C7, 0, 0, 0xB5C7, 0, 0, 0, 0, 0, 0xBBC7, 0, 0xBDC7, 0, 0xBFC7, 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, + }; + uint32 UTF8LC8[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, + 0x81C8, 0, 0x83C8, 0, 0x85C8, 0, 0x87C8, 0, 0x89C8, 0, 0x8BC8, 0, 0x8DC8, 0, 0x8FC8, 0, + 0x91C8, 0, 0x93C8, 0, 0x95C8, 0, 0x97C8, 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, + }; + uint32 UTF8LCE[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, 0xACCE, 0, 0xADCE, 0xAECE, 0xAFCE, 0, 0x8CCF, 0, 0x8DCF, 0x8ECF, + 0, 0xB1CE, 0xB2CE, 0xB3CE, 0xB4CE, 0xB5CE, 0xB6CE, 0xB7CE, 0xB8CE, 0xB9CE, 0xBACE, 0xBBCE, 0xBCCE, 0xBDCE, 0xBECE, 0xBFCE, + 0x80CF, 0x81CF, 0, 0x83CF, 0x84CF, 0x85CF, 0x86CF, 0x87CF, 0x88CF, 0x89CF, 0x8ACF, 0x8BCF, 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, + }; + uint32 UTF8LCF[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, 0xA3CF, 0, 0xA5CF, 0, 0xA7CF, 0, 0xA9CF, 0, 0xABCF, 0, 0xADCF, 0, 0xAFCF, 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, + }; + uint32 UTF8LD0[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, 0x91D1, 0x92D1, 0x93D1, 0x94D1, 0x95D1, 0x96D1, 0x97D1, 0x98D1, 0x99D1, 0x9AD1, 0x9BD1, 0x9CD1, 0, 0x9ED1, 0x9FD1, + 0xB0D0, 0xB1D0, 0xB2D0, 0xB3D0, 0xB4D0, 0xB5D0, 0xB6D0, 0xB7D0, 0xB8D0, 0xB9D0, 0xBAD0, 0xBBD0, 0xBCD0, 0xBDD0, 0xBED0, 0xBFD0, + 0x80D1, 0x81D1, 0x82D1, 0x83D1, 0x84D1, 0x85D1, 0x86D1, 0x87D1, 0x88D1, 0x89D1, 0x8AD1, 0x8BD1, 0x8CD1, 0x8DD1, 0x8ED1, 0x8FD1, + 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, + }; + uint32 UTF8LD1[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, + 0xA1D1, 0, 0xA3D1, 0, 0xA5D1, 0, 0xA7D1, 0, 0xA9D1, 0, 0xABD1, 0, 0xADD1, 0, 0xAFD1, 0, + 0xB1D1, 0, 0xB3D1, 0, 0xB5D1, 0, 0xB7D1, 0, 0xB9D1, 0, 0xBBD1, 0, 0xBDD1, 0, 0xBFD1, 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, + }; + uint32 UTF8LD2[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, + 0x81D2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x91D2, 0, 0x93D2, 0, 0x95D2, 0, 0x97D2, 0, 0x99D2, 0, 0x9BD2, 0, 0x9DD2, 0, 0x9FD2, 0, + 0xA1D2, 0, 0xA3D2, 0, 0xA5D2, 0, 0xA7D2, 0, 0xA9D2, 0, 0xABD2, 0, 0xADD2, 0, 0xAFD2, 0, + 0xB1D2, 0, 0xB3D2, 0, 0xB5D2, 0, 0xB7D2, 0, 0xB9D2, 0, 0xBBD2, 0, 0xBDD2, 0, 0xBFD2, 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, + }; + uint32 UTF8LD3[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, 0x82D3, 0, 0x84D3, 0, 0, 0, 0x88D3, 0, 0, 0, 0x8CD3, 0, 0, 0, 0, + 0x91D3, 0, 0x93D3, 0, 0x95D3, 0, 0x97D3, 0, 0x99D3, 0, 0x9BD3, 0, 0x9DD3, 0, 0x9FD3, 0, + 0xA1D3, 0, 0xA3D3, 0, 0xA5D3, 0, 0xA7D3, 0, 0xA9D3, 0, 0xABD3, 0, 0, 0, 0xAFD3, 0, + 0xB1D3, 0, 0xB3D3, 0, 0xB5D3, 0, 0, 0, 0xB9D3, 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, + }; + uint32 UTF8LD4[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, 0xA1D5, 0xA2D5, 0xA3D5, 0xA4D5, 0xA5D5, 0xA6D5, 0xA7D5, 0xA8D5, 0xA9D5, 0xAAD5, 0xABD5, 0xACD5, 0xADD5, 0xAED5, 0xAFD5, + 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, + }; + uint32 UTF8LD5[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, + 0xB0D5, 0xB1D5, 0xB2D5, 0xB3D5, 0xB4D5, 0xB5D5, 0xB6D5, 0xB7D5, 0xB8D5, 0xB9D5, 0xBAD5, 0xBBD5, 0xBCD5, 0xBDD5, 0xBED5, 0xBFD5, + 0x80D6, 0x81D6, 0x82D6, 0x83D6, 0x84D6, 0x85D6, 0x86D6, 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, + }; + uint32 UTF8LE182[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, + 0x9083E1, 0x9183E1, 0x9283E1, 0x9383E1, 0x9483E1, 0x9583E1, 0x9683E1, 0x9783E1, 0x9883E1, 0x9983E1, 0x9A83E1, 0x9B83E1, 0x9C83E1, 0x9D83E1, 0x9E83E1, 0x9F83E1, + 0xA083E1, 0xA183E1, 0xA283E1, 0xA383E1, 0xA483E1, 0xA583E1, 0xA683E1, 0xA783E1, 0xA883E1, 0xA983E1, 0xAA83E1, 0xAB83E1, 0xAC83E1, 0xAD83E1, 0xAE83E1, 0xAF83E1, + 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, + }; + uint32 UTF8LE183[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, + 0xB083E1, 0xB183E1, 0xB283E1, 0xB383E1, 0xB483E1, 0xB583E1, 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, + }; + uint32 UTF8LE1B8[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, + 0x81B8E1, 0, 0x83B8E1, 0, 0x85B8E1, 0, 0x87B8E1, 0, 0x89B8E1, 0, 0x8BB8E1, 0, 0x8DB8E1, 0, 0x8FB8E1, 0, + 0x91B8E1, 0, 0x93B8E1, 0, 0x95B8E1, 0, 0x97B8E1, 0, 0x99B8E1, 0, 0x9BB8E1, 0, 0x9DB8E1, 0, 0x9FB8E1, 0, + 0xA1B8E1, 0, 0xA3B8E1, 0, 0xA5B8E1, 0, 0xA7B8E1, 0, 0xA9B8E1, 0, 0xABB8E1, 0, 0xADB8E1, 0, 0xAFB8E1, 0, + 0xB1B8E1, 0, 0xB3B8E1, 0, 0xB5B8E1, 0, 0xB7B8E1, 0, 0xB9B8E1, 0, 0xBBB8E1, 0, 0xBDB8E1, 0, 0xBFB8E1, 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, + }; + uint32 UTF8LE1B9[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, + 0x81B9E1, 0, 0x83B9E1, 0, 0x85B9E1, 0, 0x87B9E1, 0, 0x89B9E1, 0, 0x8BB9E1, 0, 0x8DB9E1, 0, 0x8FB9E1, 0, + 0x91B9E1, 0, 0x93B9E1, 0, 0x95B9E1, 0, 0x97B9E1, 0, 0x99B9E1, 0, 0x9BB9E1, 0, 0x9DB9E1, 0, 0x9FB9E1, 0, + 0xA1B9E1, 0, 0xA3B9E1, 0, 0xA5B9E1, 0, 0xA7B9E1, 0, 0xA9B9E1, 0, 0xABB9E1, 0, 0xADB9E1, 0, 0xAFB9E1, 0, + 0xB1B9E1, 0, 0xB3B9E1, 0, 0xB5B9E1, 0, 0xB7B9E1, 0, 0xB9B9E1, 0, 0xBBB9E1, 0, 0xBDB9E1, 0, 0xBFB9E1, 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, + }; + uint32 UTF8LE1BA[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, + 0x81BAE1, 0, 0x83BAE1, 0, 0x85BAE1, 0, 0x87BAE1, 0, 0x89BAE1, 0, 0x8BBAE1, 0, 0x8DBAE1, 0, 0x8FBAE1, 0, + 0x91BAE1, 0, 0x93BAE1, 0, 0x95BAE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0xA1BAE1, 0, 0xA3BAE1, 0, 0xA5BAE1, 0, 0xA7BAE1, 0, 0xA9BAE1, 0, 0xABBAE1, 0, 0xADBAE1, 0, 0xAFBAE1, 0, + 0xB1BAE1, 0, 0xB3BAE1, 0, 0xB5BAE1, 0, 0xB7BAE1, 0, 0xB9BAE1, 0, 0xBBBAE1, 0, 0xBDBAE1, 0, 0xBFBAE1, 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, + }; + uint32 UTF8LE1BB[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, + 0x81BBE1, 0, 0x83BBE1, 0, 0x85BBE1, 0, 0x87BBE1, 0, 0x89BBE1, 0, 0x8BBBE1, 0, 0x8DBBE1, 0, 0x8FBBE1, 0, + 0x91BBE1, 0, 0x93BBE1, 0, 0x95BBE1, 0, 0x97BBE1, 0, 0x99BBE1, 0, 0x9BBBE1, 0, 0x9DBBE1, 0, 0x9FBBE1, 0, + 0xA1BBE1, 0, 0xA3BBE1, 0, 0xA5BBE1, 0, 0xA7BBE1, 0, 0xA9BBE1, 0, 0xABBBE1, 0, 0xADBBE1, 0, 0xAFBBE1, 0, + 0xB1BBE1, 0, 0xB3BBE1, 0, 0xB5BBE1, 0, 0xB7BBE1, 0, 0xB9BBE1, 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, + }; + uint32 UTF8LE1BC[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, 0x80BCE1, 0x81BCE1, 0x82BCE1, 0x83BCE1, 0x84BCE1, 0x85BCE1, 0x86BCE1, 0x87BCE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0x90BCE1, 0x91BCE1, 0x92BCE1, 0x93BCE1, 0x94BCE1, 0x95BCE1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0xA0BCE1, 0xA1BCE1, 0xA2BCE1, 0xA3BCE1, 0xA4BCE1, 0xA5BCE1, 0xA6BCE1, 0xA7BCE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0xB0BCE1, 0xB1BCE1, 0xB2BCE1, 0xB3BCE1, 0xB4BCE1, 0xB5BCE1, 0xB6BCE1, 0xB7BCE1, + 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, + }; + uint32 UTF8LE1BD[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, 0x80BDE1, 0x81BDE1, 0x82BDE1, 0x83BDE1, 0x84BDE1, 0x85BDE1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x91BDE1, 0, 0x93BDE1, 0, 0x95BDE1, 0, 0x97BDE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0xA0BDE1, 0xA1BDE1, 0xA2BDE1, 0xA3BDE1, 0xA4BDE1, 0xA5BDE1, 0xA6BDE1, 0xA7BDE1, + 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, + }; + uint32 UTF8LE1BE[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, 0x80BEE1, 0x81BEE1, 0x82BEE1, 0x83BEE1, 0x84BEE1, 0x85BEE1, 0x86BEE1, 0x87BEE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0x90BEE1, 0x91BEE1, 0x92BEE1, 0x93BEE1, 0x94BEE1, 0x95BEE1, 0x96BEE1, 0x97BEE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0xA0BEE1, 0xA1BEE1, 0xA2BEE1, 0xA3BEE1, 0xA4BEE1, 0xA5BEE1, 0xA6BEE1, 0xA7BEE1, + 0, 0, 0, 0, 0, 0, 0, 0, 0xB0BEE1, 0xB1BEE1, 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, + }; + uint32 UTF8LE1BF[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, 0x90BFE1, 0x91BFE1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0xA0BFE1, 0xA1BFE1, 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, + }; + uint32 UTF8LE1[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, (uint32)&UTF8LE182, (uint32)&UTF8LE183, 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, (uint32)&UTF8LE1B8, (uint32)&UTF8LE1B9, (uint32)&UTF8LE1BA, (uint32)&UTF8LE1BB, (uint32)&UTF8LE1BC, (uint32)&UTF8LE1BD, (uint32)&UTF8LE1BE, (uint32)&UTF8LE1BF, + 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, + }; + uint32 UTF8LE292[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, 0x9093E2, 0x9193E2, 0x9293E2, 0x9393E2, 0x9493E2, 0x9593E2, 0x9693E2, 0x9793E2, 0x9893E2, 0x9993E2, + 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, + }; + uint32 UTF8LE293[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, + 0x9A93E2, 0x9B93E2, 0x9C93E2, 0x9D93E2, 0x9E93E2, 0x9F93E2, 0xA093E2, 0xA193E2, 0xA293E2, 0xA393E2, 0xA493E2, 0xA593E2, 0xA693E2, 0xA793E2, 0xA893E2, 0xA993E2, + 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, + }; + uint32 UTF8LE2[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, (uint32)&UTF8LE292, (uint32)&UTF8LE293, 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, + }; + uint32 UTF8LEFBC[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, 0x81BDEF, 0x82BDEF, 0x83BDEF, 0x84BDEF, 0x85BDEF, 0x86BDEF, 0x87BDEF, 0x88BDEF, 0x89BDEF, 0x8ABDEF, 0x8BBDEF, 0x8CBDEF, 0x8DBDEF, 0x8EBDEF, 0x8FBDEF, + 0x90BDEF, 0x91BDEF, 0x92BDEF, 0x93BDEF, 0x94BDEF, 0x95BDEF, 0x96BDEF, 0x97BDEF, 0x98BDEF, 0x99BDEF, 0x9ABDEF, 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, + }; + uint32 UTF8LEF[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, (uint32)&UTF8LEFBC, 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, + }; + uint32 tf_lower[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, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 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, (uint32)&UTF8LC3, (uint32)&UTF8LC4, (uint32)&UTF8LC5, (uint32)&UTF8LC6, (uint32)&UTF8LC7, (uint32)&UTF8LC8, 0, 0, 0, 0, 0, (uint32)&UTF8LCE, (uint32)&UTF8LCF, + (uint32)&UTF8LD0, (uint32)&UTF8LD1, (uint32)&UTF8LD2, (uint32)&UTF8LD3, (uint32)&UTF8LD4, (uint32)&UTF8LD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, (uint32)&UTF8LE1, (uint32)&UTF8LE2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint32)&UTF8LEF, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + uint32 UTF8UC3[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, + 0x80C3, 0x81C3, 0x82C3, 0x83C3, 0x84C3, 0x85C3, 0x86C3, 0x87C3, 0x88C3, 0x89C3, 0x8AC3, 0x8BC3, 0x8CC3, 0x8DC3, 0x8EC3, 0x8FC3, + 0x90C3, 0x91C3, 0x92C3, 0x93C3, 0x94C3, 0x95C3, 0x96C3, 0, 0x98C3, 0x99C3, 0x9AC3, 0x9BC3, 0x9CC3, 0x9DC3, 0x9EC3, 0xB8C5, + 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, + }; + uint32 UTF8UC4[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, 0x80C4, 0, 0x82C4, 0, 0x84C4, 0, 0x86C4, 0, 0x88C4, 0, 0x8AC4, 0, 0x8CC4, 0, 0x8EC4, + 0, 0x90C4, 0, 0x92C4, 0, 0x94C4, 0, 0x96C4, 0, 0x98C4, 0, 0x9AC4, 0, 0x9CC4, 0, 0x9EC4, + 0, 0xA0C4, 0, 0xA2C4, 0, 0xA4C4, 0, 0xA6C4, 0, 0xA8C4, 0, 0xAAC4, 0, 0xACC4, 0, 0xAEC4, + 0, 0x49, 0, 0xB2C4, 0, 0xB4C4, 0, 0xB6C4, 0, 0, 0xB9C4, 0, 0xBBC4, 0, 0xBDC4, 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, + }; + uint32 UTF8UC5[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, + 0xBFC4, 0, 0x81C5, 0, 0x83C5, 0, 0x85C5, 0, 0x87C5, 0, 0, 0x8AC5, 0, 0x8CC5, 0, 0x8EC5, + 0, 0x90C5, 0, 0x92C5, 0, 0x94C5, 0, 0x96C5, 0, 0x98C5, 0, 0x9AC5, 0, 0x9CC5, 0, 0x9EC5, + 0, 0xA0C5, 0, 0xA2C5, 0, 0xA4C5, 0, 0xA6C5, 0, 0xA8C5, 0, 0xAAC5, 0, 0xACC5, 0, 0xAEC5, + 0, 0xB0C5, 0, 0xB2C5, 0, 0xB4C5, 0, 0xB6C5, 0, 0, 0xB9C5, 0, 0xBBC5, 0, 0xBDC5, 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, + }; + uint32 UTF8UC6[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, 0x82C6, 0, 0x84C6, 0, 0, 0x87C6, 0, 0, 0, 0x8BC6, 0, 0, 0, + 0, 0, 0x91C6, 0, 0, 0, 0, 0, 0, 0x98C6, 0, 0, 0, 0, 0, 0, + 0, 0xA0C6, 0, 0xA2C6, 0, 0xA4C6, 0, 0, 0xA7C6, 0, 0, 0, 0, 0xACC6, 0, 0, + 0xAFC6, 0, 0, 0, 0xB3C6, 0, 0xB5C6, 0, 0, 0xB8C6, 0, 0, 0, 0xBCC6, 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, + }; + uint32 UTF8UC7[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, 0x84C7, 0, 0, 0x87C7, 0, 0, 0x8AC7, 0, 0x8DC7, 0, + 0x8FC7, 0, 0x91C7, 0, 0x93C7, 0, 0x95C7, 0, 0x97C7, 0, 0x99C7, 0, 0x9BC7, 0, 0, 0x9EC7, + 0, 0xA0C7, 0, 0xA2C7, 0, 0xA4C7, 0, 0xA6C7, 0, 0xA8C7, 0, 0xAAC7, 0, 0xACC7, 0, 0xAEC7, + 0, 0, 0, 0xB1C7, 0, 0xB4C7, 0, 0, 0, 0, 0, 0xBAC7, 0, 0xBCC7, 0, 0xBEC7, + 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, + }; + uint32 UTF8UC8[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, 0x80C8, 0, 0x82C8, 0, 0x84C8, 0, 0x86C8, 0, 0x88C8, 0, 0x8AC8, 0, 0x8CC8, 0, 0x8EC8, + 0, 0x90C8, 0, 0x92C8, 0, 0x94C8, 0, 0x96C8, 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, + }; + uint32 UTF8UC9[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, 0x81C6, 0x86C6, 0, 0, 0x8AC6, 0x8EC6, 0x8FC6, 0, 0x90C6, 0, 0, 0, 0, + 0x93C6, 0, 0, 0x94C6, 0, 0, 0, 0, 0x97C6, 0x96C6, 0, 0, 0, 0, 0, 0x9CC6, + 0, 0, 0x9DC6, 0, 0, 0x9FC6, 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, + }; + uint32 UTF8UCA[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, 0xA9C6, 0, 0, 0, 0, 0xAEC6, 0, 0xB1C6, 0xB2C6, 0, 0, 0, 0, + 0, 0, 0xB7C6, 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, + }; + uint32 UTF8UCE[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, 0x86CE, 0x88CE, 0x89CE, 0x8ACE, + 0, 0x91CE, 0x92CE, 0x93CE, 0x94CE, 0x95CE, 0x96CE, 0x97CE, 0x98CE, 0x99CE, 0x9ACE, 0x9BCE, 0x9CCE, 0x9DCE, 0x9ECE, 0x9FCE, + 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, + }; + uint32 UTF8UCF[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, + 0xA0CE, 0xA1CE, 0, 0xA3CE, 0xA4CE, 0xA5CE, 0xA6CE, 0xA7CE, 0xA8CE, 0xA9CE, 0xAACE, 0xABCE, 0x8CCE, 0x8ECE, 0x8FCE, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0xA2CF, 0, 0xA4CF, 0, 0xA6CF, 0, 0xA8CF, 0, 0xAACF, 0, 0xACCF, 0, 0xAECF, + 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, + }; + uint32 UTF8UD0[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, + 0x90D0, 0x91D0, 0x92D0, 0x93D0, 0x94D0, 0x95D0, 0x96D0, 0x97D0, 0x98D0, 0x99D0, 0x9AD0, 0x9BD0, 0x9CD0, 0x9DD0, 0x9ED0, 0x9FD0, + 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, + }; + uint32 UTF8UD1[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, + 0xA0D0, 0xA1D0, 0xA2D0, 0xA3D0, 0xA4D0, 0xA5D0, 0xA6D0, 0xA7D0, 0xA8D0, 0xA9D0, 0xAAD0, 0xABD0, 0xACD0, 0xADD0, 0xAED0, 0xAFD0, + 0, 0x81D0, 0x82D0, 0x83D0, 0x84D0, 0x85D0, 0x86D0, 0x87D0, 0x88D0, 0x89D0, 0x8AD0, 0x8BD0, 0x8CD0, 0, 0x8ED0, 0x8FD0, + 0, 0xA0D1, 0, 0xA2D1, 0, 0xA4D1, 0, 0xA6D1, 0, 0xA8D1, 0, 0xAAD1, 0, 0xACD1, 0, 0xAED1, + 0, 0xB0D1, 0, 0xB2D1, 0, 0xB4D1, 0, 0xB6D1, 0, 0xB8D1, 0, 0xBAD1, 0, 0xBCD1, 0, 0xBED1, + 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, + }; + uint32 UTF8UD2[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, 0x80D2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x90D2, 0, 0x92D2, 0, 0x94D2, 0, 0x96D2, 0, 0x98D2, 0, 0x9AD2, 0, 0x9CD2, 0, 0x9ED2, + 0, 0xA0D2, 0, 0xA2D2, 0, 0xA4D2, 0, 0xA6D2, 0, 0xA8D2, 0, 0xAAD2, 0, 0xACD2, 0, 0xAED2, + 0, 0xB0D2, 0, 0xB2D2, 0, 0xB4D2, 0, 0xB6D2, 0, 0xB8D2, 0, 0xBAD2, 0, 0xBCD2, 0, 0xBED2, + 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, + }; + uint32 UTF8UD3[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, 0x81D3, 0, 0x83D3, 0, 0, 0, 0x87D3, 0, 0, 0, 0x8BD3, 0, 0, 0, + 0, 0x90D3, 0, 0x92D3, 0, 0x94D3, 0, 0x96D3, 0, 0x98D3, 0, 0x9AD3, 0, 0x9CD3, 0, 0x9ED3, + 0, 0xA0D3, 0, 0xA2D3, 0, 0xA4D3, 0, 0xA6D3, 0, 0xA8D3, 0, 0xAAD3, 0, 0, 0, 0xAED3, + 0, 0xB0D3, 0, 0xB2D3, 0, 0xB4D3, 0, 0, 0, 0xB8D3, 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, + }; + uint32 UTF8UD5[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, 0xB1D4, 0xB2D4, 0xB3D4, 0xB4D4, 0xB5D4, 0xB6D4, 0xB7D4, 0xB8D4, 0xB9D4, 0xBAD4, 0xBBD4, 0xBCD4, 0xBDD4, 0xBED4, 0xBFD4, + 0x80D5, 0x81D5, 0x82D5, 0x83D5, 0x84D5, 0x85D5, 0x86D5, 0x87D5, 0x88D5, 0x89D5, 0x8AD5, 0x8BD5, 0x8CD5, 0x8DD5, 0x8ED5, 0x8FD5, + 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, + }; + uint32 UTF8UD6[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, + 0x90D5, 0x91D5, 0x92D5, 0x93D5, 0x94D5, 0x95D5, 0x96D5, 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, + }; + uint32 UTF8UE183[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, + 0xA082E1, 0xA182E1, 0xA282E1, 0xA382E1, 0xA482E1, 0xA582E1, 0xA682E1, 0xA782E1, 0xA882E1, 0xA982E1, 0xAA82E1, 0xAB82E1, 0xAC82E1, 0xAD82E1, 0xAE82E1, 0xAF82E1, + 0xB082E1, 0xB182E1, 0xB282E1, 0xB382E1, 0xB482E1, 0xB582E1, 0xB682E1, 0xB782E1, 0xB882E1, 0xB982E1, 0xBA82E1, 0xBB82E1, 0xBC82E1, 0xBD82E1, 0xBE82E1, 0xBF82E1, + 0x8083E1, 0x8183E1, 0x8283E1, 0x8383E1, 0x8483E1, 0x8583E1, 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, + }; + uint32 UTF8UE1B8[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, 0x80B8E1, 0, 0x82B8E1, 0, 0x84B8E1, 0, 0x86B8E1, 0, 0x88B8E1, 0, 0x8AB8E1, 0, 0x8CB8E1, 0, 0x8EB8E1, + 0, 0x90B8E1, 0, 0x92B8E1, 0, 0x94B8E1, 0, 0x96B8E1, 0, 0x98B8E1, 0, 0x9AB8E1, 0, 0x9CB8E1, 0, 0x9EB8E1, + 0, 0xA0B8E1, 0, 0xA2B8E1, 0, 0xA4B8E1, 0, 0xA6B8E1, 0, 0xA8B8E1, 0, 0xAAB8E1, 0, 0xACB8E1, 0, 0xAEB8E1, + 0, 0xB0B8E1, 0, 0xB2B8E1, 0, 0xB4B8E1, 0, 0xB6B8E1, 0, 0xB8B8E1, 0, 0xBAB8E1, 0, 0xBCB8E1, 0, 0xBEB8E1, + 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, + }; + uint32 UTF8UE1B9[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, 0x80B9E1, 0, 0x82B9E1, 0, 0x84B9E1, 0, 0x86B9E1, 0, 0x88B9E1, 0, 0x8AB9E1, 0, 0x8CB9E1, 0, 0x8EB9E1, + 0, 0x90B9E1, 0, 0x92B9E1, 0, 0x94B9E1, 0, 0x96B9E1, 0, 0x98B9E1, 0, 0x9AB9E1, 0, 0x9CB9E1, 0, 0x9EB9E1, + 0, 0xA0B9E1, 0, 0xA2B9E1, 0, 0xA4B9E1, 0, 0xA6B9E1, 0, 0xA8B9E1, 0, 0xAAB9E1, 0, 0xACB9E1, 0, 0xAEB9E1, + 0, 0xB0B9E1, 0, 0xB2B9E1, 0, 0xB4B9E1, 0, 0xB6B9E1, 0, 0xB8B9E1, 0, 0xBAB9E1, 0, 0xBCB9E1, 0, 0xBEB9E1, + 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, + }; + uint32 UTF8UE1BA[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, 0x80BAE1, 0, 0x82BAE1, 0, 0x84BAE1, 0, 0x86BAE1, 0, 0x88BAE1, 0, 0x8ABAE1, 0, 0x8CBAE1, 0, 0x8EBAE1, + 0, 0x90BAE1, 0, 0x92BAE1, 0, 0x94BAE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0xA0BAE1, 0, 0xA2BAE1, 0, 0xA4BAE1, 0, 0xA6BAE1, 0, 0xA8BAE1, 0, 0xAABAE1, 0, 0xACBAE1, 0, 0xAEBAE1, + 0, 0xB0BAE1, 0, 0xB2BAE1, 0, 0xB4BAE1, 0, 0xB6BAE1, 0, 0xB8BAE1, 0, 0xBABAE1, 0, 0xBCBAE1, 0, 0xBEBAE1, + 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, + }; + uint32 UTF8UE1BB[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, 0x80BBE1, 0, 0x82BBE1, 0, 0x84BBE1, 0, 0x86BBE1, 0, 0x88BBE1, 0, 0x8ABBE1, 0, 0x8CBBE1, 0, 0x8EBBE1, + 0, 0x90BBE1, 0, 0x92BBE1, 0, 0x94BBE1, 0, 0x96BBE1, 0, 0x98BBE1, 0, 0x9ABBE1, 0, 0x9CBBE1, 0, 0x9EBBE1, + 0, 0xA0BBE1, 0, 0xA2BBE1, 0, 0xA4BBE1, 0, 0xA6BBE1, 0, 0xA8BBE1, 0, 0xAABBE1, 0, 0xACBBE1, 0, 0xAEBBE1, + 0, 0xB0BBE1, 0, 0xB2BBE1, 0, 0xB4BBE1, 0, 0xB6BBE1, 0, 0xB8BBE1, 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, + }; + uint32 UTF8UE1BC[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, + 0x88BCE1, 0x89BCE1, 0x8ABCE1, 0x8BBCE1, 0x8CBCE1, 0x8DBCE1, 0x8EBCE1, 0x8FBCE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0x98BCE1, 0x99BCE1, 0x9ABCE1, 0x9BBCE1, 0x9CBCE1, 0x9DBCE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0xA8BCE1, 0xA9BCE1, 0xAABCE1, 0xABBCE1, 0xACBCE1, 0xADBCE1, 0xAEBCE1, 0xAFBCE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0xB8BCE1, 0xB9BCE1, 0xBABCE1, 0xBBBCE1, 0xBCBCE1, 0xBDBCE1, 0xBEBCE1, 0xBFBCE1, 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, + }; + uint32 UTF8UE1BD[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, + 0x88BDE1, 0x89BDE1, 0x8ABDE1, 0x8BBDE1, 0x8CBDE1, 0x8DBDE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0x99BDE1, 0, 0x9BBDE1, 0, 0x9DBDE1, 0, 0x9FBDE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0xA8BDE1, 0xA9BDE1, 0xAABDE1, 0xABBDE1, 0xACBDE1, 0xADBDE1, 0xAEBDE1, 0xAFBDE1, 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, + }; + uint32 UTF8UE1BE[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, + 0x88BEE1, 0x89BEE1, 0x8ABEE1, 0x8BBEE1, 0x8CBEE1, 0x8DBEE1, 0x8EBEE1, 0x8FBEE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0x98BEE1, 0x99BEE1, 0x9ABEE1, 0x9BBEE1, 0x9CBEE1, 0x9DBEE1, 0x9EBEE1, 0x9FBEE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0xA8BEE1, 0xA9BEE1, 0xAABEE1, 0xABBEE1, 0xACBEE1, 0xADBEE1, 0xAEBEE1, 0xAFBEE1, 0, 0, 0, 0, 0, 0, 0, 0, + 0xB8BEE1, 0xB9BEE1, 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, + }; + uint32 UTF8UE1BF[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, + 0x98BFE1, 0x99BFE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0xA8BFE1, 0xA9BFE1, 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, + }; + uint32 UTF8UE1[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, (uint32)&UTF8UE183, 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, (uint32)&UTF8UE1B8, (uint32)&UTF8UE1B9, (uint32)&UTF8UE1BA, (uint32)&UTF8UE1BB, (uint32)&UTF8UE1BC, (uint32)&UTF8UE1BD, (uint32)&UTF8UE1BE, (uint32)&UTF8UE1BF, + 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, + }; + uint32 UTF8UE293[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, + 0xB692E2, 0xB792E2, 0xB892E2, 0xB992E2, 0xBA92E2, 0xBB92E2, 0xBC92E2, 0xBD92E2, 0xBE92E2, 0xBF92E2, 0x8093E2, 0x8193E2, 0x8293E2, 0x8393E2, 0x8493E2, 0x8593E2, + 0x8693E2, 0x8793E2, 0x8893E2, 0x8993E2, 0x8A93E2, 0x8B93E2, 0x8C93E2, 0x8D93E2, 0x8E93E2, 0x8F93E2, 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, + }; + uint32 UTF8UE2[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, (uint32)&UTF8UE293, 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, + }; + uint32 UTF8UEFBD[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, 0xA1BCEF, 0xA2BCEF, 0xA3BCEF, 0xA4BCEF, 0xA5BCEF, 0xA6BCEF, 0xA7BCEF, 0xA8BCEF, 0xA9BCEF, 0xAABCEF, 0xABBCEF, 0xACBCEF, 0xADBCEF, 0xAEBCEF, 0xAFBCEF, + 0xB0BCEF, 0xB1BCEF, 0xB2BCEF, 0xB3BCEF, 0xB4BCEF, 0xB5BCEF, 0xB6BCEF, 0xB7BCEF, 0xB8BCEF, 0xB9BCEF, 0xBABCEF, 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, + }; + uint32 UTF8UEF[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, (uint32)&UTF8UEFBD, 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, + }; + uint32 tf_upper[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, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 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, (uint32)&UTF8UC3, (uint32)&UTF8UC4, (uint32)&UTF8UC5, (uint32)&UTF8UC6, (uint32)&UTF8UC7, (uint32)&UTF8UC8, (uint32)&UTF8UC9, (uint32)&UTF8UCA, 0, 0, 0, (uint32)&UTF8UCE, (uint32)&UTF8UCF, + (uint32)&UTF8UD0, (uint32)&UTF8UD1, (uint32)&UTF8UD2, (uint32)&UTF8UD3, 0, (uint32)&UTF8UD5, (uint32)&UTF8UD6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, (uint32)&UTF8UE1, (uint32)&UTF8UE2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (uint32)&UTF8UEF, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + uint32 transform(uint8_const_ptr* ptr, uint32* table) + { + if ((**ptr & 0x80) && (**ptr & 0xF8) != 0xF8) { + uint32 result = 0; + uint8 head = **ptr; + uint8* dst = (uint8*)&result; + while ((head & 0x80) && **ptr) { + if (table) + table = (uint32*)table[**ptr]; + *dst++ = *(*ptr)++; + head <<= 1; + } + if (table && (head & 0x80) == 0) { + result = (uint32)table; + } + return result; + } else { + if (table && table[**ptr]) { + return table[*(*ptr)++]; + } + return *(*ptr)++; + } + } + + uint8_const_ptr next(uint8_const_ptr ptr) + { + if ((*ptr & 0x80) && (*ptr & 0xF8) != 0xF8) { + uint8 head = *ptr; + while ((head & 0x80) & *ptr) { + head <<= 1; + ptr++; + } + return ptr; + } else { + return ptr + 1; + } + } + + uint32 parse(uint32 cp) { + if ((cp & ~0x7F) == 0) { + return cp; + } + uint32 result = (cp & 0xFF); + uint32 mask = 0x40; + cp >>= 8; + while (cp) { + result = (result << 6) | (cp & 0x3F); + cp >>= 8; + mask <<= 5; + } + return result & (mask - 1); + } + +} diff --git a/src/base/utf8.h b/src/base/utf8.h new file mode 100644 index 0000000..6624366 --- /dev/null +++ b/src/base/utf8.h @@ -0,0 +1,18 @@ +#pragma once + +#include "types.h" + +namespace utf8 { + + extern uint32 tf_lower[256]; + extern uint32 tf_upper[256]; + + uint32 transform(uint8_const_ptr* ptr, uint32* table); + inline uint32 transform(uint8_const_ptr ptr, uint32* table) { + return transform(&ptr, table); + } + uint8_const_ptr next(uint8_const_ptr ptr); + + uint32 parse(uint32 cp); + +} diff --git a/src/data.cpp b/src/data.cpp new file mode 100644 index 0000000..58ff3aa --- /dev/null +++ b/src/data.cpp @@ -0,0 +1,597 @@ +#define NOMINMAX +#include "base/http.h" +#include "data.h" +#include "base/thread.h" +#include "app.h" +#include "wizard.h" +#include +#include + +void ProgramData::Task::stop() { + terminate_ = true; + if (thread_) { + if (WaitForSingleObject(thread_, INFINITE) != WAIT_OBJECT_0) { + // don't do this, it will likely crash everything + TerminateThread(thread_, 0); + } + CloseHandle(thread_); + thread_ = nullptr; + } +} +ProgramData::Task::~Task() { + stop(); +} + +void ProgramData::Task::start(ProgramData* data) { + data_ = data; + callback_ = data->app_->wizard()->page(); + thread_ = thread::create(this, &Task::proc); +} + +void ProgramData::Task::notify(uint32 value) { + if (!terminate_ && callback_) { + uint32 time = GetTickCount(); + if (time > lastNotify_ + 500 || value != lastNotifyCode_) { + PostMessage(data_->app_->wizard()->getHandle(), WM_TASKDONE, (WPARAM)callback_, value); + lastNotify_ = time; + lastNotifyCode_ = value; + if (lastNotifyCode_ >= LOADING) lastNotifyCode_ = 0; + } + } +} +int ProgramData::Task::proc() { + try { + uint32 res = run(); + notify(res); + } catch (Exception& ex) { + notify(-1); + } + return 0; +} + +void ProgramData::setTask(Task* task) { + // duplicating the unique_ptr just in case + { + auto tsk = task_; + if (tsk) tsk->stop(); + } + task_.reset(task); + if (task) task->start(this); +} + +//////////////////////////// + +void ProgramData::setProgram(std::string const& program) { + class ProgramTask : public Task { + public: + ProgramTask(std::string const& program) + : program_(program) + {} + private: + std::string program_; + uint32 run() { + NGDP::NGDP* ngdp = new NGDP::NGDP(program_); + if (ngdp && ngdp->regions().empty()) { + delete ngdp; + ngdp = ngdp; + } + if (!terminate_) { + data_->ngdp_.reset(ngdp); + } + return 0; + } + }; + + if (!program.empty()) { + setTask(new ProgramTask(program)); + } else { + setTask(nullptr); + ngdp_.reset(); + } +} + +////////////////////////////////// + +void ProgramData::loadBuilds() { + class BuildTask : public Task { + private: + uint32 run() { + if (!data_->ngdp_->version()) return -1; + std::string cdn_hash = data_->ngdp_->version()->cdn; + File file = data_->ngdp_->load(cdn_hash); + if (!file) return -1; + data_->cdn_config = NGDP::ParseConfig(file); + data_->builds = split(data_->cdn_config["builds"]); + notify(0); + for (size_t i = 0; i < data_->builds.size() && !terminate_; ++i) { + std::string build = data_->builds[i]; + File file = data_->ngdp_->load(build); + if (!file) continue; + data_->build_configs[build] = NGDP::ParseConfig(file); + notify(i + 1); + } + if (!terminate_) { + data_->builds_loaded = cdn_hash; + } + return data_->builds.size(); + } + }; + + builds_loaded.clear(); + setTask(new BuildTask); +} + +///////////////////////////////////// + +File ProgramData::Task::loadData(std::string const& hash, int idx) { + File file = NGDP::CascStorage::getCache(hash); + if (file) return file; + file = data_->ngdp_->load(hash, "data"); + if (!file) return file; + + data_->loading_size = file.size(); + if (data_->loading_size >= (1 << 20)) { + static uint8 buffer[1 << 18]; + while (file.tell() < data_->loading_size && !terminate_) { + file.read(buffer, sizeof buffer); + data_->loading_progress = file.tell(); + notify(LOADING + idx); + } + } + + if (file) NGDP::CascStorage::addCache(hash, file); + return file; +} + +std::vector ProgramData::loadTags(File& file, uint32 numTags, uint32 numEntries) { + std::vector result; + uint32 maskSize = (numEntries + 7) / 8; + while (numTags--) { + result.emplace_back(); + auto& tag = result.back(); + while (char chr = file.getc()) { + tag.name.push_back(chr); + } + tag.type = file.read16(true); + tag.mask.resize(maskSize); + file.read(&tag.mask[0], maskSize); + } + return result; +} + +void ProgramData::loadTags() { + class TagTask : public Task { + private: + uint32 run() { + // get build config + if (!data_->build_configs.count(data_->selected_build)) return -1; + auto buildConfig = data_->build_configs[data_->selected_build]; + + // load encoding file + File file = loadData(split(buildConfig["encoding"])[1], 0); + if (!file || terminate_) return -1; + data_->encoding_.reset(new NGDP::Encoding(NGDP::DecodeBLTE(file, std::stoi(split(buildConfig["encoding-size"])[0])))); + + // get download CDN hash + NGDP::Hash hash; + NGDP::from_string(hash, buildConfig["download"]); + auto const* enc = data_->encoding_->getEncoding(hash); + if (!enc) return -1; + + // load download file + file = loadData(NGDP::to_string(enc->keys[0]), 1); + if (!file || terminate_) return -1; + file = NGDP::DecodeBLTE(file, enc->usize); + + // parse download file + if (file.read16(true) != 'DL') return -1; + file.seek(3, SEEK_CUR); + uint32 numEntries = file.read32(true); + uint16 numTags = file.read16(true); + data_->file_sizes_.clear(); + for (uint32 i = 0; i < numEntries; ++i) { + file.read(hash, sizeof hash); + file.seek(10, SEEK_CUR); + auto const* layout = data_->encoding_->getLayout(hash); + data_->file_sizes_.push_back(layout ? layout->csize : 0); + } + data_->tags_ = ProgramData::loadTags(file, numTags, numEntries); + std::sort(data_->tags_.begin(), data_->tags_.end(), [](Tag const& lhs, Tag const& rhs) { + return lhs.type < rhs.type; + }); + std::vector> tags; + for (size_t i = 0; i < data_->tags_.size(); ++i) { + if (i == 0 || data_->tags_[i].type != data_->tags_[i - 1].type) { + tags.emplace_back(); + } + tags.back().push_back(data_->tags_[i].name); + } + data_->tags = tags; + return 0; + } + }; + + tags.clear(); + setTask(new TagTask); +} + +std::vector ProgramData::downloadMask() { + size_t maskSize = (file_sizes_.size() + 7) / 8; + std::vector mask(maskSize, 0); + for (std::string const& tags : used_tags) { + std::vector cur_mask(maskSize, 0xFF); + for (std::string const& tag : split(tags)) { + for (size_t i = 0; i < tags_.size(); ++i) { + if (tags_[i].name == tag) { + for (size_t j = 0; j < maskSize; ++j) { + cur_mask[j] &= tags_[i].mask[j]; + } + break; + } + } + } + for (size_t j = 0; j < maskSize; ++j) { + mask[j] |= cur_mask[j]; + } + } + return mask; +} +uint64 ProgramData::downloadSize() { + auto mask = downloadMask(); + uint64 size = 0; + for (size_t i = 0; i < file_sizes_.size(); ++i) { + if (mask[i / 8] & (1 << (7 - (i & 7)))) { + size += file_sizes_[i]; + } + } + return size; +} + +void ProgramData::download(std::string const& path) { + class DownloadTask : public Task { + public: + DownloadTask(std::string const& path) + : path_(path) + {} + private: + std::string path_; + uint32 run() { + auto& progress = data_->progress_; + progress.reset(new Progress); + auto& ngdp = data_->ngdp_; + + try { + NGDP::CascStorage storage(path_ / "Data"); + NGDP::DataStorage data(storage); + NGDP::Hash hash; + + // save configs + + storage.addConfig(ngdp->version()->cdn, ngdp->load(ngdp->version()->cdn)); + storage.addConfig(data_->selected_build, ngdp->load(data_->selected_build)); + + // save encoding file + + auto buildConfig = data_->build_configs[data_->selected_build]; + std::string encodingHash = split(buildConfig["encoding"])[1]; + NGDP::from_string(hash, encodingHash); + data.addFile(hash, loadData(encodingHash)); + + auto& encoding = data_->encoding_; + + // write .build.info + + File info(path_ / ".build.info", File::REWRITE); + info.printf("Branch!STRING:0|Active!DEC:1|Build Key!HEX:16|CDN Key!HEX:16"); + info.printf("|Install Key!HEX:16|IM Size!DEC:4|CDN Path!STRING:0"); + info.printf("|CDN Hosts!STRING:0|Tags!STRING:0|Armadillo!STRING:0"); + info.printf("|Last Activated!STRING:0|Version!STRING:0|Keyring!HEX:16|KeyService!STRING:0\n"); + + NGDP::from_string(hash, buildConfig["install"]); + auto const* enc = encoding->getEncoding(hash); + auto const* cdnData = ngdp->cdn(); + info.printf("%s|1|%s|%s", ngdp->region().c_str(), data_->selected_build.c_str(), ngdp->version()->cdn.c_str()); + info.printf("|%s|%u|%s", NGDP::to_string(enc->keys[0]).c_str(), enc->usize, cdnData ? cdnData->path.c_str() : ""); + info.printf("|%s|%s|", cdnData ? join(cdnData->hosts, " ").c_str() : "", join(data_->used_tags, ":").c_str()); + + __time64_t curtime; + tm timestruct; + char timebuf[128]; + _time64(&curtime); + _gmtime64_s(×truct, &curtime); + strftime(timebuf, sizeof timebuf, "%Y-%m-%dT%H:%M:%SZ", ×truct); + std::vector version; + std::string build_id; + for (auto const& p : split_multiple(buildConfig["build-name"], "_- ")) { + if (!p.empty() && std::isdigit((unsigned char) p[0])) { + std::string d; + for (size_t i = 0; i < p.size() && std::isdigit((unsigned char)p[i]); ++i) { + d.push_back(p[i]); + } + if (d.size() >= 4) { + build_id = d; + } else { + version.push_back(d); + } + } + } + info.printf("|%s|%s||\n", timebuf, (join(version, ".") + "." + build_id).c_str()); + + // load indices + + loadIndices(storage); + + log("Downloading files..."); + + // fetch download file + + NGDP::from_string(hash, buildConfig["download"]); + enc = encoding->getEncoding(hash); + File download = NGDP::DecodeBLTE(data.addFile(enc->keys[0], loadData(enc->keys[0]))); + if (download.read16(true) != 'DL') { + throw Exception("invalid download file"); + } + if (terminate_) return 1; + download.seek(3, SEEK_CUR); + uint32 numEntries = download.read32(true); + uint32 numTags = download.read16(true); + uint32 filesPos = download.tell(); + download.seek(26 * numEntries, SEEK_CUR); + data_->tags_ = ProgramData::loadTags(download, numTags, numEntries); + auto mask = data_->downloadMask(); + + // calculate size + + progress->filesTotal = 0; + progress->filesDone = 0; + download.seek(filesPos, SEEK_SET); + for (uint32 i = 0; i < numEntries; ++i) { + download.read(hash, sizeof hash); + download.seek(10, SEEK_CUR); + if (!(mask[i / 8] & (1 << (7 - (i & 7))))) continue; + ++progress->filesTotal; + auto const* layout = encoding->getLayout(hash); + if (layout) progress->sizeTotal += layout->csize; + } + notify(0); + + // download + + uint32 failedFiles = 0; + download.seek(filesPos, SEEK_SET); + for (uint32 i = 0; i < numEntries && !terminate_; ++i) { + download.read(hash, sizeof hash); + download.seek(10, SEEK_CUR); + if (!(mask[i / 8] & (1 << (7 - (i & 7))))) continue; + + File file = loadFile(hash); + if (file) { + data.addFile(hash, file); + } else { + ++failedFiles; + } + + auto const* layout = encoding->getLayout(hash); + if (layout) progress->sizeDone += layout->csize; + ++progress->filesDone; + notify(0); + } + if (terminate_) return 1; + + if (failedFiles) { + log(fmtstring("Failed to download %u files", failedFiles)); + } + + log("Installing files..."); + + // fetch install file + + NGDP::from_string(hash, buildConfig["install"]); + enc = encoding->getEncoding(hash); + File install = NGDP::DecodeBLTE(data.addFile(enc->keys[0], loadData(enc->keys[0]))); + if (install.read16(true) != 'IN') { + throw Exception("invalid install file"); + } + if (terminate_) return 1; + install.seek(2, SEEK_CUR); + numTags = install.read16(true); + numEntries = install.read32(true); + data_->tags_ = ProgramData::loadTags(install, numTags, numEntries); + mask = data_->downloadMask(); + + progress->filesTotal = 0; + progress->filesDone = 0; + progress->sizeTotal = 0; + progress->sizeDone = 0; + // calculate size + uint32 installPos = install.tell(); + for (uint32 i = 0; i < numEntries; ++i) { + std::string name; + while (char c = install.getc()) { + name.push_back(c); + } + install.read(hash, sizeof hash); + uint32 usize = install.read32(true); + if (!(mask[i / 8] & (1 << (7 - (i & 7))))) continue; + ++progress->filesTotal; + progress->sizeTotal += usize; + } + notify(0); + + // install + + install.seek(installPos, SEEK_SET); + for (uint32 i = 0; i < numEntries && !terminate_; ++i) { + std::string name; + while (char c = install.getc()) { + name.push_back(c); + } + install.read(hash, sizeof hash); + uint32 usize = install.read32(true); + if (!(mask[i / 8] & (1 << (7 - (i & 7))))) continue; + + enc = encoding->getEncoding(hash); + if (!enc) { + log("Failed to extract " + name); + continue; + } + File file = loadFile(enc->keys[0]); + if (!file) { + log("Failed to extract " + name); + continue; + } + File(path_ / name, File::REWRITE).copy(NGDP::DecodeBLTE(file, usize)); + + ++progress->filesDone; + progress->sizeDone += usize; + notify(0); + } + log("Done"); + } catch (Exception& ex) { + log(fmtstring("Error: %s", ex.what())); + } + + return 1; + } + + void log(std::string const& text) { + data_->progress_->log.push_back(text); + notify(0); + } + + struct IndexEntry { + uint16 index; + uint32 size; + uint32 offset; + }; + struct ArchiveInfo { + std::string name; + std::vector mask; + }; + enum { BlockSize = (1 << 20) }; + std::vector archives_; + std::unordered_map index_; + + void loadIndices(NGDP::CascStorage& storage) { + NGDP::Hash nilHash; + memset(nilHash, 0, sizeof nilHash); + + std::vector archives = split(data_->cdn_config["archives"]); + auto& progress = data_->progress_; + progress->filesTotal = archives.size(); + log("Loading indices..."); + + archives_.resize(archives.size()); + for (size_t i = 0; i < archives.size() && !terminate_; ++i) { + archives_[i].name = archives[i]; + + File index = NGDP::CascStorage::getCache(archives[i] + ".index"); + if (!index) { + File src = data_->ngdp_->load(archives[i], "data", true); + if (!src) continue; + index = NGDP::CascStorage::addCache(archives[i] + ".index", src); + storage.addIndex(archives[i], src); + } + progress->filesDone = i; + notify(0); + + size_t size = index.size(); + for (size_t block = 0; block + 4096 <= size; block += 4096) { + NGDP::Hash hash; + index.seek(block, SEEK_SET); + for (size_t pos = 0; pos + 24 <= 4096; pos += 24) { + index.read(hash, sizeof hash); + if (!memcmp(hash, nilHash, sizeof hash)) { + block = size; + break; + } + auto& dst = index_[NGDP::Hash_container::from(hash)]; + dst.index = i; + dst.size = index.read32(true); + dst.offset = index.read32(true); + } + } + + File mask = NGDP::CascStorage::getCache(archives[i] + ".mask"); + if (!mask) { + File raw = NGDP::CascStorage::getCache(archives[i]); + if (raw) { + uint32 chunks = (raw.size() + BlockSize - 1) / BlockSize; + archives_[i].mask.assign((chunks + 7) / 8, 0xFF); + continue; + } + } else { + archives_[i].mask.resize(mask.size()); + mask.read(&archives_[i].mask[0], archives_[i].mask.size()); + } + } + } + + File loadFile(NGDP::Hash const& hash) { + auto it = index_.find(NGDP::Hash_container::from(hash)); + if (it == index_.end()) return loadData(hash); + + uint32 offset = it->second.offset; + uint32 size = it->second.size; + uint32 blockStart = offset / BlockSize; + uint32 blockEnd = (offset + size + BlockSize - 1) / BlockSize; + auto& mask = archives_[it->second.index].mask; + uint32 getStart = blockEnd; + uint32 getEnd = blockStart; + for (uint32 i = blockStart; i < blockEnd; ++i) { + if (i / 8 >= mask.size() || !(mask[i / 8] & (1 << (i & 7)))) { + getStart = std::min(getStart, i); + getEnd = std::max(getEnd, i + 1); + } + } + if (getStart < getEnd) { + std::string url = data_->ngdp_->geturl(archives_[it->second.index].name, "data"); + HttpRequest request(url); + request.addHeader(fmtstring("Range: bytes=%u-%u", getStart * BlockSize, getEnd * BlockSize - 1)); + request.send(); + uint32 status = request.status(); + if (status != 200 && status != 206) return File(); + auto headers = request.headers(); + File result = request.response(); + File archive = NGDP::CascStorage::addCache(archives_[it->second.index].name); + if (headers.count("Content-Range")) { + uint32 start, end, total; + if (sscanf(headers["Content-Range"].c_str(), "bytes %u-%u/%u", &start, &end, &total) != 3) { + return File(); + } + if (archive.size() < total) { + archive.seek(total - 1, SEEK_SET); + archive.putc(0); + } + archive.seek(start, SEEK_SET); + archive.copy(result, end - start + 1); + start = (start + BlockSize - 1) / BlockSize; + if (end >= total - 1) { + end = (end + BlockSize) / BlockSize; + } else { + end = (end + 1) / BlockSize; + } + total = (total + BlockSize - 1) / BlockSize; + mask.resize((total + 7) / 8, 0); + for (uint32 i = start; i < end; ++i) { + mask[i / 8] |= (1 << (i & 7)); + } + File file = NGDP::CascStorage::addCache(archives_[it->second.index].name + ".mask"); + file.write(&mask[0], mask.size()); + } else { + archive.copy(result); + } + } + + File data = NGDP::CascStorage::getCache(archives_[it->second.index].name); + if (!data) return File(); + MemoryFile result; + data.seek(offset, SEEK_SET); + data.read(result.reserve(size), size); + result.seek(0); + return result; + } + }; + + setTask(new DownloadTask(path)); +} diff --git a/src/data.h b/src/data.h new file mode 100644 index 0000000..a2737e9 --- /dev/null +++ b/src/data.h @@ -0,0 +1,126 @@ +#pragma once + +#include +#include "ngdp.h" + +#define WM_TASKDONE (WM_USER+1928) + +class Application; +class Page; + +class ProgramData { + +public: + void stop() { + setTask(nullptr); + } + + enum { LOADING = -123 }; + + uint32 loading_size; + uint32 loading_progress; + + // step 1 + +public: + void setProgram(std::string const& program); + std::shared_ptr ngdp() { + return ngdp_; + } +private: + std::shared_ptr ngdp_; + + // step 2 + +public: + void loadBuilds(); + NGDP::ConfigFile cdn_config; + std::vector builds; + std::map build_configs; + std::string builds_loaded; + std::string selected_build; + + // step 3 + +public: + void loadTags(); + std::vector> tags; + std::vector used_tags; + uint64 downloadSize(); + +private: + struct Tag { + std::string name; + uint16 type; + std::vector mask; + }; + + std::shared_ptr encoding_; + std::vector file_sizes_; + std::vector tags_; + + static std::vector loadTags(File& file, uint32 numTags, uint32 numEntries); + std::vector downloadMask(); + + // step 4 + +public: + struct Progress { + std::vector log; + + uint32 filesTotal = 0; + uint32 filesDone = 0; + uint64 sizeTotal = 0; + uint64 sizeDone = 0; + }; + + void download(std::string const& path); + std::shared_ptr progress() { + return progress_; + } + void stopDownload() { + stop(); + progress_.reset(); + } + +private: + std::shared_ptr progress_; + + // internal stuff + +public: + ProgramData(Application* app) + : app_(app) + {} + +private: + Application* app_; + class Task { + public: + virtual ~Task(); + + void start(ProgramData* data); + void stop(); + + protected: + virtual uint32 run() { return 0; }; + void notify(uint32 value = 0); + ProgramData* data_ = nullptr; + bool terminate_ = false; + + File loadData(std::string const& hash, int idx = 0); + File loadData(const NGDP::Hash hash, int idx = 0) { + return loadData(NGDP::to_string(hash), idx); + } + + private: + int proc(); + HANDLE thread_ = nullptr; + Page* callback_ = nullptr; + uint32 lastNotify_ = 0; + uint32 lastNotifyCode_ = 0; + }; + friend class Task; + std::shared_ptr task_; + void setTask(Task* task); +}; diff --git a/src/frameui/controlframes.cpp b/src/frameui/controlframes.cpp new file mode 100644 index 0000000..7ad78f1 --- /dev/null +++ b/src/frameui/controlframes.cpp @@ -0,0 +1,650 @@ +#define NOMINMAX +#include +#include + +#include "frameui/framewnd.h" +#include "frameui/fontsys.h" + +#include "controlframes.h" + +//////////////////////////////////////// + +LRESULT Scrollable::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + SCROLLINFO si; + int step; + switch (message) { + case WM_SIZE: + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_PAGE | SIF_DISABLENOSCROLL; + si.nPage = HIWORD(lParam); + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + scroll(scrollPos); + return 0; + case WM_VSCROLL: + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_ALL; + GetScrollInfo(hWnd, SB_VERT, &si); + switch (LOWORD(wParam)) { + case SB_TOP: + si.nPos = si.nMin; + break; + case SB_BOTTOM: + si.nPos = si.nMax; + break; + case SB_LINEUP: + si.nPos -= 16; + break; + case SB_LINEDOWN: + si.nPos += 16; + break; + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + scroll(si.nPos); + SetFocus(hWnd); + return 0; + case WM_MOUSEWHEEL: + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &step, 0); + if (step < 0) step = 3; + scrollAccum += GET_WHEEL_DELTA_WPARAM(wParam) * step * 16; + scroll(scrollPos - scrollAccum / WHEEL_DELTA); + scrollAccum %= WHEEL_DELTA; + return 0; + } + return M_UNHANDLED; +} + +void Scrollable::scroll(int pos) { + SCROLLINFO si; + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_RANGE | SIF_PAGE; + GetScrollInfo(hWnd, SB_VERT, &si); + if (pos < si.nMin) pos = si.nMin; + if (pos > si.nMax - si.nPage + 1) pos = si.nMax - si.nPage + 1; + si.fMask = SIF_POS; + if (pos != scrollPos) { + si.nPos = pos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + + int deltaY = scrollPos - pos; + scrollPos = pos; + RECT rc; + GetClientRect(hWnd, &rc); + ScrollWindowEx(hWnd, 0, deltaY, &rc, &rc, NULL, NULL, SW_ERASE | SW_INVALIDATE); + } +} + +//////////////////////////////////////// + +ButtonFrame::ButtonFrame(std::string const& text, Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create("Button", text, WS_CHILD | WS_TABSTOP | style, 0); + setFont(FontSys::getSysFont()); + setId(id); +} +LRESULT ButtonFrame::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + if (message == WM_ERASEBKGND) { + if ((GetWindowLong(hWnd, GWL_STYLE) & BS_TYPEMASK) == BS_GROUPBOX) { + HDC hDC = (HDC) wParam; + HBRUSH hBrush = (HBRUSH) GetClassLongPtr(GetParent(hWnd), GCLP_HBRBACKGROUND); + RECT rc; + GetClientRect(hWnd, &rc); + FillRect(hDC, &rc, hBrush); + InvalidateRect(hWnd, NULL, FALSE); + return TRUE; + } + } + return M_UNHANDLED; +} + +/////////////////////////////////////////////////////// + +HotkeyFrame::HotkeyFrame(Frame* parent, int id) + : WindowFrame(parent) +{ + create(HOTKEY_CLASS, "", WS_CHILD | WS_TABSTOP | ES_WANTRETURN, 0); + setFont(FontSys::getSysFont()); + setId(id); +} + +/////////////////////////////////////////////////////// + +LinkFrame::LinkFrame(std::string const& text, Frame* parent, int id) + : WindowFrame(parent) + , _color(0xFF0000) + , _flags(0) + , hFont(NULL) + , uFont(NULL) + , pressed(false) + , hover(false) +{ + if (WNDCLASSEX* wcx = createclass("LinkFrmClass")) { + wcx->hCursor = LoadCursor(NULL, IDC_HAND); + RegisterClassEx(wcx); + } + create(text, WS_CHILD, 0); + setFont(FontSys::getSysFont()); + resetSize(); + setId(id); +} + +void LinkFrame::resetSize() { + HDC hDC = GetDC(hWnd); + SelectObject(hDC, hFont); + SIZE sz; + std::string const& text = getText(); + GetTextExtentPoint32(hDC, text.c_str(), text.length(), &sz); + ReleaseDC(hWnd, hDC); + setSize(sz.cx, sz.cy); +} +void LinkFrame::setColor(uint32 color) { + _color = color; + InvalidateRect(hWnd, NULL, TRUE); +} +void LinkFrame::setFlags(int flags) { + _flags = flags; + InvalidateRect(hWnd, NULL, TRUE); +} + +LRESULT LinkFrame::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_SETFONT: + hFont = (wParam ? (HFONT) wParam : FontSys::getSysFont()); + uFont = FontSys::changeFlags(FontSys::getFlags(hFont) | FONT_UNDERLINE, hFont); + if (lParam) InvalidateRect(hWnd, NULL, TRUE); + return 0; + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hDC = BeginPaint(hWnd, &ps); + + POINT pt; + GetCursorPos(&pt); + ScreenToClient(hWnd, &pt); + + SetBkMode(hDC, OPAQUE); + SetBkColor(hDC, GetSysColor(COLOR_BTNFACE)); + SetTextColor(hDC, _color); + if (pressed || hover) SelectObject(hDC, uFont); + else SelectObject(hDC, hFont); + RECT rc = {0, 0, width(), height()}; + std::string const& text = getText(); + DrawText(hDC, text.c_str(), text.length(), &rc, _flags); + + EndPaint(hWnd, &ps); + } + return 0; + case WM_MOUSEMOVE: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + if (!hover && x > 0 && y > 0 && x < width() && y < height()) { + hover = true; + TRACKMOUSEEVENT tme; + memset(&tme, 0, sizeof tme); + tme.cbSize = sizeof tme; + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + TrackMouseEvent(&tme); + if (!pressed) InvalidateRect(hWnd, NULL, FALSE); + } + } + return 0; + case WM_MOUSELEAVE: + { + hover = false; + TRACKMOUSEEVENT tme; + memset(&tme, 0, sizeof tme); + tme.cbSize = sizeof tme; + tme.dwFlags = TME_CANCEL | TME_LEAVE; + tme.hwndTrack = hWnd; + TrackMouseEvent(&tme); + if (!pressed) InvalidateRect(hWnd, NULL, TRUE); + } + return 0; + case WM_LBUTTONDOWN: + SetCapture(hWnd); + pressed = true; + return 0; + case WM_LBUTTONUP: + if (pressed) { + ReleaseCapture(); + pressed = false; + if (hover) notify(WM_COMMAND, MAKELONG(id(), BN_CLICKED), (LPARAM) hWnd); + } + return 0; + } + return M_UNHANDLED; +} + +/////////////////////////////////////////////////////// + +LRESULT EditFrame::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + if (message == WM_CTLCOLOREDIT || message == WM_CTLCOLORSTATIC) { + HDC hDC = (HDC) wParam; + if ((fgcolor & 0xFF000000) == 0) SetTextColor(hDC, fgcolor); + if ((bgcolor & 0xFF000000) == 0) SetBkColor(hDC, bgcolor); + if (background) return (uint32) background; + return M_UNHANDLED; + } + return M_UNHANDLED; +} +EditFrame::EditFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + bgcolor = 0xFFFFFFFF; + fgcolor = 0xFFFFFFFF; + background = NULL; + create("Edit", "", style | WS_CHILD | WS_TABSTOP, WS_EX_CLIENTEDGE); + setFont(FontSys::getSysFont()); + setId(id); +} +EditFrame::~EditFrame() { + if (background) DeleteObject(background); +} +void EditFrame::setFgColor(uint32 color) { + fgcolor = color & 0xFFFFFF; + invalidate(); +} +void EditFrame::setBgColor(uint32 color) { + bgcolor = color & 0xFFFFFF; + if (background) DeleteObject(background); + background = CreateSolidBrush(color); + invalidate(); +} + +/////////////////////////////////////////////////////// + +void ComboFrame::onMove(void* data) { + if (hWnd) { + uint32 flags = SWP_NOREPOSITION; + HWND hWndInsertAfter = NULL; + if (visible()) { + if (IsWindowVisible(hWnd)) { + flags |= SWP_NOZORDER; + } else { + flags |= SWP_SHOWWINDOW;// | SWP_NOZORDER; + hWndInsertAfter = HWND_TOP;// getParentWindow(); + } + } else { + flags |= SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW; + } + if (data) { + DeferWindowPos((HDWP)data, hWnd, hWndInsertAfter, left(), top(), width(), boxHeight, flags); + } else { + SetWindowPos(hWnd, hWndInsertAfter, left(), top(), width(), boxHeight, flags); + } + } +} +ComboFrame::ComboFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + boxHeight = 500; + create("ComboBox", "", style | WS_CHILD | WS_TABSTOP | WS_VSCROLL, 0); + setFont(FontSys::getSysFont()); + setId(id); + setHeight(21); +} +void ComboFrame::reset() { + SendMessage(hWnd, CB_RESETCONTENT, 0, 0); +} +int ComboFrame::addString(std::string const& text, int data) { + int id = SendMessage(hWnd, CB_ADDSTRING, 0, (LPARAM) text.c_str()); + if (id != CB_ERR) SendMessage(hWnd, CB_SETITEMDATA, id, data); + return id; +} +void ComboFrame::delString(int pos) { + SendMessage(hWnd, CB_DELETESTRING, pos, 0); +} +int ComboFrame::getItemData(int item) const { + return SendMessage(hWnd, CB_GETITEMDATA, item, 0); +} +void ComboFrame::setItemData(int item, int data) { + SendMessage(hWnd, CB_SETITEMDATA, item, data); +} +int ComboFrame::getCurSel() const { + return SendMessage(hWnd, CB_GETCURSEL, 0, 0); +} +void ComboFrame::setCurSel(int sel) { + SendMessage(hWnd, CB_SETCURSEL, sel, 0); +} + +/////////////////////////////////////////////////////// + +StaticFrame::StaticFrame(Frame* parent, int id, int style, int exStyle) + : WindowFrame(parent) +{ + create("Static", "", style | SS_NOTIFY | WS_CHILD, exStyle); + setFont(FontSys::getSysFont()); + setId(id); +} +StaticFrame::StaticFrame(std::string const& text, Frame* parent, int id, int style, int exStyle) + : WindowFrame(parent) +{ + create("Static", text, style | SS_NOTIFY | WS_CHILD, exStyle); + setFont(FontSys::getSysFont()); + resetSize(); + setId(id); +} +void StaticFrame::setImage(HANDLE image, int type) { + SendMessage(hWnd, STM_SETIMAGE, (WPARAM) type, (LPARAM) image); +} +void StaticFrame::resetSize() { + HDC hDC = GetDC(hWnd); + SelectObject(hDC, getFont()); + SIZE sz; + std::string text = getText(); + GetTextExtentPoint32(hDC, text.c_str(), text.length(), &sz); + ReleaseDC(hWnd, hDC); + setSize(sz.cx, sz.cy); +} + +/////////////////////////////////////////////////////// + +#include "richedit.h" + +struct EditStreamCookie { + std::string const& str; + int pos; + EditStreamCookie(std::string const& str) + : str(str) + , pos(0) + {} +}; +DWORD CALLBACK RichEditFrame::StreamCallback(DWORD_PTR cookie, LPBYTE buff, LONG cb, LONG* pcb) +{ + EditStreamCookie* ck = (EditStreamCookie*) cookie; + *pcb = ck->str.length() - ck->pos; + if (*pcb > cb) *pcb = cb; + if (*pcb) memcpy(buff, ck->str.c_str() + ck->pos, *pcb); + ck->pos += *pcb; + return 0; +} +RichEditFrame::RichEditFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(RICHEDIT_CLASS, "", style | WS_CHILD | WS_TABSTOP, WS_EX_CLIENTEDGE); + setFont(FontSys::getSysFont()); + setId(id); +} +void RichEditFrame::setBackgroundColor(uint32 color) { + SendMessage(hWnd, EM_SETBKGNDCOLOR, 0, color); +} +void RichEditFrame::setRichText(std::string const& text) { + EditStreamCookie cookie(text); + EDITSTREAM es; + es.dwCookie = (DWORD_PTR) &cookie; + es.dwError = 0; + es.pfnCallback = StreamCallback; + SendMessage(hWnd, EM_EXLIMITTEXT, 0, (text.length() < 32768 ? 32768 : text.length() + 1)); + SendMessage(hWnd, EM_STREAMIN, SF_RTF, (uint32) &es); +} + +///////////////////////////////// + +SliderFrame::SliderFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(TRACKBAR_CLASS, "", style | WS_CHILD | WS_TABSTOP, 0); + setFont(FontSys::getSysFont()); + setId(id); +} + +void SliderFrame::setPos(int pos) { + SendMessage(hWnd, TBM_SETPOS, TRUE, pos); +} +void SliderFrame::setRange(int minValue, int maxValue) { + SendMessage(hWnd, TBM_SETRANGEMIN, TRUE, minValue); + SendMessage(hWnd, TBM_SETRANGEMAX, TRUE, maxValue); +} +void SliderFrame::setLineSize(int size) { + SendMessage(hWnd, TBM_SETLINESIZE, 0, size); +} +void SliderFrame::setPageSize(int size) { + SendMessage(hWnd, TBM_SETPAGESIZE, 0, size); +} +void SliderFrame::setTicFreq(int freq) { + SendMessage(hWnd, TBM_SETTICFREQ, freq, 0); +} +int SliderFrame::getPos() { + return SendMessage(hWnd, TBM_GETPOS, 0, 0); +} + +///////////////////////////////////////// + +ProgressFrame::ProgressFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(PROGRESS_CLASS, "", style | WS_CHILD | WS_TABSTOP, 0); + setFont(FontSys::getSysFont()); + setId(id); +} + +void ProgressFrame::setPos(int pos) { + SendMessage(hWnd, PBM_SETPOS, pos, 0); +} +void ProgressFrame::setRange(int minValue, int maxValue) { + SendMessage(hWnd, PBM_SETRANGE32, minValue, maxValue); +} + +///////////////////////////////////////// + +UpDownFrame::UpDownFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(UPDOWN_CLASS, "", WS_CHILD | style, 0); + setId(id); +} + +///////////////////////////////////////// + +TabFrame::TabFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(WC_TABCONTROL, "", WS_CHILD | style | WS_CLIPSIBLINGS, 0); + setFont(FontSys::getSysFont()); + setId(id); +} +Frame* TabFrame::addTab(std::string const& text, Frame* frame) { + if (!frame) frame = new Frame(this); + size_t pos = tabs.size(); + tabs.push_back(frame); + + TCITEM item; + memset(&item, 0, sizeof item); + item.mask = TCIF_TEXT; + item.pszText = const_cast(&text[0]); + TabCtrl_InsertItem(hWnd, pos, &item); + frame->show(pos == TabCtrl_GetCurSel(hWnd)); + + RECT rc; + GetClientRect(hWnd, &rc); + int prevWidth = rc.right; + int prevHeight = rc.bottom; + TabCtrl_AdjustRect(hWnd, FALSE, &rc); + frame->setPoint(PT_TOPLEFT, rc.left, rc.top); + frame->setPoint(PT_BOTTOMRIGHT, rc.right - prevWidth, rc.bottom - prevHeight); + + return frame; +} +void TabFrame::clear() { + for (Frame* tab : tabs) tab->hide(); + tabs.clear(); + TabCtrl_DeleteAllItems(hWnd); +} + +LRESULT TabFrame::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + if (message == WM_NOTIFY) { + NMHDR* hdr = (NMHDR*) lParam; + if (hdr->hwndFrom == hWnd && hdr->code == TCN_SELCHANGE) { + int sel = TabCtrl_GetCurSel(hWnd); + for (size_t i = 0; i < tabs.size(); i++) { + if (i != sel) tabs[i]->hide(); + } + tabs[sel]->show(); + return 0; + } + } + return M_UNHANDLED; +} +void TabFrame::setCurSel(int sel) { + TabCtrl_SetCurSel(hWnd, sel); + for (size_t i = 0; i < tabs.size(); i++) { + if (i != sel) tabs[i]->hide(); + } + tabs[sel]->show(); +} + +//////////////////////////////////// + +LRESULT ColorFrame::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + static COLORREF custColors[16] = { + 0x000000, 0x800000, 0x008000, 0x808000, 0x000080, 0x800080, 0x008080, 0xC0C0C0, + 0x808080, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFF, + }; + switch (message) { + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hDC = BeginPaint(hWnd, &ps); + std::string text = getText(); + if (!text.empty()) { + RECT rc; + GetClientRect(hWnd, &rc); + SetBkColor(hDC, color); + SetTextColor(hDC, color ^ 0xFFFFFF); + SelectObject(hDC, FontSys::getSysFont()); + DrawText(hDC, text.c_str(), text.length(), &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX); + } + EndPaint(hWnd, &ps); + } + break; + case WM_ERASEBKGND: + { + HDC hDC = (HDC) wParam; + RECT rc; + GetClientRect(hWnd, &rc); + SetBkColor(hDC, color); + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + } + return TRUE; + case WM_LBUTTONDOWN: + SetCapture(hWnd); + break; + case WM_LBUTTONUP: + if (GetCapture() == hWnd) { + ReleaseCapture(); + + CHOOSECOLOR cc; + memset(&cc, 0, sizeof cc); + cc.lStructSize = sizeof cc; + cc.hwndOwner = GetParent(hWnd); + cc.rgbResult = color; + cc.Flags = CC_FULLOPEN | CC_RGBINIT; + cc.lpCustColors = custColors; + if (ChooseColor(&cc)) { + setColor(cc.rgbResult); + notify(WM_COMMAND, MAKELONG(id(), BN_CLICKED), (LPARAM) hWnd); + } + } + break; + default: + return M_UNHANDLED; + } + return 0; +} +ColorFrame::ColorFrame(uint32 clr, Frame* parent, uint32 id) + : WindowFrame(parent) +{ + color = clr; + create("", WS_CHILD, WS_EX_CLIENTEDGE); + setId(id); +} +ColorFrame::~ColorFrame() +{ +} + +//////////////////////////////////// + +TreeViewFrame::TreeViewFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(WC_TREEVIEW, "", style | WS_CHILD | WS_VISIBLE, WS_EX_CLIENTEDGE); + setId(id); + setFont(FontSys::getSysFont()); +} +void TreeViewFrame::setItemText(HTREEITEM item, std::string const& text) { + TVITEM tvi; + memset(&tvi, 0, sizeof tvi); + tvi.hItem = item; + tvi.mask = TVIF_TEXT; + tvi.pszText = const_cast(&text[0]); + TreeView_SetItem(hWnd, &tvi); +} +LPARAM TreeViewFrame::getItemData(HTREEITEM item) { + TVITEM tvi; + memset(&tvi, 0, sizeof tvi); + tvi.hItem = item; + tvi.mask = TVIF_PARAM; + TreeView_GetItem(hWnd, &tvi); + return tvi.lParam; +} + +//////////////////////////////////// + +DateTimeFrame::DateTimeFrame(Frame* parent, int id, int style) + : WindowFrame(parent) +{ + create(DATETIMEPICK_CLASS, "", style | WS_CHILD | WS_VISIBLE, 0); + setId(id); + setFont(FontSys::getSysFont()); +} +void DateTimeFrame::setFormat(char const* fmt) +{ + DateTime_SetFormat(hWnd, fmt); +} + +bool DateTimeFrame::isDateSet() const { + SYSTEMTIME st; + return (DateTime_GetSystemtime(hWnd, &st) == GDT_VALID); +} +uint64 DateTimeFrame::getDate() const { + SYSTEMTIME st; + if (DateTime_GetSystemtime(hWnd, &st) != GDT_VALID) return 0; + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + uint64 result = uint64(ft.dwLowDateTime) | (uint64(ft.dwHighDateTime) << 32); + result = result / 10000000ULL - 11644473600ULL; + return result; +} +void DateTimeFrame::setNoDate() { + DateTime_SetSystemtime(hWnd, GDT_NONE, NULL); +} +void DateTimeFrame::setDate(uint64 date) { + date = (date + 11644473600ULL) * 10000000ULL; + FILETIME ft; + ft.dwLowDateTime = uint32(date); + ft.dwHighDateTime = uint32(date >> 32); + SYSTEMTIME st; + FileTimeToSystemTime(&ft, &st); + DateTime_SetSystemtime(hWnd, GDT_VALID, &st); +} + +/////////////////////////////////////// + +StaticFrame* StaticFrame::addTip(Frame* frame, std::string const& text) { + StaticFrame* tip = new StaticFrame(text, frame->getParent()); + tip->setPoint(PT_RIGHT, frame, PT_LEFT, -8, 0); + return tip; +} diff --git a/src/frameui/controlframes.h b/src/frameui/controlframes.h new file mode 100644 index 0000000..a975d89 --- /dev/null +++ b/src/frameui/controlframes.h @@ -0,0 +1,216 @@ +#pragma once + +#include "frameui/frame.h" +#include "frameui/window.h" +#include "frameui/framewnd.h" +#include + +class Scrollable : public WindowFrame { +public: + Scrollable(Frame* parent) + : WindowFrame(parent) + , scrollPos(0) + , scrollAccum(0) + {} + +protected: + int scrollPos; + int scrollAccum; + void scroll(int pos); + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam) override; +}; + +class ButtonFrame : public WindowFrame { + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +public: + ButtonFrame(std::string const& text, Frame* parent, int id = 0, int style = BS_PUSHBUTTON); + void setCheck(bool check) { + SendMessage(hWnd, BM_SETCHECK, check ? BST_CHECKED : BST_UNCHECKED, 0); + } + bool checked() const { + return SendMessage(hWnd, BM_GETCHECK, 0, 0) == BST_CHECKED; + } +}; +class LinkFrame : public WindowFrame { + HFONT hFont; + HFONT uFont; + uint32 _color; + uint32 _flags; + bool pressed; + bool hover; + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +public: + LinkFrame(std::string const& text, Frame* parent, int id = 0); + + void setColor(uint32 color); + void setFlags(int flags); + uint32 color() const { + return _color; + } + int flags() const { + return _flags; + } + + void resetSize(); +}; + +class HotkeyFrame : public WindowFrame { +public: + HotkeyFrame(Frame* parent, int id = 0); + + int getKey() const { + return SendMessage(hWnd, HKM_GETHOTKEY, 0, 0) & 0xFFFF; + } + void setKey(int key) { + SendMessage(hWnd, HKM_SETHOTKEY, key & 0xFFFF, 0); + } +}; + +class EditFrame : public WindowFrame { + HBRUSH background; + uint32 bgcolor; + uint32 fgcolor; + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +public: + EditFrame(Frame* parent, int id = 0, int style = ES_AUTOHSCROLL); + ~EditFrame(); + void setFgColor(uint32 color); + void setBgColor(uint32 color); +}; + +class ComboFrame : public WindowFrame { + void onMove(void* data); + int boxHeight; +public: + ComboFrame(Frame* parent, int id = 0, int style = CBS_DROPDOWNLIST); + void reset(); + int addString(std::string const& text, int data = 0); + void delString(int pos); + int getItemData(int item) const; + void setItemData(int item, int data); + int getCurSel() const; + void setCurSel(int sel); + int getCount() const { + return SendMessage(hWnd, CB_GETCOUNT, 0, 0); + } + void setBoxHeight(int ht) { + boxHeight = ht; + onMove(0); + } +}; + +class StaticFrame : public WindowFrame { +public: + StaticFrame(Frame* parent, int id = 0, int style = 0, int exStyle = 0); + StaticFrame(std::string const& text, Frame* parent, int id = 0, int style = 0, int exStyle = 0); + void setImage(HANDLE image, int type = IMAGE_BITMAP); + void resetSize(); + + static StaticFrame* addTip(Frame* frame, std::string const& text); +}; + +class RichEditFrame : public WindowFrame { + static DWORD CALLBACK StreamCallback(DWORD_PTR cookie, LPBYTE buff, LONG cb, LONG* pcb); +public: + RichEditFrame(Frame* parent, int id = 0, int style = WS_VSCROLL | WS_HSCROLL | + ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_READONLY); + void setBackgroundColor(uint32 color); + void setRichText(std::string const& text); +}; + +class SliderFrame : public WindowFrame { +public: + SliderFrame(Frame* parent, int id = 0, int style = TBS_AUTOTICKS | TBS_BOTH); + + void setPos(int pos); + void setRange(int minValue, int maxValue); + void setLineSize(int size); + void setPageSize(int size); + void setTicFreq(int freq); + int getPos(); +}; +class ProgressFrame : public WindowFrame { +public: + ProgressFrame(Frame* parent, int id = 0, int style = 0); + + void setRange(int minValue, int maxValue); + void setPos(int pos); +}; + +class UpDownFrame : public WindowFrame { +public: + UpDownFrame(Frame* parent, int id = 0, int style = 0); +}; + +class TabFrame : public WindowFrame { +protected: + std::vector tabs; + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +public: + TabFrame(Frame* parent, int id = 0, int style = 0); + + size_t numTabs() const { + return tabs.size(); + } + Frame* addTab(std::string const& text, Frame* frame = NULL); + Frame* getTab(size_t pos) const { + return (pos >= tabs.size() ? nullptr : tabs[pos]); + } + + void clear(); + + int getCurSel() const { + return TabCtrl_GetCurSel(hWnd); + } + void setCurSel(int sel); +}; + +class ColorFrame : public WindowFrame { + uint32 color; + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +public: + ColorFrame(uint32 clr, Frame* parent, uint32 id); + ~ColorFrame(); + + void setColor(uint32 clr) { + color = clr; + invalidate(); + } + uint32 getColor() { + return color; + } +}; + +class TreeViewFrame : public WindowFrame { +public: + TreeViewFrame(Frame* parent, int id = 0, int style = 0); + + void setImageList(HIMAGELIST list, int type) { + TreeView_SetImageList(hWnd, list, type); + } + void setItemHeight(int height) { + TreeView_SetItemHeight(hWnd, height); + } + + HTREEITEM insertItem(TVINSERTSTRUCT* tvis) { + return TreeView_InsertItem(hWnd, tvis); + } + void deleteItem(HTREEITEM item) { + TreeView_DeleteItem(hWnd, item); + } + + LPARAM getItemData(HTREEITEM item); + + void setItemText(HTREEITEM item, std::string const& text); +}; + +class DateTimeFrame : public WindowFrame { +public: + DateTimeFrame(Frame* parent, int id = 0, int style = DTS_SHORTDATEFORMAT); + void setFormat(char const* fmt); + + bool isDateSet() const; + uint64 getDate() const; + void setNoDate(); + void setDate(uint64 date); +}; diff --git a/src/frameui/fontsys.cpp b/src/frameui/fontsys.cpp new file mode 100644 index 0000000..3388bbc --- /dev/null +++ b/src/frameui/fontsys.cpp @@ -0,0 +1,171 @@ +#include "fontsys.h" +#include + +FontSys FontSys::instance; + +//#define MKSIZE(s) (-MulDiv(s,instance.logPixelsY,72)) +#define MKSIZE(s) (-(s)) + +FontSys::FontStruct::FontStruct(LOGFONT const& lf) { + font = CreateFontIndirect(&lf); + face = lf.lfFaceName; + size = lf.lfHeight; + flags = 0; + if (lf.lfWeight > FW_NORMAL) flags |= FONT_BOLD; + if (lf.lfItalic) flags |= FONT_ITALIC; + if (lf.lfUnderline) flags |= FONT_UNDERLINE; + if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; +} + +bool operator<(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs) { + if (lhs.size != rhs.size) return lhs.size < rhs.size; + if (lhs.flags != rhs.flags) return lhs.flags < rhs.flags; + return lhs.face < rhs.face; +} +bool operator==(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs) { + if (lhs.size != rhs.size) return false; + if (lhs.flags != rhs.flags) return false; + return lhs.face == rhs.face; +} + +FontSys::FontSys() { + LOGFONT lf; + memset (&lf, 0, sizeof lf); + lf.lfHeight = -11; + lf.lfWeight = FW_NORMAL; + strcpy(lf.lfFaceName, "MS Shell Dlg 2"); + lf.lfCharSet = DEFAULT_CHARSET; + + fonts.emplace_back(lf); + + hDC = CreateCompatibleDC(NULL); + logPixelsY = GetDeviceCaps(hDC, LOGPIXELSY); +} + +FontSys::~FontSys() { + DeleteDC(hDC); +} + +HFONT FontSys::getSysFont() { + return instance.fonts[0].font; +} +HFONT FontSys::_getFont(int height, std::string const& face, int flags) { + FontStruct fs; + fs.size = height; + fs.flags = flags; + fs.face = face; + + auto pos = std::lower_bound(fonts.begin() + 1, fonts.end(), fs); + if (pos != fonts.end() && *pos == fs) { + return pos->font; + } + + LOGFONT lf; + getLogFont(&lf, -height, face, flags); + return fonts.emplace(pos, lf)->font; +} + +void FontSys::getLogFont(LOGFONT* lf, int size, std::string const& face, int flags) { + GetObject(instance.fonts[0].font, sizeof(LOGFONT), lf); + lf->lfHeight = MKSIZE(size); + strcpy(lf->lfFaceName, face.c_str()); + lf->lfWeight = (flags & FONT_BOLD ? FW_BOLD : FW_NORMAL); + lf->lfItalic = (flags & FONT_ITALIC ? TRUE : FALSE); + lf->lfUnderline = (flags & FONT_UNDERLINE ? TRUE : FALSE); + lf->lfStrikeOut = (flags & FONT_STRIKEOUT ? TRUE : FALSE); +} +HFONT FontSys::getFont(int size, std::string const& face, int flags) { + return instance._getFont(MKSIZE(size), face, flags); +} +HFONT FontSys::getFont(int size, int flags) { + return instance._getFont(MKSIZE(size), instance.fonts[0].face, flags); +} +HFONT FontSys::changeSize(int size, HFONT oldFont) { + if (oldFont == NULL) oldFont = getSysFont(); + LOGFONT lf; + GetObject(oldFont, sizeof lf, &lf); + int flags = 0; + if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; + if (lf.lfItalic) flags |= FONT_ITALIC; + if (lf.lfUnderline) flags |= FONT_UNDERLINE; + if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; + return instance._getFont(MKSIZE(size), lf.lfFaceName, flags); +} +HFONT FontSys::changeFlags(int flags, HFONT oldFont) { + if (oldFont == NULL) oldFont = getSysFont(); + LOGFONT lf; + GetObject(oldFont, sizeof lf, &lf); + return instance._getFont(lf.lfHeight, lf.lfFaceName, flags); +} + +SIZE FontSys::getTextSize(HFONT font, std::string const& text) { + SIZE sz; + SelectObject(instance.hDC, font); + GetTextExtentPoint32(instance.hDC, text.c_str(), text.length(), &sz); + return sz; +} +SIZE FontSys::getTextSize(HFONT font, char const* text, int length) { + SIZE sz; + SelectObject(instance.hDC, font); + GetTextExtentPoint32(instance.hDC, text, length, &sz); + return sz; +} +int FontSys::getMTextHeight(HFONT font, int width, std::string const& text) { + SIZE sz; + SelectObject(instance.hDC, font); + std::string word; + std::string curline; + int height = 0; + for (int i = 0; i <= text.length (); i++) { + if (text[i] && text[i] != '\n' && !isspace((uint8)text[i])) { + word += text[i]; + } + if (text[i] == 0 || isspace((uint8) text[i])) { + std::string tmp = curline + word; + GetTextExtentPoint32(instance.hDC, tmp.c_str(), tmp.length(), &sz); + int wd = sz.cx; + if (text[i] == '\n' || (wd > width && !curline.empty())) { + GetTextExtentPoint32(instance.hDC, curline.c_str(), curline.length(), &sz); + height += sz.cy; + curline.clear(); + } + curline += word; + if (text[i]) curline += text[i]; + word.clear(); + } + } + if (!curline.empty()) { + GetTextExtentPoint32(instance.hDC, curline.c_str(), curline.length(), &sz); + height += sz.cy; + } + return height; +} + +int FontSys::getFlags(HFONT font) { + if (font == NULL) font = getSysFont(); + LOGFONT lf; + GetObject(font, sizeof lf, &lf); + int flags = 0; + if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; + if (lf.lfItalic) flags |= FONT_ITALIC; + if (lf.lfUnderline) flags |= FONT_UNDERLINE; + if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; + return flags; +} + +void FontSys::setFontName(HFONT hFont, std::string const& name) { + instance.byName[name] = hFont; +} +HFONT FontSys::getFontByName(std::string const& name) { + auto it = instance.byName.find(name); + return (it == instance.byName.end() ? instance.fonts[0].font : it->second); +} + +HFONT FontSys::getFont(LOGFONT const& lf) { + int flags = 0; + if (lf.lfWidth > FW_NORMAL) flags |= FONT_BOLD; + if (lf.lfItalic) flags |= FONT_ITALIC; + if (lf.lfUnderline) flags |= FONT_UNDERLINE; + if (lf.lfStrikeOut) flags |= FONT_STRIKEOUT; + return instance._getFont(lf.lfHeight, lf.lfFaceName, flags); +} diff --git a/src/frameui/fontsys.h b/src/frameui/fontsys.h new file mode 100644 index 0000000..75ad50d --- /dev/null +++ b/src/frameui/fontsys.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include +#include +#include "base/types.h" + +#define FONT_BOLD 0x0001 +#define FONT_ITALIC 0x0002 +#define FONT_UNDERLINE 0x0004 +#define FONT_STRIKEOUT 0x0008 + +class FontSys { + struct FontStruct { + HFONT font; + std::string face; + int size; + int flags; + FontStruct() : font(nullptr) {} + FontStruct(LOGFONT const& lf); + FontStruct(FontStruct&& fs) + : font(fs.font) + , face(std::move(fs.face)) + , size(fs.size) + , flags(fs.flags) + { + fs.font = nullptr; + } + FontStruct(FontStruct const& fs) = delete; + ~FontStruct() { + if (font) DeleteObject(font); + } + }; + friend bool operator<(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs); + friend bool operator==(FontSys::FontStruct const& lhs, FontSys::FontStruct const& rhs); + std::vector fonts; + int logPixelsY; + HDC hDC; + FontSys(); + std::map byName; + static FontSys instance; + HFONT _getFont(int height, std::string const& face, int flags = 0); +public: + ~FontSys(); + + static HFONT getSysFont(); + static HFONT getFont(int size, std::string const& face, int flags = 0); + static HFONT getFont(int size, int flags = 0); + static HFONT changeSize(int size, HFONT oldFont = NULL); + static HFONT changeFlags(int flags, HFONT oldFont = NULL); + static void setFontName(HFONT hFont, std::string const& name); + static HFONT getFontByName(std::string const& name); + + static HFONT getFont(LOGFONT const& lf); + + static void getLogFont(LOGFONT* lf, int size, std::string const& face, int flags = 0); + + static int getFlags(HFONT font = NULL); + + static SIZE getTextSize(HFONT font, std::string const& text); + static SIZE getTextSize(HFONT font, char const* text, int length); + static int getMTextHeight(HFONT font, int width, std::string const& text); +}; diff --git a/src/frameui/frame.cpp b/src/frameui/frame.cpp new file mode 100644 index 0000000..09e3ea0 --- /dev/null +++ b/src/frameui/frame.cpp @@ -0,0 +1,436 @@ +#include +#include +#include "frame.h" + +RootFrame::RootFrame() + : Frame(NULL) +{ + frames.push_back(this); + master = this; + frames[0]->master = this; + frames[0]->mr_pos = 0; + moveid = 0; + updating = false; + frames[0]->mr_valid = true; + frames[0]->_x = 0; + frames[0]->_y = 0; + frames[0]->_width = 0; + frames[0]->_height = 0; +} +RootFrame::~RootFrame() { + frames[0]->master = NULL; + frames[0]->firstChild = NULL; + for (size_t i = 1; i < frames.size(); i++) { + frames[i]->master = NULL; + frames[i]->parent = NULL; + frames[i]->prevSibling = NULL; + frames[i]->nextSibling = NULL; + frames[i]->firstChild = NULL; + delete frames[i]; + } +} +void RootFrame::shutdown() { + for (Frame* frame : frames) { + frame->onMessage(FM_SHUTDOWN, 0, 0); + } +} +void RootFrame::setSize(int width, int height) { + frames[0]->_width = width; + frames[0]->_height = height; + deepUpdateFrame(frames[0]); +} +void RootFrame::addFrame(Frame* r) { + r->mr_pos = frames.size(); + frames.push_back(r); +} +void RootFrame::removeFrame(Frame* r) { + for (size_t i = r->mr_pos + 1; i < frames.size(); ++i) { + for (int j = 0; j < Frame::Anchor::count; ++j) { + if (frames[i]->anchors[j].rel == r) { + frames[i]->anchors[j].active = false; + } + } + frames[i]->mr_pos = i - 1; + frames[i - 1] = frames[i]; + } + frames.pop_back(); +} + +void RootFrame::setPoint(Frame* r, int point, Frame* rel, int relPoint, int x, int y) { + uint32 xRel = 0; + if ((relPoint & 0x0F) == 0x01) { // hCenter + xRel = 0x4000; + } else if ((relPoint & 0x0F) == 0x02) { // hRight + xRel = 0x8000; + } + uint32 yRel = 0; + if ((relPoint & 0xF0) == 0x10) { // vCenter + yRel = 0x4000; + } else if ((relPoint & 0xF0) == 0x20) { // vBottom + yRel = 0x8000; + } + setPointEx(r, point, rel, xRel, yRel, x, y); +} +void RootFrame::setPointEx(Frame* r, int point, Frame* rel, uint32 xRel, uint32 yRel, int x, int y) { + if (rel == NULL) rel = frames[0]; + // move the tree + if (!updating) moveid++; + int cur = r->mr_pos; + int target = rel->mr_pos; + if (cur < target && updating) return; + r->mr_moving = moveid; + int count = 1; + if (cur < target) { + std::vector temp; + temp.push_back(r); + while (++cur <= target) { + for (int i = 0; i < Frame::Anchor::count; i++) { + if (frames[cur]->anchors[i].rel && + frames[cur]->anchors[i].rel->mr_moving == moveid) + { + frames[cur]->mr_moving = moveid; + temp.push_back(frames[cur]); + break; + } + } + if (cur == target && frames[cur]->mr_moving == moveid) return; + } + count = 0; + for (cur = r->mr_pos; cur <= target; cur++) { + if (frames[cur]->mr_moving == moveid) { + count++; + } else { + frames[cur]->mr_pos = cur - count; + frames[cur - count] = frames[cur]; + } + } + for (size_t i = 0; i < temp.size(); i++) { + temp[i]->mr_pos = target - count + i + 1; + frames[target - count + i + 1] = temp[i]; + } + } else { + target = cur; + } + + // add the anchor + if ((point & 0x0F) == 0x00) { // hLeft + r->anchors[Frame::Anchor::hCenter].active = false; + if (r->anchors[Frame::Anchor::hRight].active) { + r->anchors[Frame::Anchor::hWidth].active = false; + } + Frame::Anchor& a = r->anchors[Frame::Anchor::hLeft]; + a.active = true; + a.rel = rel; + a.relRatio = xRel; + a.offset = x; + } else if ((point & 0x0F) == 0x01) { // hCenter + if (r->anchors[Frame::Anchor::hLeft].active == false && + r->anchors[Frame::Anchor::hRight].active == false) + { + Frame::Anchor& a = r->anchors[Frame::Anchor::hCenter]; + a.active = true; + a.rel = rel; + a.relRatio = xRel; + a.offset = x; + } + } else { // hRight + r->anchors[Frame::Anchor::hCenter].active = false; + if (r->anchors[Frame::Anchor::hLeft].active) { + r->anchors[Frame::Anchor::hWidth].active = false; + } + Frame::Anchor& a = r->anchors[Frame::Anchor::hRight]; + a.active = true; + a.rel = rel; + a.relRatio = xRel; + a.offset = x; + } + if ((point & 0xF0) == 0x00) { // vTop + r->anchors[Frame::Anchor::vCenter].active = false; + if (r->anchors[Frame::Anchor::vBottom].active) { + r->anchors[Frame::Anchor::vHeight].active = false; + } + Frame::Anchor& a = r->anchors[Frame::Anchor::vTop]; + a.active = true; + a.rel = rel; + a.relRatio = yRel; + a.offset = y; + } else if ((point & 0xF0) == 0x10) { // vCenter + if (r->anchors[Frame::Anchor::vTop].active == false && + r->anchors[Frame::Anchor::vBottom].active == false) + { + Frame::Anchor& a = r->anchors[Frame::Anchor::vCenter]; + a.active = true; + a.rel = rel; + a.relRatio = yRel; + a.offset = y; + } + } else { // vBottom + r->anchors[Frame::Anchor::vCenter].active = false; + if (r->anchors[Frame::Anchor::vTop].active) { + r->anchors[Frame::Anchor::vHeight].active = false; + } + Frame::Anchor& a = r->anchors[Frame::Anchor::vBottom]; + a.active = true; + a.rel = rel; + a.relRatio = yRel; + a.offset = y; + } + // update positions + if (!updating) { + updating = true; + void* moveData = beginMoving(); + for (size_t cur = target - count + 1; cur < frames.size(); cur++) { + for (int i = 0; i < Frame::Anchor::count && frames[cur]->mr_moving != moveid; i++) { + if (frames[cur]->anchors[i].rel && + frames[cur]->anchors[i].rel->mr_moving == moveid) { + frames[cur]->mr_moving = moveid; + } + } + if (frames[cur]->mr_moving == moveid) updateFrame(frames[cur], moveData); + } + endMoving(moveData); + updating = false; + } +} +void RootFrame::setWidth(Frame* r, int width) { + if (r->anchors[Frame::Anchor::hLeft].active && + r->anchors[Frame::Anchor::hRight].active) { + return; + } + Frame::Anchor& c = r->anchors[Frame::Anchor::hWidth]; + c.active = true; + c.offset = width; + deepUpdateFrame(r); +} +void RootFrame::setHeight(Frame* r, int height) { + if (r->anchors[Frame::Anchor::vTop].active && + r->anchors[Frame::Anchor::vBottom].active) { + return; + } + Frame::Anchor& c = r->anchors[Frame::Anchor::vHeight]; + c.active = true; + c.offset = height; + deepUpdateFrame(r); +} +void RootFrame::deepUpdateFrame(Frame* r) { + if (!updating) { + updating = true; + void* moveData = beginMoving(); + moveid++; + r->mr_moving = moveid; + for (size_t cur = r->mr_pos; cur < frames.size(); cur++) { + for (int i = 0; i < Frame::Anchor::count && frames[cur]->mr_moving != moveid; i++) { + if (frames[cur]->anchors[i].rel && + frames[cur]->anchors[i].rel->mr_moving == moveid) { + frames[cur]->mr_moving = moveid; + } + } + if (frames[cur]->mr_moving == moveid) updateFrame(frames[cur], moveData); + } + endMoving(moveData); + updating = false; + } +} +inline int getRegionX(Frame* r, uint32 ratio) { + return r->left() + ((r->width() * ratio) >> 15); +} +inline int getRegionY(Frame* r, uint32 ratio) { + return r->top() + ((r->height() * ratio) >> 15); +} +void RootFrame::updateFrame(Frame* r, void* data) { + int oldLeft = r->left(); + int oldTop = r->top(); + int oldRight = r->right(); + int oldBottom = r->bottom(); + if (r->anchors[Frame::Anchor::hLeft].active && + r->anchors[Frame::Anchor::hRight].active) + { + Frame::Anchor& la = r->anchors[Frame::Anchor::hLeft]; + Frame::Anchor& ra = r->anchors[Frame::Anchor::hRight]; + if (la.rel && la.rel->mr_valid && ra.rel && ra.rel->mr_valid) { + r->_x = getRegionX(la.rel, la.relRatio) + la.offset; + r->_width = getRegionX(ra.rel, ra.relRatio) + ra.offset - r->_x; + } else { + if (r->mr_valid) { + r->mr_valid = false; + r->onChangeVisibility(data); + } + return; + } + } else if (r->anchors[Frame::Anchor::hWidth].active) { + r->_width = r->anchors[Frame::Anchor::hWidth].offset; + Frame::Anchor& la = r->anchors[Frame::Anchor::hLeft]; + Frame::Anchor& ra = r->anchors[Frame::Anchor::hRight]; + Frame::Anchor& ca = r->anchors[Frame::Anchor::hCenter]; + if (la.active && la.rel && la.rel->mr_valid) { + r->_x = getRegionX(la.rel, la.relRatio) + la.offset; + } else if (ra.active && ra.rel && ra.rel->mr_valid) { + r->_x = getRegionX(ra.rel, ra.relRatio) + ra.offset - r->_width; + } else if (ca.active && ca.rel && ca.rel->mr_valid) { + r->_x = getRegionX(ca.rel, ca.relRatio) + ca.offset - r->_width / 2; + } else { + if (r->mr_valid) { + r->mr_valid = false; + r->onChangeVisibility(data); + } + return; + } + } + if (r->anchors[Frame::Anchor::vTop].active && + r->anchors[Frame::Anchor::vBottom].active) + { + Frame::Anchor& ta = r->anchors[Frame::Anchor::vTop]; + Frame::Anchor& ba = r->anchors[Frame::Anchor::vBottom]; + if (ta.rel && ta.rel->mr_valid && ba.rel && ba.rel->mr_valid) { + r->_y = getRegionY(ta.rel, ta.relRatio) + ta.offset; + r->_height = getRegionY(ba.rel, ba.relRatio) + ba.offset - r->_y; + } else { + if (r->mr_valid) { + r->mr_valid = false; + r->onChangeVisibility(data); + } + return; + } + } else if (r->anchors[Frame::Anchor::vHeight].active) { + r->_height = r->anchors[Frame::Anchor::vHeight].offset; + Frame::Anchor& ta = r->anchors[Frame::Anchor::vTop]; + Frame::Anchor& ba = r->anchors[Frame::Anchor::vBottom]; + Frame::Anchor& ca = r->anchors[Frame::Anchor::vCenter]; + if (ta.active && ta.rel && ta.rel->mr_valid) { + r->_y = getRegionY(ta.rel, ta.relRatio) + ta.offset; + } else if (ba.active && ba.rel && ba.rel->mr_valid) { + r->_y = getRegionY(ba.rel, ba.relRatio) + ba.offset - r->_height; + } else if (ca.active && ca.rel && ca.rel->mr_valid) { + r->_y = getRegionY(ca.rel, ca.relRatio) + ca.offset - r->_height / 2; + } else { + if (r->mr_valid) { + r->mr_valid = false; + r->onChangeVisibility(data); + } + return; + } + } + if (r->left() != oldLeft || r->top() != oldTop || + r->right() != oldRight || r->bottom() != oldBottom || + !r->mr_valid) + { + if (!r->mr_valid) { + r->mr_valid = true; + r->onChangeVisibility(data); + } else { + r->onMove(data); + } + } +} + +//////////////////////////// + +Frame::Frame(Frame* _parent) + : parent(_parent) + , master(nullptr) + , mr_pos(0) + , mr_moving(0) + , mr_valid(false) + , _x(0) + , _y(0) + , _width(0) + , _height(0) + , _visible(true) +{ + memset(anchors, 0, sizeof anchors); + if (parent) master = parent->master; + if (master) master->addFrame(this); + + firstChild = NULL; + lastChild = NULL; + if (parent) { + prevSibling = parent->lastChild; + if (parent->lastChild) parent->lastChild->nextSibling = this; + else parent->firstChild = this; + parent->lastChild = this; + } else { + prevSibling = NULL; + } + nextSibling = NULL; +} +Frame::~Frame() { + setParent(NULL); + Frame* cur = firstChild; + while (cur) { + Frame* next = cur->nextSibling; + cur->parent = NULL; + cur->prevSibling = NULL; + cur->nextSibling = NULL; + delete cur; + cur = next; + } + if (master) master->removeFrame(this); +} + +void Frame::setParent(Frame* _parent) { + if (parent == _parent) return; + if (parent) { + if (prevSibling) prevSibling->nextSibling = nextSibling; + else parent->firstChild = nextSibling; + if (nextSibling) nextSibling->prevSibling = prevSibling; + else parent->lastChild = prevSibling; + prevSibling = NULL; + nextSibling = NULL; + } + parent = _parent; + if (parent) { + prevSibling = parent->lastChild; + nextSibling = NULL; + if (parent->lastChild) parent->lastChild->nextSibling = this; + else parent->firstChild = this; + parent->lastChild = this; + } +} + +void Frame::onChangeVisibility(void* data) { + onMove(data); + for (Frame* cur = firstChild; cur; cur = cur->nextSibling) { + if (cur->_visible) cur->onChangeVisibility(data); + } +} +void Frame::show(bool s) { + if (s != _visible) { + _visible = s; + void* moveData = master->beginMoving(); + onChangeVisibility(moveData); + master->endMoving(moveData); + } +} + +LRESULT Frame::notify(uint32 message, WPARAM wParam, LPARAM lParam) { + Frame* cur = this; + uint32 result = M_UNHANDLED; + while (cur && (result = cur->onMessage(message, wParam, lParam)) == M_UNHANDLED) { + cur = cur->getParent(); + if (cur == this) break; + } + return result; +} + +void Frame::setWidth(int width) { + master->setWidth(this, width); +} +void Frame::setHeight(int height) { + master->setHeight(this, height); +} +void Frame::setPoint(int point, Frame* rel, int relPoint, int x, int y) { + master->setPoint(this, point, rel, relPoint, x, y); +} +void Frame::setPointEx(int point, Frame* rel, double xRel, double yRel, int x, int y) { + master->setPointEx(this, point, rel, uint32(xRel * 0x8000), uint32(yRel * 0x8000), x, y); +} +void Frame::clearAllPoints() { + for (int i = 0; i < Anchor::count; i++) { + anchors[i].active = false; + } + anchors[Anchor::hWidth].active = true; + anchors[Anchor::vHeight].active = true; + master->deepUpdateFrame(this); +} + +//////////////////////////////////// diff --git a/src/frameui/frame.h b/src/frameui/frame.h new file mode 100644 index 0000000..3473444 --- /dev/null +++ b/src/frameui/frame.h @@ -0,0 +1,158 @@ +#pragma once + +#include +#include +#include "base/types.h" + +#define PT_TOPLEFT 0x00 +#define PT_TOP 0x01 +#define PT_TOPRIGHT 0x02 +#define PT_LEFT 0x10 +#define PT_CENTER 0x11 +#define PT_RIGHT 0x12 +#define PT_BOTTOMLEFT 0x20 +#define PT_BOTTOM 0x21 +#define PT_BOTTOMRIGHT 0x22 + +#define M_UNHANDLED 0x80000000 +#define FM_SHUTDOWN 0x7F000001 + +class Frame { + // master frame data + friend class RootFrame; + int mr_pos; + int mr_moving; + bool mr_valid; + + bool _visible; + int _x; + int _y; + int _width; + int _height; + struct Anchor { + enum {hLeft, hCenter, hRight, hWidth, vTop, vCenter, vBottom, vHeight, count}; + bool active; + Frame* rel; + uint32 relRatio; + int offset; + } anchors[8]; + + RootFrame* master; + Frame* parent; + Frame* firstChild; + Frame* lastChild; + Frame* prevSibling; + Frame* nextSibling; + + void onChangeVisibility(void* data); +protected: + virtual void onMove(void* data) {} +public: + Frame(Frame* parent); + virtual ~Frame(); + + // hierarchy + void setParent(Frame* parent); + Frame* getParent() const { + return parent; + } + Frame* getFirstChild() const { + return firstChild; + } + Frame* getLastChild() const { + return lastChild; + } + Frame* getPrevSibling() const { + return prevSibling; + } + Frame* getNextSibling() const { + return nextSibling; + } + + // visibility + void show(bool s = true); + void hide() { + show(false); + } + bool visible() const { + return _visible && mr_valid && (parent ? parent->visible() : true); + } + + // positioning + int left() const { + return _x; + } + int top() const { + return _y; + } + int right() const { + return _x + _width; + } + int bottom() const { + return _y + _height; + } + int width() const { + return _width; + } + int height() const { + return _height; + } + void setWidth(int width); + void setHeight(int height); + void setSize(int width, int height) { + setWidth(width); + setHeight(height); + } + void setPoint(int point, Frame* rel, int relPoint, int x, int y); + void setPoint(int point, Frame* rel, int x, int y) { + setPoint(point, rel, point, x, y); + } + void setPoint(int point, int x, int y) { + setPoint(point, parent, point, x, y); + } + void setPointEx(int point, Frame* rel, double xRel, double yRel, int x, int y); + void setPointEx(int point, double xRel, double yRel, int x, int y) { + setPointEx(point, parent, xRel, yRel, x, y); + } + void clearAllPoints(); + void setAllPoints(Frame* rel) { + setPoint(PT_TOPLEFT, rel, PT_TOPLEFT, 0, 0); + setPoint(PT_BOTTOMRIGHT, rel, PT_BOTTOMRIGHT, 0, 0); + } + void setAllPoints() { + setPoint(PT_TOPLEFT, parent, PT_TOPLEFT, 0, 0); + setPoint(PT_BOTTOMRIGHT, parent, PT_BOTTOMRIGHT, 0, 0); + } + + // M_UNHANDLED = unprocessed + virtual LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + return M_UNHANDLED; + } + LRESULT notify(uint32 message, WPARAM wParam, LPARAM lParam); +}; + +class RootFrame : public Frame { + friend class Frame; + + std::vector frames; + int moveid; + bool updating; + + void addFrame(Frame* r); + void updateFrame(Frame* r, void* data); + void deepUpdateFrame(Frame* r); + void setPoint(Frame* r, int point, Frame* rel, int relPoint, int x, int y); + void setPointEx(Frame* r, int point, Frame* rel, uint32 xRel, uint32 yRel, int x, int y); + void setWidth(Frame* r, int width); + void setHeight(Frame* r, int height); + void removeFrame(Frame* r); +protected: + virtual void* beginMoving() { return 0; } + virtual void endMoving(void* data) {} + void shutdown(); +public: + RootFrame(); + ~RootFrame(); + + void setSize(int width, int height); +}; diff --git a/src/frameui/framewnd.cpp b/src/frameui/framewnd.cpp new file mode 100644 index 0000000..5ca48fe --- /dev/null +++ b/src/frameui/framewnd.cpp @@ -0,0 +1,209 @@ +#include + +#include "framewnd.h" + +WindowFrame::WindowFrame(Frame* parent) + : Frame(parent) +{ + Frame* cur = getParent(); + while (cur->getParent()) cur = cur->getParent(); + RootWindow* frm = dynamic_cast(cur); + if (frm) ownerWindow = frm->getHandle(); + else ownerWindow = nullptr; +} + +HWND WindowFrame::getParentWindow() const { + return HWND_TOP; + Frame* cur = getParent(); + WindowFrame* curWnd = nullptr; + while (cur && !(curWnd = dynamic_cast(cur))) { + cur = cur->getParent(); + } + if (cur && curWnd) { + return curWnd->getHandle(); + } else { + return ownerWindow; + } +} + +void WindowFrame::onMove(void* data) { + if (hWnd) { + uint32 flags = SWP_NOREPOSITION; + HWND hWndInsertAfter = NULL; + if (visible()) { + if (IsWindowVisible(hWnd)) { + flags |= SWP_NOZORDER; + } else { + flags |= SWP_SHOWWINDOW; + hWndInsertAfter = getParentWindow(); + } + } else { + flags |= SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW; + } + if (data) { + DeferWindowPos((HDWP)data, hWnd, hWndInsertAfter, left(), top(), width(), height(), flags); + } else { + SetWindowPos(hWnd, hWndInsertAfter, left(), top(), width(), height(), flags); + } + } +} +void WindowFrame::create(std::string const& text, uint32 style, uint32 exStyle) { + Window::create(0, 0, 10, 10, text, style, exStyle, ownerWindow); +} +void WindowFrame::create(std::string const& wndClass, std::string const& text, uint32 style, uint32 exStyle) { + Window::subclass(wndClass, 0, 0, 10, 10, text, style, exStyle, ownerWindow); +} + +LRESULT WindowFrame::onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam) +{ + uint32 result; + if ((result = onMessage(message, wParam, lParam)) != M_UNHANDLED) { + return result; + } + Frame* cur = getParent(); + while (cur && cur->getParent()) cur = cur->getParent(); + RootWindow* frm = dynamic_cast(cur); + if (frm) { + frm->r_message = message; + frm->r_frame = getParent(); + } + result = Window::onWndMessage(message, wParam, lParam); + if (frm) { + frm->r_message = 0; + frm->r_frame = NULL; + } + return result; +} + +/////////////////////////////////////////////////////// + +RootWindow::RootWindow() + : r_message(0) + , r_frame(nullptr) + , c_frame(nullptr) +{ +} +RootWindow::~RootWindow() { +} + +void* RootWindow::beginMoving() { + return BeginDeferWindowPos(32); +} +void RootWindow::endMoving(void* data) { + EndDeferWindowPos((HDWP) data); +} + +LRESULT RootWindow::onControlMessage(HWND hControl, uint32 message, WPARAM wParam, LPARAM lParam) { + if (hControl == NULL) return onMessage(message, wParam, lParam); + Window* control = Window::fromHandle(hControl); + while (control == NULL) { + hControl = GetParent(hControl); + if (hControl == NULL || hControl == hWnd) break; + control = Window::fromHandle(hControl); + } + Frame* cur = dynamic_cast(control); + uint32 result = M_UNHANDLED; + while (cur && (result = cur->onMessage(message, wParam, lParam)) == M_UNHANDLED) { + cur = cur->getParent(); + } + return result; +} + +void RootWindow::setCapture(Frame* frame) { + Frame* cur = frame; + while (cur->getParent()) cur = cur->getParent(); + RootWindow* frm = dynamic_cast(cur); + if (frm) { + if (frm->c_frame) frm->c_frame->onMessage(WM_CAPTURECHANGED, 0, 0); + else SetCapture(frm->getHandle()); + frm->c_frame = frame; + } +} + +LRESULT RootWindow::onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_DESTROY: + shutdown(); + break; + case WM_NOTIFY: + { + LRESULT result = onControlMessage(((NMHDR*) lParam)->hwndFrom, message, wParam, lParam); + return result == M_UNHANDLED ? 0 : result; + } + break; + case WM_COMMAND: + { + LRESULT result = onControlMessage((HWND) lParam, message, wParam, lParam); + return result == M_UNHANDLED ? 0 : result; + } + break; + case WM_CTLCOLORBTN: + case WM_CTLCOLORDLG: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: + { + LRESULT result = onControlMessage((HWND) lParam, message, wParam, lParam); + if (result != M_UNHANDLED) return result; + } + break; + case WM_DRAWITEM: + { + DRAWITEMSTRUCT* dis = (DRAWITEMSTRUCT*) lParam; + if (dis->CtlType != ODT_MENU) { + LRESULT result = onControlMessage(dis->hwndItem, message, wParam, lParam); + if (result != M_UNHANDLED) return result; + } + } + break; + case WM_SIZE: + { + RECT rc; + GetClientRect(hWnd, &rc); + setSize(rc.right, rc.bottom); + } + break; + case WM_CAPTURECHANGED: + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEWHEEL: + case WM_MOUSEHWHEEL: + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: + case WM_MOUSEMOVE: + if (c_frame) { + if (message != WM_CAPTURECHANGED) { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + x -= c_frame->left(); + y -= c_frame->top(); + lParam = MAKELONG(x, y); + } + uint32 result = c_frame->onMessage(message, wParam, lParam); + if (message == WM_CAPTURECHANGED) c_frame = NULL; + if (result != M_UNHANDLED) return result; + else return 0; + } + break; + } + LRESULT result = M_UNHANDLED; + if (message == r_message && r_frame) { + Frame* cur = r_frame; + while (cur && (result = cur->onMessage(message, wParam, lParam)) == M_UNHANDLED) { + cur = cur->getParent(); + } + } else { + result = onMessage(message, wParam, lParam); + } + if (result != M_UNHANDLED) return result; + return Window::onWndMessage(message, wParam, lParam); +} diff --git a/src/frameui/framewnd.h b/src/frameui/framewnd.h new file mode 100644 index 0000000..b639f22 --- /dev/null +++ b/src/frameui/framewnd.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include "frameui/frame.h" +#include "frameui/window.h" + +class WindowFrame : public Frame, public Window { + HWND ownerWindow; +protected: + void onMove(void* data); + LRESULT onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam); +protected: + void create(std::string const& text, uint32 style, uint32 exStyle); + void create(std::string const& wndClass, std::string const& text, uint32 style, uint32 exStyle); + HWND getOwner() const { + return ownerWindow; + } + HWND getParentWindow() const; +public: + WindowFrame(Frame* parent); +}; + +class RootWindow : public RootFrame, public Window { + LRESULT onControlMessage(HWND hControl, uint32 message, WPARAM wParam, LPARAM lParam); + LRESULT onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam); + + void* beginMoving(); + void endMoving(void* data); + + friend class WindowFrame; + uint32 r_message; + Frame* r_frame; + + Frame* c_frame; +public: + RootWindow(); + ~RootWindow(); + + static void setCapture(Frame* frame); +}; diff --git a/src/frameui/listctrl.cpp b/src/frameui/listctrl.cpp new file mode 100644 index 0000000..94d0153 --- /dev/null +++ b/src/frameui/listctrl.cpp @@ -0,0 +1,39 @@ +#include "frameui/framewnd.h" +#include "frameui/fontsys.h" +#include "listctrl.h" + +ListFrame::ListFrame(Frame* parent, int id, int style, int styleEx) + : WindowFrame(parent) +{ + create(WC_LISTVIEW, "", WS_CHILD | WS_TABSTOP | style, WS_EX_CLIENTEDGE); + setFont(FontSys::getSysFont()); + setId(id); + ListView_SetExtendedListViewStyle(hWnd, styleEx); +} + +void ListFrame::clear() { + ListView_DeleteAllItems(hWnd); +} +int ListFrame::addItem(std::string const& name, int data) { + LVITEM lvi; + memset(&lvi, 0, sizeof lvi); + lvi.iItem = ListView_GetItemCount(hWnd); + lvi.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM; + lvi.pszText = const_cast(name.c_str()); + lvi.lParam = data; + ListView_InsertItem(hWnd, &lvi); + return lvi.iItem; +} + +int ListFrame::getCount() const { + return ListView_GetItemCount(hWnd); +} + +int ListFrame::getItemData(int item) { + LVITEM lvi; + memset(&lvi, 0, sizeof lvi); + lvi.iItem = item; + lvi.mask = LVIF_PARAM; + ListView_GetItem(hWnd, &lvi); + return lvi.lParam; +} diff --git a/src/frameui/listctrl.h b/src/frameui/listctrl.h new file mode 100644 index 0000000..c11908c --- /dev/null +++ b/src/frameui/listctrl.h @@ -0,0 +1,24 @@ +#pragma once + +#include "frameui/frame.h" +#include "frameui/window.h" +#include "frameui/framewnd.h" + +#include + +class ListFrame : public WindowFrame { +public: + ListFrame(Frame* parent, int id = 0, + int style = LVS_LIST | LVS_SHOWSELALWAYS, + int styleEx = 0); + + void clear(); + + int getItemData(int item); + int getCount() const; + int addItem(std::string const& name, int data = 0); + + int getCurSel() const { + return ListView_GetNextItem(hWnd, -1, LVNI_SELECTED); + } +}; diff --git a/src/frameui/searchlist.cpp b/src/frameui/searchlist.cpp new file mode 100644 index 0000000..c943386 --- /dev/null +++ b/src/frameui/searchlist.cpp @@ -0,0 +1,474 @@ +#include "searchlist.h" +#include "fontsys.h" +#include +#include + +//////////////////////////////////////// + +LRESULT Scrollable::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + SCROLLINFO si; + int step; + switch (message) { + case WM_SIZE: + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_PAGE | SIF_DISABLENOSCROLL; + si.nPage = HIWORD(lParam); + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + scroll(scrollPos); + return 0; + case WM_VSCROLL: + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_ALL; + GetScrollInfo(hWnd, SB_VERT, &si); + switch (LOWORD(wParam)) { + case SB_TOP: + si.nPos = si.nMin; + break; + case SB_BOTTOM: + si.nPos = si.nMax; + break; + case SB_LINEUP: + si.nPos -= 16; + break; + case SB_LINEDOWN: + si.nPos += 16; + break; + case SB_PAGEUP: + si.nPos -= si.nPage; + break; + case SB_PAGEDOWN: + si.nPos += si.nPage; + break; + case SB_THUMBTRACK: + si.nPos = si.nTrackPos; + break; + } + scroll(si.nPos); + SetFocus(hWnd); + return 0; + case WM_MOUSEWHEEL: + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &step, 0); + if (step < 0) step = 3; + scrollAccum += GET_WHEEL_DELTA_WPARAM(wParam) * step * 16; + scroll(scrollPos - scrollAccum / WHEEL_DELTA); + scrollAccum %= WHEEL_DELTA; + return 0; + } + return M_UNHANDLED; +} + +void Scrollable::scroll(int pos) { + SCROLLINFO si; + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_RANGE | SIF_PAGE; + GetScrollInfo(hWnd, SB_VERT, &si); + if (pos < si.nMin) pos = si.nMin; + if (pos > si.nMax - si.nPage + 1) pos = si.nMax - si.nPage + 1; + si.fMask = SIF_POS; + if (pos != scrollPos) { + si.nPos = pos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + + int deltaY = scrollPos - pos; + scrollPos = pos; + RECT rc; + GetClientRect(hWnd, &rc); + ScrollWindowEx(hWnd, 0, deltaY, &rc, &rc, NULL, NULL, SW_ERASE | SW_INVALIDATE); + } +} + +//////////////////////////////////////// + +SearchList::SearchList(Frame* parent, int id) + : Scrollable(parent) + , cursel(-1) +{ + itemHeight = FontSys::getTextSize(FontSys::getSysFont(), "123").cy + 3; + + if (WNDCLASSEX* wcx = createclass("SearchListClass")) { + wcx->hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wcx->hCursor = LoadCursor(NULL, IDC_ARROW); + RegisterClassEx(wcx); + } + create("", WS_CHILD | WS_VSCROLL, WS_EX_CLIENTEDGE); + setId(id); +} + +void SearchList::clear() { + items.clear(); + display.clear(); + resize(); +} +void SearchList::insert(uint32 id, std::string const& text) { + items.emplace_back(id, text); +} +void SearchList::insertEx(uint32 id, std::string const& text) { + itemsEx.emplace_back(id, text); +} + +static bool contains(std::vector const& kmp, std::string const& query, std::string const& text) { + if (kmp.empty()) return true; + size_t cur = 0; + for (size_t i = 0; i < text.length(); ++i) { + while (cur && query[cur] != tolower((uint8) text[i])) { + cur = kmp[cur - 1]; + } + cur += (query[cur] == tolower((uint8)text[i])); + if (cur == query.length()) return true; + } + return false; +} + +void SearchList::search(std::string const& query_) { + query = strlower(query_); + std::vector kmp(query.length(), 0); + for (size_t i = 1; i < query.length(); ++i) { + kmp[i] = kmp[i - 1]; + while (kmp[i] && query[kmp[i]] != query[i]) { + kmp[i] = kmp[kmp[i] - 1]; + } + kmp[i] += (query[kmp[i]] == query[i]); + } + Item* sel = nullptr; + if (cursel >= 0) sel = display[cursel]; + display.clear(); + cursel = -1; + scrollPos = 0; + scrollAccum = 0; + auto* list = &items; + if (query.length() && itemsEx.size()) { + list = &itemsEx; + } + for (auto& item : *list) { + if (contains(kmp, query, item.text)) { + if (&item == sel) cursel = display.size(); + display.push_back(&item); + } + } + resize(); +} + +void SearchList::sort() { + std::sort(items.begin(), items.end()); +} +void SearchList::sortEx() { + std::sort(itemsEx.begin(), itemsEx.end()); +} +void SearchList::update() { + search(query); +} +void SearchList::resize() { + RECT rc; + GetClientRect(hWnd, &rc); + SCROLLINFO si; + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = display.size() * itemHeight; + si.nPage = rc.bottom; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + scroll(scrollPos); + + InvalidateRect(hWnd, NULL, TRUE); +} + +void SearchList::render(HDC hDC) { + RECT rc; + GetClientRect(hWnd, &rc); + SelectObject(hDC, FontSys::getSysFont()); + int top = (rc.top + scrollPos) / itemHeight; + int bottom = (rc.bottom + scrollPos + itemHeight) / itemHeight; + if (top < 0) top = 0; + if (bottom > display.size()) bottom = display.size(); + + uint32 fgHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT); + uint32 bgHighlight = GetSysColor(COLOR_HIGHLIGHT); + uint32 fgNormal = 0x000000; + uint32 bgNormal = 0xFFFFFF; + + for (int index = top; index < bottom; ++index) { + Item* item = display[index]; + if (index == cursel) { + SetTextColor(hDC, fgHighlight); + SetBkColor(hDC, bgHighlight); + } else { + SetTextColor(hDC, fgNormal); + SetBkColor(hDC, bgNormal); + } + RECT irc = rc; + irc.top = index * itemHeight - scrollPos; + irc.bottom = irc.top + itemHeight; + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &irc, NULL, 0, NULL); + DrawText(hDC, item->text.c_str(), item->text.length(), &irc, DT_SINGLELINE | DT_NOPREFIX | DT_LEFT | DT_VCENTER); + } + rc.top = bottom * itemHeight - scrollPos; + if (rc.top < rc.bottom) { + SetBkColor(hDC, bgNormal); + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + } +} + +LRESULT SearchList::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + int x, y, index; + PAINTSTRUCT ps; + HDC hDC; + switch (message) { + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + render(hDC); + EndPaint(hWnd, &ps); + return 0; + case WM_LBUTTONDOWN: + SetFocus(hWnd); + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + index = (y + scrollPos) / itemHeight; + if (index < 0 || index >= display.size()) { + index = -1; + } + if (index != cursel) { + cursel = index; + notify(WM_COMMAND, MAKELONG(id(), BN_CLICKED), (LPARAM)hWnd); + InvalidateRect(hWnd, NULL, TRUE); + } + return 0; + } + return Scrollable::onMessage(message, wParam, lParam); +} + +/////////////////////////////////////////// + +class OptionList::Editor : public ComboFrame { +public: + Editor(OptionList* parent, int id = 0) + : ComboFrame(parent, id) + { + } + + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam) override { + if (message == WM_KILLFOCUS || (message == WM_COMMAND && HIWORD(wParam) == CBN_CLOSEUP)) { + hide(); + SetFocus(getOwner()); + } + return M_UNHANDLED; + } +}; + +OptionList::OptionList(Frame* parent, int id) + : Scrollable(parent) + , editor(nullptr) + , cursel(-1) +{ + itemHeight = FontSys::getTextSize(FontSys::getSysFont(), "123").cy + 5; + + if (WNDCLASSEX* wcx = createclass("OptionListClass")) { + wcx->hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wcx->hCursor = LoadCursor(NULL, IDC_ARROW); + RegisterClassEx(wcx); + } + create("", WS_CHILD | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_CLIENTEDGE); + setId(id); + + editor = new Editor(this); + editor->addString("", -1); +} + +void OptionList::addOption(std::string const& text) { + if (editor) editor->addString(text, options.size()); + options.push_back(text); +} + +void OptionList::update() { + RECT rc; + GetClientRect(hWnd, &rc); + SCROLLINFO si; + memset(&si, 0, sizeof si); + si.cbSize = sizeof si; + si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = items.size() * itemHeight; + si.nPage = rc.bottom; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + scroll(scrollPos); + + InvalidateRect(hWnd, NULL, TRUE); +} + +void OptionList::render(HDC hDC) { + RECT rc; + GetClientRect(hWnd, &rc); + SelectObject(hDC, FontSys::getSysFont()); + int top = (rc.top + scrollPos) / itemHeight; + int bottom = (rc.bottom + scrollPos + itemHeight) / itemHeight; + if (top < 0) top = 0; + if (bottom > items.size()) bottom = items.size(); + + uint32 fgNormal = 0x000000; + uint32 bgNormal = 0xFFFFFF; + uint32 bgLine = 0x808080; + + for (int index = top; index < bottom; ++index) { + std::string item = items[index]; + std::string value; + if (choices[index] >= 0) value = options[choices[index]]; + + SetTextColor(hDC, fgNormal); + SetBkColor(hDC, bgNormal); + RECT irc = rc; + irc.top = index * itemHeight - scrollPos; + irc.bottom = irc.top + itemHeight; + if (cursel == index && editor->visible()) { + irc.right = rc.right / 2; + } + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &irc, NULL, 0, NULL); + irc.top += 1; + irc.bottom -= 1; + irc.left += 1; + irc.right = rc.right / 2 - 2; + DrawText(hDC, item.c_str(), item.length(), &irc, DT_SINGLELINE | DT_NOPREFIX | DT_LEFT | DT_VCENTER); + irc.left = irc.right + 3; + irc.right = rc.right - 1; + if (cursel != index || !editor->visible()) { + DrawText(hDC, value.c_str(), value.length(), &irc, DT_SINGLELINE | DT_NOPREFIX | DT_LEFT | DT_VCENTER); + } + SetBkColor(hDC, bgLine); + irc.right = rc.right / 2; + irc.left = irc.right - 1; + irc.top -= 1; + irc.bottom += 1; + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &irc, NULL, 0, NULL); + irc.left = rc.left; + irc.right = rc.right; + irc.top = irc.bottom - 1; + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &irc, NULL, 0, NULL); + } + rc.top = bottom * itemHeight - scrollPos; + if (rc.top < rc.bottom) { + SetBkColor(hDC, bgNormal); + ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL); + } +} + +LRESULT OptionList::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + int x, y, index; + PAINTSTRUCT ps; + HDC hDC; + RECT rc; + switch (message) { + case WM_ERASEBKGND: + return TRUE; + case WM_PAINT: + hDC = BeginPaint(hWnd, &ps); + render(hDC); + EndPaint(hWnd, &ps); + return 0; + case WM_SIZE: + InvalidateRect(hWnd, NULL, TRUE); + break; + case WM_COMMAND: + if (editor && cursel >= 0 && HIWORD(wParam) == CBN_SELCHANGE && (HWND) lParam == editor->getHandle()) { + int sel = editor->getCurSel(); + choices[cursel] = (sel >= 0 ? editor->getItemData(sel) : -1); + notify(WM_OPTIONCHANGE, id(), cursel); + } + return 0; + case WM_LBUTTONDOWN: + SetFocus(hWnd); + x = GET_X_LPARAM(lParam); + y = GET_Y_LPARAM(lParam); + cursel = (y + scrollPos) / itemHeight; + GetClientRect(hWnd, &rc); + if (x < rc.right / 2) cursel = -1; + if (cursel >= 0 && cursel < items.size() && editor) { + editor->setPoint(PT_TOPLEFT, rc.right / 2 - 1, cursel * itemHeight - scrollPos); + editor->setWidth(rc.right / 2 + 3); + editor->show(); + SetFocus(editor->getHandle()); + ComboBox_SetCurSel(editor->getHandle(), choices[cursel] + 1); + ComboBox_ShowDropdown(editor->getHandle(), TRUE); + } else { + cursel = -1; + } + return 0; + } + return Scrollable::onMessage(message, wParam, lParam); +} + +/////////////////////////////////////////// +// +//TestWindow::TestWindow() { +// if (WNDCLASSEX* wcx = createclass("MainWndClass")) { +// wcx->hbrBackground = HBRUSH(COLOR_BTNFACE + 1); +// wcx->hCursor = LoadCursor(NULL, IDC_ARROW); +// RegisterClassEx(wcx); +// } +// create(CW_USEDEFAULT, 0, 400, 700, "Test Window", +// WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0); +// +// query = new EditFrame(this, 100); +// query->setPoint(PT_TOPLEFT, 0, 0); +// query->setPoint(PT_TOPRIGHT, 0, 0); +// query->setHeight(21); +// +// list = new SearchList(this, 101); +// list->setPoint(PT_TOPLEFT, query, PT_BOTTOMLEFT, 0, 4); +// list->setPoint(PT_TOPRIGHT, query, PT_BOTTOMRIGHT, 0, 4); +// list->setHeight(300); +// +// list->insert(0, "fasdfasdf"); +// list->insert(1, "gasdfasdg"); +// list->insert(2, "sadfasdgq"); +// list->insert(3, "gqfeqwe"); +// list->insert(4, "gasdfawe"); +// list->insert(5, "asdfawe"); +// list->insert(6, "gasdfawe"); +// list->insert(7, "asdgawe"); +// list->insert(8, "gasdfawe"); +// list->insert(9, "badsfawe"); +// list->update(); +// +// opts = new OptionList(this, 102); +// opts->setPoint(PT_TOPLEFT, list, PT_BOTTOMLEFT, 0, 4); +// opts->setPoint(PT_BOTTOMRIGHT, 0, 0); +// +// opts->addItem("Item 1", -1); +// opts->addItem("Item 2", 0); +// opts->addItem("Item 3", 1); +// opts->addItem("Item 4", 2); +// opts->addItem("Item 5", 3); +// opts->addOption("Value 1"); +// opts->addOption("Value 2"); +// opts->addOption("Value 3"); +// opts->addOption("Value 4"); +// opts->update(); +//} +// +//LRESULT TestWindow::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { +// if (message == WM_COMMAND) { +// int id = LOWORD(wParam); +// if (id == 100) { +// if (HIWORD(wParam) == EN_CHANGE) list->search(query->getText()); +// } else if (id == 101) { +// } +// return 0; +// } +// return M_UNHANDLED; +//} +// +//void TestWindow::loop() { +// ShowWindow(hWnd, SW_SHOW); +// while (hWnd) { +// MSG msg; +// if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { +// TranslateMessage(&msg); +// DispatchMessage(&msg); +// if (msg.message == WM_QUIT) { +// DestroyWindow(hWnd); +// } +// } +// } +//} diff --git a/src/frameui/searchlist.h b/src/frameui/searchlist.h new file mode 100644 index 0000000..afbcd35 --- /dev/null +++ b/src/frameui/searchlist.h @@ -0,0 +1,19 @@ +#pragma once + +#include "framewnd.h" +#include "controlframes.h" + +class Scrollable : public WindowFrame { +public: + Scrollable(Frame* parent) + : WindowFrame(parent) + , scrollPos(0) + , scrollAccum(0) + {} + +protected: + int scrollPos; + int scrollAccum; + void scroll(int pos); + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam) override; +}; diff --git a/src/frameui/window.cpp b/src/frameui/window.cpp new file mode 100644 index 0000000..9afd242 --- /dev/null +++ b/src/frameui/window.cpp @@ -0,0 +1,335 @@ +#include "window.h" + +#include "frameui/fontsys.h" + +#include +#include + +struct Window::TTData { + HWND hTip; + RECT tipRect; + int hitCode; + HFONT hFont; + std::string fixedTip; +}; +static LRESULT CALLBACK TooltipWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + if (uMsg == WM_PAINT) { + std::string text = Window::getWindowText(hWnd); + + RECT rc; + GetClientRect(hWnd, &rc); + PAINTSTRUCT ps; + HDC hDC = BeginPaint(hWnd, &ps); + + HFONT hFont = (HFONT)GetWindowLongPtr(hWnd, GWLP_USERDATA); + + SelectObject(hDC, hFont); + SetBkColor(hDC, 0xE1FFFF); + SetTextColor(hDC, 0x000000); + + HPEN hPen = CreatePen(PS_SOLID, 0, 0x000000); + HPEN hPrev = (HPEN)SelectObject(hDC, hPen); + Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom); + rc.left += 5; + rc.top += 2; + rc.bottom -= 2; + rc.right -= 5; + DrawText(hDC, text.c_str(), text.length(), &rc, DT_LEFT | DT_TOP); + SelectObject(hDC, hPrev); + DeleteObject(hPen); + + EndPaint(hWnd, &ps); + return 0; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam);; +} + +ATOM Window::windowClass = NULL; +std::map Window::handleMap; + +Window* Window::fromHandle(HWND hWnd) { + auto it = handleMap.find(hWnd); + return (it == handleMap.end() ? nullptr : it->second); +} + +WNDCLASSEX* Window::createclass(std::string const& wndClass) { + regClass = wndClass; + + WNDCLASSEX* wcx = new WNDCLASSEX; + HINSTANCE hInstance = GetModuleHandle(NULL); + if (!GetClassInfoEx(hInstance, regClass.c_str(), wcx)) { + memset(wcx, 0, sizeof(WNDCLASSEX)); + wcx->cbSize = sizeof(WNDCLASSEX); + wcx->lpfnWndProc = WindowProc; + wcx->hInstance = hInstance; + wcx->lpszClassName = regClass.c_str(); + wcx->hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); + return wcx; + } + delete wcx; + return NULL; +} +void Window::create(int x, int y, int width, int height, std::string const& text, uint32 style, uint32 exStyle, + HWND parent) +{ + if (!windowClass && regClass.empty()) { + WNDCLASSEX wcex; + memset(&wcex, 0, sizeof wcex); + wcex.cbSize = sizeof wcex; + wcex.lpfnWndProc = WindowProc; + wcex.hInstance = GetModuleHandle(NULL); + wcex.lpszClassName = "WUTILSWINDOW"; + wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); + windowClass = RegisterClassEx(&wcex); + } + hWnd = CreateWindowEx(exStyle, regClass.empty() ? "WUTILSWINDOW" : regClass.c_str(), text.c_str(), style, + x, y, width, height, parent, NULL, GetModuleHandle(NULL), this); + handleMap[hWnd] = this; +} +void Window::create(std::string const& wndClass, int x, int y, int width, int height, std::string const& text, uint32 style, + uint32 exStyle, HWND parent) { + hWnd = CreateWindowEx(exStyle, wndClass.c_str(), text.c_str(), style, x, y, width, height, + parent, NULL, GetModuleHandle(NULL), NULL); + handleMap[hWnd] = this; +} +void Window::subclass(std::string const& wndClass, int x, int y, int width, int height, std::string const& text, uint32 style, + uint32 exStyle, HWND parent) { + hWnd = CreateWindowEx(exStyle, wndClass.c_str(), text.c_str(), style, x, y, width, height, + parent, NULL, GetModuleHandle(NULL), NULL); + handleMap[hWnd] = this; + origProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR) WindowProc); +} + +LRESULT CALLBACK Window::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + Window* wnd = fromHandle(hWnd); + if (wnd == NULL && uMsg == WM_CREATE) { + CREATESTRUCT* cs = (CREATESTRUCT*)lParam; + wnd = (Window*)cs->lpCreateParams; + if (wnd) wnd->hWnd = hWnd; + } + if (wnd) { + bool send = true; + if (wnd->ttData) { + TRACKMOUSEEVENT tme; + memset(&tme, 0, sizeof tme); + tme.cbSize = sizeof tme; + tme.hwndTrack = wnd->hWnd; + if (uMsg == WM_MOUSEMOVE) { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + if (wnd->ttData->hitCode >= 0) { + if (pt.x < wnd->ttData->tipRect.left || pt.x >= wnd->ttData->tipRect.right || + pt.y < wnd->ttData->tipRect.top || pt.y >= wnd->ttData->tipRect.bottom) { + wnd->ttData->hitCode = -1; + } + } + if (wnd->ttData->hitCode < 0) { + ToolInfo ti; + wnd->ttData->hitCode = wnd->toolHitTest(pt, &ti); + if (wnd->ttData->hitCode >= 0) { + tme.dwFlags = TME_HOVER | TME_LEAVE; + tme.dwHoverTime = HOVER_DEFAULT; + TrackMouseEvent(&tme); + + wnd->ttData->tipRect = ti.rc; + SetWindowText(wnd->ttData->hTip, ti.text.c_str()); + + HDC hDC = GetDC(wnd->ttData->hTip); + SelectObject(hDC, wnd->ttData->hFont); + RECT rc = { 0, 0, 1024, 1024 }; + int ht = DrawText(hDC, ti.text.c_str(), ti.text.length(), &rc, DT_LEFT | DT_TOP | DT_CALCRECT); + ReleaseDC(wnd->ttData->hTip, hDC); + + POINT ptTL; + ptTL.x = wnd->ttData->tipRect.left; + ptTL.y = wnd->ttData->tipRect.bottom + 5; + ClientToScreen(wnd->hWnd, &ptTL); + + SetWindowLongPtr(wnd->ttData->hTip, GWLP_USERDATA, (LONG_PTR)wnd->ttData->hFont); + + InvalidateRect(wnd->ttData->hTip, NULL, TRUE); + SetWindowPos(wnd->ttData->hTip, HWND_TOPMOST, + ptTL.x, ptTL.y, rc.right + 10, ht + 5, + SWP_NOACTIVATE); + } else { + tme.dwFlags = TME_CANCEL; + TrackMouseEvent(&tme); + ShowWindow(wnd->ttData->hTip, SW_HIDE); + } + } + } else if (uMsg == WM_MOUSELEAVE) { + ShowWindow(wnd->ttData->hTip, SW_HIDE); + wnd->ttData->hitCode = -1; + send = false; + } else if (uMsg == WM_MOUSEHOVER) { + tme.dwFlags = TME_CANCEL; + TrackMouseEvent(&tme); + + if (wnd->ttData->hitCode >= 0) ShowWindow(wnd->ttData->hTip, SW_SHOWNA); + send = false; + } else if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN || uMsg == WM_MBUTTONDOWN || + uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEHWHEEL || uMsg == WM_KEYDOWN) { + ShowWindow(wnd->ttData->hTip, SW_HIDE); + wnd->ttData->hitCode = -1; + } + } + if (send) { + if (uMsg == WM_CLOSE || uMsg == WM_DESTROY) wnd->endModal(); + uint32 result = wnd->onWndMessage(uMsg, wParam, lParam); + if (uMsg == WM_DESTROY) wnd->hWnd = NULL; + return result; + } else { + return 0; + } + } else { + return DefWindowProc(hWnd, uMsg, wParam, lParam); + } +} +LRESULT Window::onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + if (origProc) return CallWindowProc(origProc, hWnd, message, wParam, lParam); + else return DefWindowProc(hWnd, message, wParam, lParam); +} + +Window::Window() { + hWnd = NULL; + origProc = NULL; + ttData = NULL; +} +Window::~Window() { + if (hWnd) { + if (origProc) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)origProc); + handleMap.erase(hWnd); + DestroyWindow(hWnd); + } + if (ttData) delete ttData; +} + +void Window::setText(std::string const& text) +{ + SetWindowText(hWnd, text.c_str()); +} +std::string Window::getText() const { + return getWindowText(hWnd); +} +std::string Window::getWindowText(HWND hWnd) { + size_t length = GetWindowTextLength(hWnd); + std::string str; + str.resize(length + 1); + GetWindowText(hWnd, &str[0], str.length()); + str.resize(length); + return str; +} + +void Window::setFont(HFONT hFont) { + SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE); +} +HFONT Window::getFont() const { + return (HFONT)SendMessage(hWnd, WM_GETFONT, NULL, NULL); +} + +void Window::enable(bool e) { + EnableWindow(hWnd, e); +} +void Window::showWindow(bool s) { + ShowWindow(hWnd, s ? SW_SHOW : SW_HIDE); +} + +int Window::id() const { + return GetWindowLong(hWnd, GWL_ID); +} +void Window::setId(int id) { + SetWindowLong(hWnd, GWL_ID, id); +} + +void Window::invalidate(bool erase) { + InvalidateRect(hWnd, NULL, erase ? TRUE : FALSE); +} + +void Window::setRedraw(bool r) { + SendMessage(hWnd, WM_SETREDRAW, r ? TRUE : FALSE, 0); + if (r) RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); +} + +int Window::toolHitTest(POINT pt, ToolInfo* ti) { + if (ttData && ttData->fixedTip.length()) { + GetClientRect(hWnd, &ti->rc); + ti->text = ttData->fixedTip; + return 0; + } + return -1; +} +void Window::enableTooltips(bool enable) { + if (hWnd == NULL) return; + if (enable && ttData == NULL) { + ttData = new TTData; + ttData->hFont = FontSys::getSysFont(); + WNDCLASSEX wcx; + HINSTANCE hInstance = GetModuleHandle(NULL); + if (!GetClassInfoEx(hInstance, "DRTooltip", &wcx)) { + memset(&wcx, 0, sizeof wcx); + wcx.cbSize = sizeof wcx; + wcx.lpfnWndProc = TooltipWindowProc; + wcx.hInstance = hInstance; + wcx.lpszClassName = "DRTooltip"; + wcx.hbrBackground = CreateSolidBrush(0xE1FFFF); + RegisterClassEx(&wcx); + } + ttData->hTip = CreateWindowEx(WS_EX_TOPMOST, "DRTooltip", + NULL, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWnd, NULL, + hInstance, NULL); + + ttData->hitCode = -1; + } else if (!enable && ttData != NULL) { + DestroyWindow(ttData->hTip); + delete ttData; + ttData = NULL; + } +} +void Window::setTooltipFont(HFONT hFont) { + if (ttData) ttData->hFont = hFont; +} +HFONT Window::getTooltipFont() { + return (ttData ? ttData->hFont : NULL); +} + +void Window::endModal() { + if (continueModal) { + continueModal = false; + SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | + SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); + HWND hParent = GetWindow(hWnd, GW_OWNER); + if (hParent) { + EnableWindow(hParent, TRUE); + if (GetActiveWindow() == hWnd) SetActiveWindow(hParent); + } + PostMessage(hWnd, WM_CLOSE, 0, 0); + } +} +int Window::doModal() { + if (hWnd == NULL) return 0; + ShowWindow(hWnd, SW_SHOW); + HWND hParent = GetWindow(hWnd, GW_OWNER); + if (hParent) EnableWindow(hParent, FALSE); + MSG msg; + continueModal = true; + while (continueModal) { + if (!GetMessage(&msg, NULL, 0, 0)) { + PostQuitMessage(msg.wParam); + return 0; + } + if (!IsDialogMessage(hWnd, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return 0; +} +void Window::setTooltip(char const* tip) { + if (tip && *tip) { + enableTooltips(true); + ttData->fixedTip = tip; + } else { + enableTooltips(false); + } +} diff --git a/src/frameui/window.h b/src/frameui/window.h new file mode 100644 index 0000000..b6f4920 --- /dev/null +++ b/src/frameui/window.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include "base/types.h" + +class Window +{ + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static ATOM windowClass; + static std::map handleMap; + struct TTData; + TTData* ttData; + std::string regClass; + bool continueModal; +protected: + HWND hWnd; + WNDPROC origProc; + virtual LRESULT onWndMessage(uint32 message, WPARAM wParam, LPARAM lParam); + WNDCLASSEX* createclass(std::string const& wndClass); + void create(int x, int y, int width, int height, std::string const& text, uint32 style, uint32 exStyle, + HWND parent = NULL); + void create(std::string const& wndClass, int x, int y, int width, int height, std::string const& text, uint32 style, + uint32 exStyle, HWND parent = NULL); + void subclass(std::string const& wndClass, int x, int y, int width, int height, std::string const& text, uint32 style, + uint32 exStyle, HWND parent = NULL); + + struct ToolInfo { + RECT rc; + std::string text; + }; + virtual int toolHitTest(POINT pt, ToolInfo* ti); + void endModal(); +public: + Window(); + virtual ~Window(); + + operator HWND() const { + return hWnd; + } + HWND getHandle() const { + return hWnd; + } + + static Window* fromHandle(HWND hWnd); + + // random functions + void setText(std::string const& text); + std::string getText() const; + + void setFont(HFONT hFont); + HFONT getFont() const; + void setTooltipFont(HFONT hFont); + HFONT getTooltipFont(); + + void enable(bool e = true); + void disable() { + enable(false); + } + void showWindow(bool s = true); + void hideWindow() { + showWindow(false); + } + void setRedraw(bool r); + + int id() const; + void setId(int id); + + void invalidate(bool erase = true); + + void enableTooltips(bool enable = true); + void setTooltip(char const* tip); + + int doModal(); + + static std::string getWindowText(HWND hWnd); +}; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..4dd5631 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,23 @@ +#include "app.h" +#include +#include "base/error.h" + +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { + try { + Application app(hInstance, hPrevInstance, lpCmdLine, nCmdShow); + return app.run(); + } catch (Exception& ex) { + MessageBox(NULL, ex.what(), "Error", MB_OK | MB_ICONERROR); + return 1; + } +} diff --git a/src/ngdp.cpp b/src/ngdp.cpp new file mode 100644 index 0000000..2ab89e8 --- /dev/null +++ b/src/ngdp.cpp @@ -0,0 +1,457 @@ +#include "ngdp.h" +#include "base/http.h" +#include "base/path.h" +#include "base/checksum.h" +#include + +namespace NGDP { + + const std::string HOST = "http://cn.patch.battle.net:1119"; + + const std::map ProgramCodes = { + {"agent", "Battle.net Agent"}, + {"bna", "Battle.net App"}, + {"bnt", "Heroes of the Storm Alpha (Deprecated)"}, + {"d3", "Diablo 3 Retail"}, + {"d3cn", "Diablo 3 China"}, + {"d3t", "Diablo 3 Test"}, + {"demo", "Demo (Partial)"}, + {"hero", "Heroes of the Storm Retail"}, + {"herot", "Heroes of the Storm Test"}, + {"hsb", "Hearthstone"}, + {"pro", "Overwatch Retail"}, + {"prodev", "Overwatch Dev"}, + {"sc2", "StarCraft II (Partial)"}, + {"s2", "StarCraft II"}, + {"s2t", "StarCraft II Test (Partial)"}, + {"s2b", "StarCraft II Beta"}, + {"test", "Test (Partial)"}, + {"storm", "Heroes of the Storm (Deprecated)"}, + {"war3", "Warcraft III (Partial)"}, + {"wow", "World of Warcraft Retail"}, + {"wowt", "World of Warcraft Test"}, + {"wow_beta", "World of Warcraft Beta"}, + }; + + NGDP::NGDP(std::string const& app) + : program_(app) + { + File file = HttpRequest::get(HOST + "/" + app + "/cdns"); + if (!file) { + throw Exception("failed to fetch cdns file"); + } + for (std::string const& line : file) { + if (line.find('!') != std::string::npos || line.empty()) continue; + auto parts = split(line, '|'); + auto& config = cdns_[parts[0]]; + config.path = parts[1]; + config.hosts = split(parts[2], ' '); + } + + file = HttpRequest::get(HOST + "/" + app + "/versions"); + if (!file) { + throw Exception("failed to fetch versions file"); + } + for (std::string const& line : file) { + if (line.find('!') != std::string::npos || line.empty()) continue; + auto parts = split(line, '|'); + auto& config = versions_[parts[0]]; + config.build = parts[1]; + config.cdn = parts[2]; + config.id = std::stoi(parts[3]); + config.version = parts[4]; + if (cdns_.count(parts[0])) { + regions_.push_back(parts[0]); + } + } + } + + bool NGDP::setRegion(std::string const& region) { + if (!cdns_.count(region) || !versions_.count(region)) { + return false; + } + region_ = region; + base_ = "http://" + cdns_[region].hosts[0] + "/" + cdns_[region].path + "/"; + return true; + } + + std::string NGDP::geturl(std::string const& hash, std::string const& type, bool index) const { + std::string url = base_ + type + "/" + hash.substr(0, 2) + "/" + hash.substr(2, 2) + "/" + hash; + if (index) url += ".index"; + return url; + } + File NGDP::load(std::string const& hash, std::string const& type, bool index) const { + return HttpRequest::get(geturl(hash, type, index)); + } + + File DecodeBLTE(File& blte, uint32 eusize) { + if (blte.read32(true) != 'BLTE') return File(); + uint32 headerSize = blte.read32(true); + if (headerSize) { + std::vector csize; + std::vector usize; + uint16 flags = blte.read16(true); + uint16 chunks = blte.read16(true); + for (uint16 i = 0; i < chunks; ++i) { + csize.push_back(blte.read32(true)); + usize.push_back(blte.read32(true)); + blte.seek(16, SEEK_CUR); + } + MemoryFile dst; + std::vector tmp; + for (uint16 i = 0; i < chunks; ++i) { + uint8 type = blte.read8(); + if (type == 'N') { + if (csize[i] - 1 != usize[i]) return File(); + blte.read(dst.reserve(usize[i]), usize[i]); + } else if (type == 'Z') { + tmp.resize(csize[i] - 1); + blte.read(&tmp[0], tmp.size()); + if (gzinflate(&tmp[0], tmp.size(), dst.reserve(usize[i]), &usize[i])) return File(); + } else { + // unsupported compression + return File(); + } + } + dst.seek(0); + return dst; + } else { + uint64 offset = blte.tell(); + uint64 size = blte.size() - offset; + if (blte.read8() == 'N') { + return blte.subfile(offset, size); + } else if (eusize) { + blte.seek(offset, SEEK_SET); + std::vector tmp(size); + blte.read(&tmp[0], size); + MemoryFile dst; + if (gzinflate(&tmp[0], size, dst.reserve(eusize), &eusize)) return File(); + dst.seek(0); + return dst; + } else { + // unsupported compression + return File(); + } + } + } + + ConfigFile ParseConfig(File& file) { + ConfigFile result; + if (!file) return result; + for (std::string const& line : file) { + if (line[0] == '#') continue; + size_t pos = line.find(" = "); + if (pos == std::string::npos) continue; + result[line.substr(0, pos)] = line.substr(pos + 3); + } + return result; + } + +#pragma pack(push, 1) + struct EncodingFileHeader { + uint16 signature; + uint8 unk; + uint8 sizeA; + uint8 sizeB; + uint16 flagsA; + uint16 flagsB; + uint32 entriesA; + uint32 entriesB; + uint8 unk2; + uint32 stringSize; + }; +#pragma pack(pop) + + void from_string(Hash hash, std::string const& str) { + int val; + for (int i = 0; i < sizeof(Hash); ++i) { + sscanf(&str[i * 2], "%02x", &val); + hash[i] = val; + } + } + std::string to_string(const Hash hash) { + return MD5::format(hash); + } + + Encoding::Encoding(File& file) { + EncodingFileHeader header; + file.read(&header, sizeof header); + flip(header.signature); + flip(header.entriesA); + flip(header.entriesB); + flip(header.stringSize); + if (header.signature != 'EN' || header.sizeA != 16 || header.sizeB != 16) { + throw Exception("invalid encoding file"); + } + + uint32 size = file.size(); + uint32 posHeaderA = sizeof(EncodingFileHeader) + header.stringSize; + uint32 posEntriesA = posHeaderA + header.entriesA * 32; + uint32 posHeaderB = posEntriesA + header.entriesA * 4096; + uint32 posEntriesB = posHeaderB + header.entriesB * 32; + uint32 posLayout = posEntriesB + header.entriesB * 4096; + + data_.resize(header.stringSize + (header.entriesA + header.entriesB) * 4096 + (size - posLayout)); + char* layouts = (char*) &data_[0]; + uint8* entriesA = &data_[header.stringSize]; + uint8* entriesB = entriesA + header.entriesA * 4096; + layout_ = (char*) (entriesB + header.entriesB * 4096); + + file.read(layouts, header.stringSize); + file.seek(posEntriesA, SEEK_SET); + file.read(entriesA, header.entriesA * 4096); + file.seek(posEntriesB, SEEK_SET); + file.read(entriesB, header.entriesB * 4096); + file.read(layout_, size - posLayout); + + for (char* ptr = layouts; ptr < layouts + header.stringSize; ++ptr) { + layouts_.push_back(ptr); + while (*ptr) ++ptr; + } + + file.seek(posHeaderA, SEEK_SET); + encodingTable_.resize(header.entriesA); + for (uint32 i = 0; i < header.entriesA; ++i) { + file.read(encodingTable_[i].hash, sizeof(Hash)); + Hash blockHash, realHash; + file.read(blockHash, sizeof blockHash); + MD5::checksum(entriesA, 4096, realHash); + if (memcmp(realHash, blockHash, sizeof(Hash))) { + throw Exception("encoding file checksum mismatch"); + } + for (uint8* ptr = entriesA; ptr + sizeof(EncodingEntry) <= entriesA + 4096;) { + EncodingEntry* entry = reinterpret_cast(ptr); + if (!entry->keyCount) break; + encodingTable_[i].entries.push_back(entry); + flip(entry->usize); + ptr += sizeof(EncodingEntry) + (entry->keyCount - 1) * sizeof(Hash); + } + entriesA += 4096; + } + + Hash nilHash; + memset(nilHash, 0, sizeof(Hash)); + + file.seek(posHeaderB, SEEK_SET); + layoutTable_.resize(header.entriesB); + for (uint32 i = 0; i < header.entriesB; ++i) { + file.read(layoutTable_[i].key, sizeof(Hash)); + Hash blockHash, realHash; + file.read(blockHash, sizeof blockHash); + MD5::checksum(entriesB, 4096, realHash); + if (memcmp(realHash, blockHash, sizeof(Hash))) { + throw Exception("encoding file checksum mismatch"); + } + for (uint8* ptr = entriesB; ptr + sizeof(LayoutEntry) <= entriesB + 4096;) { + LayoutEntry* entry = reinterpret_cast(ptr); + if (!memcmp(entry->key, nilHash, sizeof(Hash))) { + break; + } + layoutTable_[i].entries.push_back(entry); + flip(entry->stringIndex); + flip(entry->csize); + ptr += sizeof(LayoutEntry); + } + entriesB += 4096; + } + } + + template + typename Vec::const_iterator find_hash(Vec const& vec, Comp less) { + if (vec.empty() || less(vec[0])) return vec.end(); + size_t left = 0, right = vec.size(); + while (right - left > 1) { + size_t mid = (left + right) / 2; + if (less(vec[mid])) { + right = mid; + } else { + left = mid; + } + } + return vec.begin() + left; + } + + Encoding::EncodingEntry const* Encoding::getEncoding(const Hash hash) const { + auto it = find_hash(encodingTable_, [&hash](EncodingHeader const& rhs) { + return memcmp(hash, rhs.hash, sizeof(Hash)) < 0; + }); + if (it == encodingTable_.end()) return nullptr; + auto sub = find_hash(it->entries, [&hash](EncodingEntry const* rhs) { + return memcmp(hash, rhs->hash, sizeof(Hash)) < 0; + }); + if (sub == it->entries.end()) return nullptr; + if (memcmp((*sub)->hash, hash, sizeof(Hash))) return nullptr; + return *sub; + } + Encoding::LayoutEntry const* Encoding::getLayout(const Hash key) const { + auto it = find_hash(layoutTable_, [&key](LayoutHeader const& rhs) { + return memcmp(key, rhs.key, sizeof(Hash)) < 0; + }); + if (it == layoutTable_.end()) return nullptr; + auto sub = find_hash(it->entries, [&key](LayoutEntry const* rhs) { + return memcmp(key, rhs->key, sizeof(Hash)) < 0; + }); + if (sub == it->entries.end()) return nullptr; + if (memcmp((*sub)->key, key, sizeof(Hash))) return nullptr; + return *sub; + } + + CascStorage::CascStorage(std::string const& root) + : root_(root) + { + path::create(root / "config"); + path::create(root / "data"); + path::create(root / "indices"); + path::create(root / "patch"); + + std::vector names; + WIN32_FIND_DATA fdata; + HANDLE hFind = FindFirstFile((root / "data" / "*").c_str(), &fdata); + if (hFind == INVALID_HANDLE_VALUE) return; + do { + if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + names.push_back(fdata.cFileName); + } + } while (FindNextFile(hFind, &fdata)); + FindClose(hFind); + + for (std::string const& name : names) { + DeleteFile((root / "data" / name).c_str()); + } + } + + File& CascStorage::addConfig(std::string const& hash, File& file) { + file.seek(0); + File(root_ / "config" / hash.substr(0, 2) / hash.substr(2, 2) / hash, File::REWRITE).copy(file); + file.seek(0); + return file; + } + File& CascStorage::addIndex(std::string const& hash, File& file) { + file.seek(0); + File(root_ / "indices" / hash + ".index", File::REWRITE).copy(file); + file.seek(0); + return file; + } + File CascStorage::addData(std::string const& name) { + return File(root_ / "data" / name, File::REWRITE); + } + + File& CascStorage::addCache(std::string const& name, File& file) { + file.seek(0); + File(path::root() / "cache" / name, File::REWRITE).copy(file); + file.seek(0); + return file; + } + File CascStorage::addCache(std::string const& name) { + return File(path::root() / "cache" / name, File::MODIFY); + } + File CascStorage::getCache(std::string const& name) { + return File(path::root() / "cache" / name); + } + + DataStorage::DataStorage(CascStorage& storage) + : storage_(storage) + , indexCount_(0) + , dataCount_(0) + { + } + + File& DataStorage::addFile(const Hash hash, File& file) { + if (!file) return file; + if (index_.size() >= MaxIndexEntries) { + writeIndex(); + } + if (!data_ || data_.size() + file.size() + 30 > MaxDataSize) { + data_ = storage_.addData(fmtstring("data.%03u", dataCount_++)); + } + index_.emplace_back(); + auto& entry = index_.back(); + memcpy(entry.hash, hash, sizeof(Hash)); + entry.index = dataCount_ - 1; + entry.offset = data_.tell(); + entry.size = 30 + file.size(); + + for (int i = 15; i >= 0; --i) { + data_.write8(hash[i]); + } + data_.write32(30 + file.size()); + data_.write16(0); + data_.write32(0); + data_.write32(0); + file.seek(0); + data_.copy(file); + file.seek(0); + return file; + } + +#pragma pack(push, 1) + struct IndexHeader { + uint16 version = 7; + uint8 keyIndex; + uint8 extraBytes = 0; + uint8 sizeBytes = 4; + uint8 offsBytes = 5; + uint8 keyBytes = 9; + uint8 segmentBits = 30; + uint64 maxOffset; + }; + struct WriteIndexEntry { + uint8 hash[9]; + uint8 pos[5]; + uint32 size; + }; +#pragma pack(pop) + + void DataStorage::writeIndex() { + if (index_.empty()) return; + + IndexHeader header; + header.keyIndex = indexCount_++; + header.maxOffset = _byteswap_uint64(MaxDataSize); + + File index = storage_.addData(fmtstring("%02x%08x.idx", indexCount_ - 1, 1)); + index.write32(sizeof(IndexHeader)); + index.write32(hashlittle(&header, sizeof header, 0)); + index.write(&header, sizeof header); + + std::sort(index_.begin(), index_.end(), [](IndexEntry const& lhs, IndexEntry const& rhs) { + return memcmp(lhs.hash, rhs.hash, sizeof(Hash)) < 0; + }); + + // pad + index.write32(0); + index.write32(0); + + uint32 blockPos = index.tell(); + uint32 blockSize = 0; + uint32 blockHash = 0; + index.write32(blockSize); + index.write32(blockHash); + for (IndexEntry const& entry : index_) { + WriteIndexEntry write; + memcpy(write.hash, entry.hash, sizeof(write.hash)); + *(uint32*) (write.pos + 1) = _byteswap_ulong(entry.offset); + write.pos[0] = entry.index / 4; + write.pos[1] |= ((entry.index & 3) << 6); + write.size = entry.size; + + index.write(&write, sizeof write); + blockSize += sizeof(write); + blockHash = hashlittle(&write, sizeof write, blockHash); + } + + while (index.tell() & 3) { + index.write8(0); + } + while (index.tell() < 0xA0000) { + index.write32(0); + } + + index.seek(blockPos, SEEK_SET); + index.write32(blockSize); + index.write32(blockHash); + + index_.clear(); + } + +} diff --git a/src/ngdp.h b/src/ngdp.h new file mode 100644 index 0000000..a439bfd --- /dev/null +++ b/src/ngdp.h @@ -0,0 +1,182 @@ +#pragma once +#include "base/common.h" +#include "base/json.h" +#include "base/file.h" +#include + +namespace NGDP { + + extern const std::string HOST; + + extern const std::map ProgramCodes; + + typedef uint8 Hash[16]; + void from_string(Hash hash, std::string const& str); + std::string to_string(const Hash hash); + + struct Hash_container { + Hash _; + struct hash { + size_t operator()(Hash_container const& hash) const { + return *reinterpret_cast(hash._); + } + }; + struct equal { + bool operator()(Hash_container const& lhs, Hash_container const& rhs) const { + return !memcmp(lhs._, rhs._, sizeof(Hash)); + } + }; + static Hash_container const& from(const Hash hash) { + return *reinterpret_cast(hash); + } + }; + + struct CdnData { + std::string path; + std::vector hosts; + }; + struct VersionData { + std::string build; + std::string cdn; + uint32 id; + std::string version; + }; + + class NGDP { + public: + NGDP(std::string const& app); + + std::string const& program() const { + return program_; + } + std::string const& region() const { + return region_; + } + + std::vector regions() const { + return regions_; + } + bool setRegion(std::string const& region); + + VersionData const* version() const { + return getptr(versions_, region_); + } + + CdnData const* cdn() const { + return getptr(cdns_, region_); + } + + std::string geturl(std::string const& hash, std::string const& type = "config", bool index = false) const; + File load(std::string const& hash, std::string const& type = "config", bool index = false) const; + File load(const Hash hash, std::string const& type = "config", bool index = false) const { + return load(to_string(hash), type, index); + } + + private: + std::string program_; + std::string region_; + std::map cdns_; + std::map versions_; + std::vector regions_; + std::string base_; + }; + + File DecodeBLTE(File& blte, uint32 usize = 0); + typedef std::map ConfigFile; + ConfigFile ParseConfig(File& file); + + class Encoding { + public: + Encoding(File& file); + +#pragma pack(push, 1) + struct EncodingEntry { + uint16 keyCount; + uint32 usize; + Hash hash; + Hash keys[1]; + }; + struct LayoutEntry { + Hash key; + uint32 stringIndex; + uint8 unk; + uint32 csize; + }; +#pragma pack(pop) + + EncodingEntry const* getEncoding(const Hash hash) const; + LayoutEntry const* getLayout(const Hash key) const; + + char const* const& layout(uint32 index) const { + return layouts_[index]; + } + char const* const& layout() const { + return layout_; + } + + private: + std::vector data_; + struct EncodingHeader { + Hash hash; + std::vector entries; + }; + struct LayoutHeader { + Hash key; + std::vector entries; + }; + std::vector encodingTable_; + std::vector layoutTable_; + std::vector layouts_; + char* layout_; + }; + + class CascStorage { + public: + CascStorage(std::string const& root); + + File& addConfig(std::string const& hash, File& file); + File& addIndex(std::string const& hash, File& file); + File addData(std::string const& name); + + static File& addCache(std::string const& name, File& file); + static File addCache(std::string const& name); + static File getCache(std::string const& name); + + private: + std::string root_; + }; + + class DataStorage { + public: + DataStorage(CascStorage& storage); + ~DataStorage() { + finish(); + } + + File& addFile(const Hash hash, File& file); // <- original (compressed) file + + void finish() { + writeIndex(); + } + + private: + enum { + MaxIndexEntries = (0x8E000 - 0x28) / 18, + MaxDataSize = 0x40000000, + }; + CascStorage& storage_; + struct IndexEntry { + Hash hash; + uint32 size; + uint16 index; + uint32 offset; + }; + std::vector index_; + File data_; + uint32 indexCount_; + uint32 dataCount_; + + void writeIndex(); + }; + +} diff --git a/src/pages/build.cpp b/src/pages/build.cpp new file mode 100644 index 0000000..4d4fe99 --- /dev/null +++ b/src/pages/build.cpp @@ -0,0 +1,119 @@ +#include "build.h" +#include "ngdp.h" +#include "app.h" +#include "program.h" +#include "tags.h" + +enum { + ID_BUILD = 1000, +}; + +BuildPage::BuildPage(Wizard* wizard) + : Page(wizard) +{ + build_ = new ComboFrame(this, ID_BUILD); + build_->addString("Loading CDN config...", -1); + build_->setCurSel(0); + build_->setPoint(PT_TOPLEFT, 120, 0); + build_->setPoint(PT_RIGHT, 0, 0); + build_->disable(); + ComboBox_SetCueBannerText(build_->getHandle(), L"Select one"); + StaticFrame::addTip(build_, "Select build"); + + tags_ = new EditFrame(this, 0, ES_AUTOHSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY); + tags_->setPoint(PT_TOP, build_, PT_BOTTOM, 0, 6); + tags_->setPoint(PT_LEFT, 0, 0); + tags_->setPoint(PT_BOTTOMRIGHT, 0, 0); + tags_->hide(); +} + +void BuildPage::init() { + wizard_->enableNext(false); + + auto& data = wizard_->app()->data(); + auto ngdp = data.ngdp(); + if (ngdp && ngdp->version() && ngdp->version()->cdn == data.builds_loaded && data.builds.size() == data.build_configs.size()) { + build_->reset(); + for (std::string const& build : data.builds) { + std::string name = data.build_configs[build]["build-name"]; + if (build == ngdp->version()->build) { + name += " (current)"; + } + build_->addString(name); + if (build == data.selected_build) { + build_->setCurSel(build_->getCount() - 1); + } + } + build_->enable(); + onMessage(WM_COMMAND, MAKELONG(ID_BUILD, CBN_SELCHANGE), 0); + } else { + wizard_->app()->data().loadBuilds(); + } +} + +LRESULT BuildPage::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + auto& data = wizard_->app()->data(); + switch (message) { + case WM_COMMAND: + if (LOWORD(wParam) == ID_BUILD && HIWORD(wParam) == CBN_SELCHANGE) { + int index = build_->getCurSel(); + if (index >= 0 && index < data.builds.size() && data.build_configs.count(data.builds[index])) { + static const std::string skipTags = "download|encoding|encoding-size|install|patch|patch-config|root"; + std::string text; + auto const& build = data.build_configs[data.builds[index]]; + data.selected_build = data.builds[index]; + for (auto& kv : build) { + if (skipTags.find(kv.first) != std::string::npos) continue; + text.append(kv.first); + text.append(" = "); + text.append(kv.second); + text.append("\r\n"); + } + tags_->setText(text); + tags_->show(); + wizard_->enableNext(true); + } else { + data.selected_build.clear(); + tags_->hide(); + wizard_->enableNext(false); + } + } + return 0; + case WM_TASKDONE: + if (lParam == -1) { + build_->reset(); + build_->addString("Failed to load CDN config", -1); + build_->setCurSel(0); + build_->disable(); + } else if (lParam == 0) { + build_->reset(); + for (std::string const& build : data.builds) { + build_->addString("Loading...", -1); + } + build_->enable(); + } else if (lParam != ProgramData::LOADING) { + build_->delString(lParam - 1); + std::string build = data.builds[lParam - 1]; + std::string name = data.build_configs[build]["build-name"]; + if (build == data.ngdp()->version()->build) { + name += " (current)"; + } + SendMessage(build_->getHandle(), CB_INSERTSTRING, lParam - 1, (LPARAM) name.c_str()); + } + return 0; + default: + return M_UNHANDLED; + } +} + +Page* BuildPage::getPrev() { + return new ProgramPage(wizard_); +} +Page* BuildPage::getNext() { + auto& data = wizard_->app()->data(); + if (data.build_configs.count(data.selected_build)) { + return new TagsPage(wizard_); + } else { + return nullptr; + } +} diff --git a/src/pages/build.h b/src/pages/build.h new file mode 100644 index 0000000..e1be5bc --- /dev/null +++ b/src/pages/build.h @@ -0,0 +1,19 @@ +#pragma once + +#include "wizard.h" + +class BuildPage : public Page { +public: + BuildPage(Wizard* wizard); + + bool hasPrev() const { return true; } + Page* getPrev(); + bool hasNext() const { return true; } + Page* getNext(); + +private: + ComboFrame* build_; + EditFrame* tags_; + void init(); + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +}; diff --git a/src/pages/download.cpp b/src/pages/download.cpp new file mode 100644 index 0000000..b3d2ae4 --- /dev/null +++ b/src/pages/download.cpp @@ -0,0 +1,178 @@ +#include "download.h" +#include "ngdp.h" +#include "app.h" +#include "tags.h" +#include "frameui/fontsys.h" +#include +#include + +enum { + ID_BROWSE = 1000, + ID_START = 1001, +}; + +DownloadPage::DownloadPage(Wizard* wizard) + : Page(wizard) + , logRead_(0) +{ + StaticFrame* tip = new StaticFrame("Download location:", this); + tip->setPoint(PT_TOPLEFT, 0, 0); + + browse_ = new ButtonFrame("Browse", this, ID_BROWSE); + browse_->setPoint(PT_TOP, tip, PT_BOTTOM, 0, 5); + browse_->setPoint(PT_RIGHT, 0, 0); + browse_->setSize(80, 21); + + path_ = new EditFrame(this); + path_->setPoint(PT_TOPLEFT, tip, PT_BOTTOMLEFT, 0, 5); + path_->setPoint(PT_BOTTOMRIGHT, browse_, PT_BOTTOMLEFT, -8, 0); + path_->setText(path::root()); + + note_ = new StaticFrame("", this); + note_->setPoint(PT_TOPLEFT, path_, PT_BOTTOMLEFT, 0, 8); + + loading_ = new ProgressFrame(this); + loading_->setPoint(PT_BOTTOMLEFT, 0, 0); + loading_->setPoint(PT_BOTTOMRIGHT, 0, 0); + loading_->setHeight(21); + + files_ = new StaticFrame("X", this); + files_->setPoint(PT_BOTTOMLEFT, loading_, PT_TOPLEFT, 0, -6); + files_->setPoint(PT_RIGHT, 0, 0); + + size_ = new StaticFrame("X", this); + size_->setPoint(PT_BOTTOMLEFT, files_, PT_TOPLEFT, 0, 0); + size_->setPoint(PT_RIGHT, 0, 0); + + files_->setText(""); + size_->setText(""); + + log_ = new EditFrame(this, 0, ES_AUTOHSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY); + log_->setPoint(PT_TOPLEFT, path_, PT_BOTTOMLEFT, 0, 8); + log_->setPoint(PT_BOTTOMRIGHT, size_, PT_TOPRIGHT, 0, -8); + + log_->hide(); + loading_->hide(); + size_->hide(); + files_->hide(); + + start_ = new ButtonFrame("Start", this, ID_START); + start_->setPoint(PT_TOPRIGHT, this, PT_BOTTOMRIGHT, 0, 5); + start_->setSize(100, 21); + + note_->setText("Estimated size: " + formatSize(wizard_->app()->data().downloadSize())); +} + +bool browseForFolder(std::wstring prompt, std::wstring& result) { + IFileDialog* pfd; + if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd)))) { + return false; + } + DWORD dwOptions; + if (SUCCEEDED(pfd->GetOptions(&dwOptions))) { + pfd->SetOptions(dwOptions | FOS_PICKFOLDERS); + } + pfd->SetTitle(prompt.c_str()); + if (FAILED(pfd->Show(NULL))) { + pfd->Release(); + return false; + } + IShellItem* psi; + if (FAILED(pfd->GetResult(&psi))) { + pfd->Release(); + return false; + } + wchar_t* str; + if (FAILED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &str)) || !str) { + psi->Release(); + pfd->Release(); + return false; + } + result = str; + psi->Release(); + pfd->Release(); + return true; +} + +LRESULT DownloadPage::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + auto& data = wizard_->app()->data(); + switch (message) { + case WM_COMMAND: + if (LOWORD(wParam) == ID_BROWSE && HIWORD(wParam) == BN_CLICKED) { + std::wstring path; + if (browseForFolder(L"Select download location", path)) { + SetWindowTextW(path_->getHandle(), path.c_str()); + } + } else if (LOWORD(wParam) == ID_START && HIWORD(wParam) == BN_CLICKED) { + if (data.progress()) { + data.stopDownload(); + start_->setText("Start"); + wizard_->enablePrev(true); + log_->hide(); + loading_->hide(); + size_->hide(); + files_->hide(); + note_->show(); + path_->enable(); + browse_->enable(); + } else { + logRead_ = 0; + logText_ = ""; + data.download(path_->getText()); + start_->setText("Cancel"); + wizard_->enablePrev(false); + log_->show(); + log_->setText(""); + loading_->hide(); + size_->show(); + size_->setText(""); + files_->show(); + files_->setText(""); + note_->hide(); + path_->disable(); + browse_->disable(); + } + } + return 0; + case WM_TASKDONE: + update(lParam == ProgramData::LOADING); + if (lParam == 1) { + loading_->hide(); + start_->setText("Done"); + start_->enable(false); + wizard_->enablePrev(true); + } + return 0; + default: + return M_UNHANDLED; + } +} + +void DownloadPage::update(bool loading) { + auto progress = wizard_->app()->data().progress(); + if (!progress) return; + if (progress->log.size() > logRead_) { + while (progress->log.size() > logRead_) { + if (!logText_.empty()) logText_.append("\r\n"); + logText_.append(progress->log[logRead_++]); + } + log_->setText(logText_); + } + uint64 sizeDone = progress->sizeDone; + if (loading) sizeDone += wizard_->app()->data().loading_progress; + files_->setText(fmtstring("Files: %u/%u", progress->filesDone, progress->filesTotal)); + size_->setText(fmtstring("Downloaded: %s/%s", formatSize(sizeDone).c_str(), formatSize(progress->sizeTotal).c_str())); + size_->show(progress->sizeTotal != 0); + if (progress->sizeTotal) { + loading_->setRange(0, progress->sizeTotal / 1024); + loading_->setPos(sizeDone / 1024); + } else { + loading_->setRange(0, progress->filesTotal); + loading_->setPos(progress->filesDone); + } + loading_->show(); +} + +Page* DownloadPage::getPrev() { + return new TagsPage(wizard_); +} diff --git a/src/pages/download.h b/src/pages/download.h new file mode 100644 index 0000000..e6f984c --- /dev/null +++ b/src/pages/download.h @@ -0,0 +1,28 @@ +#pragma once + +#include "wizard.h" + +class DownloadPage : public Page { +public: + DownloadPage(Wizard* wizard); + + bool hasPrev() const { return true; } + Page* getPrev(); + +private: + EditFrame* path_; + ButtonFrame* start_; + ButtonFrame* browse_; + + StaticFrame* note_; + + EditFrame* log_; + StaticFrame* files_; + StaticFrame* size_; + ProgressFrame* loading_; + size_t logRead_; + std::string logText_; + + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); + void update(bool loading); +}; diff --git a/src/pages/program.cpp b/src/pages/program.cpp new file mode 100644 index 0000000..1ca7064 --- /dev/null +++ b/src/pages/program.cpp @@ -0,0 +1,115 @@ +#include "program.h" +#include "ngdp.h" +#include "app.h" +#include "build.h" + +enum { + ID_PROGRAM = 1000, + ID_REGION = 1001, + ID_LINK = 1002, +}; + +ProgramPage::ProgramPage(Wizard* wizard) + : Page(wizard) +{ + StaticFrame* tip = new StaticFrame("Welcome to BlizzGet", this); + tip->setPoint(PT_TOPLEFT, 0, 0); + StaticFrame* tip2 = new StaticFrame("This tool can download any Blizzard game from CDN", this); + tip2->setPoint(PT_TOPLEFT, tip, PT_BOTTOMLEFT, 0, 0); + tip = new StaticFrame("For bugs and suggestions, go to", this); + tip->setPoint(PT_TOPLEFT, tip2, PT_BOTTOMLEFT, 0, 0); + LinkFrame* link = new LinkFrame("https://github.com/d07RiV/blizzget", this, ID_LINK); + link->setPoint(PT_TOPLEFT, tip, PT_BOTTOMLEFT, 0, 0); + + program_ = new ComboFrame(this, ID_PROGRAM); + for (auto const& kv : NGDP::ProgramCodes) { + programs_.push_back(kv.first); + program_->addString(kv.first + " - " + kv.second); + } + program_->setPoint(PT_TOPLEFT, link, PT_BOTTOMLEFT, 120, 16); + program_->setPoint(PT_RIGHT, 0, 0); + ComboBox_SetCueBannerText(program_->getHandle(), L"Select one"); + StaticFrame::addTip(program_, "Program code:"); + + region_ = new ComboFrame(this, ID_REGION); + region_->setPoint(PT_TOPLEFT, program_, PT_BOTTOMLEFT, 0, 8); + region_->setPoint(PT_RIGHT, 0, 0); + region_->addString("Select program first"); + region_->setCurSel(0); + region_->disable(); + ComboBox_SetCueBannerText(region_->getHandle(), L"Select region"); + StaticFrame::addTip(region_, "Region:"); +} +void ProgramPage::init() { + wizard_->enableNext(false); + auto ngdp = wizard_->app()->data().ngdp(); + if (ngdp) { + auto it = std::find(programs_.begin(), programs_.end(), ngdp->program()); + if (it == programs_.end()) return; + program_->setCurSel(it - programs_.begin()); + regions_ = wizard_->app()->data().ngdp()->regions(); + region_->reset(); + for (std::string const& r : regions_) { + region_->addString(r); + } + it = std::find(regions_.begin(), regions_.end(), ngdp->region()); + region_->setCurSel(it == regions_.end() ? -1 : it - regions_.begin()); + region_->enable(); + wizard_->enableNext(ngdp->version()); + } +} + +LRESULT ProgramPage::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_COMMAND: + if (LOWORD(wParam) == ID_PROGRAM && HIWORD(wParam) == CBN_SELCHANGE) { + int index = program_->getCurSel(); + region_->reset(); + region_->addString("Loading..."); + region_->setCurSel(0); + region_->disable(); + wizard_->app()->data().setProgram(index >= 0 && index < programs_.size() ? programs_[index] : ""); + wizard_->enableNext(false); + } else if (LOWORD(wParam) == ID_REGION && HIWORD(wParam) == CBN_SELCHANGE) { + int index = region_->getCurSel(); + auto ngdp = wizard_->app()->data().ngdp(); + if (ngdp && index >= 0 && index < regions_.size()) { + wizard_->enableNext(ngdp->setRegion(regions_[index])); + } else { + wizard_->enableNext(false); + } + } else if (LOWORD(wParam) == ID_LINK && HIWORD(wParam) == BN_CLICKED) { + ShellExecute(NULL, "open", "https://github.com/d07RiV/blizzget", NULL, NULL, SW_SHOWNORMAL); + } + return 0; + case WM_TASKDONE: + if (lParam == ProgramData::LOADING) return 0; + if (!wizard_->app()->data().ngdp()) { + region_->reset(); + region_->addString("Failed to load region list"); + region_->setCurSel(0); + region_->disable(); + return 0; + } + regions_ = wizard_->app()->data().ngdp()->regions(); + region_->reset(); + for (std::string const& r : regions_) { + region_->addString(r); + } + region_->setCurSel(0); + wizard_->enableNext(wizard_->app()->data().ngdp()->setRegion(regions_[0])); + region_->enable(); + return 0; + default: + return M_UNHANDLED; + } +} + +Page* ProgramPage::getNext() { + auto ngdp = wizard_->app()->data().ngdp(); + if (ngdp && ngdp->version()) { + return new BuildPage(wizard_); + } else { + return nullptr; + } +} diff --git a/src/pages/program.h b/src/pages/program.h new file mode 100644 index 0000000..3f08b7c --- /dev/null +++ b/src/pages/program.h @@ -0,0 +1,20 @@ +#pragma once + +#include "wizard.h" + +class ProgramPage : public Page { +public: + ProgramPage(Wizard* wizard); + + bool hasNext() const { return true; } + Page* getNext(); + +private: + ComboFrame* program_; + ComboFrame* region_; + void init(); + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); + + std::vector programs_; + std::vector regions_; +}; diff --git a/src/pages/tags.cpp b/src/pages/tags.cpp new file mode 100644 index 0000000..0ec89bf --- /dev/null +++ b/src/pages/tags.cpp @@ -0,0 +1,153 @@ +#include "tags.h" +#include "ngdp.h" +#include "app.h" +#include "build.h" +#include "download.h" +#include "frameui/fontsys.h" +#include + +enum { + ID_ADD = 1000, + ID_REMOVE = 1001, +}; + +TagsPage::TagsPage(Wizard* wizard) + : Page(wizard) + , tags_(nullptr) + , remove_(nullptr) +{ + note_ = new StaticFrame("Fetching encoding table...", this); + note_->setPoint(PT_TOPLEFT, 32, 0); + loading_ = new ProgressFrame(this); + loading_->setPoint(PT_TOPLEFT, note_, PT_BOTTOMLEFT, 0, 8); + loading_->setPoint(PT_RIGHT, -32, 0); + loading_->setHeight(21); + loading_->hide(); +} + +void TagsPage::init() { + wizard_->enableNext(false); + wizard_->app()->data().loadTags(); +} + +void TagsPage::addTags(int index, std::string str) { + auto& data = wizard_->app()->data(); + if (index >= options_.size()) { + tags_->addItem(str); + data.used_tags.push_back(str); + } else { + if (index) str.push_back(' '); + int sel = options_[index]->getCurSel(); + if (sel >= 0) sel = options_[index]->getItemData(sel); + if (sel < 0) { + for (auto const& tag : data.tags[index]) { + addTags(index + 1, str + tag); + } + } else { + addTags(index + 1, str + data.tags[index][sel]); + } + } +} + +LRESULT TagsPage::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + auto& data = wizard_->app()->data(); + switch (message) { + case WM_NOTIFY: + if (((NMHDR*) lParam)->code == LVN_ITEMCHANGED) { + int sel = tags_->getCurSel(); + remove_->enable(sel >= 0); + } + return 0; + case WM_COMMAND: + if (LOWORD(wParam) == ID_ADD && HIWORD(wParam) == BN_CLICKED) { + addTags(0, ""); + size_->setText("Total size: " + formatSize(data.downloadSize())); + } else if (LOWORD(wParam) == ID_REMOVE && HIWORD(wParam) == BN_CLICKED) { + int pos; + while ((pos = tags_->getCurSel()) >= 0) { + ListView_DeleteItem(tags_->getHandle(), pos); + data.used_tags.erase(data.used_tags.begin() + pos); + } + size_->setText("Total size: " + formatSize(data.downloadSize())); + } + return 0; + case WM_TASKDONE: + if (lParam == -1) { + loading_->hide(); + note_->setText("Failed to load build tags"); + } else if (lParam == ProgramData::LOADING + 0 || lParam == ProgramData::LOADING + 1) { + if (lParam == ProgramData::LOADING + 0) { + note_->setText("Fetching encoding table..."); + } else { + note_->setText("Fetching download list..."); + } + loading_->setRange(0, data.loading_size); + loading_->setPos(data.loading_progress); + loading_->show(data.loading_progress < data.loading_size); + } else { + loading_->hide(); + note_->setText("Select build tags:"); + int curWidth = 1000; + Frame* prevBox = note_; + Frame* prevLine = note_; + for (auto const& tags : data.tags) { + int maxWidth = std::max(60, FontSys::getTextSize(FontSys::getSysFont(), "Any").cx); + ComboFrame* box = new ComboFrame(this); + options_.push_back(box); + if (tags.size() > 1) { + box->addString("Any", -1); + } + for (size_t i = 0; i < tags.size(); ++i) { + box->addString(tags[i], i); + maxWidth = std::max(maxWidth, FontSys::getTextSize(FontSys::getSysFont(), tags[i]).cx); + } + box->setCurSel(0); + box->setWidth(maxWidth + 20); + if (curWidth + maxWidth + 28 > 300) { + box->setPoint(PT_TOPLEFT, prevLine, PT_BOTTOMLEFT, 0, 8); + prevLine = box; + curWidth = maxWidth + 20; + } else { + box->setPoint(PT_BOTTOMLEFT, prevBox, PT_BOTTOMRIGHT, 8, 0); + curWidth += maxWidth + 28; + } + prevBox = box; + } + + ButtonFrame* btn = new ButtonFrame("+", this, ID_ADD); + btn->setSize(21, 21); + btn->setPoint(PT_TOPRIGHT, note_, PT_BOTTOMLEFT, -8, 8); + + size_ = new StaticFrame("Total size", this); + size_->setPoint(PT_LEFT, note_, PT_LEFT, 0, 0); + size_->setPoint(PT_BOTTOMRIGHT, 0, 0); + + tags_ = new ListFrame(this); + tags_->setPoint(PT_TOPLEFT, prevLine, PT_BOTTOMLEFT, 0, 8); + tags_->setPoint(PT_BOTTOMRIGHT, size_, PT_TOPRIGHT, 0, -8); + + remove_ = new ButtonFrame("-", this, ID_REMOVE); + remove_->setSize(21, 21); + remove_->setPoint(PT_TOPRIGHT, tags_, PT_TOPLEFT, -8, 0); + remove_->disable(); + + if (data.used_tags.size()) { + for (std::string const& tag : data.used_tags) { + tags_->addItem(tag); + } + } + size_->setText("Total size: " + formatSize(data.downloadSize())); + wizard_->enableNext(true); + } + return 0; + default: + return M_UNHANDLED; + } +} + +Page* TagsPage::getPrev() { + return new BuildPage(wizard_); +} +Page* TagsPage::getNext() { + return new DownloadPage(wizard_); +} diff --git a/src/pages/tags.h b/src/pages/tags.h new file mode 100644 index 0000000..f6d6d24 --- /dev/null +++ b/src/pages/tags.h @@ -0,0 +1,25 @@ +#pragma once + +#include "wizard.h" +#include "frameui/listctrl.h" + +class TagsPage : public Page { +public: + TagsPage(Wizard* wizard); + + bool hasPrev() const { return true; } + Page* getPrev(); + bool hasNext() const { return true; } + Page* getNext(); + +private: + StaticFrame* note_; + StaticFrame* size_; + ProgressFrame* loading_; + void addTags(int index, std::string str); + ButtonFrame* remove_; + std::vector options_; + ListFrame* tags_; + void init(); + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +}; diff --git a/src/wizard.cpp b/src/wizard.cpp new file mode 100644 index 0000000..ac71631 --- /dev/null +++ b/src/wizard.cpp @@ -0,0 +1,80 @@ +#include "wizard.h" +#include "app.h" + +#include "resource.h" + +enum { + ID_BUTTON_PREV = 7000, + ID_BUTTON_NEXT = 7001, +}; + +Wizard::Wizard(Application* app) + : app_(app) + , page_(nullptr) + , buttonPrev_(nullptr) + , buttonNext_(nullptr) + , hIcon(LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BATTLE_130))) +{ + if (WNDCLASSEX* wcx = createclass("MainWndClass")) { + wcx->hbrBackground = HBRUSH(COLOR_BTNFACE + 1); + wcx->hCursor = LoadCursor(NULL, IDC_ARROW); + wcx->hIcon = hIcon; + RegisterClassEx(wcx); + } + create(CW_USEDEFAULT, 0, 400, 500, "Blizzard Downloader", + (WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX)) | WS_CLIPCHILDREN, WS_EX_CONTROLPARENT); + + buttonPrev_ = new ButtonFrame("Back", this, ID_BUTTON_PREV); + buttonPrev_->setSize(100, 21); + buttonPrev_->setPoint(PT_BOTTOMLEFT, 10, -10); + buttonPrev_->hide(); + buttonNext_ = new ButtonFrame("Next", this, ID_BUTTON_NEXT); + buttonNext_->setSize(100, 21); + buttonNext_->setPoint(PT_BOTTOMRIGHT, -10, -10); + buttonNext_->hide(); + + showWindow(); +} + +void Wizard::setPage(Page* page) { + app_->data().stop(); + delete page_; + page_ = page; + page->setPoint(PT_TOPLEFT, 10, 10); + page->setPoint(PT_BOTTOMRIGHT, buttonNext_, PT_TOPRIGHT, 0, -5); + buttonPrev_->enable(true); + buttonNext_->enable(true); + buttonPrev_->show(page->hasPrev()); + buttonNext_->show(page->hasNext()); + page->show(); + page->init(); +} + +LRESULT Wizard::onMessage(uint32 message, WPARAM wParam, LPARAM lParam) { + switch (message) { + case WM_COMMAND: + if (LOWORD(wParam) == ID_BUTTON_PREV && HIWORD(wParam) == BN_CLICKED) { + if (page_ && page_->hasPrev()) { + Page* page = page_->getPrev(); + if (page) setPage(page); + } + } else if (LOWORD(wParam) == ID_BUTTON_NEXT && HIWORD(wParam) == BN_CLICKED) { + if (page_ && page_->hasNext()) { + Page* page = page_->getNext(); + if (page) setPage(page); + } + } + return 0; + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_TASKDONE: + if (page_ == (Page*) wParam) { + page_->onMessage(WM_TASKDONE, 0, lParam); + } + return 0; + default: + return M_UNHANDLED; + } + return 0; +} diff --git a/src/wizard.h b/src/wizard.h new file mode 100644 index 0000000..aaf9b9b --- /dev/null +++ b/src/wizard.h @@ -0,0 +1,55 @@ +#pragma once + +#include "frameui/framewnd.h" +#include "frameui/controlframes.h" + +class Application; +class Page; + +class Wizard : public RootWindow { +public: + Wizard(Application* app); + + Page* page() { + return page_; + } + void setPage(Page* page); + + void enablePrev(bool enable) { + buttonPrev_->enable(enable); + } + void enableNext(bool enable) { + buttonNext_->enable(enable); + } + + Application* app() const { + return app_; + } + +private: + HICON hIcon; + Application* app_; + Page* page_; + ButtonFrame* buttonPrev_; + ButtonFrame* buttonNext_; + LRESULT onMessage(uint32 message, WPARAM wParam, LPARAM lParam); +}; + +class Page : public Frame { +public: + Page(Wizard* wizard) + : Frame(wizard) + , wizard_(wizard) + { + hide(); + } + + virtual void init() {} + virtual bool hasNext() const { return false; } + virtual bool hasPrev() const { return false; } + virtual Page* getNext() { return nullptr; } + virtual Page* getPrev() { return nullptr; } + +protected: + Wizard* wizard_; +}; diff --git a/vc13/Battle_130.ico b/vc13/Battle_130.ico new file mode 100644 index 0000000000000000000000000000000000000000..c537310389f7cdccce3d382d3c5522daeb0b482d GIT binary patch literal 95399 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

    !1OXlYK1H0^7DGAY0U z|6IEc&~u^%?uURq;JAMf^=JJP)|tT@HJjv`fqN3WTyAIxhX?bR`|xYU8Z$3Tl`NI* znI5|M2_1CAVlxkS3bvV+?ySsX%hO+g+A}Z3o;@>`32==UND!#p@-yUq@bM47TjJ{vn()%9#1v&cj_l{f-oVp1xaT^T~_iD2~ZTmZEJim^Tv~|CNeI z$OLFy{87|K4@XPn`3s26oyE}BEjav|PvVaEy&i>$Ez;?z1x3Y)n7J76dB3VVV(g1-wW`- z8NeWS0+vL1@D*kPi0Z%$^>xIW=^Ve9Sf7j>s85!l*5|kiU)LGzi4{I*z(YNHDxXxm z$j2E^LG6^Ync&P3HsJ|B_eD6Qxgw2;pok7LsBDo8Z$HM0}ZboBz zFM`zt1my~QVg*4NLpFg$M*YV<8_je75zWeoh$9gG2hfQ~C6dxqIz~L$W)!Clwy^fr z^Tn>d!q5gWK}8bJe2xv9&F16(mkx-v$$cQ;H5Ygo@(NndWkCI~r=hXJS824@KO?n& zr5_I}tz-5Tk4ClH6wc0UrXYPuB2cU=pSgA<^0u7zk<*<1kVG4E1Bo%y(MC$azlVFDZ^0OT0}Y~0EKV2J?$vu{OR0JUx} z1Rs&I?E)jrK;TRPH@%l9K-6x~dkCoQZ-iVyN6HF=BZErA*3Wx0*0cRGgfva?$=l&= zhhgvsS77z`zd(L?QlW5KAWh0EK=RoL5NL{(fi?rpcx?_FpKvZZ&we|0?ql{PUykI0 zsY;CT90H};yHWW5r;y=s_`J-R3FZk*&{4ZlWgxIBw!8*ex%SQf$0HrX$*qW=^CmPO z@l@1#jXsf997xblc;6ZORox7mfceoeJS4k}+1Eb>yZ-!p6!?~2W+w3{Kk4wxkSA+} z-+7#5XnYnWftuYr1E}_+&q4K>Z)D_XO>DHX!7_5w&xTDC82a!9xbKHoqdYLi1badR zXz^v$kVif8kYfg-JU$>lI)!*(5>>{8+SwA~;s92d{Zm_I#s|>7_B#kF1IX~O>3mT*olVGj4}Y2C_fN0W zW>yX~1K7a8Z+8EEhX4Tik}v_5I0Il>NZ2SkV$aH^|9DfRg!~$~H{|aVNGAc5E|BLH zyXOSV*6tkfU{oLf3c2*BHDIbN%LljN@Xg44{w=8Q+9ABKZUmbz;ocNChw{EDhg2Y) zcinayZJuC~nFO8XIZQt4i3nf#ZtPlO;IOnHeFEqTCXnqLK&7#a!jC_T?C#sy1nn5u;)$Z zV(%?CGIlf}0-3T0TIWvzVz(e_%4Fsa%5BG@{;DfbjRIz-HN?^-UG@tY5I$^>jnU7) zidJPzq(E;4IrbN#BLFgsZmx_58^>x*jtx37+Uzs8^F_@6o4k^Re$(fOY%5$)fFuzy$taPhGfOABLiFD_K{(y-J?fP`9c z^^V%u(O5(CtXE=v<4H^ymXpoV3C~}Q)@~kUwDyaaqB_5ToXD(`BIy3DI$b2}MIWMU z({8&VHuiMdyz=NhxN55%j=4o`ED^F3&Kg zQYd7R+3^=dKlv|oZ@fnC^Dp#?-J$|m`DfwJuu+PMoS$)=I`!O_i^75dFaVs`#7qDI z0DKi-@4*4U)RrT#vbey*37xdyRJ>gr(7#yJ^0lx9g1Erwe~DV z|7#tR?2{f#95PDFY{)Za^Pg`O8_-Nmxn7qw&PqGly&sOM(#osoFzwV~jG()=fPSWB zhhOq9n4WkLR;Q;Cw;ML+KlctZ8?m_iCKP`Cb%Z?kexV}z%I!KHMJR$i9{Dsh&v`W( zgOdX2Ohuz!c0Sc!pg;hTlWuJD7>>W=8r<>5=Q49|1^FSKy*DqDd1Q;CTCcn%_uhM` z|Md6#0|zjsof|KEFKQ?JjY#huD<)=ypJ~HlUmx-}{uZnE?P4>sXa&rF9tpN)Z_oX% z*Bm>rd1wV&jcuqzg@UPY5@v)@^X1Vjdw%(-#RUHbM)kjm=;mKZu;NRXY^-_S0-h3` z%aT}b4xH_4cHGE&IqfX4rYoY@yqCKH831fl0Knq_77h{sCbt}k)x~+V+D*j((iVB$ z(X)2EicBK&(LFCnZ_j8}I*I6P^307`E+@4g@_4MDelF@fdkZ4>I=)wzz2`+GHWit0 z{`(sdg#|&&oKv7<5(4A=Ofz+;3FfZkLz)Ak5^aOc{}!U!8ggu;$If{rst-FCbMq_c ztgT4O%H#F3p~!Aq=&Yl7{ST47?KcRUEkWt{a#{PFe?a4;M=?cOS3VB!{`6zLMMmS9 zBFSgjd|I7DaL09s{`4b6J8zMbhs`k&v%r8Y6XvDh^YeoAuxaWxcdKy4oSACpK(h03ag)R}KaM3i;yclbeph3e!Zb76pI+3E}N2%R$Q5z7P?k-pvw1ezwbQ zH0_wUG@p13pz1vCe`t#+x$U%Tgx+=1gcSw=`5HQ(xP-w)UN~!FGH?BzfN@ICODuKnQ3Xes-;xECA3f~p}6-}WEp*o zPJRTMPk13(`Leh_lhh=!ThF7f=2>~)70Wn!OFt&R`EmT^^4Fuom_~tnsIw}KmtN}A zPG86IqQ44M;nI$j|A8^Fv=_E@H63*=_PcQUo%t+O&$|Tml@+-ODO7v>1DWQFZ)6(I zMyUScM@(zAMEt)ikp}?;Wd5Wd>j`;s0-JFT*!&mf5KnbhDkEg~m0h0)cH9Us!SC|q zFO21Z%L#iMCT zlBvqLZW3>u4CsIXfbq@}vj2H0y2ywqI@f*W7B`V|UVG>1CZ)(-?&RYTT3L}1YCOoL z%RrzmKp^I(!P+v)qoWvn`YW+^?3q|xVr+zm5A(=HCP-X!WValKaLZPJ^|f7R_sIig zjEA4Z-_zg|DtvUp>*E>2c+dt0F8}dn-2ABzh-^YRrp5SPewo8hZt1npk&b|ZV7}vw z^)uq^Xm|?o)ZxI&95S;z+zHN|mh7Io4}K)7FS#7mMq8F(cQn7G{)PTBa)104)_3ia zaS>q;L8WF)+RGPYhY_TV3w?!h1%ht{7YvBo>xF`F)MePS3tKe=Gxq{}??klgW<>k$ zMOo&1(5_+d#D^mIyBA@lIED4aCH4T=W7xb67#^0lqq8E>O({V7y_w1FedZZxhemMP zV1(A?FTt(f`Vw*j<7!7=K^E=EeUe(7q{W7Ls;lKa}_uYl1>wYV@G>4uOGiB!8KSn@y zHfEGyDxU*So|0iUxybtY@jaxCZmoWea00(6P z*%`pQ6p{5@g7p6BA_S%@y%6gMf}n zMnp!~rCcTOfyyTkFf%L^yE9u1bXy|vsMtKkX*`e5Se`+|Dg64P$VwD5)0Zu!fX;WpTFnHP&?+UNO|VHEtQpGNTeA0y}+B5?o~S1tV~0FXv0d%is0BBCcF zA^7dJc@ZlRZ#@=x;st1&@;J1a{U}y3%qdIbip^{O~8TO=g`C`9<<}v*!kw? zGp(=_`Tj8x;KO74O}Q=_V8w-*nS8v6YScf1s4|Rhc?5B>PiV9(r~CWvKsdikDFPWC zD6}6Rv1Se3VhQz&uRwL`NVHa!UnY~W>+2brU1-z9Fv9JV(OWSr&C=PLM*^Ufh13L7VxZ0+{4ZQDDKEjKSFD(4M4oixJZNEV1U%%8-Kd8 zeYL%s7af6O1J?U5$5)K70+moFD$#!#Y0d-zIW{qmNNkGP^%f`Q2c^C4`oEPO`n|)B zMalCHCKv$B?YmpV0jw-cKR^H&7!{F#Q=5*$Dzo95lmR#j-Y4aDEn1djN*508GteK> zmISrs83cMiH}Nk7a%g!9srC`4V4Vm5@XRe{3n$<(0e_#ivX`@cgXmkh7v;}iilEpp zCmgxH?yFu6aKS50(EU50-^&w222yczo!QSJI!By{&g0HQ>%>Pf!7njDSYaU6QGLDt z;k%9>z}zQt=H4?jg_)Pc(BuW3IQ zes=EQmPs7@%P-*8f4+cSw<6k*LlyNHQ#!nH`p+?WHZKLF&xTgUaMFO$8+4Xr-Fydp>;wQX6JT!dy$S#x zC<9;sAe?|(kH+e<0)Sl3dboAZm2}8BW~&|@ogdhk0bM81xAXny7pm(}{7XD*{u58! z_?Yvs{@}CFT%2=keAfgB93fXb62j_$2bzeIM}?j2;ylU%>;x;wJ~ia0$qFupAmdLfwiE+-U|f-Q>Tx;*u8BU zETQ|WA7cM?ze9$H%retLG@}BLB4N{W&BudlVwGnAGOr(BjbPd_%f>jfJdG?9`atY4 z=m_u{FiuqU9}vb$byLB}G}j zdt8$HQ?r0#m%Hq(WzQZ<)&Nv-P-z0p?7ds80<0|VJ2(K?xRoyhE{SD8kr622-A|$S znlkHd^>E_2B^=!$aeyXBo+}UTiWPwRGv9!<(ZkVMU++!#(?CJTYO{$~F6L0a`oqZG zd@bVgfN<_uMn+O!X48>qpZpkfPJJ9&Q`^zvegK}is1qgo zX+EcXpAdYwTX|y$&-G?T*w$~m6$>}t2rTXw8+rKhgltN}ta$jsR+dkK>2rjP8fR+D z2v?Z4XMX{s+B}GdmlEKqO+=MtH4Y-GO@y;@&EFQF(751IR8Rg}G*^i5>tG+Pb<6!Y zX*7e{#b;t4Ps27m=FXD{GP*j7Q^q)D30c35GShu3sv!C~$o@W5iT|O7iW*!PWwGI3C-Gx^DkO1Il z1^|l;09tZc#G2|>Q~M+0&>*5k9T7=*3Ka9{RXEEBnm{Dq6jUnYQNH#nWPkTvguFT~55?udL7_4s68Yysm|c*OLT$e0&24&Kj-2nF zoZ5=+5htU4>SNK~dIF>Q6}~^4b-k`8H`VSQ-9KRXZr~lK$0$IhQo>ZLis>6}KyAGy zZ1&vlJCNfPJ(m@L#C<10i#x;WjG3@w>MJ6cDp;LopjDSPve@nws1OvH*oE)>%!oB{ zwYHs6OI_lgBaw4({gl5$V_D^4Fq%KKCIB0kZCi&he8ok$<4d1JVPdmbg0$OVV={Hf z0smC3!$7!mE`@CuAs)@dz=DL)#=))l8hSzqH(fb_RRGO%Jzr zfC~h~N8oP;3dndQB@HyzHqz~?oPbkPTd@C78GtYWI0IlN0N+=g81!C(>O207(?4*A z%3?)86j;!+bq7$`B<(VqQ$6QRsMcF{{r`Z1@0kIF5rj-@<_88*Se-%s#$O=Zc$_}YA+)~os2cNoh}7hyM&D*4 zR|e^@af@^UPBs;y5Gtl4G9VskKL9f;LM8Nk`HM%iafct*I`tR7ota{P$87#ZSzU-y zeiQ1O#mLrC9QotV;?_%Fh0Ms5sJ<*K31#Fw&{|V=R80^)K)#k$z#K`{@6}(DEL3ON zb<%`^B$U;nv;0%UBWkA@eREB-$pFKl!p3iNxy7{}BL8 zG5}boCIDiBl0HN4Wi!h!t>}lY{U2!hFyAq485YYT?NpYp2d~VC;FfT94>HXDE6`fxzOC&G>%zw_tO*M}{|Eb4dNin$$okEy{@)wqQ{ZdY!e`^R6%!wXq{f+y42m&9EunUVDatIW2Q!;rX#T%PYk5Jnq3M2T z0e~+>PLAQ^UBAO!uRaS+xZhajy%IOUcAMT{h>&834>35&-0ir%!D= z8fydq(v9+fjQN3>0Wqt|cfFcSOaXH59Hpb`DmssPI@ZoOAC1LXbxe=s3^W=pA^1R& z5wHoylV5OQ;XyL_oJ>B!_Z@J0uToVphii9L<)#}EDlF>=gsdMWW@G37`*K7#{z@#XL5WYO zsIly(^w4vkKp4t>09?!KHEp>a*ggin&L5SEs9pGORF8a^NWSXC_h*Rh&)XUq!)fsh zW?uFfEKJX!G&;d7tcnQ14xnTHW5cq8#H6Q_Bqjk7Mq+Ody8n`e?ubMont z^?wU{{YC|jhT3LKg&G;oNp40Qqh~B>$JBZEu46u{#{FD;X?8w6UVq1cY3rtb9ChQ* zaqH{P$Iuy1z{+#pjeU3Bt+pB~3eU7bzHbPXy*DEK%H;@{Ng`}s9{#MBNsS{+M9N89 zojVGHfJCv8$HN_i-M(SeU;0k0A90Epe=(8i8b1+!^bg>q;VfF0oP}N2{tCshjVk=O z#119n=?hTGOH*lmhA##dH)6un6Xj9eGyNq+e7$bZEaG%kU!cB<`ni{2ZPQ8U@Y-!OGYb_Q9Rm<*p{Ckc{T|ZKDd6Gf ze1j*H4uHTrh6uiHBjMol`c1Fp2);Zf92~-fM=~gW`F*(MqnD$}?ET6>9}fTEH}U7? zyvRQwONqtO&Sy-e(pN&?H$K2jnmvd`agtE224svwOg~ux($vl~kA_zmT19taBh&ov zLUoF#U01mm=$?Mf0yvm3GwG;JB~;%3O5FLi&!RBCMbz};!Y{&a^?fH&hLd?-VCkR$pnUp!@AuPOJ@YL$|ixgZ2{*+shP4H5Di`08+uhPZF6{Wha#dz`YjIt_}Bh)8`CE zHV)yWwY`{s&nt1yH9tgda8#Hod?V4;C!T}lXI+ZvyYG`Btcn4k%c~y`Vesy2QT*vw z5LWtyGt({9X@}i$eraLs%31@R?Z>0~l6RreKZYi+bOa*!nT!QYe($*=Hg4_1=Fh(u zw_I@zoz@CLMU3I3fM~q}bVGeXxkk47TT_ zx&ZvrUA@d0+K(Qf1Eg>mf4_!$XmaPmkH z5?WoqPZNA!!0EMm(tT<=kTKHZ($|mUrV5z2<|^Fz{x@Qg+5E+!QJGUNn?clSBW$kW z@b`WRf2j|lBPt1L0Eoq!eP2Gnz&HO583vfK&VOL$VIVf}m>rlxc}fZ3%bQ|9|7mBU z`rJ3678XTuRPjKK@DtiEKIbvEwI4_R=!>}Z(wB=}hlR?ZC?PJ&%;^e7i6`vINMfG! z@`RIniS??0zmX|^qx*LSD`g!lb&fD)&8(CD8ANzk{co0K>`aX((_>qW6 zw9f_JQmo=}B7JuQF&p33-=B~5r@R97rb6S1AtKr0AUZIrBpsq z!#(V=B9J1uX-jpz?0f?de?{w420_P^|I2LUBgTu^^2Z4#jcDr{g(A#1V#nvv7dJ3)^+$vwl_uRtIIj6fvoVe` zIW(Vn5!N2@RM!5w+N%&G*Z9p}7UjtSoVMrBxbxL#W4+!M1x&My`tw|P!tRfQ6piQ; z=~R_zCp=Xc&S|mRoO$co%|?I?5YWpW$Zk zUGh91Y8gd7g71SGJpdKm;jB5p~D$)e8txY-;B)qO~1+-OupkohQDe z=cZj+wc?o!X(k4}vg-<<#y&+L|1J+;@}xKiBUKt~Vq!A`fJ0#bSq1=yaVH=%0h+SH zN}zN6^+_|UOtL?(f#b;x7*KUzrn6LHc@@27M zh_ZM2yy4PUDlo)~bf~r?biTPjwY;l+)5OwcJ+XBM^f=!AOs<>CWYR^{xuLZF25!3v ze}LoE@L~yLZ2~X`Fv%FeuG^&#VCjJZK!pJSuMD*H7_6_a$z{Ntjsx&Wnl=f{#Mk$e zP~oXVp-XWYKvY5!CypcI#WU`%&ZBwGMOZ)eEVQ}93xAF36OErL_^{_E*7IT8>SgCU zHhh}-fTV*@f6oP!^=sRBKOQuZN8z{M$B$li4mz14asz{+9F{1{r8D(rvgTU$83ZB( zw9{rRV0JGiPB?A5}Y-k z@O)JN_W7uHIwD(=x$lIh-_ri!uuZ6hI}2bwKqKUNMF`-pd)d?lrtRPhYpR7 zo&5;`sec)XVlo|!O>UG8L&RHK_AQz?cY}?^JUfgx)a#5z+$*ehQ07Wf)ZOk?afL zjuWHjeS;O8HeN#OzI(BsY_^!~ z-kRTyBVPAj+%fr3RQK*yEI^hQ&z36~Ser)w_dkt*=R)M``;0|(r?#Ma?rTvy>Y-?@ zugc_|+Og-@`}8vt{?R@>BwWSfYo3ffH~bleQC>^1Pe%F~#o=q~1H2O9x|A;a0_Kox zE3le5QW=7OE|D$500{Kh8L56uCl#^VSgK$r9#_KW-|P6qxR^{pwk2b<@H!HV#f?oc z0N8tw08nNOAXhAjRe<%ib-@5~xxBHTl4h9|?gJPHWb)G$0oP=ZXiO7JdJU=p;K44f z!;VGsq8faMV0my5gTMR|ig#R(E@K$2zj-36PkIUJ#bIVrt=Y)F1N|{JkQ?pC zLxVLey!Of1ef=L%7~dc$zbxcgkO@X9fD<3KJB{q81XR!vxqyC7l@f2>MX)m~d05gI z(5nkEQVB<#BDiUvN!mM!2X=KKxdIUTsDNG|AaN+B(@32b30aCnc{=U`m|`Ztorh)u zY-A?DT6G=mcH3kGBFsbeAaFk?Kgj1sJimbv1dj+3b3ihKz|ty36|~LUX;xXk>S(|5 zvskZ;N=INK2#7e^eEP11I3f7@dw9otfD!f*e4w}1SNF`c`RG6yCuN&hU>ftL>u(po zZ94I26uOyQP-CW41*X?_(NU7YB{$;-PjcgeG` z|MuIM=2td9)BdKeK;X>kB;C7T4nOZSMS%&X7>4h7{8L-dA1%x9x7+&Bemd{7-mf2! zqXN<#$ZwHxHM-YNZY-h@sIvQ*8%r}H?3me|vn1XymJDE$0l@Sj0YI^M`o?X?F$Tcs zq%r|)$F0V9hnak-mkW$t7i%76x~=Wk-Yo?w_@Xvda);O49(11ldek5LJT&HJVWi@K z>-lg6-w*&IWU0$~p5}L)dObh_aIecW`RG_5j$GS|&Y!QvZ8H&Si!011FN&Om$BY8= zAG!!(VGud?S>|A%ImZ3*rJgc7I$R5I7SLFpL!p?#=s$lNx9n{ouC2(rgd*u@gv`h& zGF!KyGcYCq)M|Yt=uU7C75*$rlVv<~Z8vtk`fSWHo4>#SE0-$?yIL zfqv)k@yK)ZxuRlWFgD3zW3@oxoZ8D_mx>L&ScPX^D5m9rFOuh*+au+@#Q92r(M>=W zJnS9n>f3%l=*Pq|U?5EZQ5tMw5_=f{bPg5(GKJ#ln+`ipngDH;5Cq!Vp!3cjO`0dj zuO}B+6DhFAiu*CFR-L1ekY3Y1{ZM2*=`7EnJ-Hd}OFoNgy^V+msHDd2gS@Ba0R7$r z3fcxWAIyF95_~cy8blb?A7Xa$u|WfcAO0uq{p^P@ecE%-*?N*pF^vrJW7!7j0022< zNklXXQiY!DYa}XCiftUkd-=#xhRcc?))2az5tw>_K5znk#a59}|9f zj#7UT(~vqJ0Af#I=|K*yj*)r=vnm24UHUyVsw-9LeWtqBN_X#jbiT6mAWi`rx2f35 zNMaSBH&Zgzt0L_L+<=*#x65U~rP+f7fUU6gfl zZI;V?j=#iliNXX;DPfZHUiOJ=L}3fIYiO=6A*{|};~TEP&7E;{xK^LoDC_QNK1=iT z)6Bgh(l4}{KcB-Vafi%FGWY#v4L%ooL+I9MTlfud7HmUp@crw6hWe3MQiO zoEgeV=fR_!s_Jy}O0I|dG%<9hY^d28P$F#NFk#e`Fp~${$!bkQ>v&fzC>S`e*~DM& zPVf7(DcRFype0939aN-VHP`fh`W*4=rgxd}3A8w7c|8-cyVTSVyEO62A*^rVy`O@; zXOX^LT-O=(O}Ws`SLrB(-TLjcZB6F1ow7Mx{hskUJYGz&yic?1_O0no(Oh(7aX8hA z?lhzHTSM|RmKOSS0!<^G^;|k_Jv2#$+RraOoL>}&2%74LU^_nYNSb?JaV~SEhcDlJ zGAweP{l$Xj_Gz{E{CyB%$*$yJpXGY<_Mr*+9iefU2F0mKgSY?DP*1m5#)e zLKcZ+?@!H%!{2&sGh7R#0uh@XQHGlytfNi4AGwShw&8wr4~yU3Dg8)V8h2RNE<_sm z_%Zes9O{10kZOeI>&uyt65je>UnFS8_tsXU54vke%iToXq;e@nw3;FtKB`-=XZyIr zcOrl3-o)2V{OHpivBT}HWelzJ)1JZ6>7HE2$L)14a*g{qQ8zO}Fn4G>(*^oa$_{Y; zDW~V$Gg@ZApiMt38(aS|DV2V(XjRfNmrs1BZCD^_RLc!bxm_qp-$B+0v}e|%DcZ@b zHdgmZ^R=thKl{=*$}UA`0WLDvJVaxYE2%~qP0(Ebef6_()S~MpE&0?!WVLQzG|!us zfcRjfwxfudZ^N>;{f3oX%Y%b$PE30z{W3d?=5YuzQY4o!dHdJ?w0#R+EQ0$#>0CG?H6)RShb3S?V*RVf zEu>vw%X$h9$W718rbARxC-8reaXm>3JNmkKixR<M6Q|4tZFn>CB_1J(8Du;KDE*PIB}=5kv3 zwh(=(#OVFh{h8GdYO}x32FXR}uQkpB*esQeT@J4kc%P+>o$pEKExo+n33VzXV1GVi z2K)v0En#6P=qiDZtK%$2R(qq3NU2t|@Sv8mvf^pjrKA^Mxf{h#ak8)#dZDSH>A&|q{J z>0h+j?Vkz5zL#)NZEA4R-g)v%kVb9SXEMw1l+)4Pl}A!3)e*OF)bf@*-o~4E6xpqM zgYWCz6G3Oj^Qv=)b}y3eLAAZ6%A&;WSI2+28-g(3$s=vnB`|%)d__sIl~Kx50kQmCf@3)CPL9# zkFZeWZ}sm{RLqi8#$(Io{X}!BaqOd0aTU39r&U@Ye)Jv5n9L!Oi)Xk%-cZ;cQg*7L zpnFl&endtnC6Z^TF>8TQ;n2@{yJXs)TgkUCji2mkf3YK4>6)A0=h8dU_`^bB56Pp5dul(DW*9-&yVqn5w@dZ&YAoIWfu#ty)eKEJDL5X8%SA)bV2VnL6)an%x4 zK@i%@R&$l9;pnhQLl^om8Ot4uX7u;tslNgTnG*TySzB-1W%YEzH|T~@A5T{Bq;{^f z%=m1^<#Lc<9;>b$|5)d*CjMC}jJ0X{ZBRzz8Lye>@Zh>nVW4l{r@3w{dCXim zRXnn&rr+F-?d~7gshRK@Ris*?ut17L*#%8<=2i1wotg?3|5zVg7aobV$eMYRol{RSvmg2( z>2=MX>hJH{(Kb!{TI>0i#bOwZfJlU|9NM9+}q1C zoCeFh^mnbAQcB_!AEst0{e9?a^S$n5Sp7))d`T?S*-d-Z^(ndtC+zuxw(~vgLTfA= ze>7Xibh8+;l-Md8t>Y-tkNa_F52d?>B1qona2_>tdk?EGrKpiIEy;7pTtCiD!;#k~ z&|A&hdAxDo?v-S~!Ux?iPD;>T;-(@AR25Ug8NY_P<(_j?<^J^58GnC*k!W|OfgQ8= zWoWVa>FP^@#F`yr=Xi_7vQdWMy34WJBP1OGSnJI)62kzzcYS~b*2IBwu#s&;RN{ck zDTgd*$XAsEEwgqgETl#Fy1RNS!HNJjD)INs@K(E@ROnVgAt)O*0ZgY zQR*~N_5%(h?lZCdgKCWRXik$ypPRn5xw3UqLVFxV#8CQH1eC~jP;htbD~Ecjt)F4k z(HoFIScoKs+p=Wt`#k@1^z6Nv--;ylG6Bau-yUN=$3Ht}4sRCkh~g?dBt<@ zPz3TlYYy5`3#t4g&fgca9`&fL#*Lj$y`Ck!@Gu-}#7AzRPK}DNN9tsusB?s7Og$RL z1hupG{2!UIm9BGE#uL5bd@&z=yDq7w%lCSO)C*I&2djG0@$n@iezE1Wm?=%ZxMqc3hepr((q&`4+fmr>7Cm#72nQcbla; zQsWJckW=Cck&MKIpu3_Cp=v%#3@KHwcr+s8?8H@KEmg*HqX%t*PZs(NhZ~m1U{`kc zjoXx~)uKPajPYNtKFuMA892iP0ytm>X7iE9W%&YmbI*o)Q&SpBFf#@WyK2OBBi$>BF-xaowt47hPc16ap!%f|2Yr54?c zZ0!METj)}F&}XH&D)=N{-V?*#53^CCw5ke5C?mr>kyV7~BigXECO0eMdawCzLm22` z8SZA?t3`wbG%BxOk4ETJ|~7fGlN= z%m>*5+p?3wZ#8!;Iul95f`FEsv|3Kmvbz0Al{ZX|{0-SNwfPUlb$twzQDiO#2Qdq; zt~lKp{Zfi$J)NfM1ySAYouHSce`Kq0j$!ybfH8wY2Sh>D8(Rg%XFN%J% zGd*=sQZOWlLTnfrEW_-GUtT8Ctj_hjd=yJUu0Iq8O>pVQ=q-#$k(%30b%1%c#`sMi zTzC-;6vrDe;tz;C?e(E3yC4Z(hcl!Q3o~FgVVGZGmpMioznsDB;qlnj$2XSz?s8po z&4){NI{nQLCFjZ0b@wgV3aY4^H@q(|57;eWC8h72j*Zq~?h$T#W7wSoxbaTnY)>e@ ze~K*m5qDTAlWP4VZjQ`LCDe(k`FA%;h`&ywD`O~0?p>nLS-#kAAh{NpSjqDShcbWs z?WFkTO+XRx4P&X1!ws6=!)}ojcc+d=iDE16-uRojUJ2>Ct_fim=gax%Q!*)C`?@4_ zGl4pNx)%87G8m4=*H|JcdBJtg4ScTrZYV-9ICY@`ZbUxp7z6P})}%On81eTYLacna z16%P%dOn~pa)z6tX(Ft{FNuRm_2fB*4w!9~#gr&}!PmTNrIfcp_>!l%EpPbS z%j)1SiY;VM`v{cAD#w%ZCFr=r!a~tb$2n`{SMgrg)?%S&Hl52loTDvaEteK|owF&v za$_!5_i-nj*Y4eDUh2R78cH}Rz8H^dH^-eFomOW4(P0PA?B}~158t3L)ozYgjQX5xQsWctY(I4OZhD*PZ%=N8&v!azHzS`8= zb{6uM&3=cbib7(idD62tWN7NMLFjo4d5HbW1%H8~$XHw4qj%KJ^Ki=I-tH?;wIrn8 zOGP9Fxq!>;0X@?4mLSt*_ae2ja*Z@*yus3Stmx{on`4_kpLhLKI^JI!c3I!Bqrg)m z_hu^=r!ZXxx-PZ6%FKYK^9z5QXzpp-1F@Rt!{cwh8Hvb~xo~|R{KKA#)A?29c#^f} zG1kyH63uAQ#zt}YlNiuWd{uiz*51bSF!V;KNt*daYWG=Cviurujr{3pPIm~#S7>iS z)+PDm$k}LlgIv>%6w=ILQnIkil>b4BKzB4C_&1#y`<$Gv1_}T0_ZC0cM!;yDX6AC( z3uMZx-H_+sM)r0@4+t5JG-)MSY3rIn zT6q7d$gnaxvLTEnd;9J|Z1LUOPxJ#P`(aV|X+k^HS&G`Tof_XibY02xxm9b7<=kwD-0 zo-!-A)|7vuvgK3VmsuO1Q;-w(rOd){{*k5%E-fO_Pbzns zSaCjHYDBh1(!#*SW3iMV4!Q^~%)1Oh=BnZKlv3WWR9ERS9%A35E$xo!bqNOd8&Qn4 z)td&y3!u0A4R>aJaO$?cS;)V>16x6rA!=5$f+=JV7n76;PWDx(1trE9A4r)2T-nViyK^sS!7Igt;p%7w<3VrbQKcZdhgYM0>O8&?I<#O8FBy zl9pC_@bOba&s#jv?i2FroX{?(Iy2+~0ox_gkwn%G9Xm8;Wip*;UfjJ_x;Mo(DQ$MQ zu%wOv=JnE!UvdpK&#~H;f5*U*Ad#fn@e-jkg_otEKymvc(redFzKbQV1>q@IlRFaQKN`^Q+7uK=g zp(%kxkcWf`b9who$ez#j_>4HO7df&3w}B9Q&Ti>@#ZoW@gHX{A{&Zh1;%eEFD2m>; zdjnGB0P}0@l)0UXbC7(6?M3iTffU)dg^;2B+=oav4ip1D7hDf%ogAIs zN*p95Yj1`5v&hFN_#D+=oth(Lj#d1b9uf#{MyyuE8}sdl z>}kw5R4L_9P18$z#9Q4t9?_Z4NzVI?N=g~2Hr#NvNUciK%ZRL?j-(*A(kuMceEi|` zGgs!zHN3JM{OE_$SsySn$Sj?|*j&>DGT2Kgvsr7cGbyP)h9pTAqqFoeU(`dn zs1h4he-9)wwt~Yw>H6E>OD}@YdCh0Lw4+^*-DNwsYG)ES{F$A8sj(Pplrc2*%;Xcs zdB@IZ<>ZKXbXztE#XV+>>PxyM3;5DBX7l`0cFc+c?(PK+y4MBk3!`Fb!w)$YSf#{I z4en_6O})yG@vvero*xoh!3-kZ^7Sy4I4TSCUCO7uem7k7xC5F)vXHyVmy_eV?6r?) zPx9h~3iiqX+eRz(L)&f6M2&(krGXSuoVt3$`C>i+8tg3-e#vOSs345cZ{ans*M?`F zelHm;#5B2Vm2fRUXzY?+_bSvue41H*_^I5mfMJT&nD>=iGPNUL`UmRZX@5^ZxNmMexpSjiJ`kPU!pAb4^&K-F6FPXb?k+o8D~g&%H?`6m|w||Ha7yI zN$Io1k4lWjuwS=AYT=<|*xcHm2RYiG%Jwzc)IOIw+&oV$j%YIr;nA=YB= z@GBQR1D4_FeN`fS&-q6LJu}tmUo!8coM_0Nhcf6y`iIh{Y!T1lgfwiT)%DftI@>=J z#0wJ$V8gHZVt*lS*7zWsC`Pfp;OY&1diIrUDZkyP;3ujovm3or+Jk!?BK)05r!z!r z_nvab@^n?}UfO6>R-twMmLMrz8_e~4WAbx{TS2q)%ALno0pb;bX%E%1!@D(`=l zL6QB2oH;JxVg8fhSBv?c$XXk2zD)mHJ`pJbGNe+_k~O0sNA*13zyJ!gY45jmVDOoq-fa1E-NhdY@k?I@#r_| z14gCVG3MOKF*yHseIkPyZAW&xk0b+DqdmX0* z6>M*XVxEtWIH1_FF@E$eIBfQi@I>*Mlub;L8a1l3G}NhmP?WJC#7xkbt#=P{5b zLP6mm^>w%8J`LH?CHy7sqx)bNq@NQuOEWcKi=$cMqOuho=zK1^)Zy9v!Py^utgH;r z>!O9ek0$AeMAjJ2lp-*{Qa|>T@C>H$h+X3LCOSN_$_CBx%)?EdW`2>EG+jb~txxH# zaY5JS2R;4Cet4S>Kbn_2Dyx}@(A_az-l7RH`!5>&Svd!EpYq6H$gBnq@Nat0Nyl`Q2$%9^$!T6ox!V>Xp%L+}q`o*+>~GPH%BrQ+ zI5<`D*&$d_oz|qKsn>knTjIR^epdM|T3OfYa|R7zMR!fMsZq=peV&t<*5?M(Sjp&z zM>Wu58A6GwzsmhR@J^dm2b)=wyDz@X+>ydPoux!lC@&35zS#`n*!@lPgzT*Wf}ef3p@fQ?!xsBk2!(JfoKeuRLcsV2QCN)y9p;wFYeMTZRvNKPbE8 zXu4;HwTX2HSQ8)c00o_4gPRvf3ePa;Y3c6bMhqhfkSs?cM~ETOz(&?<7~c!VI&82vj;m8YNa|~1?xoYy1OyToi!SF$wiNf#_T&?p+`}QuwO_X>z z3>RMz-J3)T+Tm$-XVdDPd_0l@3l%A@g1)torYohu^tqBwWK(XXiwGK0lxwZ}`v=?Y4B+>{#?|#z zV8`F17r214{+#L1iK?lFRouX(4*OgRZm4$Vn+X(KVr0_rX8eR>J=@8B8h+OI7A=TB zop#%2D5oBkB^D4kpBj+2Zw}E~lx=J_MX&HV@X;AFpY)z)J9I>Uy{@OPtp*d-3wwn$ zI(9pSQCg?otIkciPq}^H7>TvvGq#MB1XC#NGpd9OY~~|U32o`*E+&8D7D@(*<%x2s z-_MM#uUkmO8`v-**Ao{`w;dNH3FKuyaM6spQbgEagBsxyI>9Ybjng2CQm~_@cg06N zjwi)goc#XKJV9PWWcY3Y8+NqkN&3}2=RJ8ci4uSO66EOb&{rW}c8R1MvddFkrG?6v zp6!q;s+Zpiy}#|%iHwm{iOHPiIK5Z7ID~$*EJQ&3v$|N>9*yBloPp9gM>wZqHI|9G z_fULi#7P2mgQKHNg5-;v=K$X)%Fp{l*!WGAoO%vSl~#$YIYWbGrF*W*pgBz;2d0~h zmu5dLivfLi7*?-~1Z_IybUeyS_-QIvAoZQdS^FaM9uAceo4^g6EsSWIe6!=k$N%R8 z_WaTBFGUs74eB_jCp~f-aE*RYMKg}Ey{=ZGC%~ z@Tabt5}YnI=+r(=O|A|%@*LlZT%RL;@}4V}KTz18T&z@3KFPg2IZ}^|x#y4F3P);x z&AgF*V~ozuh~M_ugZb2QPokqDb*knTj6eC$K8wn1_s^y%d`asa>G*`bEPdyORiS5^ zY6LR}K0(wmY*2z*9v**WwLs9e#f1dDX#%IFy9e_gC`F2Jf<2b5e~q_cXc*^`4_r3i zDJqyUZW&l(lbn3ONF8idj7p7kqw>3-kDTlwz6qE(zsL+J-B6Au>was>=53XD?T0oF zqQ^JpoA1R>NSzNx*eZ{yy*Mc!A2z`vy87BHSzXBE&OTjdjM{&8I)w z$MaLc>Yt<48ISoM#>SfEClO)n_Nvd&sVQj)VPkS8Fc(4ChKd^*Eb>rKs-eD8TgP)kF+)TmUzJNi7`#- z*1(*8XGAB!QSv0!snk+tPq4OqKcYI!oql2RgI43L#wvCidez`omAK3VeSM;-ALX0! z8@SxDJCDp74bSc(cV^N_9A2``mCagCMS3-|ZI9!A%HCVUepC1xN;0CA>E7*mva_%n z*rh%@qaeP*VCos`?(m*-aq#52P3dX2fFny(hK3enBhxY}>G;6v+6AM3{7b!HZkW9S z3SzzWpGZg%z-M#)zU@^|b@@^6v{2g*X6Wrvjt@r^S(K*bC`pyVg#fpn< zW|&b_;1l~F+^TGSty8pXh7;)W@8Ms{^0!aazA5QjMX5@H2VQCmHf}PS7w6xvP^6Dt z-+MoT*F%J)q^VFIux9g-pi1ZipF6re@3ez^Py~_6-OE6&OzU`9IXQRSO`y%mCtB%s zZQ@Ik){Is&-A&hw^qE^yLM<=LT|*4PTd-@R`}+Q{Pp#bf{=(H>*Z!CM3?2tG$!r6_w~;vsJg6bZ_nF%n|+E~au2tc zAH!A>^+2#y9esH^Xm1C%XGP+&uJfva-NCV4FKy-`C&Fl*>h#%(8;NuiVOqoC7pA=@ zG_wqoN%qpjW+;!#w-eKSWnhsPs}C|AKJ;Pt*K4Fbi2lg>#`X1N(7lldG&l2TFIRbA zBrZndW}$ze%*?V4Hkzmk5b4WI5^Tr*di{2NXbr!qnhaMCTzS8|5vWNcaBvRC#8|pA zgD(V{uZ(pPE`@{BN7SR*tOT#YL$a<#r z%`HMqhKaOd^w5e1a;=(QBiQ$*V6I^kMwImsbK-Jf%^JifH4HMqGQV941?X`S7LGuDef^ ze38X#RKM0Lty5z0tYTy;{%Wc>|1i1UI_GDu1sp}qv2Y&*`CP^Nhp0tYH9Y?NYWaGG$&(*$chRDHQ7Dj`y}xR+Pk32}5PdvdA8u@Xso!SR z%KW7b7v=%OZ&?XWyQOIF>Z9MM?Zm;S>%>-PAC`+R6MSRh?PkK9z^Uop??D*)Ig;Rq z&V3lHyHh07YzzxWwuuax2q&ojm3Q*^a$eTFig{iRNt8HG3Z{b*^`Kckrk#*trLKG2 z?;k7VJ6dlRm5+NEsRtI zxV2d7pK0_v-Pb7Ql$B-8HEMjw6CJYsjoAMxv_3y~iS9>fWO$x_TFJhadffJqqlDsne&eN(>niuF=@}Gp zXQGqm$~NYElz}szP256nlfYd9GM_`ko$MO-8l42?5w{_$#9qs$i8_i)8aV~ zG-^c|JkzeGxutp(_e%_8)2b9Br`x-zll_zQBpMv!XOT;wDgF`vZ}zZX_M(!}+{+Y%j&(3y;aPECmMLoS8CwlN#=8zNZNt$D zBi04-3m$h@eFuA<{0ov;ONMAA58n+WVA_8zRIQW0ob-QnGy91^4jF?$20H*ht@PV& zv?$W!lZmCZ-RBw_#A-^&A~`|f`5alTw?z{ZDoj{Wd)hhrSYn#LRjv35ZX$T?UT^Ex2&s9$nt|%^x<)dKp7!96d_W@8bJn zGx=8>wb5OZm0vrUrjsNb--S2i&s|$@E*k4|bR5i!fdAPh?lO??} zsrR3i^S(l9^`bk=-G|L`!x*_lW8#fsNj{$v8rbYDvlunh2yV?yZsQYHn>-nU?Bt8f zYO%{5ChpJ`N??4^B{tQ5*l(tm6)61@DP5Rx-UI9I2$pCxdQ4=jQgx=-hcAQojv2Bk zMK#r;BSu27^&BD%(-xp*!TBy9^q`2-KPEP9L`zQf>ixBUo1~l(>P4ypw^j2EM%iD3C!wdyS|?tT)`E8X8M}7`EL1JL!C+=$p#Zq-$ABg zw>IB)Ky`MmmP%A0xe1Wp7Z-f4P%ri;uy+s0y2b_Y)B3^6+M=_um3=%r9O%{Hu$j3W(&DE<4&d``R=!0!So6D+MXA|jD;RoA~H42fM z@?spR%J*XpyEm$ExQR@B@9QYiXFWR1G8W;MQ>Uv5Yb#fwm;MN zo80{vDz!RoO(%k%kmSxWQmVPdbvnAMMbADu^m+dS-k7k=ea-sHE0XwUpx$&Qj)W_6 zWhdN#Jf%TeS{6=#e(*6oe0VtD_YxG>kvG;U^X}>ov|+}O;6?;zz+smtCCY>^BK+&* zuLt~Jo#!s<(btA84+z-tI6M@KdNFxe-ScybAtG<|`CwICGMk%&-`8ZnUMjVll#VG+ zLlm8lqI&F38qvJmas-MImtObekUt3DVF*{$zVm$rTeoZ}Q$*C8T(!X+3oq(KlRoBN z&9B#X(w&&4EMy`UbC=k1Ne{-mI_i~?;xVBWh`y`KBeCn>JW*Dqh2Jd8+Y_8l?$zS9 zEZ)PgCo*{ar~b$3+yV{lJ$YioqufQ6*2*VhpWqK&acfdU9%Z1}@3Zy){`FKQ_9e{T ztxWG3ZUhf_xXUWPNAFV~j^){XrYzC^i1x#kdSm12QViAE%Qbl1Og) z8f#Wpu|f$S{4BD~Py|ExK98y81-UR8nDW?nTe!c8NY)->c=^mq#149$X*0m~+pq#t zU!`wkG;+uFTXyto(?d&J4)nvuQ=N~d>7Ep|1?5Y}_OjA3L)WNPzi8%MZo-y~1;7}; z(w{L$fs4Hs`|Bfu>sYq=E>dEk(9GtkeRw#5=TaxSeA}T=ljV?`nB?W%J9qdM zcn>o!3@=}vhSOr_i3EKAh(6KJpn{}v{k&J7fIRJd`06Y51OBvOv*nC)`BjDm>{LBH zLA5eRWLo;l?_Ne3ccmKc8H5K5V45q__)w!@t(2#NfuTX`B#~9pNvX_FVns@^vt!R#a5>}G+SrP>K2QyqJMcfNQf$v|&n+bm zkkxpB2K%~6SO*9gihi7D*UI(lb)!#3H>qpF7V=% zo(c}T8Mb9DhTTIBSs7F~(LcYsvJ+DEtK645A{rj==wd7=(6LXwnsY$j4VIUpFP0D6Q$-DM`Ont_zati|V>e!7g3*fl}o)MUI~O0}#R&f4eq z&N3V#Dg-MZY?CLQOAa0RT^I1W6`2fVR;1s1@h#McSEKENJI07!=+wpp#?@fTYWr?& zz}e=Dj{R!+Xz7;P5WmL_IgkCitZ&I!s^$B`eL>1%c&9}k943gAN2JgLGePT=?Oh1I zTiq9Fay_1fiJZ9XpRap(T}L{$Bo*m%WcUGB1%ZRY|Zn78xZ{21Ar&ka~M&kVB|{+Wkf4g*gb$%Mq*Oc<#I?5Ci7%&jLc2T~^s%dyc6& z+Lt9TW!LNpQC}`a7iI3^^|i&C-Veqc+==HbH*x=zqe#Q4Q@C>Oeo=}NIMJHSOT;%= zhBK?iR)r;+uit3fU{GT%mNE-})vNi-lOnc5nczx4b@7R~E$DuFVT}9bT~Tpi*lZ;# zfK6m2ocmRHdyurdH_E?qd2s8EYeqxT>idgvIHtYc$FJb4 zb1G+6X;gn_X!KXbCmCMyi~Kt9`p4Kr6VfpWMxwUWWEU>B z&!Jp|*sHYPQmJDwzR@6wIg_>Dr&i4|dB(8f`iWrg0ClTtP)8%BA!t7O9NPe0UT)*= zZQJ|&Khy$m*{D9c!$nM8JJs`AW`&9NXQawz?h3{<8)J#-CHl3eV(lc;Fwazq%V44I zkTGtz(3R|ZKaz*tx37NoDo^u5+Fkv{AkPEzsCvmDWHyQi{E;Z4AxyZ$!|L!elo$9z zcS8JPmu^?Mgz&Tn?S^mgn;SNJ>h6(!;+f;Eq88i3SM@va{?TmwYVvGUZgNuEdppI< z;o*_#7vkzI^`t+W(==Lvf>U9{dJ|VzmpGf@bSN;5chI6^_ek|j@TA`8{r(-Yu(0${ z>c_VUAOD@H@e5e&6+v%pRN(Gjub+3_;;UMQe(^A8YD?^$wswLQYp*z3&9c|$&BBqr z<0BeeF<8>S0#|JeRbFuDbQOxB5esG!WX8W*vM+Xt5sBKPtjj;B<;>KN;8dFPqfBqi zArImqPu>{VldZA6Sm3(w>{K;Kc@iyBx#P2a^1?GR*l9>e%|r#=Jmk%S{yIE9_9KU5h~5IZbQpUeCi}HorAWs7D#4F;*7g z=Y+m4%g^Uke^Z(TMnUf)^Hy6f_D;IgKlmx-;LECsZV1yHu_w> zW{tYWSN9V#r5x^QS#?Y#K4glj^8Tt3m$xNo%MjK2&VnDz65Y1^V3x;9dyzrl7s~S3 z_fqlaQhj4X$0)U70Tu%`gCDFMcuHWb^t|awI`?hgB~YrqQlYlo_Yc1Q_2PAG?U6@e zYfOkdRf@4yk)eORcU|Vb_f?W>m?U-jIkerojJu=#Cz%J22tfXJPoe$(i!WZ^Zu39- z+tN?<-~_F{nyIi@pZCn&{q-%Za=u8qj`v-2KA-k?nm!$aJ5E~{w`EP={AOzEJjAvs zs@xvoxh14w^oOwcvs^ZM*E00o>g@Lnvk~846+?PR`eK*CJg$~RMk_dRkDA=0sSoinLT7kFb3#13>Lxq_wfJu3j+f!j+g*@i-Lsk5>7%0 zC`kzc6)6#*A|nFS7KpXi262!fj(-h$EY40FJTz1WzQ$r8+*0LlSwtQF z#tPsORHv7|EaXE5xI(@VJ{=(6wh#k?#T;TXhS&@sMj>`afQyCJfrtSY3&T~Al^z&K zaszE4CZH|I1ayU%fxa*^&=X++29OzwG6Q4COvG5g9dQ<53LVYFS%J9(3$T!2{cDzz ztiTE~#L-fc4f-2l{~kjeZKT+M79TUXuSNuXbm*Y+?0?IdL-m+Jb(o5={;k_Y?4K_q z(SN=X{`DXhU5HHwVnZ+*O7a3OdTKy~gK18Phqa|5$N@A27=gL~6Le$(T7t|#2Z}*g z7%Gd1L6jAWffX2wu>litHgHFR4VX%@12f3XA+wM|7zeOKm^25l`oGK?`d?3o12`y= zf=CNWh?5JLL1hqS5p|eKu>Y+SQMVBk2f`P^C&D*^0l}gL8G=onAHm2B6a_c{0WQu8 z2|nJ95&eSRkJW|Nn^v!Sufk5tpGT zComMJ0_l$U(6t;;J90orC=XCs1hX+z-+#FE5&8ZvZiH_H1A+ySTLc?|QH7rY;%5US z1h_XO1b9G^j}<8K&;unz47`j$^=};i+TuTP{A&+LQ&2t-KK|+IpI=>JHlWDK0%X`& zfGQ7^I}t=qIsWn)L#!%%4B)8~HgHs8fXcJ~5AT2H`d^)hx^*F~{N;vp^1rzeOv+F_ z2u39yh@by2KNJHVP~c+$@?7*lftwyE{wEIT+JA8%+Jg~j{?!#ifB(_ezgV;cS%EYM zHMp-$4j!3O025g_5M`kSLUfEk8}gw5#T90b52DOSfd)T2)UW=<{y%v}==5Km|H<`V zoj^Vj`Tom|V1^9ACJ!+pI2HK*hhLtT1;}#J0$DCP=sey3!~w;L(3Kh#yDA?OP=Y>i zRpw>}>QFz_7GeQf0xUq8mkE@5V}c*KF!1XI3~aqd0@KBqAl-u$2r|(^*HM5nFRZ_e zh*%M01EMVv_D>)G@{C~q+Xo@$f7}fJoo_{m1Hp`7M=;8ALY$ChApQK!zbp?kltUUI z4aFeyf5*W~4@8*g0UIS1;A4aXekM5JqM-(C6tqBqjsfCe1n)wSK;IJ>7)^zNxf~eS zuYv*41_R3#n4l*S2N;Qy11VP4zgpIUw2aWj|I3TW(Z75t|JBGpE&Sz1FheE-aU&QJ zta7}pfE3~Q7Ar5Iqb0t0-_!vYmy zM8H%D4j9R4L5ejxsP#nxF6vakUXcbG=SjhEDmplN1I5t|12s>G05=^}FDo?0{q0-- zbn(A=m7yFX`XE9h3Xld6I*|Lz{f`B~gkVE3B3Na4SO6*EKYnRQ7osdwK%A8tNc^uj z#98Q|YpKCVIttjWgn?B^AHOT0{6buptuS!ajsga=@j%fdA`oXo0GP;_fH*S?;H80d z#ZL>mW01j5s0%AD`m@4ygZ#F++NW#=QS<|3@DPZUpmRZYYm` zx&Mnv7~(@P3Nldw8D3^cKL~z&Ai>E9_!!_ofRXa=IUyz}4(K{AS{k4&LIHZBV1I2S z2?pLpVt`;XV&JJy3gR4yKzAY**nq|ygr*Maptfj50t@9hpdknqNH7xsaTa2zzeD$E zB-9|?8H%AF2C5~q_`+RWe5g1hWHO5J8go-(kgUtPn`tFvXcU1aWZJkAp`7`)Zp0zC7yNjQMxQ9*iubk9Nw#Z3dMLa@P2GYm8Z zqkslKB+woL1D%gypcOj4^@G~S8wnIYKn77(=s<}NVk95|>@<{s=fBvw=qP|BG-i?# z;zRrdQ2v+zHw`&7#!>t=9_Yvm#fUgEQ&Iv0aZ=Fa4+G`is8Iid>Y<~8&Qk&!5;%yl z#|5pSXwdi!-Pe;*L)s?-ex?Lq{S`8}gcuLsq5(@aazKs;wJQVl-{%f~1}gCNDJmGw zz=g(fYG5Km1ze%$@3eaapdkPSbcRClgu}px1Q-~D`d+#-I-nyb1#HxCzzOA-@J!e z6M)YtsF0>800}M?2(lyx8|5&dDnJHQ1mIxw85;NlwZm~ED!8jn2FUQp0YB8fjF9g2 zCCI?qUXA3+!&q!UD&(34XFa~UGg76b#~76gC*hZ5+^kb%`w6ksd~y#1-2SwP&+_6h58i@ROY!G4(NmWKO>}Z zE?Ve$9Wu)Q)82JPS9M)!Aqf!buRrOb3aIyn>QhG)fv7?t2_e*I7KmO2LInwdglGbU zKolDcwrK_owh8uR;c@7{a% z*=L`9_WAbrK;wxWy9IHt7sPlV{_~yvMSp{`z4*M$ zlV~;HZLunn{Sg1#U*(AN4fcp0=Y{7EII(?aShTdA!GwuPW_-jrdVb?bWlNbyW2n~{ z#+G9ZuK1Gk`s0TjF^e(P=x)L|`ekykiF!JyF&$&Jjk{T6MzPfczdLS+SGexHc8qb2 zvF&Or_mMj4Z!u7R9nv^|jp9E#4|N{SF;Vsx-S6sei>L9lqr~j#$wu6}+zvNdT=C|B zJ=Yb^54P*A@xtEadVE7WuPE|_FWZR{f20I?as2dN=w$9M`NTWth9f7=2yagl=ZhCk z)Q>{*0#A-1=eC!bb5)OP&5mk~k#+KqTxY(yF${CFEo{fY7)$-Vzti7L{benSpkIl< zDBl^3wGu<)C=!2T11$))_+rZ(SA4_xa-`mk^Ov7-A3m0```JUI=+EN&MvSH1)i_EF z<2ZzJ-i_uswN!ZEQ?7Zh9CJeSSQGSaUd)#~ab~qMytNj%jnZRJtrI@vIKD-nm-QWw z+2PoF6HFfBI|k+d;y>xknI(40zCMHJk^Y=p^m$n$zSEn!53PM%xBU&Hv9ZjEZyDcb zq;PKd_%d#dMnQr%K7Mc*p6RjYXX3}EyYV_Ez{GefIjdRCleP+u1N(5Z-I-W}8P-q( zdh15Pq|u>w#YlYm5ZCszT-P~P_z82rW&_8G^UG}Dduk2z7nAe-vKsb>tlM;b%Sw@$yAWwHN-*d`{x}7^6k`O*Hk6rHKCOC~=K_ z@TV?4b*}iDdaj;hfX-Qu`&K#Pr`-@V1g?8Tz_e(`h3eQf!UE%%U|RC3TruIn?>Ey^Z)>pU4(8S9x(M)(Ba(N0hN zm9c)u0xhC^0#)vn#P`I~CNZ>q9FOtLuj0Apg;>1d!}&2Q)dRV)Zs=b<5`U(@$h!SG z=MQe%zdYNEIl341v~cebfH%(A#=T~u7m@xQVOD0@cNgv~S+)_G{<8F%uVq=j= z#!A`0i~io!zkv9_c*aE0S9Dc-G3K#qPboQVurF=tk5^B);Nu7EFd@c|`3!Sd#-C!V zKR&xM41c69bJBc}NgS+z_(mT0m8smXMEdyC#~3SvJh5@EGwyUcaIVqX`l{I zv<<^+hwSi6t~0VPken+~{F@RVXkyF=v)P{*=k(M_=Hs%qGyX{K>hFuBv3~S#N{~OI z>Eq>j0l*!J{iC?|9fMGBf9}P#xY6#8zuw^b*fWy(Qdt%f;3>&N+YL1cAi({7^r|2b< z6Nr>C!Q9{YpfXQ~JG&h5HSO?s;ude8bHlQt0LEM54cxO^=|7niYbf{a>_>XAH>RgY z-_^e~I{_1;I43#p1Y4X)Y^Z>`2;MZA*l5PMa2#JZ7NDO$u*n^{VbS#cDDF9;@rUzH zDtInwk()?g4EPSK z9mF?h4Pul9;bG`)7>mDf-M!T^oVte*FOEcYUKl>QKusE zI-$PM4RsUUv1Ym(F%?(zHxLi%7^e3A|Dc`m1moxRk@&??FZ3)4#o`Ik^hqa_XZoQ$ zBN|oN9Ip&wr^KRji9-$bBa>rLoE1;|d#Kt(6|wed#Gz)0-o#S{R~3A@gxIU#uhXb+ z^MW9yr{EB?#uMWh7m3;_!T9{TJ^qvW|Fp{qbCTk)c4`C;FY(8ttwub@{mHM7I^*?z z7v^COc%S*q>nFAN$sQk^UOSHUfe89)EXq>jF+Vwm$2e@8?Ms~374wMm*XBf{CN~mw zxlyRhiclEwB-%NP_Mc1rW$!YYwUxTbDVUish8Q++SEYBb!oo|_L+P`j#OlLo%Lu%E z#sR-(K0Z)Cf@7t_{TnolsrLAQbM~bp_E?k^iKZa{ z;{f%l&f;}?5*DWM9?rYE>{u+F5QAm;BC%MU8^^sU$8EwG>d))EXzCx$&!c!ArTQZ} zEiKAa{x7wfWvqG3q3y-q^V341^v(!Fg*6NdGvye8vh-NmScg}*o;*Q3;s*CJr&k;B z0sZHF!M2D8t(+Qw#o38iSrCU+lj3+xLo?PR~c@c+AQ|e z8Bu5|4&^%%+17Zx_n?!?zkYwx4!`AIsiDY-iHz~n6M~2-dg9_5JDgf>kF7J4uz6ZC zwoXsFD_eLzB%6zpu&F2!8!79iB%_6E#)cXG9Gmf2BmJ5Z&wj;o%;K@4AO@YwiU;kl z#|GBmD$+xgy~Wlxy`z=R%NY~udH+iGzk#x%fc7Xz!sU&Ol&0^=_L<|cjnYWjIwJ+!W+h@* zg)he^nSDy)c(Gp`yS0?nlVj1nVxH1pYL;8(<#W!3q4uu5qd877)H_!Br1_J3Vr zyc+LKe3wYWgfu+bF^+NDrvJ-~<5R;A%Vc)_7CbOzbR9qon?mwDB{M z*5VYj%t@uBpm}x*nr8Ff(kN`7C4EW;{||F)o<5#ql!T2Oj{~bpZT>_3x3TV7n;lL+ ziNSKt6`S61>?h+P^MIqZJwHfu7xT1;2{V6o*04X|7@2X?zA$W zAcixrT!;3#nb=j5f!*`cv3vfHL_VW*Qg%@~O489@lE!D!&_-#QBa(_{N)!9EZB~lv z%U0^qyP@K){>`k-E@7NidQY^)1e?8Op3&C4U;K94jPa0h79S8hi8L~fJ<=9}_vu5g z^)X-E$F+cY@7V@3^~yq5X*PPwtxEO{9(&3&?|vrV?JcvSo6=Qk#hz03mC`vs;|G0e zWq+DEhSHZE)S+*4mC|48-ffjra1ZCG#4wpBYw0HvABOBLdW)|%Q}0&lEPl{ll1jU# zp`$nhJ6VIi+8B!G_PgQnRt*N0Mxwhk5BtlracE&C4pn5KcVQOKMdY)gbKCJCzdxWP z6Z;orVjugrmm+=I!#+uWcFoH`2ghh9$Eb~CalEmH{!gsKWcW+h;u%;uAxgzBiDw&W zbDN*g-t<4wTWq~^uIQbn#(NL#)5Z5H+m>Zv_uM@6lu^p_sdqjOFU-Z!McGRF7UiI? z$|lFEa&c_%ypQMd`B8pUXWS}+|Cu@Ev1H6{cPgL9FIPdLeUyku8{XNQl9A^J}D{W&W z<07`&Q<8$CwFNlSxdwW7*O$y1x5*WSS-9L$kGA<%Y@d;cX6oHaz1!()yV%z~^HQmE z8g)*`LF(LFVWqxS^i^i!_@XSFpspvYvvIm62WM(?a9>?6&MwKrxy5<7f2l}5&WkLY zK#?P5iR~!go#Q=cMfl9UeCEvJT%6)NPV!wR_|D_(V;|c%%D$XgQG}=N?ZC90@x((t zvV;Snb#pm9CqD%znwH_do%OhveL1^(74Gj^i}QQeEW>lk5SaMe13`q9g&k= zcueje*n?Yq_7>l9v!8No7arkzZyf2sBfV|7*4u)s2Y2Aw;U=8hyBUR9`!0F!zY=nL z^zLpiSxmaDA-(U&iNhtQ?Q$G;$w>}&cK?6;-?GDYc`@yLM~<|+@U;9XS(LjxEl*zj z=r1hHZiGSW-luVO`C@2{&GZ4mPZdv#IDl}bEX>Cxr}ZJnN_bX^Q$_63SBdS~Td(83 z!zSt(;dxQyUGh%b`#qs?bNNE2aX&6?6KC!jOB|~xHAeBP%Ch1Vzo~9wGL}zCV-9U4 z4=Nj*igVG(d}s%AidJ%|ghSO{S%~&U6doJr7f_PbJ#w#bryBU|^1^h~O-feply?h< zOSn?OtW_AaZilJM=lSuW#EpbEK`s*cCBoY%BCd3oAH{v5;zlWc6gg7lM+ryD#*-rN zgU?pw>WF{%k%L3N6YrbNXJ(P}B=3-SDXtSaH`0diK?En#xVe6*Cr>4pm}7o4`5fd} z2!BC1MTOL1h~p$29vh#BT&w61C9{d`2_I-iLMX9vZ>*bcR(v4Yqsm@Yo)NB+@KK~c zLp&wL;b2>N!t-IBQEH9Z#B8NruXsLD-{~=hn8TD7$HN!ucstl0{8MEC(&3g7cbYEU4e zef^2^Qv6u!_6@@N8G8JVxw!B^-eqn1&3S-9+~2Tu+0MDtdLis z+KsSrRjlMs2yU0f+JMw4rG4S4*zi$XtzR&@X~`y>+u}?N+8O=pJW!J3g}Qt#b09~o z;a=v%3U`H>eo4%5UXEaU?BiVy2kpzg3idR_+qlbp800)y*{0OFq|UB*8iU-1L}FU; zk1!jAbE@${EhYf1;h$Nz5R%lQ^+w%8fTO7<9v`L?Ml6ZZAe?G zY*X46Q9J{|^jV{cQuRp-POTV@XUQwrTH*<7xCK)ay|Jl8gIBqi6ny7fwzs9&4Y9<$ z!-%18nWw=A7aTD$UPmleL(E&l8jqIs3F5bA);EmgUHDqqKWW2^@#HoPwLhM9cBzM| z8awM!fo2QV7P;Z}HaptSo6q_XpZ6g@PLHi@bIUw8g^hf2#R28{e7{LJ3qI&r*g74hkISk1mI@UprNDTI4JeKyQ&OL@Te5rHW>U?4c;U~1ucVd5?5g%m6 zjUBAb@$=L$FZ^!6o*W+5Ajv_v+C=}O4i)4?Xq>%~9cjb^tT&DG_G0bM8-c7J-)dOeSwp3L+14))k3d(g3u{fnRWNfr zSpVbsfh8_@kKBYr*8Ha@5qq1Ufsa9tCw4pFvy1duazol{I8L5sRj-usHxK4iR>q>C zI^R&OES_^EkbZZe(GB~TxO1NQV@i@mVU6WETJp=NFKbpY95<<<_#3>?NB_9CW0dmw z?y8Zjh1;vK`S`LUHkaAz$x>&RTJLyipZTQdkj+>e$J&L|6cxvcu_!)(xH>W2cg~I= zjw>|~ViqN4RmUu3JtAR@pW>BC9XP_rn>8%fci6Z3A{U(9G#uZub|KjDTW4L-SMQ3H zvF_{-YmKa-hO?$DF-PSE%nc^Qhp+}A7{1h~Y&^SYKR>LV?XBt?`B99C^ymAxYVqc2 zdt%LjyniebiDyUnkjpmCKyEbq-aL#o99w*NvCkRRQ#dcp0q7)O6QwL)7ma#a;TEH{=X-`WK@*~ZvKK--qk?Ov=X*yMt zxwOq5ey#Y<7?l?jYg0EicMn=X`V*djUn9A{s@)Hh~8M6Kj@z3WI zBPmYT6Svo6PO1j8lC`YE>F~=V&Un1df%vUEx`|8E^{**2fidT zj=6?EO05C(Th@`LjAp#@!Q1yb;mP(9*fi4@M_2gZuf*0bY;s~=5y+ZK1ZxPTes2g`}z`p@-k8tXRl8wAmznmE7YX@Zl_ zO$j019Ezg2DE7gC*N@myCtq~dutv>w_C~WC77_>VC=0^zd;D=`jUR54N63FO00S$7 zu)C6&I`NjWv;^|x6VP1Zh2@jJ!@LDYolS21yv$hU)skClu(U9ZIVE}Z#JJ0e6EDb+ zx>6K&Eeyi%x%OV>I&!(ugEb91)@AI8#S>f4O-7Y9m3VRpj@At$o)(Il%w&F^fcgo< zL#cycn(L-UvSwl?J{_kpUcuo6yWKJ`Pv!HHr#BF%E+fvnP_SvicyowN=R^^wk4OLV z(b!vI#_mNC`1~4qBjhl&mU*E#F^RZjFpe)JmRO}{`)R~y1P8R?VuIBOMz%&_wgFg8 zJyuO7Hc7qiDTqRI#U!dCB)H}5u071Fj?x%I>XW&;*P~h`0%1V z-eK+Y7o5un>YQ<|!4CJ;J1R`FX(sV6ViQ9+tl(PPiBC2XbKO3h^^@WV;;qS8uXKvV zuIj034En{;w1XF1J@(g%bG^uP-PtU@b@ButL-CRB$$+l!VZb)DD04U z(r$$rW)LGwhr$bq;~ZL93_rFnd%BM5LgH-E#E|0^US(@{5ECT6C>W|>th?qCKdL3h zRnK}Faj65u(~b~N5{yi+vZLR_%ntK<2s0DBtcQAaQ%}J$+vkkO@eQT$w-{m8xPNwH zOAYOlj!lIz*j|)?mKh1yNu0csW8PJgjGp-^I9Qs3!{zDdCDwMNocIqhrc;ZoI9-*A zGa}WL8sb1TnK;e!QZN!z`YbmRU`7~lyewyGb-LeN}3~DoK-9DDN z;Qa&9@%n#C~EL0e*_2opI-`2A+Ur$WeBIpa^%I2{tO1qM3YwYo{1R4 zkOccPFJXQ!*AZil{GHf$-woYk)ayQ$XAOGYhe6(Y`nxk+MvWjJ&IM0)n()SbCj7@k zfjHE_oS3{S**AS(BoC8k<$ZgW>F~})6F$1G$GZ;);E{GM`H{|CYjpVhmI-C#at2$p zSer;8JA@7Cho3mW`}wW`Q~Q7B=4^V%sBPOLHF>_!s? z))<(xG2b4v*@QSVZg!Y3+`*o?lo1Oj>TtPDkC#sx@a|<39PEdoX`um69}85u({es#(VWx4LmS6%SVgBpB#LyK*- z+$*sC4CbTzHihEB?Hp?pIfJx$A@lk8K=P@1E%qANpvAL?wfOTT?gy`#aCWQBKjir& zj_=!#hhtfx7PUnte0-h!VUJPVql{qPmV3+7CVYC6Yd-CHv4eYTiwkZwo6t}m0Uxst zE2jJ4v&Tl0C#T1aHVxi-K#RwA8}Y^kFT8ol59gc5pe&EMO@celZPwzI<9fVv*<0!E z#d){6H~=5e7TZd-c;Td(zNf*yW#k-Kg(vL9{laiGlIQ=zarzkVd-EcHKgV2QX#5ss zgy5r_-n1F_B=`E_tqY#a5dv{@*H}Dzl=&&g{>9VOV@EV9QpS*{?T1P}GxYqj>@eKf z7l%h%jCf^$HoE8u587;mqdl&$pH0R7sLKfYfh^}U>Uqw++2j(e$&XO-zrbzZ<$oj`EDmTeDuD$$9kjkS^AQ(RhzO_ac4k;TD^J41M?gBcFLyp0%?J KVnq1w%YOlQ3rJAD0eVkhS8!X`Gfl`Smc8`~P%HMGPwc4Jd!XZDEZ?48}(oNonv zO+SLRqLTc8^_7e18OW&gvBIk>{=K$ye>YRXn#Ok38Sl%Sm_5 zUR%ey*0XbK*()2^l{KKAGrqL8y@k@@_rmH>+Kl7=vY~t}S{Hj~P5hGe@fa^HY{vQ5 zct?Kda_Tqywm9_}=afGh(4X;TZ{+89@X`A>$nE;Sd>)Gyh3MGeD@D?na~~EP(eqJn zx%z0GBhEKuR>Do)aAs!@cPPg>_nxG(XyQHeU?-bK=&0Fq;wWTMhm7f=^^8aw5KnEI z^nRwfLdh;Vu83Oc=#g*7e%ChCOQ=2irjN`>iF_SmS3Hl=-GQ&pZb3$SH?XS)wM~r6 z2jRALisIW=E?jelmq?#`iE`a#+M0N;u`kN#xUOE`Q@mA_`&zGa_NGS#&D^%-qio-v zY>~Es=Yq#1B@8)ak34j**gm#YtPe)@iQ<6s->odN==4B~es`ZEkG&&uOn4HSZY>X6 z_M=U{E7ovm{-&d*Tw|R#e&w<(ZH+9{+>se`Dwrv^oA8PXL3>apca=?czyGGJ^JWw61Sa5JIX^NnskCchG z#`$^Lu26%`;8DGsAQ|k|>n%%E;mID!Nb8iQy7|*~bw(emHd)-_ZLRYfc4=**c)%-g z3U)_?O7|^ZZ&ku++K + + + + Debug + Win32 + + + Release + Win32 + + + + {5C7B85D1-E985-4331-862E-B4864324DCB5} + Win32Proj + BlizzGet + + + + Application + true + v120 + MultiByte + + + Application + false + v120 + true + MultiByte + + + + + + + + + + + + + true + + + false + + + + + + Level2 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + ../libs;../src;./ + + + Windows + true + ../libs + comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level2 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + ./;../libs/;../src + MultiThreaded + + + Windows + true + true + true + ../libs + comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + libcmt.lib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vc13/BlizzGet.vcxproj.filters b/vc13/BlizzGet.vcxproj.filters new file mode 100644 index 0000000..cb13f08 --- /dev/null +++ b/vc13/BlizzGet.vcxproj.filters @@ -0,0 +1,226 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {49b335fb-4d74-4e3a-bd5a-30213f6bc659} + + + {77292007-2477-4c3b-8cf3-188ebcd657fb} + + + {21d34fab-6962-4f59-9819-d2078d91e4a7} + + + {a3f7604a-19e5-4519-98cd-d883b7400bac} + + + {7fbda502-e098-492a-a874-85590a929e03} + + + {ca7a40cf-b104-4d1b-bee4-a3b11be5f813} + + + {5bf51ea9-d4c9-43e0-aed6-ef53f22e288d} + + + {7f32c3d0-bdb8-48e1-b2ff-a6f827929e83} + + + {4f824606-2631-4807-a689-de2b0ebe5350} + + + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + Base\Source Files + + + FrameUI\Source Files + + + FrameUI\Source Files + + + FrameUI\Source Files + + + FrameUI\Source Files + + + FrameUI\Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Pages\Source Files + + + Source Files + + + Pages\Source Files + + + FrameUI\Source Files + + + Pages\Source Files + + + Pages\Source Files + + + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + Base\Header Files + + + FrameUI\Header Files + + + FrameUI\Header Files + + + FrameUI\Header Files + + + FrameUI\Header Files + + + FrameUI\Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Pages\Header Files + + + Header Files + + + Pages\Header Files + + + Pages\Header Files + + + FrameUI\Header Files + + + Pages\Header Files + + + + + Resource Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/vc13/resource.h b/vc13/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..e92536404f9bbca8c6cf9dd0491508b47a2b3bc0 GIT binary patch literal 994 zcmb7?-A=+#5QOL2#CK@IrHP380;MH}2!&Wm^r{gAQ$rwWslV~n)o)u6G^BxSPS5UU zcXrNfzrX6L>jMkaQ!HOC^*KS|1@hD;3iXK{>xkOA9CejwtW*nSoT--NhU7Bky4Q@z z(+TG2Q4`HMDfuP$1G$9En5vv;LOdli!#mxY5P?-zkMu@OlZr&|*cJIDwJ8{DMt0W< zG{dra4!nI%%<*_xpa!`^tf4b{s*sy5$wl}_TFEr8<{+QbAR}W{!JE6YBbKu%%j{`-8F1G77Q-^4C4S#>D zV_wm7L#<1-DcaE;C?Vf2`{@yfJN1fJvtxQ%x`jh5!wKn$@I3q&CN2mO{(lWkuk*c; zZQEVUWtv}!>*x|>v)y~%#k>5M2C%mGRdp&Hw_joGftzx8kY E19g^$;s5{u literal 0 HcmV?d00001

v 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 J&4M1=_iwV5@%I1# literal 0 HcmV?d00001 diff --git a/libs/zlib/zlib64d.lib b/libs/zlib/zlib64d.lib new file mode 100644 index 0000000000000000000000000000000000000000..d5970f30585dfdaad9d677cc485d4d4c498e0c92 GIT binary patch literal 275630 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�nmXJI{uAIXUCLBl+giJz%?9N(feN@TQXlVH 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 z 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 literal 0 HcmV?d00001 diff --git a/libs/zlib/zlib64r.lib b/libs/zlib/zlib64r.lib new file mode 100644 index 0000000000000000000000000000000000000000..83db6c0989863a7f4641624cad062ed7657a726d GIT binary patch literal 263836 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