chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// Common/AutoPtr.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_AUTOPTR_H
|
||||
#define ZIP7_INC_COMMON_AUTOPTR_H
|
||||
|
||||
template<class T> class CMyUniquePtr
|
||||
// CMyAutoPtr
|
||||
{
|
||||
T *_p;
|
||||
|
||||
CMyUniquePtr(CMyUniquePtr<T>& p); // : _p(p.release()) {}
|
||||
CMyUniquePtr<T>& operator=(T *p);
|
||||
CMyUniquePtr<T>& operator=(CMyUniquePtr<T>& p);
|
||||
/*
|
||||
{
|
||||
reset(p.release());
|
||||
return (*this);
|
||||
}
|
||||
*/
|
||||
void reset(T* p = NULL)
|
||||
{
|
||||
if (p != _p)
|
||||
delete _p;
|
||||
_p = p;
|
||||
}
|
||||
public:
|
||||
CMyUniquePtr(T *p = NULL) : _p(p) {}
|
||||
~CMyUniquePtr() { delete _p; }
|
||||
T& operator*() const { return *_p; }
|
||||
T* operator->() const { return _p; }
|
||||
// operator bool() const { return _p != NULL; }
|
||||
T* get() const { return _p; }
|
||||
T* release()
|
||||
{
|
||||
T *tmp = _p;
|
||||
_p = NULL;
|
||||
return tmp;
|
||||
}
|
||||
void Create_if_Empty()
|
||||
{
|
||||
if (!_p)
|
||||
_p = new T;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
// Common/CRC.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/7zCrc.h"
|
||||
|
||||
static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;
|
||||
@@ -0,0 +1,3 @@
|
||||
// Common/C_FileIO.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,6 @@
|
||||
// Common/C_FileIO.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_C_FILEIO_H
|
||||
#define ZIP7_INC_COMMON_C_FILEIO_H
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
// CksumReg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
#include "../7zip/Compress/BZip2Crc.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CCksumHasher
|
||||
, IHasher
|
||||
)
|
||||
CBZip2Crc _crc;
|
||||
UInt64 _size;
|
||||
public:
|
||||
// Byte _mtDummy[1 << 7];
|
||||
CCksumHasher()
|
||||
{
|
||||
_crc.Init(0);
|
||||
_size = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CCksumHasher::Init())
|
||||
{
|
||||
_crc.Init(0);
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CCksumHasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
_size += size;
|
||||
CBZip2Crc crc = _crc;
|
||||
for (UInt32 i = 0; i < size; i++)
|
||||
crc.UpdateByte(((const Byte *)data)[i]);
|
||||
_crc = crc;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CCksumHasher::Final(Byte *digest))
|
||||
{
|
||||
UInt64 size = _size;
|
||||
CBZip2Crc crc = _crc;
|
||||
while (size)
|
||||
{
|
||||
crc.UpdateByte((Byte)size);
|
||||
size >>= 8;
|
||||
}
|
||||
const UInt32 val = crc.GetDigest();
|
||||
SetUi32(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
|
||||
@@ -0,0 +1,21 @@
|
||||
// ComTry.h
|
||||
|
||||
#ifndef ZIP7_INC_COM_TRY_H
|
||||
#define ZIP7_INC_COM_TRY_H
|
||||
|
||||
#include "MyWindows.h"
|
||||
// #include "Exception.h"
|
||||
// #include "NewHandler.h"
|
||||
|
||||
#define COM_TRY_BEGIN try {
|
||||
#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
|
||||
|
||||
/*
|
||||
#define COM_TRY_END } \
|
||||
catch(const CNewException &) { return E_OUTOFMEMORY; } \
|
||||
catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \
|
||||
*/
|
||||
// catch(const CSystemException &e) { return e.ErrorCode; }
|
||||
// catch(...) { return E_FAIL; }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,231 @@
|
||||
// CommandLineParser.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "CommandLineParser.h"
|
||||
|
||||
namespace NCommandLineParser {
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
|
||||
{
|
||||
dest1.Empty();
|
||||
dest2.Empty();
|
||||
bool quoteMode = false;
|
||||
unsigned i;
|
||||
for (i = 0; i < src.Len(); i++)
|
||||
{
|
||||
const wchar_t c = src[i];
|
||||
if ((c == L' ' || c == L'\t') && !quoteMode)
|
||||
{
|
||||
dest2 = src.Ptr(i + 1);
|
||||
return i != 0;
|
||||
}
|
||||
if (c == L'\"')
|
||||
quoteMode = !quoteMode;
|
||||
else
|
||||
dest1 += c;
|
||||
}
|
||||
return i != 0;
|
||||
}
|
||||
|
||||
void SplitCommandLine(const UString &s, UStringVector &parts)
|
||||
{
|
||||
#if 0
|
||||
/* we don't use CommandLineToArgvW() because
|
||||
it can remove tail backslash:
|
||||
"1\"
|
||||
converted to
|
||||
1"
|
||||
*/
|
||||
parts.Clear();
|
||||
{
|
||||
int nArgs;
|
||||
LPWSTR *szArgList = CommandLineToArgvW(s, &nArgs);
|
||||
if (szArgList)
|
||||
{
|
||||
for (int i = 0; i < nArgs; i++)
|
||||
{
|
||||
// printf("%2d: |%S|\n", i, szArglist[i]);
|
||||
parts.Add(szArgList[i]);
|
||||
}
|
||||
LocalFree(szArgList);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
#ifdef _UNICODE
|
||||
throw 20240406;
|
||||
#else
|
||||
*/
|
||||
UString sTemp (s);
|
||||
sTemp.Trim();
|
||||
parts.Clear();
|
||||
for (;;)
|
||||
{
|
||||
UString s1, s2;
|
||||
if (SplitCommandLine(sTemp, s1, s2))
|
||||
parts.Add(s1);
|
||||
if (s2.IsEmpty())
|
||||
break;
|
||||
sTemp = s2;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static const char * const kStopSwitchParsing = "--";
|
||||
|
||||
static bool inline IsItSwitchChar(wchar_t c)
|
||||
{
|
||||
return (c == '-');
|
||||
}
|
||||
|
||||
CParser::CParser():
|
||||
_switches(NULL),
|
||||
StopSwitchIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
CParser::~CParser()
|
||||
{
|
||||
delete []_switches;
|
||||
}
|
||||
|
||||
|
||||
// if (s) contains switch then function updates switch structures
|
||||
// out: true, if (s) is a switch
|
||||
bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
|
||||
{
|
||||
if (s.IsEmpty() || !IsItSwitchChar(s[0]))
|
||||
return false;
|
||||
|
||||
unsigned pos = 1;
|
||||
unsigned switchIndex = 0;
|
||||
int maxLen = -1;
|
||||
|
||||
for (unsigned i = 0; i < numSwitches; i++)
|
||||
{
|
||||
const char * const key = switchForms[i].Key;
|
||||
const unsigned switchLen = MyStringLen(key);
|
||||
if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
|
||||
continue;
|
||||
if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
|
||||
{
|
||||
switchIndex = i;
|
||||
maxLen = (int)switchLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxLen < 0)
|
||||
{
|
||||
ErrorMessage = "Unknown switch:";
|
||||
return false;
|
||||
}
|
||||
|
||||
pos += (unsigned)maxLen;
|
||||
|
||||
CSwitchResult &sw = _switches[switchIndex];
|
||||
const CSwitchForm &form = switchForms[switchIndex];
|
||||
|
||||
if (!form.Multi && sw.ThereIs)
|
||||
{
|
||||
ErrorMessage = "Multiple instances for switch:";
|
||||
return false;
|
||||
}
|
||||
|
||||
sw.ThereIs = true;
|
||||
|
||||
const unsigned rem = s.Len() - pos;
|
||||
if (rem < form.MinLen)
|
||||
{
|
||||
ErrorMessage = "Too short switch:";
|
||||
return false;
|
||||
}
|
||||
|
||||
sw.WithMinus = false;
|
||||
sw.PostCharIndex = -1;
|
||||
|
||||
switch (form.Type)
|
||||
{
|
||||
case NSwitchType::kMinus:
|
||||
if (rem == 1)
|
||||
{
|
||||
sw.WithMinus = (s[pos] == '-');
|
||||
if (sw.WithMinus)
|
||||
return true;
|
||||
ErrorMessage = "Incorrect switch postfix:";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NSwitchType::kChar:
|
||||
if (rem == 1)
|
||||
{
|
||||
const wchar_t c = s[pos];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
|
||||
if (sw.PostCharIndex >= 0)
|
||||
return true;
|
||||
}
|
||||
ErrorMessage = "Incorrect switch postfix:";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NSwitchType::kString:
|
||||
{
|
||||
sw.PostStrings.Add(s.Ptr(pos));
|
||||
return true;
|
||||
}
|
||||
// case NSwitchType::kSimple:
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (pos != s.Len())
|
||||
{
|
||||
ErrorMessage = "Too long switch:";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
|
||||
{
|
||||
StopSwitchIndex = -1;
|
||||
ErrorMessage.Empty();
|
||||
ErrorLine.Empty();
|
||||
NonSwitchStrings.Clear();
|
||||
delete []_switches;
|
||||
_switches = NULL;
|
||||
_switches = new CSwitchResult[numSwitches];
|
||||
|
||||
FOR_VECTOR (i, commandStrings)
|
||||
{
|
||||
const UString &s = commandStrings[i];
|
||||
if (StopSwitchIndex < 0)
|
||||
{
|
||||
if (s.IsEqualTo(kStopSwitchParsing))
|
||||
{
|
||||
StopSwitchIndex = (int)NonSwitchStrings.Size();
|
||||
continue;
|
||||
}
|
||||
if (!s.IsEmpty() && IsItSwitchChar(s[0]))
|
||||
{
|
||||
if (ParseString(s, switchForms, numSwitches))
|
||||
continue;
|
||||
ErrorLine = s;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
NonSwitchStrings.Add(s);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Common/CommandLineParser.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H
|
||||
#define ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
namespace NCommandLineParser {
|
||||
|
||||
bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
|
||||
void SplitCommandLine(const UString &s, UStringVector &parts);
|
||||
|
||||
namespace NSwitchType
|
||||
{
|
||||
enum EEnum
|
||||
{
|
||||
kSimple,
|
||||
kMinus,
|
||||
kString,
|
||||
kChar
|
||||
};
|
||||
}
|
||||
|
||||
struct CSwitchForm
|
||||
{
|
||||
const char *Key;
|
||||
Byte Type;
|
||||
bool Multi;
|
||||
Byte MinLen;
|
||||
// int MaxLen;
|
||||
const char *PostCharSet;
|
||||
};
|
||||
|
||||
struct CSwitchResult
|
||||
{
|
||||
bool ThereIs;
|
||||
bool WithMinus;
|
||||
int PostCharIndex;
|
||||
UStringVector PostStrings;
|
||||
|
||||
CSwitchResult(): ThereIs(false) {}
|
||||
};
|
||||
|
||||
class CParser
|
||||
{
|
||||
CSwitchResult *_switches;
|
||||
|
||||
bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches);
|
||||
public:
|
||||
UStringVector NonSwitchStrings;
|
||||
int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--"
|
||||
AString ErrorMessage;
|
||||
UString ErrorLine;
|
||||
|
||||
CParser();
|
||||
~CParser();
|
||||
bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings);
|
||||
const CSwitchResult& operator[](unsigned index) const { return _switches[index]; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// Common.h
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_H
|
||||
#define ZIP7_INC_COMMON_H
|
||||
|
||||
#include "../../C/Precomp.h"
|
||||
#include "Common0.h"
|
||||
#include "MyWindows.h"
|
||||
|
||||
/*
|
||||
This file is included to all cpp files in 7-Zip.
|
||||
Each folder contains StdAfx.h file that includes "Common.h".
|
||||
So 7-Zip includes "Common.h" in both modes:
|
||||
with precompiled StdAfx.h
|
||||
and
|
||||
without precompiled StdAfx.h
|
||||
|
||||
include "Common.h" before other h files of 7-zip,
|
||||
if you need predefined macros.
|
||||
do not include "Common.h", if you need only interfaces,
|
||||
and you don't need predefined macros.
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,330 @@
|
||||
// Common0.h
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
|
||||
#ifndef ZIP7_INC_COMMON0_H
|
||||
#define ZIP7_INC_COMMON0_H
|
||||
|
||||
#include "../../C/Compiler.h"
|
||||
|
||||
/*
|
||||
This file contains compiler related things for cpp files.
|
||||
This file is included to all cpp files in 7-Zip via "Common.h".
|
||||
Also this file is included in "IDecl.h" (that is included in interface files).
|
||||
So external modules can use 7-Zip interfaces without
|
||||
predefined macros defined in "Common.h".
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4710) // function not inlined
|
||||
// 'CUncopyable::CUncopyable':
|
||||
#pragma warning(disable : 4514) // unreferenced inline function has been removed
|
||||
#if _MSC_VER < 1300
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#pragma warning(disable : 4714) // function marked as __forceinline not inlined
|
||||
#pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information
|
||||
#endif
|
||||
#if _MSC_VER < 1400
|
||||
#pragma warning(disable : 4511) // copy constructor could not be generated // #pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning(disable : 4512) // assignment operator could not be generated
|
||||
#endif
|
||||
#if _MSC_VER > 1400 && _MSC_VER <= 1900
|
||||
// #pragma warning(disable : 4996)
|
||||
// strcat: This function or variable may be unsafe
|
||||
// GetVersion was declared deprecated
|
||||
#endif
|
||||
|
||||
#if _MSC_VER > 1200
|
||||
// -Wall warnings
|
||||
|
||||
#if _MSC_VER <= 1600
|
||||
#pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace
|
||||
#endif
|
||||
|
||||
// #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label
|
||||
// #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden
|
||||
#pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
|
||||
#pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
|
||||
#if _MSC_VER >= 1600 && _MSC_VER < 1920
|
||||
#pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught
|
||||
#endif
|
||||
#if _MSC_VER >= 1600
|
||||
#pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch
|
||||
#endif
|
||||
#if _MSC_VER < 1800
|
||||
// we disable the warning, if we don't use 'final' in class
|
||||
#pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
#pragma warning(disable : 5026) // move constructor was implicitly defined as deleted
|
||||
#pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted
|
||||
#endif
|
||||
#if _MSC_VER >= 1912
|
||||
#pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern "C"' function under - EHc.Undefined behavior may occur if this function throws an exception.
|
||||
#endif
|
||||
#if _MSC_VER >= 1925
|
||||
// #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly
|
||||
#endif
|
||||
#if _MSC_VER >= 1934
|
||||
// #pragma warning(disable : 5264) // const variable is not used
|
||||
#endif
|
||||
|
||||
#endif // _MSC_VER > 1200
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#if defined(_MSC_VER) // && !defined(__clang__)
|
||||
#define Z7_DECLSPEC_NOTHROW __declspec(nothrow)
|
||||
#elif defined(__clang__) || defined(__GNUC__)
|
||||
#define Z7_DECLSPEC_NOTHROW __attribute__((nothrow))
|
||||
#else
|
||||
#define Z7_DECLSPEC_NOTHROW
|
||||
#endif
|
||||
|
||||
/*
|
||||
#if defined (_MSC_VER) && _MSC_VER >= 1900 \
|
||||
|| defined(__clang__) && __clang_major__ >= 6 \
|
||||
|| defined(__GNUC__) && __GNUC__ >= 6
|
||||
#define Z7_noexcept noexcept
|
||||
#else
|
||||
#define Z7_noexcept throw()
|
||||
#endif
|
||||
*/
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
|
||||
#if /* defined(_WIN32) && */ __clang_major__ >= 16
|
||||
#pragma GCC diagnostic ignored "-Wc++98-compat-pedantic"
|
||||
#endif
|
||||
|
||||
#if __clang_major__ >= 4 && __clang_major__ < 12 && !defined(_WIN32)
|
||||
/*
|
||||
if compiled with new GCC libstdc++, GCC libstdc++ can use:
|
||||
13.2.0/include/c++/
|
||||
<new> : #define _NEW
|
||||
<stdlib.h> : #define _GLIBCXX_STDLIB_H 1
|
||||
*/
|
||||
#pragma GCC diagnostic ignored "-Wreserved-id-macro"
|
||||
#endif
|
||||
|
||||
// noexcept, final, = delete
|
||||
#pragma GCC diagnostic ignored "-Wc++98-compat"
|
||||
#if __clang_major__ >= 4
|
||||
// throw() dynamic exception specifications are deprecated
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
|
||||
#endif
|
||||
|
||||
#if __clang_major__ <= 6 // check it
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#pragma GCC diagnostic ignored "-Wglobal-constructors"
|
||||
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
|
||||
|
||||
#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 // 18.1.0RC
|
||||
#pragma GCC diagnostic ignored "-Wswitch-default"
|
||||
#endif
|
||||
// #pragma GCC diagnostic ignored "-Wunused-private-field"
|
||||
// #pragma GCC diagnostic ignored "-Wnonportable-system-include-path"
|
||||
// #pragma GCC diagnostic ignored "-Wsuggest-override"
|
||||
// #pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
// #pragma GCC diagnostic ignored "-Winconsistent-missing-override"
|
||||
// #pragma GCC diagnostic ignored "-Wsuggest-destructor-override"
|
||||
// #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
// #pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-dtor"
|
||||
// #pragma GCC diagnostic ignored "-Wdeprecated-copy-dtor"
|
||||
// #ifndef _WIN32
|
||||
// #pragma GCC diagnostic ignored "-Wweak-vtables"
|
||||
// #endif
|
||||
/*
|
||||
#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40400) \
|
||||
|| defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)
|
||||
// enumeration values not explicitly handled in switch
|
||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||
#endif
|
||||
*/
|
||||
#endif // __clang__
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
// #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||
#endif
|
||||
|
||||
|
||||
/* There is BUG in MSVC 6.0 compiler for operator new[]:
|
||||
It doesn't check overflow, when it calculates size in bytes for allocated array.
|
||||
So we can use Z7_ARRAY_NEW macro instead of new[] operator. */
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
|
||||
#define Z7_ARRAY_NEW(p, T, size) p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)];
|
||||
#else
|
||||
#define Z7_ARRAY_NEW(p, T, size) p = new T[size];
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 8))
|
||||
#define Z7_ATTR_NORETURN __attribute__((noreturn))
|
||||
#elif (defined(__clang__) && (__clang_major__ >= 3))
|
||||
#if __has_feature(cxx_attributes)
|
||||
#define Z7_ATTR_NORETURN [[noreturn]]
|
||||
#else
|
||||
#define Z7_ATTR_NORETURN __attribute__((noreturn))
|
||||
#endif
|
||||
#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
|
||||
#define Z7_ATTR_NORETURN [[noreturn]]
|
||||
#else
|
||||
#define Z7_ATTR_NORETURN
|
||||
#endif
|
||||
|
||||
|
||||
// final in "GCC 4.7.0"
|
||||
// In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.)
|
||||
|
||||
#if defined (__cplusplus) && __cplusplus >= 201103L \
|
||||
|| defined(_MSC_VER) && _MSC_VER >= 1800 \
|
||||
|| defined(__clang__) && __clang_major__ >= 4 \
|
||||
/* || defined(__GNUC__) && __GNUC__ >= 9 */
|
||||
#define Z7_final final
|
||||
#if defined(__clang__) && __cplusplus < 201103L
|
||||
#pragma GCC diagnostic ignored "-Wc++11-extensions"
|
||||
#endif
|
||||
#elif defined (__cplusplus) && __cplusplus >= 199711L \
|
||||
&& defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)
|
||||
#define Z7_final __final
|
||||
#else
|
||||
#define Z7_final
|
||||
#if defined(__clang__) && __clang_major__ >= 4 \
|
||||
|| defined(__GNUC__) && __GNUC__ >= 4
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define Z7_class_final(c) class c Z7_final
|
||||
|
||||
|
||||
#if defined (__cplusplus) && __cplusplus >= 201103L \
|
||||
|| (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#define Z7_CPP_IS_SUPPORTED_default
|
||||
#define Z7_eq_delete = delete
|
||||
// #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default;
|
||||
#else
|
||||
#define Z7_eq_delete
|
||||
// #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201103L) \
|
||||
|| defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \
|
||||
|| defined(__clang__) && __clang_major__ >= 4
|
||||
#if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */
|
||||
#pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override'
|
||||
#define Z7_DESTRUCTOR_override
|
||||
#else
|
||||
#define Z7_DESTRUCTOR_override override
|
||||
#endif
|
||||
#define Z7_override override
|
||||
#else
|
||||
#define Z7_override
|
||||
#define Z7_DESTRUCTOR_override
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define Z7_CLASS_NO_COPY(cls) \
|
||||
private: \
|
||||
cls(const cls &) Z7_eq_delete; \
|
||||
cls &operator=(const cls &) Z7_eq_delete;
|
||||
|
||||
class CUncopyable
|
||||
{
|
||||
protected:
|
||||
CUncopyable() {} // allow constructor
|
||||
// ~CUncopyable() {}
|
||||
Z7_CLASS_NO_COPY(CUncopyable)
|
||||
};
|
||||
|
||||
#define MY_UNCOPYABLE :private CUncopyable
|
||||
// #define MY_UNCOPYABLE
|
||||
|
||||
|
||||
// typedef void (*Z7_void_Function)(void);
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<Z7_void_Function>(e))
|
||||
#else
|
||||
#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<void*>(e))
|
||||
// #define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(e)
|
||||
#endif
|
||||
|
||||
#define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name) \
|
||||
Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name))
|
||||
|
||||
// || defined(__clang__)
|
||||
// || defined(__GNUC__)
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define Z7_DECLSPEC_NOVTABLE __declspec(novtable)
|
||||
#else
|
||||
#define Z7_DECLSPEC_NOVTABLE
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#define Z7_PURE_INTERFACES_BEGIN \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
|
||||
_Pragma("GCC diagnostic ignored \"-Wweak-vtables\"")
|
||||
#define Z7_PURE_INTERFACES_END \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
#else
|
||||
#define Z7_PURE_INTERFACES_BEGIN
|
||||
#define Z7_PURE_INTERFACES_END
|
||||
#endif
|
||||
|
||||
// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
|
||||
#include "NewHandler.h"
|
||||
|
||||
/*
|
||||
// #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) Z7_ARRAY_SIZE(a)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif // ZIP7_INC_COMMON0_H
|
||||
|
||||
|
||||
|
||||
// #define Z7_REDEFINE_NULL
|
||||
|
||||
#if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */
|
||||
|
||||
// NULL is defined in <stddef.h>
|
||||
#include <stddef.h>
|
||||
#undef NULL
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined (__cplusplus) && __cplusplus >= 201103L \
|
||||
|| (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#define NULL nullptr
|
||||
#else
|
||||
#define NULL 0
|
||||
#endif
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#else // Z7_REDEFINE_NULL
|
||||
|
||||
#if defined(__clang__) && __clang_major__ >= 5
|
||||
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
|
||||
#endif
|
||||
|
||||
#endif // Z7_REDEFINE_NULL
|
||||
|
||||
// for precompiler:
|
||||
// #include "MyWindows.h"
|
||||
@@ -0,0 +1,77 @@
|
||||
// CrcReg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/7zCrc.h"
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CCrcHasher
|
||||
, IHasher
|
||||
, ICompressSetCoderProperties
|
||||
)
|
||||
UInt32 _crc;
|
||||
Z7_CRC_UPDATE_FUNC _updateFunc;
|
||||
|
||||
Z7_CLASS_NO_COPY(CCrcHasher)
|
||||
|
||||
bool SetFunctions(UInt32 tSize);
|
||||
public:
|
||||
Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
|
||||
|
||||
CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }
|
||||
};
|
||||
|
||||
bool CCrcHasher::SetFunctions(UInt32 tSize)
|
||||
{
|
||||
const Z7_CRC_UPDATE_FUNC f = z7_GetFunc_CrcUpdate(tSize);
|
||||
if (!f)
|
||||
{
|
||||
_updateFunc = CrcUpdate;
|
||||
return false;
|
||||
}
|
||||
_updateFunc = f;
|
||||
return true;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
|
||||
{
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
if (propIDs[i] == NCoderPropID::kDefaultProp)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (!SetFunctions(prop.ulVal))
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CCrcHasher::Init())
|
||||
{
|
||||
_crc = CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CCrcHasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
_crc = _updateFunc(_crc, data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CCrcHasher::Final(Byte *digest))
|
||||
{
|
||||
const UInt32 val = CRC_GET_DIGEST(_crc);
|
||||
SetUi32(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)
|
||||
@@ -0,0 +1,16 @@
|
||||
// Common/Defs.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_DEFS_H
|
||||
#define ZIP7_INC_COMMON_DEFS_H
|
||||
|
||||
template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; }
|
||||
template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; }
|
||||
|
||||
template <class T> inline int MyCompare(T a, T b)
|
||||
{ return a == b ? 0 : (a < b ? -1 : 1); }
|
||||
|
||||
inline int BoolToInt(bool v) { return (v ? 1 : 0); }
|
||||
inline unsigned BoolToUInt(bool v) { return (v ? 1u : 0u); }
|
||||
inline bool IntToBool(int v) { return (v != 0); }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
// Common/DynLimBuf.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "DynLimBuf.h"
|
||||
#include "MyString.h"
|
||||
|
||||
CDynLimBuf::CDynLimBuf(size_t limit) throw()
|
||||
{
|
||||
_chars = NULL;
|
||||
_pos = 0;
|
||||
_size = 0;
|
||||
_sizeLimit = limit;
|
||||
_error = true;
|
||||
unsigned size = 1 << 4;
|
||||
if (size > limit)
|
||||
size = (unsigned)limit;
|
||||
_chars = (Byte *)MyAlloc(size);
|
||||
if (_chars)
|
||||
{
|
||||
_size = size;
|
||||
_error = false;
|
||||
}
|
||||
}
|
||||
|
||||
CDynLimBuf & CDynLimBuf::operator+=(char c) throw()
|
||||
{
|
||||
if (_error)
|
||||
return *this;
|
||||
if (_size == _pos)
|
||||
{
|
||||
size_t n = _sizeLimit - _size;
|
||||
if (n == 0)
|
||||
{
|
||||
_error = true;
|
||||
return *this;
|
||||
}
|
||||
if (n > _size)
|
||||
n = _size;
|
||||
|
||||
n += _pos;
|
||||
|
||||
Byte *newBuf = (Byte *)MyAlloc(n);
|
||||
if (!newBuf)
|
||||
{
|
||||
_error = true;
|
||||
return *this;
|
||||
}
|
||||
memcpy(newBuf, _chars, _pos);
|
||||
MyFree(_chars);
|
||||
_chars = newBuf;
|
||||
_size = n;
|
||||
}
|
||||
_chars[_pos++] = (Byte)c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
CDynLimBuf &CDynLimBuf::operator+=(const char *s) throw()
|
||||
{
|
||||
if (_error)
|
||||
return *this;
|
||||
unsigned len = MyStringLen(s);
|
||||
size_t rem = _sizeLimit - _pos;
|
||||
if (rem < len)
|
||||
{
|
||||
len = (unsigned)rem;
|
||||
_error = true;
|
||||
}
|
||||
if (_size - _pos < len)
|
||||
{
|
||||
size_t n = _pos + len;
|
||||
if (n - _size < _size)
|
||||
{
|
||||
n = _sizeLimit;
|
||||
if (n - _size > _size)
|
||||
n = _size * 2;
|
||||
}
|
||||
|
||||
Byte *newBuf = (Byte *)MyAlloc(n);
|
||||
if (!newBuf)
|
||||
{
|
||||
_error = true;
|
||||
return *this;
|
||||
}
|
||||
memcpy(newBuf, _chars, _pos);
|
||||
MyFree(_chars);
|
||||
_chars = newBuf;
|
||||
_size = n;
|
||||
}
|
||||
memcpy(_chars + _pos, s, len);
|
||||
_pos += len;
|
||||
return *this;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
// Common/DynLimBuf.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_DYN_LIM_BUF_H
|
||||
#define ZIP7_INC_COMMON_DYN_LIM_BUF_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "../../C/Alloc.h"
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
class CDynLimBuf
|
||||
{
|
||||
Byte *_chars;
|
||||
size_t _pos;
|
||||
size_t _size;
|
||||
size_t _sizeLimit;
|
||||
bool _error;
|
||||
|
||||
CDynLimBuf(const CDynLimBuf &s);
|
||||
|
||||
// ---------- forbidden functions ----------
|
||||
CDynLimBuf &operator+=(wchar_t c);
|
||||
|
||||
public:
|
||||
CDynLimBuf(size_t limit) throw();
|
||||
~CDynLimBuf() { MyFree(_chars); }
|
||||
|
||||
size_t Len() const { return _pos; }
|
||||
bool IsError() const { return _error; }
|
||||
void Empty() { _pos = 0; _error = false; }
|
||||
|
||||
operator const Byte *() const { return _chars; }
|
||||
// const char *Ptr() const { return _chars; }
|
||||
|
||||
CDynLimBuf &operator+=(char c) throw();
|
||||
CDynLimBuf &operator+=(const char *s) throw();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
// Common/DynamicBuffer.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_DYNAMIC_BUFFER_H
|
||||
#define ZIP7_INC_COMMON_DYNAMIC_BUFFER_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MyTypes.h"
|
||||
|
||||
template <class T> class CDynamicBuffer
|
||||
{
|
||||
T *_items;
|
||||
size_t _size;
|
||||
size_t _pos;
|
||||
|
||||
CDynamicBuffer(const CDynamicBuffer &buffer);
|
||||
void operator=(const CDynamicBuffer &buffer);
|
||||
|
||||
void Grow(size_t size)
|
||||
{
|
||||
size_t delta = _size >= 64 ? _size : 64;
|
||||
if (delta < size)
|
||||
delta = size;
|
||||
size_t newCap = _size + delta;
|
||||
if (newCap < delta)
|
||||
{
|
||||
newCap = _size + size;
|
||||
if (newCap < size)
|
||||
throw 20120116;
|
||||
}
|
||||
|
||||
T *newBuffer = new T[newCap];
|
||||
if (_pos != 0)
|
||||
memcpy(newBuffer, _items, _pos * sizeof(T));
|
||||
delete []_items;
|
||||
_items = newBuffer;
|
||||
_size = newCap;
|
||||
}
|
||||
|
||||
public:
|
||||
CDynamicBuffer(): _items(NULL), _size(0), _pos(0) {}
|
||||
// operator T *() { return _items; }
|
||||
operator const T *() const { return _items; }
|
||||
~CDynamicBuffer() { delete []_items; }
|
||||
|
||||
void Free()
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
_size = 0;
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
T *GetCurPtrAndGrow(size_t addSize)
|
||||
{
|
||||
size_t rem = _size - _pos;
|
||||
if (rem < addSize)
|
||||
Grow(addSize - rem);
|
||||
T *res = _items + _pos;
|
||||
_pos += addSize;
|
||||
return res;
|
||||
}
|
||||
|
||||
void AddData(const T *data, size_t size)
|
||||
{
|
||||
memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));
|
||||
}
|
||||
|
||||
size_t GetPos() const { return _pos; }
|
||||
|
||||
// void Empty() { _pos = 0; }
|
||||
};
|
||||
|
||||
typedef CDynamicBuffer<Byte> CByteDynamicBuffer;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,215 @@
|
||||
// Common/IntToString.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#include "IntToString.h"
|
||||
|
||||
#define CONVERT_INT_TO_STR(charType, tempSize) \
|
||||
if (val < 10) \
|
||||
*s++ = (charType)('0' + (unsigned)val); \
|
||||
else { \
|
||||
Byte temp[tempSize]; \
|
||||
size_t i = 0; \
|
||||
do { \
|
||||
temp[++i] = (Byte)('0' + (unsigned)(val % 10)); \
|
||||
val /= 10; } \
|
||||
while (val >= 10); \
|
||||
*s++ = (charType)('0' + (unsigned)val); \
|
||||
do { *s++ = (charType)temp[i]; } \
|
||||
while (--i); \
|
||||
} \
|
||||
*s = 0; \
|
||||
return s;
|
||||
|
||||
char * ConvertUInt32ToString(UInt32 val, char *s) throw()
|
||||
{
|
||||
CONVERT_INT_TO_STR(char, 16)
|
||||
}
|
||||
|
||||
char * ConvertUInt64ToString(UInt64 val, char *s) throw()
|
||||
{
|
||||
if (val <= (UInt32)0xFFFFFFFF)
|
||||
return ConvertUInt32ToString((UInt32)val, s);
|
||||
CONVERT_INT_TO_STR(char, 24)
|
||||
}
|
||||
|
||||
wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()
|
||||
{
|
||||
CONVERT_INT_TO_STR(wchar_t, 16)
|
||||
}
|
||||
|
||||
wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()
|
||||
{
|
||||
if (val <= (UInt32)0xFFFFFFFF)
|
||||
return ConvertUInt32ToString((UInt32)val, s);
|
||||
CONVERT_INT_TO_STR(wchar_t, 24)
|
||||
}
|
||||
|
||||
void ConvertInt64ToString(Int64 val, char *s) throw()
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*s++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
ConvertUInt64ToString((UInt64)val, s);
|
||||
}
|
||||
|
||||
void ConvertInt64ToString(Int64 val, wchar_t *s) throw()
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*s++ = L'-';
|
||||
val = -val;
|
||||
}
|
||||
ConvertUInt64ToString((UInt64)val, s);
|
||||
}
|
||||
|
||||
|
||||
void ConvertUInt64ToOct(UInt64 val, char *s) throw()
|
||||
{
|
||||
{
|
||||
UInt64 v = val;
|
||||
do
|
||||
s++;
|
||||
while (v >>= 3);
|
||||
}
|
||||
*s = 0;
|
||||
do
|
||||
{
|
||||
const unsigned t = (unsigned)val & 7;
|
||||
*--s = (char)('0' + t);
|
||||
}
|
||||
while (val >>= 3);
|
||||
}
|
||||
|
||||
MY_ALIGN(16) const char k_Hex_Upper[16] =
|
||||
{ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
|
||||
MY_ALIGN(16) const char k_Hex_Lower[16] =
|
||||
{ '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
|
||||
|
||||
void ConvertUInt32ToHex(UInt32 val, char *s) throw()
|
||||
{
|
||||
{
|
||||
UInt32 v = val;
|
||||
do
|
||||
s++;
|
||||
while (v >>= 4);
|
||||
}
|
||||
*s = 0;
|
||||
do
|
||||
{
|
||||
const unsigned t = (unsigned)val & 0xF;
|
||||
*--s = GET_HEX_CHAR_UPPER(t);
|
||||
}
|
||||
while (val >>= 4);
|
||||
}
|
||||
|
||||
void ConvertUInt64ToHex(UInt64 val, char *s) throw()
|
||||
{
|
||||
{
|
||||
UInt64 v = val;
|
||||
do
|
||||
s++;
|
||||
while (v >>= 4);
|
||||
}
|
||||
*s = 0;
|
||||
do
|
||||
{
|
||||
const unsigned t = (unsigned)val & 0xF;
|
||||
*--s = GET_HEX_CHAR_UPPER(t);
|
||||
}
|
||||
while (val >>= 4);
|
||||
}
|
||||
|
||||
void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()
|
||||
{
|
||||
s[8] = 0;
|
||||
int i = 7;
|
||||
do
|
||||
{
|
||||
{ const unsigned t = (unsigned)val & 0xF; s[i--] = GET_HEX_CHAR_UPPER(t); }
|
||||
{ const unsigned t = (Byte)val >> 4; val >>= 8; s[i--] = GET_HEX_CHAR_UPPER(t); }
|
||||
}
|
||||
while (i >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s)
|
||||
{
|
||||
s[8] = 0;
|
||||
for (int i = 7; i >= 0; i--)
|
||||
{
|
||||
const unsigned t = (unsigned)val & 0xF;
|
||||
val >>= 4;
|
||||
s[i] = GET_HEX_CHAR(t);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
MY_ALIGN(16) static const Byte k_Guid_Pos[] =
|
||||
{ 6,4,2,0, 11,9, 16,14, 19,21, 24,26,28,30,32,34 };
|
||||
|
||||
char *RawLeGuidToString(const Byte *g, char *s) throw()
|
||||
{
|
||||
s[ 8] = '-';
|
||||
s[13] = '-';
|
||||
s[18] = '-';
|
||||
s[23] = '-';
|
||||
s[36] = 0;
|
||||
for (unsigned i = 0; i < 16; i++)
|
||||
{
|
||||
char *s2 = s + k_Guid_Pos[i];
|
||||
const unsigned v = g[i];
|
||||
s2[0] = GET_HEX_CHAR_UPPER(v >> 4);
|
||||
s2[1] = GET_HEX_CHAR_UPPER(v & 0xF);
|
||||
}
|
||||
return s + 36;
|
||||
}
|
||||
|
||||
char *RawLeGuidToString_Braced(const Byte *g, char *s) throw()
|
||||
{
|
||||
*s++ = '{';
|
||||
s = RawLeGuidToString(g, s);
|
||||
*s++ = '}';
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw()
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
const Byte *lim = src + size;
|
||||
do
|
||||
{
|
||||
const unsigned b = *src++;
|
||||
dest[0] = GET_HEX_CHAR_LOWER(b >> 4);
|
||||
dest[1] = GET_HEX_CHAR_LOWER(b & 0xF);
|
||||
dest += 2;
|
||||
}
|
||||
while (src != lim);
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
|
||||
void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw()
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
const Byte *lim = src + size;
|
||||
do
|
||||
{
|
||||
const unsigned b = *src++;
|
||||
dest[0] = GET_HEX_CHAR_UPPER(b >> 4);
|
||||
dest[1] = GET_HEX_CHAR_UPPER(b & 0xF);
|
||||
dest += 2;
|
||||
}
|
||||
while (src != lim);
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Common/IntToString.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_INT_TO_STRING_H
|
||||
#define ZIP7_INC_COMMON_INT_TO_STRING_H
|
||||
|
||||
#include "MyTypes.h"
|
||||
|
||||
// return: the pointer to the "terminating" null character after written characters
|
||||
|
||||
char * ConvertUInt32ToString(UInt32 value, char *s) throw();
|
||||
char * ConvertUInt64ToString(UInt64 value, char *s) throw();
|
||||
|
||||
wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();
|
||||
wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();
|
||||
void ConvertInt64ToString(Int64 value, char *s) throw();
|
||||
void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
|
||||
|
||||
void ConvertUInt64ToOct(UInt64 value, char *s) throw();
|
||||
|
||||
extern const char k_Hex_Upper[16];
|
||||
extern const char k_Hex_Lower[16];
|
||||
|
||||
#define GET_HEX_CHAR_UPPER(t) (k_Hex_Upper[t])
|
||||
#define GET_HEX_CHAR_LOWER(t) (k_Hex_Lower[t])
|
||||
/*
|
||||
// #define GET_HEX_CHAR_UPPER(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
|
||||
static inline unsigned GetHex_Lower(unsigned v)
|
||||
{
|
||||
const unsigned v0 = v + '0';
|
||||
v += 'a' - 10;
|
||||
if (v < 'a')
|
||||
v = v0;
|
||||
return v;
|
||||
}
|
||||
static inline char GetHex_Upper(unsigned v)
|
||||
{
|
||||
return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void ConvertUInt32ToHex(UInt32 value, char *s) throw();
|
||||
void ConvertUInt64ToHex(UInt64 value, char *s) throw();
|
||||
void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();
|
||||
// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();
|
||||
|
||||
// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.
|
||||
char *RawLeGuidToString(const Byte *guid, char *s) throw();
|
||||
char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();
|
||||
|
||||
void ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw();
|
||||
void ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
// Common/Lang.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Lang.h"
|
||||
#include "StringToInt.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
#include "../Windows/FileIO.h"
|
||||
|
||||
void CLang::Clear() throw()
|
||||
{
|
||||
_ids.Clear();
|
||||
_offsets.Clear();
|
||||
Comments.Clear();
|
||||
delete []_text;
|
||||
_text = NULL;
|
||||
}
|
||||
|
||||
static const char * const kLangSignature = ";!@Lang2@!UTF-8!\n";
|
||||
|
||||
bool CLang::OpenFromString(const AString &s2)
|
||||
{
|
||||
UString su;
|
||||
if (!ConvertUTF8ToUnicode(s2, su))
|
||||
return false;
|
||||
if (su.IsEmpty())
|
||||
return false;
|
||||
const wchar_t *s = su;
|
||||
const wchar_t *sLim = s + su.Len();
|
||||
if (*s == 0xFEFF)
|
||||
s++;
|
||||
for (const char *p = kLangSignature;; s++)
|
||||
{
|
||||
const Byte c = (Byte)(*p++);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (*s != c)
|
||||
return false;
|
||||
}
|
||||
|
||||
wchar_t *text = new wchar_t[(size_t)(sLim - s) + 1];
|
||||
_text = text;
|
||||
|
||||
UString comment;
|
||||
Int32 id = -1024;
|
||||
unsigned pos = 0;
|
||||
|
||||
while (s != sLim)
|
||||
{
|
||||
const unsigned start = pos;
|
||||
do
|
||||
{
|
||||
wchar_t c = *s++;
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c == '\\')
|
||||
{
|
||||
if (s == sLim)
|
||||
return false;
|
||||
c = *s++;
|
||||
switch (c)
|
||||
{
|
||||
case '\n': return false;
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case '\\': /* c = '\\'; */ break;
|
||||
default: text[pos++] = L'\\'; break;
|
||||
}
|
||||
}
|
||||
text[pos++] = c;
|
||||
}
|
||||
while (s != sLim);
|
||||
|
||||
{
|
||||
unsigned j = start;
|
||||
for (; j < pos; j++)
|
||||
if (text[j] != ' ' && text[j] != '\t')
|
||||
break;
|
||||
if (j == pos)
|
||||
{
|
||||
id++;
|
||||
pos = start;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// start != pos
|
||||
text[pos++] = 0;
|
||||
|
||||
if (text[start] == ';')
|
||||
{
|
||||
comment = text + start;
|
||||
comment.TrimRight();
|
||||
if (comment.Len() != 1)
|
||||
Comments.Add(comment);
|
||||
id++;
|
||||
pos = start;
|
||||
continue;
|
||||
}
|
||||
|
||||
const wchar_t *end;
|
||||
const UInt32 id32 = ConvertStringToUInt32(text + start, &end);
|
||||
if (*end == 0)
|
||||
{
|
||||
if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id)
|
||||
return false;
|
||||
id = (Int32)id32;
|
||||
pos = start;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id < 0)
|
||||
return false;
|
||||
_ids.Add((UInt32)id++);
|
||||
_offsets.Add(start);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CLang::Open(CFSTR fileName, const char *id)
|
||||
{
|
||||
Clear();
|
||||
NWindows::NFile::NIO::CInFile file;
|
||||
if (!file.Open(fileName))
|
||||
return false;
|
||||
UInt64 length;
|
||||
if (!file.GetLength(length))
|
||||
return false;
|
||||
if (length > (1 << 20))
|
||||
return false;
|
||||
|
||||
AString s;
|
||||
const unsigned len = (unsigned)length;
|
||||
char *p = s.GetBuf(len);
|
||||
size_t processed;
|
||||
if (!file.ReadFull(p, len, processed))
|
||||
return false;
|
||||
file.Close();
|
||||
if (len != processed)
|
||||
return false;
|
||||
|
||||
char *p2 = p;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
const char c = p[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c != 0x0D)
|
||||
*p2++ = c;
|
||||
}
|
||||
*p2 = 0;
|
||||
s.ReleaseBuf_SetLen((unsigned)(p2 - p));
|
||||
|
||||
if (OpenFromString(s))
|
||||
{
|
||||
const wchar_t *name = Get(0);
|
||||
if (name && StringsAreEqual_Ascii(name, id))
|
||||
return true;
|
||||
}
|
||||
|
||||
Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
const wchar_t *CLang::Get(UInt32 id) const throw()
|
||||
{
|
||||
const int index = _ids.FindInSorted(id);
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
return _text + (size_t)_offsets[(unsigned)index];
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Common/Lang.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_LANG_H
|
||||
#define ZIP7_INC_COMMON_LANG_H
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
class CLang
|
||||
{
|
||||
wchar_t *_text;
|
||||
|
||||
bool OpenFromString(const AString &s);
|
||||
public:
|
||||
CRecordVector<UInt32> _ids;
|
||||
CRecordVector<UInt32> _offsets;
|
||||
UStringVector Comments;
|
||||
|
||||
CLang(): _text(NULL) {}
|
||||
~CLang() { Clear(); }
|
||||
bool Open(CFSTR fileName, const char *id);
|
||||
void Clear() throw();
|
||||
bool IsEmpty() const { return _ids.IsEmpty(); }
|
||||
const wchar_t *Get(UInt32 id) const throw();
|
||||
const wchar_t *Get_by_index(unsigned index) const throw()
|
||||
{
|
||||
return _text + (size_t)_offsets[index];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
// Common/ListFileUtils.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
#include "ListFileUtils.h"
|
||||
#include "MyBuffer.h"
|
||||
#include "StringConvert.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
#include "../Windows/FileIO.h"
|
||||
|
||||
#define CSysInFile NWindows::NFile::NIO::CInFile
|
||||
#define MY_GET_LAST_ERROR ::GetLastError()
|
||||
|
||||
|
||||
#define kQuoteChar '\"'
|
||||
|
||||
|
||||
static void AddName(UStringVector &strings, UString &s)
|
||||
{
|
||||
s.Trim();
|
||||
if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar)
|
||||
{
|
||||
s.DeleteBack();
|
||||
s.Delete(0);
|
||||
}
|
||||
if (!s.IsEmpty())
|
||||
strings.Add(s);
|
||||
}
|
||||
|
||||
|
||||
static bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError)
|
||||
{
|
||||
size_t processed;
|
||||
if (!file.ReadFull(data, size, processed))
|
||||
{
|
||||
lastError = MY_GET_LAST_ERROR;
|
||||
return false;
|
||||
}
|
||||
if (processed != size)
|
||||
{
|
||||
lastError = 1; // error: size of listfile was changed
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError)
|
||||
{
|
||||
lastError = 0;
|
||||
CSysInFile file;
|
||||
if (!file.Open(fileName))
|
||||
{
|
||||
lastError = MY_GET_LAST_ERROR;
|
||||
return false;
|
||||
}
|
||||
UInt64 fileSize;
|
||||
if (!file.GetLength(fileSize))
|
||||
{
|
||||
lastError = MY_GET_LAST_ERROR;
|
||||
return false;
|
||||
}
|
||||
if (fileSize >= ((UInt32)1 << 31) - 32)
|
||||
return false;
|
||||
UString u;
|
||||
if (codePage == Z7_WIN_CP_UTF16 || codePage == Z7_WIN_CP_UTF16BE)
|
||||
{
|
||||
if ((fileSize & 1) != 0)
|
||||
return false;
|
||||
CByteArr buf((size_t)fileSize);
|
||||
|
||||
if (!My_File_Read(file, buf, (size_t)fileSize, lastError))
|
||||
return false;
|
||||
|
||||
file.Close();
|
||||
const size_t num = (size_t)fileSize / 2;
|
||||
wchar_t *p = u.GetBuf((unsigned)num);
|
||||
if (codePage == Z7_WIN_CP_UTF16)
|
||||
for (size_t i = 0; i < num; i++)
|
||||
{
|
||||
const wchar_t c = GetUi16(buf.ConstData() + (size_t)i * 2);
|
||||
if (c == 0)
|
||||
return false;
|
||||
p[i] = c;
|
||||
}
|
||||
else
|
||||
for (size_t i = 0; i < num; i++)
|
||||
{
|
||||
const wchar_t c = (wchar_t)GetBe16(buf.ConstData() + (size_t)i * 2);
|
||||
if (c == 0)
|
||||
return false;
|
||||
p[i] = c;
|
||||
}
|
||||
p[num] = 0;
|
||||
u.ReleaseBuf_SetLen((unsigned)num);
|
||||
}
|
||||
else
|
||||
{
|
||||
AString s;
|
||||
char *p = s.GetBuf((unsigned)fileSize);
|
||||
|
||||
if (!My_File_Read(file, p, (size_t)fileSize, lastError))
|
||||
return false;
|
||||
|
||||
file.Close();
|
||||
s.ReleaseBuf_CalcLen((unsigned)fileSize);
|
||||
if (s.Len() != fileSize)
|
||||
return false;
|
||||
|
||||
// #ifdef CP_UTF8
|
||||
if (codePage == CP_UTF8)
|
||||
{
|
||||
// we must check UTF8 here, if convert function doesn't check
|
||||
if (!CheckUTF8_AString(s))
|
||||
return false;
|
||||
if (!ConvertUTF8ToUnicode(s, u))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
// #endif
|
||||
MultiByteToUnicodeString2(u, s, codePage);
|
||||
}
|
||||
|
||||
const wchar_t kGoodBOM = 0xFEFF;
|
||||
// const wchar_t kBadBOM = 0xFFFE;
|
||||
|
||||
UString s;
|
||||
unsigned i = 0;
|
||||
for (; i < u.Len() && u[i] == kGoodBOM; i++);
|
||||
for (; i < u.Len(); i++)
|
||||
{
|
||||
wchar_t c = u[i];
|
||||
/*
|
||||
if (c == kGoodBOM || c == kBadBOM)
|
||||
return false;
|
||||
*/
|
||||
if (c == '\n' || c == 0xD)
|
||||
{
|
||||
AddName(strings, s);
|
||||
s.Empty();
|
||||
}
|
||||
else
|
||||
s += c;
|
||||
}
|
||||
AddName(strings, s);
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Common/ListFileUtils.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_LIST_FILE_UTILS_H
|
||||
#define ZIP7_INC_COMMON_LIST_FILE_UTILS_H
|
||||
|
||||
#include "MyString.h"
|
||||
#include "MyTypes.h"
|
||||
|
||||
#define Z7_WIN_CP_UTF16 1200
|
||||
#define Z7_WIN_CP_UTF16BE 1201
|
||||
|
||||
// bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);
|
||||
|
||||
// = CP_OEMCP
|
||||
bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage,
|
||||
DWORD &lastError);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
// Sha256Prepare.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/LzFind.h"
|
||||
|
||||
static struct CLzFindPrepare { CLzFindPrepare() { LzFindPrepare(); } } g_CLzFindPrepare;
|
||||
@@ -0,0 +1,44 @@
|
||||
// Md5Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Md5.h"
|
||||
|
||||
#include "../Common/MyBuffer2.h"
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CMd5Hasher
|
||||
, IHasher
|
||||
)
|
||||
CAlignedBuffer1 _buf;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7];
|
||||
|
||||
CMd5 *Md5() { return (CMd5 *)(void *)(Byte *)_buf; }
|
||||
public:
|
||||
CMd5Hasher():
|
||||
_buf(sizeof(CMd5))
|
||||
{
|
||||
Md5_Init(Md5());
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CMd5Hasher::Init())
|
||||
{
|
||||
Md5_Init(Md5());
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CMd5Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
Md5_Update(Md5(), (const Byte *)data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CMd5Hasher::Final(Byte *digest))
|
||||
{
|
||||
Md5_Final(Md5(), digest);
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CMd5Hasher, 0x208, "MD5", MD5_DIGEST_SIZE)
|
||||
@@ -0,0 +1,297 @@
|
||||
// Common/MyBuffer.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_BUFFER_H
|
||||
#define ZIP7_INC_COMMON_MY_BUFFER_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Defs.h"
|
||||
#include "MyTypes.h"
|
||||
|
||||
/* 7-Zip now uses CBuffer only as CByteBuffer.
|
||||
So there is no need to use Z7_ARRAY_NEW macro in CBuffer code. */
|
||||
|
||||
template <class T> class CBuffer
|
||||
{
|
||||
T *_items;
|
||||
size_t _size;
|
||||
|
||||
public:
|
||||
void Free()
|
||||
{
|
||||
if (_items)
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
}
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
CBuffer(): _items(NULL), _size(0) {}
|
||||
CBuffer(size_t size): _items(NULL), _size(0)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
_items = new T[size];
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
CBuffer(const CBuffer &buffer): _items(NULL), _size(0)
|
||||
{
|
||||
const size_t size = buffer._size;
|
||||
if (size != 0)
|
||||
{
|
||||
_items = new T[size];
|
||||
memcpy(_items, buffer._items, size * sizeof(T));
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
~CBuffer() { delete []_items; }
|
||||
|
||||
operator T *() { return _items; }
|
||||
operator const T *() const { return _items; }
|
||||
const T* ConstData() const { return _items; }
|
||||
T* NonConstData() const { return _items; }
|
||||
T* NonConstData() { return _items; }
|
||||
// const T* Data() const { return _items; }
|
||||
// T* Data() { return _items; }
|
||||
|
||||
size_t Size() const { return _size; }
|
||||
|
||||
void Alloc(size_t size)
|
||||
{
|
||||
if (size != _size)
|
||||
{
|
||||
Free();
|
||||
if (size != 0)
|
||||
{
|
||||
_items = new T[size];
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AllocAtLeast(size_t size)
|
||||
{
|
||||
if (size > _size)
|
||||
{
|
||||
Free();
|
||||
_items = new T[size];
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void CopyFrom(const T *data, size_t size)
|
||||
{
|
||||
Alloc(size);
|
||||
if (size != 0)
|
||||
memcpy(_items, data, size * sizeof(T));
|
||||
}
|
||||
|
||||
void ChangeSize_KeepData(size_t newSize, size_t keepSize)
|
||||
{
|
||||
if (newSize == _size)
|
||||
return;
|
||||
T *newBuffer = NULL;
|
||||
if (newSize != 0)
|
||||
{
|
||||
newBuffer = new T[newSize];
|
||||
if (keepSize > _size)
|
||||
keepSize = _size;
|
||||
if (keepSize != 0)
|
||||
memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T));
|
||||
}
|
||||
delete []_items;
|
||||
_items = newBuffer;
|
||||
_size = newSize;
|
||||
}
|
||||
|
||||
void Wipe()
|
||||
{
|
||||
if (_size != 0)
|
||||
memset(_items, 0, _size * sizeof(T));
|
||||
}
|
||||
|
||||
CBuffer& operator=(const CBuffer &buffer)
|
||||
{
|
||||
if (&buffer != this)
|
||||
CopyFrom(buffer, buffer._size);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
|
||||
{
|
||||
size_t size1 = b1.Size();
|
||||
if (size1 != b2.Size())
|
||||
return false;
|
||||
if (size1 == 0)
|
||||
return true;
|
||||
return memcmp(b1, b2, size1 * sizeof(T)) == 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
|
||||
{
|
||||
size_t size1 = b1.Size();
|
||||
if (size1 != b2.Size())
|
||||
return true;
|
||||
if (size1 == 0)
|
||||
return false;
|
||||
return memcmp(b1, b2, size1 * sizeof(T)) != 0;
|
||||
}
|
||||
|
||||
|
||||
// typedef CBuffer<char> CCharBuffer;
|
||||
// typedef CBuffer<wchar_t> CWCharBuffer;
|
||||
typedef CBuffer<Byte> CByteBuffer;
|
||||
|
||||
|
||||
class CByteBuffer_Wipe: public CByteBuffer
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CByteBuffer_Wipe)
|
||||
public:
|
||||
// CByteBuffer_Wipe(): CBuffer<Byte>() {}
|
||||
CByteBuffer_Wipe(size_t size): CBuffer<Byte>(size) {}
|
||||
~CByteBuffer_Wipe() { Wipe(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <class T> class CObjArray
|
||||
{
|
||||
protected:
|
||||
T *_items;
|
||||
private:
|
||||
// we disable copy
|
||||
CObjArray(const CObjArray &buffer);
|
||||
void operator=(const CObjArray &buffer);
|
||||
public:
|
||||
void Free()
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
}
|
||||
CObjArray(size_t size): _items(NULL)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
Z7_ARRAY_NEW(_items, T, size)
|
||||
// _items = new T[size];
|
||||
}
|
||||
}
|
||||
CObjArray(): _items(NULL) {}
|
||||
~CObjArray() { delete []_items; }
|
||||
|
||||
operator T *() { return _items; }
|
||||
operator const T *() const { return _items; }
|
||||
const T* ConstData() const { return _items; }
|
||||
T* NonConstData() const { return _items; }
|
||||
T* NonConstData() { return _items; }
|
||||
// const T* Data() const { return _items; }
|
||||
// T* Data() { return _items; }
|
||||
|
||||
void Alloc(size_t newSize)
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
Z7_ARRAY_NEW(_items, T, newSize)
|
||||
// _items = new T[newSize];
|
||||
}
|
||||
};
|
||||
|
||||
typedef CObjArray<Byte> CByteArr;
|
||||
typedef CObjArray<bool> CBoolArr;
|
||||
typedef CObjArray<int> CIntArr;
|
||||
typedef CObjArray<unsigned> CUIntArr;
|
||||
|
||||
|
||||
template <class T> class CObjArray2
|
||||
{
|
||||
T *_items;
|
||||
unsigned _size;
|
||||
|
||||
// we disable copy
|
||||
CObjArray2(const CObjArray2 &buffer);
|
||||
void operator=(const CObjArray2 &buffer);
|
||||
public:
|
||||
|
||||
void Free()
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
_size = 0;
|
||||
}
|
||||
CObjArray2(): _items(NULL), _size(0) {}
|
||||
/*
|
||||
CObjArray2(const CObjArray2 &buffer): _items(NULL), _size(0)
|
||||
{
|
||||
size_t newSize = buffer._size;
|
||||
if (newSize != 0)
|
||||
{
|
||||
T *newBuffer = new T[newSize];;
|
||||
_items = newBuffer;
|
||||
_size = newSize;
|
||||
const T *src = buffer;
|
||||
for (size_t i = 0; i < newSize; i++)
|
||||
newBuffer[i] = src[i];
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
CObjArray2(size_t size): _items(NULL), _size(0)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
_items = new T[size];
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
~CObjArray2() { delete []_items; }
|
||||
|
||||
operator T *() { return _items; }
|
||||
operator const T *() const { return _items; }
|
||||
|
||||
unsigned Size() const { return (unsigned)_size; }
|
||||
bool IsEmpty() const { return _size == 0; }
|
||||
|
||||
// SetSize doesn't keep old items. It allocates new array if size is not equal
|
||||
void SetSize(unsigned size)
|
||||
{
|
||||
if (size == _size)
|
||||
return;
|
||||
T *newBuffer = NULL;
|
||||
if (size != 0)
|
||||
{
|
||||
Z7_ARRAY_NEW(newBuffer, T, size)
|
||||
// newBuffer = new T[size];
|
||||
}
|
||||
delete []_items;
|
||||
_items = newBuffer;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
/*
|
||||
CObjArray2& operator=(const CObjArray2 &buffer)
|
||||
{
|
||||
Free();
|
||||
size_t newSize = buffer._size;
|
||||
if (newSize != 0)
|
||||
{
|
||||
T *newBuffer = new T[newSize];;
|
||||
_items = newBuffer;
|
||||
_size = newSize;
|
||||
const T *src = buffer;
|
||||
for (size_t i = 0; i < newSize; i++)
|
||||
newBuffer[i] = src[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,185 @@
|
||||
// Common/MyBuffer2.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_BUFFER2_H
|
||||
#define ZIP7_INC_COMMON_MY_BUFFER2_H
|
||||
|
||||
#include "../../C/Alloc.h"
|
||||
|
||||
#include "MyTypes.h"
|
||||
|
||||
class CMidBuffer
|
||||
{
|
||||
Byte *_data;
|
||||
size_t _size;
|
||||
|
||||
Z7_CLASS_NO_COPY(CMidBuffer)
|
||||
|
||||
public:
|
||||
CMidBuffer(): _data(NULL), _size(0) {}
|
||||
~CMidBuffer() { ::MidFree(_data); }
|
||||
|
||||
void Free() { ::MidFree(_data); _data = NULL; _size = 0; }
|
||||
|
||||
bool IsAllocated() const { return _data != NULL; }
|
||||
operator Byte *() { return _data; }
|
||||
operator const Byte *() const { return _data; }
|
||||
size_t Size() const { return _size; }
|
||||
|
||||
void Alloc(size_t size)
|
||||
{
|
||||
if (!_data || size != _size)
|
||||
{
|
||||
::MidFree(_data);
|
||||
_size = 0;
|
||||
_data = NULL;
|
||||
_data = (Byte *)::MidAlloc(size);
|
||||
if (_data)
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void AllocAtLeast(size_t size)
|
||||
{
|
||||
if (!_data || size > _size)
|
||||
{
|
||||
::MidFree(_data);
|
||||
const size_t kMinSize = (size_t)1 << 16;
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
_size = 0;
|
||||
_data = NULL;
|
||||
_data = (Byte *)::MidAlloc(size);
|
||||
if (_data)
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CAlignedBuffer1
|
||||
{
|
||||
Byte *_data;
|
||||
|
||||
Z7_CLASS_NO_COPY(CAlignedBuffer1)
|
||||
|
||||
public:
|
||||
~CAlignedBuffer1()
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
}
|
||||
|
||||
CAlignedBuffer1(size_t size)
|
||||
{
|
||||
_data = NULL;
|
||||
_data = (Byte *)z7_AlignedAlloc(size);
|
||||
if (!_data)
|
||||
throw 1;
|
||||
}
|
||||
|
||||
operator Byte *() { return _data; }
|
||||
operator const Byte *() const { return _data; }
|
||||
};
|
||||
|
||||
|
||||
class CAlignedBuffer
|
||||
{
|
||||
Byte *_data;
|
||||
size_t _size;
|
||||
|
||||
Z7_CLASS_NO_COPY(CAlignedBuffer)
|
||||
|
||||
public:
|
||||
CAlignedBuffer(): _data(NULL), _size(0) {}
|
||||
~CAlignedBuffer()
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
}
|
||||
|
||||
/*
|
||||
CAlignedBuffer(size_t size): _size(0)
|
||||
{
|
||||
_data = NULL;
|
||||
_data = (Byte *)z7_AlignedAlloc(size);
|
||||
if (!_data)
|
||||
throw 1;
|
||||
_size = size;
|
||||
}
|
||||
*/
|
||||
|
||||
void Free()
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
_data = NULL;
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
bool IsAllocated() const { return _data != NULL; }
|
||||
operator Byte *() { return _data; }
|
||||
operator const Byte *() const { return _data; }
|
||||
size_t Size() const { return _size; }
|
||||
|
||||
void Alloc(size_t size)
|
||||
{
|
||||
if (!_data || size != _size)
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
_size = 0;
|
||||
_data = NULL;
|
||||
_data = (Byte *)z7_AlignedAlloc(size);
|
||||
if (_data)
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void AllocAtLeast(size_t size)
|
||||
{
|
||||
if (!_data || size > _size)
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
_size = 0;
|
||||
_data = NULL;
|
||||
_data = (Byte *)z7_AlignedAlloc(size);
|
||||
if (_data)
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
|
||||
// (size <= size_max)
|
||||
void AllocAtLeast_max(size_t size, size_t size_max)
|
||||
{
|
||||
if (!_data || size > _size)
|
||||
{
|
||||
z7_AlignedFree(_data);
|
||||
_size = 0;
|
||||
_data = NULL;
|
||||
if (size_max < size) size_max = size; // optional check
|
||||
const size_t delta = size / 2;
|
||||
size += delta;
|
||||
if (size < delta || size > size_max)
|
||||
size = size_max;
|
||||
_data = (Byte *)z7_AlignedAlloc(size);
|
||||
if (_data)
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
CMidAlignedBuffer must return aligned pointer.
|
||||
- in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc()
|
||||
VirtualAlloc(): Memory allocated is automatically initialized to zero.
|
||||
MidAlloc(0) returns NULL
|
||||
- in non-Windows systems it uses g_AlignedAlloc.
|
||||
g_AlignedAlloc::Alloc(size = 0) can return non NULL.
|
||||
*/
|
||||
|
||||
typedef
|
||||
#ifdef _WIN32
|
||||
CMidBuffer
|
||||
#else
|
||||
CAlignedBuffer
|
||||
#endif
|
||||
CMidAlignedBuffer;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,693 @@
|
||||
// MyCom.h
|
||||
|
||||
#ifndef ZIP7_INC_MY_COM_H
|
||||
#define ZIP7_INC_MY_COM_H
|
||||
|
||||
#include "MyWindows.h"
|
||||
#include "MyTypes.h"
|
||||
|
||||
template <class T>
|
||||
class CMyComPtr
|
||||
{
|
||||
T* _p;
|
||||
public:
|
||||
CMyComPtr(): _p(NULL) {}
|
||||
CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
|
||||
CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
|
||||
~CMyComPtr() { if (_p) _p->Release(); }
|
||||
void Release() { if (_p) { _p->Release(); _p = NULL; } }
|
||||
operator T*() const { return (T*)_p; }
|
||||
T* Interface() const { return (T*)_p; }
|
||||
// T& operator*() const { return *_p; }
|
||||
T** operator&() { return &_p; }
|
||||
T* operator->() const { return _p; }
|
||||
T* operator=(T* p)
|
||||
{
|
||||
if (p)
|
||||
p->AddRef();
|
||||
if (_p)
|
||||
_p->Release();
|
||||
_p = p;
|
||||
return p;
|
||||
}
|
||||
T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
|
||||
bool operator!() const { return (_p == NULL); }
|
||||
// bool operator==(T* pT) const { return _p == pT; }
|
||||
void Attach(T* p2)
|
||||
{
|
||||
Release();
|
||||
_p = p2;
|
||||
}
|
||||
T* Detach()
|
||||
{
|
||||
T* pt = _p;
|
||||
_p = NULL;
|
||||
return pt;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
|
||||
{
|
||||
return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
|
||||
{
|
||||
CLSID clsid;
|
||||
HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
|
||||
ATLASSERT(_p == NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
|
||||
return hr;
|
||||
}
|
||||
*/
|
||||
template <class Q>
|
||||
HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
|
||||
{
|
||||
// if (*pp) throw 20220216; // for debug
|
||||
return _p->QueryInterface(iid, (void**)pp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class iface, class cls>
|
||||
class CMyComPtr2
|
||||
{
|
||||
cls* _p;
|
||||
|
||||
CMyComPtr2(const CMyComPtr2<iface, cls>& lp);
|
||||
CMyComPtr2(cls* p);
|
||||
CMyComPtr2(iface* p);
|
||||
iface* operator=(const CMyComPtr2<iface, cls>& lp);
|
||||
iface* operator=(cls* p);
|
||||
iface* operator=(iface* p);
|
||||
public:
|
||||
CMyComPtr2(): _p(NULL) {}
|
||||
~CMyComPtr2()
|
||||
{
|
||||
if (_p)
|
||||
{
|
||||
iface *ip = _p;
|
||||
ip->Release();
|
||||
}
|
||||
}
|
||||
// void Release() { if (_p) { (iface *)_p->Release(); _p = NULL; } }
|
||||
cls* operator->() const { return _p; }
|
||||
cls* ClsPtr() const { return _p; }
|
||||
operator iface*() const
|
||||
{
|
||||
iface *ip = _p;
|
||||
return ip;
|
||||
}
|
||||
iface* Interface() const
|
||||
{
|
||||
iface *ip = _p;
|
||||
return ip;
|
||||
}
|
||||
// operator bool() const { return _p != NULL; }
|
||||
bool IsDefined() const { return _p != NULL; }
|
||||
void Create_if_Empty()
|
||||
{
|
||||
if (!_p)
|
||||
{
|
||||
_p = new cls;
|
||||
iface *ip = _p;
|
||||
ip->AddRef();
|
||||
}
|
||||
}
|
||||
iface* Detach()
|
||||
{
|
||||
iface *ip = _p;
|
||||
_p = NULL;
|
||||
return ip;
|
||||
}
|
||||
void SetFromCls(cls *src)
|
||||
{
|
||||
if (src)
|
||||
{
|
||||
iface *ip = src;
|
||||
ip->AddRef();
|
||||
}
|
||||
if (_p)
|
||||
{
|
||||
iface *ip = _p;
|
||||
ip->Release();
|
||||
}
|
||||
_p = src;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class iface, class cls>
|
||||
class CMyComPtr2_Create
|
||||
{
|
||||
cls* _p;
|
||||
|
||||
CMyComPtr2_Create(const CMyComPtr2_Create<iface, cls>& lp);
|
||||
CMyComPtr2_Create(cls* p);
|
||||
CMyComPtr2_Create(iface* p);
|
||||
iface* operator=(const CMyComPtr2_Create<iface, cls>& lp);
|
||||
iface* operator=(cls* p);
|
||||
iface* operator=(iface* p);
|
||||
public:
|
||||
CMyComPtr2_Create(): _p(new cls)
|
||||
{
|
||||
iface *ip = _p;
|
||||
ip->AddRef();
|
||||
}
|
||||
~CMyComPtr2_Create()
|
||||
{
|
||||
iface *ip = _p;
|
||||
ip->Release();
|
||||
}
|
||||
cls* operator->() const { return _p; }
|
||||
cls* ClsPtr() const { return _p; }
|
||||
operator iface*() const
|
||||
{
|
||||
iface *ip = _p;
|
||||
return ip;
|
||||
}
|
||||
iface* Interface() const
|
||||
{
|
||||
iface *ip = _p;
|
||||
return ip;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \
|
||||
CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
|
||||
{
|
||||
*bstr = ::SysAllocString(src);
|
||||
return (*bstr) ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
class CMyComBSTR
|
||||
{
|
||||
BSTR m_str;
|
||||
Z7_CLASS_NO_COPY(CMyComBSTR)
|
||||
public:
|
||||
CMyComBSTR(): m_str(NULL) {}
|
||||
~CMyComBSTR() { ::SysFreeString(m_str); }
|
||||
BSTR* operator&() { return &m_str; }
|
||||
operator LPCOLESTR() const { return m_str; }
|
||||
// operator bool() const { return m_str != NULL; }
|
||||
// bool operator!() const { return m_str == NULL; }
|
||||
|
||||
void Wipe_and_Free()
|
||||
{
|
||||
if (m_str)
|
||||
{
|
||||
memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
|
||||
Empty();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// operator BSTR() const { return m_str; }
|
||||
|
||||
CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
|
||||
// CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
|
||||
// CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
|
||||
// CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
|
||||
|
||||
/*
|
||||
CMyComBSTR(REFGUID src)
|
||||
{
|
||||
LPOLESTR szGuid;
|
||||
StringFromCLSID(src, &szGuid);
|
||||
m_str = ::SysAllocString(szGuid);
|
||||
CoTaskMemFree(szGuid);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
CMyComBSTR& operator=(const CMyComBSTR& src)
|
||||
{
|
||||
if (m_str != src.m_str)
|
||||
{
|
||||
if (m_str)
|
||||
::SysFreeString(m_str);
|
||||
m_str = src.MyCopy();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
*/
|
||||
|
||||
CMyComBSTR& operator=(LPCOLESTR src)
|
||||
{
|
||||
::SysFreeString(m_str);
|
||||
m_str = ::SysAllocString(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned Len() const { return ::SysStringLen(m_str); }
|
||||
|
||||
BSTR MyCopy() const
|
||||
{
|
||||
// We don't support Byte BSTRs here
|
||||
return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
|
||||
/*
|
||||
UINT byteLen = ::SysStringByteLen(m_str);
|
||||
BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
|
||||
if (res && byteLen != 0 && m_str)
|
||||
memcpy(res, m_str, byteLen);
|
||||
return res;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
void Attach(BSTR src) { m_str = src; }
|
||||
BSTR Detach()
|
||||
{
|
||||
BSTR s = m_str;
|
||||
m_str = NULL;
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
void Empty()
|
||||
{
|
||||
::SysFreeString(m_str);
|
||||
m_str = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CMyComBSTR_Wipe: public CMyComBSTR
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CMyComBSTR_Wipe)
|
||||
public:
|
||||
CMyComBSTR_Wipe(): CMyComBSTR() {}
|
||||
~CMyComBSTR_Wipe() { Wipe_and_Free(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
|
||||
But if some class_1 derived from CMyUnknownImp
|
||||
uses Z7_COM_ADDREF_RELEASE and IUnknown::Release()
|
||||
and some another class_2 is derived from class_1,
|
||||
then class_1 must use virtual destructor:
|
||||
virtual ~class_1();
|
||||
In that case, class_1::Release() calls correct destructor of class_2.
|
||||
We can use virtual ~CMyUnknownImp() to disable warning
|
||||
"class has virtual functions, but destructor is not virtual".
|
||||
Also we can use virtual ~IUnknown() {} in MyWindows.h
|
||||
*/
|
||||
|
||||
class CMyUnknownImp
|
||||
{
|
||||
Z7_CLASS_NO_COPY(CMyUnknownImp)
|
||||
protected:
|
||||
ULONG _m_RefCount;
|
||||
CMyUnknownImp(): _m_RefCount(0) {}
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
// virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define Z7_COM_QI_BEGIN \
|
||||
private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \
|
||||
{ *outObject = NULL;
|
||||
|
||||
#define Z7_COM_QI_ENTRY(i) \
|
||||
else if (iid == IID_ ## i) \
|
||||
{ i *ti = this; *outObject = ti; }
|
||||
// { *outObject = (void *)(i *)this; }
|
||||
|
||||
#define Z7_COM_QI_ENTRY_UNKNOWN_0 \
|
||||
if (iid == IID_IUnknown) \
|
||||
{ IUnknown *tu = this; *outObject = tu; }
|
||||
|
||||
#define Z7_COM_QI_ENTRY_UNKNOWN(i) \
|
||||
if (iid == IID_IUnknown) \
|
||||
{ i *ti = this; IUnknown *tu = ti; *outObject = tu; }
|
||||
// { *outObject = (void *)(IUnknown *)(i *)this; }
|
||||
|
||||
#define Z7_COM_QI_BEGIN2(i) \
|
||||
Z7_COM_QI_BEGIN \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i) \
|
||||
Z7_COM_QI_ENTRY(i)
|
||||
|
||||
|
||||
#define Z7_COM_ADDREF_RELEASE_MT \
|
||||
private: \
|
||||
STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \
|
||||
{ return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \
|
||||
STDMETHOD_(ULONG, Release)() Z7_override Z7_final \
|
||||
{ const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \
|
||||
if (v != 0) return (ULONG)v; \
|
||||
delete this; return 0; }
|
||||
|
||||
#define Z7_COM_QI_END_MT \
|
||||
else return E_NOINTERFACE; \
|
||||
InterlockedIncrement((LONG *)&_m_RefCount); /* AddRef(); */ return S_OK; }
|
||||
|
||||
// you can define Z7_COM_USE_ATOMIC,
|
||||
// if you want to call Release() from different threads (for example, for .NET code)
|
||||
// #define Z7_COM_USE_ATOMIC
|
||||
|
||||
#if defined(Z7_COM_USE_ATOMIC) && !defined(Z7_ST)
|
||||
|
||||
#ifndef _WIN32
|
||||
#if 0
|
||||
#include "../../C/Threads.h"
|
||||
#else
|
||||
EXTERN_C_BEGIN
|
||||
LONG InterlockedIncrement(LONG volatile *addend);
|
||||
LONG InterlockedDecrement(LONG volatile *addend);
|
||||
EXTERN_C_END
|
||||
#endif
|
||||
#endif // _WIN32
|
||||
|
||||
#define Z7_COM_ADDREF_RELEASE Z7_COM_ADDREF_RELEASE_MT
|
||||
#define Z7_COM_QI_END Z7_COM_QI_END_MT
|
||||
|
||||
#else // !Z7_COM_USE_ATOMIC
|
||||
|
||||
#define Z7_COM_ADDREF_RELEASE \
|
||||
private: \
|
||||
STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \
|
||||
{ return ++_m_RefCount; } \
|
||||
STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \
|
||||
{ if (--_m_RefCount != 0) return _m_RefCount; \
|
||||
delete this; return 0; }
|
||||
|
||||
#define Z7_COM_QI_END \
|
||||
else return E_NOINTERFACE; \
|
||||
++_m_RefCount; /* AddRef(); */ return S_OK; }
|
||||
|
||||
#endif // !Z7_COM_USE_ATOMIC
|
||||
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_SPEC(i) \
|
||||
Z7_COM_QI_BEGIN \
|
||||
i \
|
||||
Z7_COM_QI_END \
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_0 \
|
||||
Z7_COM_QI_BEGIN \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN_0 \
|
||||
Z7_COM_QI_END \
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_1(i) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i) \
|
||||
Z7_COM_QI_ENTRY(i) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_2(i1, i2) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
Z7_COM_QI_ENTRY(i4) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
Z7_COM_QI_ENTRY(i4) \
|
||||
Z7_COM_QI_ENTRY(i5) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
Z7_COM_QI_ENTRY(i4) \
|
||||
Z7_COM_QI_ENTRY(i5) \
|
||||
Z7_COM_QI_ENTRY(i6) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
Z7_COM_QI_ENTRY(i4) \
|
||||
Z7_COM_QI_ENTRY(i5) \
|
||||
Z7_COM_QI_ENTRY(i6) \
|
||||
Z7_COM_QI_ENTRY(i7) \
|
||||
)
|
||||
|
||||
#define Z7_COM_UNKNOWN_IMP_8(i1, i2, i3, i4, i5, i6, i7, i8) \
|
||||
Z7_COM_UNKNOWN_IMP_SPEC( \
|
||||
Z7_COM_QI_ENTRY_UNKNOWN(i1) \
|
||||
Z7_COM_QI_ENTRY(i1) \
|
||||
Z7_COM_QI_ENTRY(i2) \
|
||||
Z7_COM_QI_ENTRY(i3) \
|
||||
Z7_COM_QI_ENTRY(i4) \
|
||||
Z7_COM_QI_ENTRY(i5) \
|
||||
Z7_COM_QI_ENTRY(i6) \
|
||||
Z7_COM_QI_ENTRY(i7) \
|
||||
Z7_COM_QI_ENTRY(i8) \
|
||||
)
|
||||
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_1(i1) \
|
||||
Z7_COM_UNKNOWN_IMP_1(i1) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_2(i1, i2) \
|
||||
Z7_COM_UNKNOWN_IMP_2(i1, i2) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
|
||||
Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
|
||||
Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
|
||||
Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
Z7_IFACE_COM7_IMP(i5) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
|
||||
Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
Z7_IFACE_COM7_IMP(i5) \
|
||||
Z7_IFACE_COM7_IMP(i6) \
|
||||
|
||||
#define Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \
|
||||
Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
Z7_IFACE_COM7_IMP(i5) \
|
||||
Z7_IFACE_COM7_IMP(i6) \
|
||||
Z7_IFACE_COM7_IMP(i7) \
|
||||
|
||||
|
||||
#define Z7_CLASS_IMP_COM_0(c) \
|
||||
Z7_class_final(c) : \
|
||||
public IUnknown, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_0 \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_1(c, i1) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_1(i1) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_2(c, i1, i2) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_2(i1, i2) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_3(i1, i2, i3) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public i5, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public i5, \
|
||||
public i6, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \
|
||||
private:
|
||||
|
||||
|
||||
#define Z7_CLASS_IMP_COM_7(c, i1, i2, i3, i4, i5, i6, i7) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public i5, \
|
||||
public i6, \
|
||||
public i7, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \
|
||||
private:
|
||||
|
||||
|
||||
/*
|
||||
#define Z7_CLASS_IMP_NOQIB_0(c) \
|
||||
Z7_class_final(c) : \
|
||||
public IUnknown, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_0 \
|
||||
private:
|
||||
*/
|
||||
|
||||
#define Z7_CLASS_IMP_NOQIB_1(c, i1) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_0 \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_1(i2) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_2(i2, i3) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
private:
|
||||
|
||||
#define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
|
||||
/*
|
||||
#define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \
|
||||
Z7_class_final(c) : \
|
||||
public i1, \
|
||||
public i2, \
|
||||
public i3, \
|
||||
public i4, \
|
||||
public i5, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \
|
||||
Z7_IFACE_COM7_IMP(i1) \
|
||||
Z7_IFACE_COM7_IMP(i2) \
|
||||
Z7_IFACE_COM7_IMP(i3) \
|
||||
Z7_IFACE_COM7_IMP(i4) \
|
||||
Z7_IFACE_COM7_IMP(i5) \
|
||||
*/
|
||||
|
||||
|
||||
#define Z7_CLASS_IMP_IInStream(c) \
|
||||
class c Z7_final : \
|
||||
public IInStream, \
|
||||
public CMyUnknownImp { \
|
||||
Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \
|
||||
|
||||
|
||||
#define k_My_HRESULT_WritingWasCut 0x20000010
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
// Common/Exception.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_EXCEPTION_H
|
||||
#define ZIP7_INC_COMMON_EXCEPTION_H
|
||||
|
||||
#include "MyWindows.h"
|
||||
|
||||
struct CSystemException
|
||||
{
|
||||
HRESULT ErrorCode;
|
||||
CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
// Common/MyGuidDef.h
|
||||
|
||||
// #pragma message "Common/MyGuidDef.h"
|
||||
|
||||
#ifndef GUID_DEFINED
|
||||
#define GUID_DEFINED
|
||||
|
||||
// #pragma message "GUID_DEFINED"
|
||||
|
||||
#include "MyTypes.h"
|
||||
|
||||
typedef struct {
|
||||
UInt32 Data1;
|
||||
UInt16 Data2;
|
||||
UInt16 Data3;
|
||||
Byte Data4[8];
|
||||
} GUID;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define REFGUID const GUID &
|
||||
#else
|
||||
#define REFGUID const GUID *
|
||||
#endif
|
||||
|
||||
// typedef GUID IID;
|
||||
typedef GUID CLSID;
|
||||
|
||||
#define REFCLSID REFGUID
|
||||
#define REFIID REFGUID
|
||||
|
||||
#ifdef __cplusplus
|
||||
inline int operator==(REFGUID g1, REFGUID g2)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(g1); i++)
|
||||
if (((const Byte *)&g1)[i] != ((const Byte *)&g2)[i])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
|
||||
#endif
|
||||
|
||||
#endif // GUID_DEFINED
|
||||
|
||||
#ifndef EXTERN_C
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN_C extern "C"
|
||||
#else
|
||||
#define EXTERN_C extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEFINE_GUID
|
||||
#undef DEFINE_GUID
|
||||
#endif
|
||||
|
||||
#ifdef INITGUID
|
||||
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
EXTERN_C const GUID name; \
|
||||
EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||
#else
|
||||
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
EXTERN_C const GUID name
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// Common/MyInitGuid.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_INITGUID_H
|
||||
#define ZIP7_INC_COMMON_MY_INITGUID_H
|
||||
|
||||
/*
|
||||
This file must be included only to one C++ file in project before
|
||||
declarations of COM interfaces with DEFINE_GUID macro.
|
||||
|
||||
Each GUID must be initialized exactly once in project.
|
||||
There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h):
|
||||
- if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name.
|
||||
- if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID.
|
||||
|
||||
Also we need IID_IUnknown that is initialized in some file for linking:
|
||||
MSVC: by default the linker uses some lib file that contains IID_IUnknown
|
||||
MinGW: add -luuid switch for linker
|
||||
WinCE: we define IID_IUnknown in this file
|
||||
Other: we define IID_IUnknown in this file
|
||||
*/
|
||||
|
||||
// #include "Common.h"
|
||||
/* vc6 without sdk needs <objbase.h> before <initguid.h>,
|
||||
but it doesn't work in new msvc.
|
||||
So we include full "MyWindows.h" instead of <objbase.h> */
|
||||
// #include <objbase.h>
|
||||
#include "MyWindows.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifdef __clang__
|
||||
// #pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
|
||||
#endif
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#include <basetyps.h>
|
||||
#endif
|
||||
|
||||
// for vc6 without sdk we must define INITGUID here
|
||||
#define INITGUID
|
||||
#include <initguid.h>
|
||||
|
||||
#ifdef UNDER_CE
|
||||
DEFINE_GUID(IID_IUnknown,
|
||||
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
|
||||
#endif
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#define INITGUID
|
||||
#include "MyGuidDef.h"
|
||||
DEFINE_GUID(IID_IUnknown,
|
||||
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
// MyLinux.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_LINUX_H
|
||||
#define ZIP7_INC_COMMON_MY_LINUX_H
|
||||
|
||||
// #include "../../C/7zTypes.h"
|
||||
|
||||
#define MY_LIN_DT_UNKNOWN 0
|
||||
#define MY_LIN_DT_FIFO 1
|
||||
#define MY_LIN_DT_CHR 2
|
||||
#define MY_LIN_DT_DIR 4
|
||||
#define MY_LIN_DT_BLK 6
|
||||
#define MY_LIN_DT_REG 8
|
||||
#define MY_LIN_DT_LNK 10
|
||||
#define MY_LIN_DT_SOCK 12
|
||||
#define MY_LIN_DT_WHT 14
|
||||
|
||||
#define MY_LIN_S_IFMT 00170000
|
||||
#define MY_LIN_S_IFSOCK 0140000
|
||||
#define MY_LIN_S_IFLNK 0120000
|
||||
#define MY_LIN_S_IFREG 0100000
|
||||
#define MY_LIN_S_IFBLK 0060000
|
||||
#define MY_LIN_S_IFDIR 0040000
|
||||
#define MY_LIN_S_IFCHR 0020000
|
||||
#define MY_LIN_S_IFIFO 0010000
|
||||
|
||||
#define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK)
|
||||
#define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG)
|
||||
#define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR)
|
||||
#define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR)
|
||||
#define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK)
|
||||
#define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO)
|
||||
#define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK)
|
||||
|
||||
#define MY_LIN_S_ISUID 0004000
|
||||
#define MY_LIN_S_ISGID 0002000
|
||||
#define MY_LIN_S_ISVTX 0001000
|
||||
|
||||
#define MY_LIN_S_IRWXU 00700
|
||||
#define MY_LIN_S_IRUSR 00400
|
||||
#define MY_LIN_S_IWUSR 00200
|
||||
#define MY_LIN_S_IXUSR 00100
|
||||
|
||||
#define MY_LIN_S_IRWXG 00070
|
||||
#define MY_LIN_S_IRGRP 00040
|
||||
#define MY_LIN_S_IWGRP 00020
|
||||
#define MY_LIN_S_IXGRP 00010
|
||||
|
||||
#define MY_LIN_S_IRWXO 00007
|
||||
#define MY_LIN_S_IROTH 00004
|
||||
#define MY_LIN_S_IWOTH 00002
|
||||
#define MY_LIN_S_IXOTH 00001
|
||||
|
||||
/*
|
||||
// major/minor encoding for makedev(): MMMMMmmmmmmMMMmm:
|
||||
|
||||
inline UInt32 MY_dev_major(UInt64 dev)
|
||||
{
|
||||
return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff);
|
||||
}
|
||||
|
||||
inline UInt32 MY_dev_minor(UInt64 dev)
|
||||
{
|
||||
return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~0xff);
|
||||
}
|
||||
|
||||
inline UInt64 MY_dev_makedev(UInt32 __major, UInt32 __minor)
|
||||
{
|
||||
return (__minor & 0xff) | ((__major & 0xfff) << 8)
|
||||
| ((UInt64) (__minor & ~0xff) << 12)
|
||||
| ((UInt64) (__major & ~0xfff) << 32);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
// MyMap.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MyMap.h"
|
||||
|
||||
static const unsigned kNumBitsMax = sizeof(UInt32) * 8;
|
||||
|
||||
static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) throw()
|
||||
{
|
||||
if (startPos == sizeof(value) * 8)
|
||||
return 0;
|
||||
value >>= startPos;
|
||||
if (numBits == sizeof(value) * 8)
|
||||
return value;
|
||||
return value & (((UInt32)1 << numBits) - 1);
|
||||
}
|
||||
|
||||
static inline unsigned GetSubBit(UInt32 v, unsigned n) { return (unsigned)(v >> n) & 1; }
|
||||
|
||||
bool CMap32::Find(UInt32 key, UInt32 &valueRes) const throw()
|
||||
{
|
||||
valueRes = (UInt32)(Int32)-1;
|
||||
if (Nodes.Size() == 0)
|
||||
return false;
|
||||
if (Nodes.Size() == 1)
|
||||
{
|
||||
const CNode &n = Nodes[0];
|
||||
if (n.Len == kNumBitsMax)
|
||||
{
|
||||
valueRes = n.Values[0];
|
||||
return (key == n.Key);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned cur = 0;
|
||||
unsigned bitPos = kNumBitsMax;
|
||||
for (;;)
|
||||
{
|
||||
const CNode &n = Nodes[cur];
|
||||
bitPos -= n.Len;
|
||||
if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))
|
||||
return false;
|
||||
unsigned bit = GetSubBit(key, --bitPos);
|
||||
if (n.IsLeaf[bit])
|
||||
{
|
||||
valueRes = n.Values[bit];
|
||||
return (key == n.Keys[bit]);
|
||||
}
|
||||
cur = (unsigned)n.Keys[bit];
|
||||
}
|
||||
}
|
||||
|
||||
bool CMap32::Set(UInt32 key, UInt32 value)
|
||||
{
|
||||
if (Nodes.Size() == 0)
|
||||
{
|
||||
CNode n;
|
||||
n.Key = n.Keys[0] = n.Keys[1] = key;
|
||||
n.Values[0] = n.Values[1] = value;
|
||||
n.IsLeaf[0] = n.IsLeaf[1] = 1;
|
||||
n.Len = kNumBitsMax;
|
||||
Nodes.Add(n);
|
||||
return false;
|
||||
}
|
||||
if (Nodes.Size() == 1)
|
||||
{
|
||||
CNode &n = Nodes[0];
|
||||
if (n.Len == kNumBitsMax)
|
||||
{
|
||||
if (key == n.Key)
|
||||
{
|
||||
n.Values[0] = n.Values[1] = value;
|
||||
return true;
|
||||
}
|
||||
unsigned i = kNumBitsMax - 1;
|
||||
for (; GetSubBit(key, i) == GetSubBit(n.Key, i); i--);
|
||||
n.Len = (UInt16)(kNumBitsMax - (1 + i));
|
||||
const unsigned newBit = GetSubBit(key, i);
|
||||
n.Values[newBit] = value;
|
||||
n.Keys[newBit] = key;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned cur = 0;
|
||||
unsigned bitPos = kNumBitsMax;
|
||||
for (;;)
|
||||
{
|
||||
CNode &n = Nodes[cur];
|
||||
bitPos -= n.Len;
|
||||
if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))
|
||||
{
|
||||
unsigned i = (unsigned)n.Len - 1;
|
||||
for (; GetSubBit(key, bitPos + i) == GetSubBit(n.Key, bitPos + i); i--);
|
||||
|
||||
CNode e2(n);
|
||||
e2.Len = (UInt16)i;
|
||||
|
||||
n.Len = (UInt16)(n.Len - (1 + i));
|
||||
unsigned newBit = GetSubBit(key, bitPos + i);
|
||||
n.Values[newBit] = value;
|
||||
n.IsLeaf[newBit] = 1;
|
||||
n.IsLeaf[1 - newBit] = 0;
|
||||
n.Keys[newBit] = key;
|
||||
n.Keys[1 - newBit] = (UInt32)Nodes.Size();
|
||||
Nodes.Add(e2);
|
||||
return false;
|
||||
}
|
||||
const unsigned bit = GetSubBit(key, --bitPos);
|
||||
|
||||
if (n.IsLeaf[bit])
|
||||
{
|
||||
if (key == n.Keys[bit])
|
||||
{
|
||||
n.Values[bit] = value;
|
||||
return true;
|
||||
}
|
||||
unsigned i = bitPos - 1;
|
||||
for (; GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--);
|
||||
|
||||
CNode e2;
|
||||
|
||||
const unsigned newBit = GetSubBit(key, i);
|
||||
e2.Values[newBit] = value;
|
||||
e2.Values[1 - newBit] = n.Values[bit];
|
||||
e2.IsLeaf[newBit] = e2.IsLeaf[1 - newBit] = 1;
|
||||
e2.Keys[newBit] = key;
|
||||
e2.Keys[1 - newBit] = e2.Key = n.Keys[bit];
|
||||
e2.Len = (UInt16)(bitPos - (1 + i));
|
||||
|
||||
n.IsLeaf[bit] = 0;
|
||||
n.Keys[bit] = (UInt32)Nodes.Size();
|
||||
|
||||
Nodes.Add(e2);
|
||||
return false;
|
||||
}
|
||||
cur = (unsigned)n.Keys[bit];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// MyMap.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_MAP_H
|
||||
#define ZIP7_INC_COMMON_MY_MAP_H
|
||||
|
||||
#include "MyTypes.h"
|
||||
#include "MyVector.h"
|
||||
|
||||
class CMap32
|
||||
{
|
||||
struct CNode
|
||||
{
|
||||
UInt32 Key;
|
||||
UInt32 Keys[2];
|
||||
UInt32 Values[2];
|
||||
UInt16 Len;
|
||||
Byte IsLeaf[2];
|
||||
};
|
||||
CRecordVector<CNode> Nodes;
|
||||
|
||||
public:
|
||||
|
||||
void Clear() { Nodes.Clear(); }
|
||||
bool Find(UInt32 key, UInt32 &valueRes) const throw();
|
||||
bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
// Common/MyTypes.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_TYPES_H
|
||||
#define ZIP7_INC_COMMON_MY_TYPES_H
|
||||
|
||||
#include "Common0.h"
|
||||
#include "../../C/7zTypes.h"
|
||||
|
||||
// typedef int HRes;
|
||||
// typedef HRESULT HRes;
|
||||
|
||||
struct CBoolPair
|
||||
{
|
||||
bool Val;
|
||||
bool Def;
|
||||
|
||||
CBoolPair(): Val(false), Def(false) {}
|
||||
|
||||
void Init()
|
||||
{
|
||||
Val = false;
|
||||
Def = false;
|
||||
}
|
||||
|
||||
void SetTrueTrue()
|
||||
{
|
||||
Val = true;
|
||||
Def = true;
|
||||
}
|
||||
|
||||
void SetVal_as_Defined(bool val)
|
||||
{
|
||||
Val = val;
|
||||
Def = true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
// MyUnknown.h
|
||||
|
||||
#ifndef ZIP7_INC_MY_UNKNOWN_H
|
||||
#define ZIP7_INC_MY_UNKNOWN_H
|
||||
|
||||
#include "MyWindows.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
// Common/MyVector.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
@@ -0,0 +1,724 @@
|
||||
// Common/MyVector.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_MY_VECTOR_H
|
||||
#define ZIP7_INC_COMMON_MY_VECTOR_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
const unsigned k_VectorSizeMax = ((unsigned)1 << 31) - 1;
|
||||
|
||||
template <class T>
|
||||
class CRecordVector
|
||||
{
|
||||
T *_items;
|
||||
unsigned _size;
|
||||
unsigned _capacity;
|
||||
|
||||
void MoveItems(unsigned destIndex, unsigned srcIndex)
|
||||
{
|
||||
memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));
|
||||
}
|
||||
|
||||
void ReAllocForNewCapacity(const unsigned newCapacity)
|
||||
{
|
||||
T *p;
|
||||
Z7_ARRAY_NEW(p, T, newCapacity)
|
||||
// p = new T[newCapacity];
|
||||
if (_size != 0)
|
||||
memcpy(p, _items, (size_t)_size * sizeof(T));
|
||||
delete []_items;
|
||||
_items = p;
|
||||
_capacity = newCapacity;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void ReserveOnePosition()
|
||||
{
|
||||
if (_size != _capacity)
|
||||
return;
|
||||
if (_capacity >= k_VectorSizeMax)
|
||||
throw 2021;
|
||||
const unsigned rem = k_VectorSizeMax - _capacity;
|
||||
unsigned add = (_capacity >> 2) + 1;
|
||||
if (add > rem)
|
||||
add = rem;
|
||||
ReAllocForNewCapacity(_capacity + add);
|
||||
}
|
||||
|
||||
CRecordVector(): _items(NULL), _size(0), _capacity(0) {}
|
||||
|
||||
CRecordVector(const CRecordVector &v): _items(NULL), _size(0), _capacity(0)
|
||||
{
|
||||
const unsigned size = v.Size();
|
||||
if (size != 0)
|
||||
{
|
||||
// Z7_ARRAY_NEW(_items, T, size)
|
||||
_items = new T[size];
|
||||
_size = size;
|
||||
_capacity = size;
|
||||
memcpy(_items, v._items, (size_t)size * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Size() const { return _size; }
|
||||
bool IsEmpty() const { return _size == 0; }
|
||||
|
||||
void ConstructReserve(unsigned size)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
Z7_ARRAY_NEW(_items, T, size)
|
||||
// _items = new T[size];
|
||||
_capacity = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Reserve(unsigned newCapacity)
|
||||
{
|
||||
if (newCapacity > _capacity)
|
||||
{
|
||||
if (newCapacity > k_VectorSizeMax)
|
||||
throw 2021;
|
||||
ReAllocForNewCapacity(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
void ChangeSize_KeepData(unsigned newSize)
|
||||
{
|
||||
Reserve(newSize);
|
||||
_size = newSize;
|
||||
}
|
||||
|
||||
void ClearAndReserve(unsigned newCapacity)
|
||||
{
|
||||
Clear();
|
||||
if (newCapacity > _capacity)
|
||||
{
|
||||
if (newCapacity > k_VectorSizeMax)
|
||||
throw 2021;
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
_capacity = 0;
|
||||
Z7_ARRAY_NEW(_items, T, newCapacity)
|
||||
// _items = new T[newCapacity];
|
||||
_capacity = newCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
void ClearAndSetSize(unsigned newSize)
|
||||
{
|
||||
ClearAndReserve(newSize);
|
||||
_size = newSize;
|
||||
}
|
||||
|
||||
void ReserveDown()
|
||||
{
|
||||
if (_size == _capacity)
|
||||
return;
|
||||
T *p = NULL;
|
||||
if (_size != 0)
|
||||
{
|
||||
// Z7_ARRAY_NEW(p, T, _size)
|
||||
p = new T[_size];
|
||||
memcpy(p, _items, (size_t)_size * sizeof(T));
|
||||
}
|
||||
delete []_items;
|
||||
_items = p;
|
||||
_capacity = _size;
|
||||
}
|
||||
|
||||
~CRecordVector() { delete []_items; }
|
||||
|
||||
void ClearAndFree()
|
||||
{
|
||||
delete []_items;
|
||||
_items = NULL;
|
||||
_size = 0;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
void Clear() { _size = 0; }
|
||||
|
||||
void DeleteBack() { _size--; }
|
||||
|
||||
void DeleteFrom(unsigned index)
|
||||
{
|
||||
// if (index <= _size)
|
||||
_size = index;
|
||||
}
|
||||
|
||||
void DeleteFrontal(unsigned num)
|
||||
{
|
||||
if (num != 0)
|
||||
{
|
||||
MoveItems(0, num);
|
||||
_size -= num;
|
||||
}
|
||||
}
|
||||
|
||||
void Delete(unsigned index)
|
||||
{
|
||||
MoveItems(index, index + 1);
|
||||
_size -= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
void Delete(unsigned index, unsigned num)
|
||||
{
|
||||
if (num > 0)
|
||||
{
|
||||
MoveItems(index, index + num);
|
||||
_size -= num;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
CRecordVector& operator=(const CRecordVector &v)
|
||||
{
|
||||
if (&v == this)
|
||||
return *this;
|
||||
const unsigned size = v.Size();
|
||||
if (size > _capacity)
|
||||
{
|
||||
delete []_items;
|
||||
_capacity = 0;
|
||||
_size = 0;
|
||||
_items = NULL;
|
||||
_items = new T[size];
|
||||
_capacity = size;
|
||||
}
|
||||
_size = size;
|
||||
if (size != 0)
|
||||
memcpy(_items, v._items, (size_t)size * sizeof(T));
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRecordVector& operator+=(const CRecordVector &v)
|
||||
{
|
||||
const unsigned size = v.Size();
|
||||
if (size != 0)
|
||||
{
|
||||
if (_size >= k_VectorSizeMax || size > k_VectorSizeMax - _size)
|
||||
throw 2021;
|
||||
const unsigned newSize = _size + size;
|
||||
Reserve(newSize);
|
||||
memcpy(_items + _size, v._items, (size_t)size * sizeof(T));
|
||||
_size = newSize;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned Add(const T item)
|
||||
{
|
||||
ReserveOnePosition();
|
||||
const unsigned size = _size;
|
||||
_size = size + 1;
|
||||
_items[size] = item;
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned Add2(const T &item)
|
||||
{
|
||||
ReserveOnePosition();
|
||||
const unsigned size = _size;
|
||||
_size = size + 1;
|
||||
_items[size] = item;
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned AddInReserved(const T item)
|
||||
{
|
||||
const unsigned size = _size;
|
||||
_size = size + 1;
|
||||
_items[size] = item;
|
||||
return size;
|
||||
}
|
||||
|
||||
void Insert(unsigned index, const T item)
|
||||
{
|
||||
ReserveOnePosition();
|
||||
MoveItems(index + 1, index);
|
||||
_items[index] = item;
|
||||
_size++;
|
||||
}
|
||||
|
||||
void InsertInReserved(unsigned index, const T item)
|
||||
{
|
||||
MoveItems(index + 1, index);
|
||||
_items[index] = item;
|
||||
_size++;
|
||||
}
|
||||
|
||||
void MoveToFront(unsigned index)
|
||||
{
|
||||
if (index != 0)
|
||||
{
|
||||
const T temp = _items[index];
|
||||
memmove(_items + 1, _items, (size_t)index * sizeof(T));
|
||||
_items[0] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
const T& operator[](unsigned index) const { return _items[index]; }
|
||||
T& operator[](unsigned index) { return _items[index]; }
|
||||
const T& operator[](int index) const { return _items[(unsigned)index]; }
|
||||
T& operator[](int index) { return _items[(unsigned)index]; }
|
||||
|
||||
const T* ConstData() const { return _items; }
|
||||
T* NonConstData() const { return _items; }
|
||||
T* NonConstData() { return _items; }
|
||||
|
||||
const T* Data() const { return _items; }
|
||||
T* Data() { return _items; }
|
||||
|
||||
const T& FrontItem() const { return _items[0]; }
|
||||
T& FrontItem() { return _items[0]; }
|
||||
/*
|
||||
const T Front() const { return _items[0]; }
|
||||
T Front() { return _items[0]; }
|
||||
const T& Front() const { return _items[0]; }
|
||||
T& Front() { return _items[0]; }
|
||||
*/
|
||||
const T& Back() const { return _items[(size_t)_size - 1]; }
|
||||
T& Back() { return _items[(size_t)_size - 1]; }
|
||||
|
||||
/*
|
||||
void Swap(unsigned i, unsigned j)
|
||||
{
|
||||
const T temp = _items[i];
|
||||
_items[i] = _items[j];
|
||||
_items[j] = temp;
|
||||
}
|
||||
*/
|
||||
|
||||
int FindInSorted(const T item, unsigned left, unsigned right) const
|
||||
{
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T midVal = (*this)[mid];
|
||||
if (item == midVal)
|
||||
return (int)mid;
|
||||
if (item < midVal)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindInSorted2(const T &item, unsigned left, unsigned right) const
|
||||
{
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T& midVal = (*this)[mid];
|
||||
const int comp = item.Compare(midVal);
|
||||
if (comp == 0)
|
||||
return (int)mid;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FindInSorted(const T item) const
|
||||
{
|
||||
return FindInSorted(item, 0, _size);
|
||||
}
|
||||
|
||||
int FindInSorted2(const T &item) const
|
||||
{
|
||||
return FindInSorted2(item, 0, _size);
|
||||
}
|
||||
|
||||
unsigned AddToUniqueSorted(const T item)
|
||||
{
|
||||
unsigned left = 0, right = _size;
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T midVal = (*this)[mid];
|
||||
if (item == midVal)
|
||||
return mid;
|
||||
if (item < midVal)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
Insert(right, item);
|
||||
return right;
|
||||
}
|
||||
|
||||
unsigned AddToUniqueSorted2(const T &item)
|
||||
{
|
||||
unsigned left = 0, right = _size;
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T& midVal = (*this)[mid];
|
||||
const int comp = item.Compare(midVal);
|
||||
if (comp == 0)
|
||||
return mid;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
Insert(right, item);
|
||||
return right;
|
||||
}
|
||||
|
||||
static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)
|
||||
{
|
||||
const T temp = p[k];
|
||||
for (;;)
|
||||
{
|
||||
unsigned s = (k << 1);
|
||||
if (s > size)
|
||||
break;
|
||||
if (s < size && compare(p + s + 1, p + s, param) > 0)
|
||||
s++;
|
||||
if (compare(&temp, p + s, param) >= 0)
|
||||
break;
|
||||
p[k] = p[s];
|
||||
k = s;
|
||||
}
|
||||
p[k] = temp;
|
||||
}
|
||||
|
||||
void Sort(int (*compare)(const T*, const T*, void *), void *param)
|
||||
{
|
||||
unsigned size = _size;
|
||||
if (size <= 1)
|
||||
return;
|
||||
T* p = _items - 1;
|
||||
{
|
||||
unsigned i = size >> 1;
|
||||
do
|
||||
SortRefDown(p, i, size, compare, param);
|
||||
while (--i);
|
||||
}
|
||||
do
|
||||
{
|
||||
const T temp = p[size];
|
||||
p[size--] = p[1];
|
||||
p[1] = temp;
|
||||
SortRefDown(p, 1, size, compare, param);
|
||||
}
|
||||
while (size > 1);
|
||||
}
|
||||
|
||||
static void SortRefDown2(T* p, unsigned k, unsigned size)
|
||||
{
|
||||
const T temp = p[k];
|
||||
for (;;)
|
||||
{
|
||||
unsigned s = (k << 1);
|
||||
if (s > size)
|
||||
break;
|
||||
if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0)
|
||||
s++;
|
||||
if (temp.Compare(p[s]) >= 0)
|
||||
break;
|
||||
p[k] = p[s];
|
||||
k = s;
|
||||
}
|
||||
p[k] = temp;
|
||||
}
|
||||
|
||||
void Sort2()
|
||||
{
|
||||
unsigned size = _size;
|
||||
if (size <= 1)
|
||||
return;
|
||||
T* p = _items - 1;
|
||||
{
|
||||
unsigned i = size >> 1;
|
||||
do
|
||||
SortRefDown2(p, i, size);
|
||||
while (--i);
|
||||
}
|
||||
do
|
||||
{
|
||||
const T temp = p[size];
|
||||
p[size--] = p[1];
|
||||
p[1] = temp;
|
||||
SortRefDown2(p, 1, size);
|
||||
}
|
||||
while (size > 1);
|
||||
}
|
||||
};
|
||||
|
||||
typedef CRecordVector<int> CIntVector;
|
||||
typedef CRecordVector<unsigned int> CUIntVector;
|
||||
typedef CRecordVector<bool> CBoolVector;
|
||||
typedef CRecordVector<unsigned char> CByteVector;
|
||||
typedef CRecordVector<void *> CPointerVector;
|
||||
|
||||
template <class T>
|
||||
class CObjectVector
|
||||
{
|
||||
CPointerVector _v;
|
||||
public:
|
||||
unsigned Size() const { return _v.Size(); }
|
||||
bool IsEmpty() const { return _v.IsEmpty(); }
|
||||
void ReserveDown() { _v.ReserveDown(); }
|
||||
// void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); }
|
||||
void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); }
|
||||
|
||||
CObjectVector() {}
|
||||
CObjectVector(const CObjectVector &v)
|
||||
{
|
||||
const unsigned size = v.Size();
|
||||
_v.ConstructReserve(size);
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
AddInReserved(v[i]);
|
||||
}
|
||||
CObjectVector& operator=(const CObjectVector &v)
|
||||
{
|
||||
if (&v == this)
|
||||
return *this;
|
||||
Clear();
|
||||
const unsigned size = v.Size();
|
||||
_v.Reserve(size);
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
AddInReserved(v[i]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CObjectVector& operator+=(const CObjectVector &v)
|
||||
{
|
||||
const unsigned addSize = v.Size();
|
||||
if (addSize != 0)
|
||||
{
|
||||
const unsigned size = Size();
|
||||
if (size >= k_VectorSizeMax || addSize > k_VectorSizeMax - size)
|
||||
throw 2021;
|
||||
_v.Reserve(size + addSize);
|
||||
for (unsigned i = 0; i < addSize; i++)
|
||||
AddInReserved(v[i]);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T& operator[](unsigned index) const { return *((T *)_v[index]); }
|
||||
T& operator[](unsigned index) { return *((T *)_v[index]); }
|
||||
const T& operator[](int index) const { return *((T *)_v[(unsigned)index]); }
|
||||
T& operator[](int index) { return *((T *)_v[(unsigned)index]); }
|
||||
const T& Front() const { return operator[](0); }
|
||||
T& Front() { return operator[](0); }
|
||||
const T& Back() const { return *(T *)_v.Back(); }
|
||||
T& Back() { return *(T *)_v.Back(); }
|
||||
|
||||
void MoveToFront(unsigned index) { _v.MoveToFront(index); }
|
||||
|
||||
unsigned Add(const T& item)
|
||||
{
|
||||
_v.ReserveOnePosition();
|
||||
return AddInReserved(item);
|
||||
}
|
||||
|
||||
unsigned AddInReserved(const T& item)
|
||||
{
|
||||
return _v.AddInReserved(new T(item));
|
||||
}
|
||||
|
||||
void ReserveOnePosition()
|
||||
{
|
||||
_v.ReserveOnePosition();
|
||||
}
|
||||
|
||||
unsigned AddInReserved_Ptr_of_new(T *ptr)
|
||||
{
|
||||
return _v.AddInReserved(ptr);
|
||||
}
|
||||
|
||||
#define VECTOR_ADD_NEW_OBJECT(v, a) \
|
||||
(v).ReserveOnePosition(); \
|
||||
(v).AddInReserved_Ptr_of_new(new a);
|
||||
|
||||
|
||||
T& AddNew()
|
||||
{
|
||||
_v.ReserveOnePosition();
|
||||
T *p = new T;
|
||||
_v.AddInReserved(p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
T& AddNewInReserved()
|
||||
{
|
||||
T *p = new T;
|
||||
_v.AddInReserved(p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
void Insert(unsigned index, const T& item)
|
||||
{
|
||||
_v.ReserveOnePosition();
|
||||
_v.InsertInReserved(index, new T(item));
|
||||
}
|
||||
|
||||
T& InsertNew(unsigned index)
|
||||
{
|
||||
_v.ReserveOnePosition();
|
||||
T *p = new T;
|
||||
_v.InsertInReserved(index, p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
~CObjectVector()
|
||||
{
|
||||
for (unsigned i = _v.Size(); i != 0;)
|
||||
delete (T *)_v[--i];
|
||||
}
|
||||
|
||||
void ClearAndFree()
|
||||
{
|
||||
Clear();
|
||||
_v.ClearAndFree();
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
for (unsigned i = _v.Size(); i != 0;)
|
||||
delete (T *)_v[--i];
|
||||
_v.Clear();
|
||||
}
|
||||
|
||||
void DeleteFrom(unsigned index)
|
||||
{
|
||||
const unsigned size = _v.Size();
|
||||
for (unsigned i = index; i < size; i++)
|
||||
delete (T *)_v[i];
|
||||
_v.DeleteFrom(index);
|
||||
}
|
||||
|
||||
void DeleteFrontal(unsigned num)
|
||||
{
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
delete (T *)_v[i];
|
||||
_v.DeleteFrontal(num);
|
||||
}
|
||||
|
||||
void DeleteBack()
|
||||
{
|
||||
delete (T *)_v.Back();
|
||||
_v.DeleteBack();
|
||||
}
|
||||
|
||||
void Delete(unsigned index)
|
||||
{
|
||||
delete (T *)_v[index];
|
||||
_v.Delete(index);
|
||||
}
|
||||
// void Delete(int index) { Delete((unsigned)index); }
|
||||
|
||||
/*
|
||||
void Delete(unsigned index, unsigned num)
|
||||
{
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
delete (T *)_v[index + i];
|
||||
_v.Delete(index, num);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int Find(const T& item) const
|
||||
{
|
||||
unsigned size = Size();
|
||||
for (unsigned i = 0; i < size; i++)
|
||||
if (item == (*this)[i])
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
int FindInSorted(const T& item) const
|
||||
{
|
||||
unsigned left = 0, right = Size();
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T& midVal = (*this)[mid];
|
||||
const int comp = item.Compare(midVal);
|
||||
if (comp == 0)
|
||||
return (int)mid;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned AddToUniqueSorted(const T& item)
|
||||
{
|
||||
unsigned left = 0, right = Size();
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T& midVal = (*this)[mid];
|
||||
const int comp = item.Compare(midVal);
|
||||
if (comp == 0)
|
||||
return mid;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
Insert(right, item);
|
||||
return right;
|
||||
}
|
||||
|
||||
/*
|
||||
unsigned AddToSorted(const T& item)
|
||||
{
|
||||
unsigned left = 0, right = Size();
|
||||
while (left != right)
|
||||
{
|
||||
// const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned mid = (left + right) / 2;
|
||||
const T& midVal = (*this)[mid];
|
||||
const int comp = item.Compare(midVal);
|
||||
if (comp == 0)
|
||||
{
|
||||
right = mid + 1;
|
||||
break;
|
||||
}
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
Insert(right, item);
|
||||
return right;
|
||||
}
|
||||
*/
|
||||
|
||||
void Sort(int (*compare)(void *const *, void *const *, void *), void *param)
|
||||
{ _v.Sort(compare, param); }
|
||||
|
||||
static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)
|
||||
{ return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); }
|
||||
|
||||
void Sort() { _v.Sort(CompareObjectItems, NULL); }
|
||||
};
|
||||
|
||||
#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,292 @@
|
||||
// MyWindows.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#ifdef __GNUC__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "MyWindows.h"
|
||||
|
||||
static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }
|
||||
static inline void FreeForBSTR(void *pv) { ::free(pv);}
|
||||
|
||||
/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string.
|
||||
We must select CBstrSizeType for another systems (not Win32):
|
||||
|
||||
if (CBstrSizeType is UINT32),
|
||||
then we support only strings smaller than 4 GB.
|
||||
Win32 version always has that limitation.
|
||||
|
||||
if (CBstrSizeType is UINT),
|
||||
(UINT can be 16/32/64-bit)
|
||||
We can support strings larger than 4 GB (if UINT is 64-bit),
|
||||
but sizeof(UINT) can be different in parts compiled by
|
||||
different compilers/settings,
|
||||
and we can't send such BSTR strings between such parts.
|
||||
*/
|
||||
|
||||
typedef UINT32 CBstrSizeType;
|
||||
// typedef UINT CBstrSizeType;
|
||||
|
||||
#define k_BstrSize_Max 0xFFFFFFFF
|
||||
// #define k_BstrSize_Max UINT_MAX
|
||||
// #define k_BstrSize_Max ((UINT)(INT)-1)
|
||||
|
||||
BSTR SysAllocStringByteLen(LPCSTR s, UINT len)
|
||||
{
|
||||
/* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end.
|
||||
We provide also aligned null OLECHAR at the end. */
|
||||
|
||||
if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)))
|
||||
return NULL;
|
||||
|
||||
UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1);
|
||||
void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType));
|
||||
if (!p)
|
||||
return NULL;
|
||||
*(CBstrSizeType *)p = (CBstrSizeType)len;
|
||||
BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
|
||||
if (s)
|
||||
memcpy(bstr, s, len);
|
||||
for (; len < size; len++)
|
||||
((Byte *)bstr)[len] = 0;
|
||||
return bstr;
|
||||
}
|
||||
|
||||
BSTR SysAllocStringLen(const OLECHAR *s, UINT len)
|
||||
{
|
||||
if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR))
|
||||
return NULL;
|
||||
|
||||
UINT size = len * (UINT)sizeof(OLECHAR);
|
||||
void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR));
|
||||
if (!p)
|
||||
return NULL;
|
||||
*(CBstrSizeType *)p = (CBstrSizeType)size;
|
||||
BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
|
||||
if (s)
|
||||
memcpy(bstr, s, size);
|
||||
bstr[len] = 0;
|
||||
return bstr;
|
||||
}
|
||||
|
||||
BSTR SysAllocString(const OLECHAR *s)
|
||||
{
|
||||
if (!s)
|
||||
return NULL;
|
||||
const OLECHAR *s2 = s;
|
||||
while (*s2 != 0)
|
||||
s2++;
|
||||
return SysAllocStringLen(s, (UINT)(s2 - s));
|
||||
}
|
||||
|
||||
void SysFreeString(BSTR bstr)
|
||||
{
|
||||
if (bstr)
|
||||
FreeForBSTR((CBstrSizeType *)(void *)bstr - 1);
|
||||
}
|
||||
|
||||
UINT SysStringByteLen(BSTR bstr)
|
||||
{
|
||||
if (!bstr)
|
||||
return 0;
|
||||
return *((CBstrSizeType *)(void *)bstr - 1);
|
||||
}
|
||||
|
||||
UINT SysStringLen(BSTR bstr)
|
||||
{
|
||||
if (!bstr)
|
||||
return 0;
|
||||
return *((CBstrSizeType *)(void *)bstr - 1) / (UINT)sizeof(OLECHAR);
|
||||
}
|
||||
|
||||
|
||||
HRESULT VariantClear(VARIANTARG *prop)
|
||||
{
|
||||
if (prop->vt == VT_BSTR)
|
||||
SysFreeString(prop->bstrVal);
|
||||
prop->vt = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src)
|
||||
{
|
||||
HRESULT res = ::VariantClear(dest);
|
||||
if (res != S_OK)
|
||||
return res;
|
||||
if (src->vt == VT_BSTR)
|
||||
{
|
||||
dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,
|
||||
SysStringByteLen(src->bstrVal));
|
||||
if (!dest->bstrVal)
|
||||
return E_OUTOFMEMORY;
|
||||
dest->vt = VT_BSTR;
|
||||
}
|
||||
else
|
||||
*dest = *src;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)
|
||||
{
|
||||
if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;
|
||||
if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;
|
||||
if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;
|
||||
if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD GetLastError()
|
||||
{
|
||||
return (DWORD)errno;
|
||||
}
|
||||
|
||||
void SetLastError(DWORD dw)
|
||||
{
|
||||
errno = (int)dw;
|
||||
}
|
||||
|
||||
|
||||
static LONG TIME_GetBias()
|
||||
{
|
||||
time_t utc = time(NULL);
|
||||
struct tm *ptm = localtime(&utc);
|
||||
int localdaylight = ptm->tm_isdst; /* daylight for local timezone */
|
||||
ptm = gmtime(&utc);
|
||||
ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */
|
||||
LONG bias = (int)(mktime(ptm)-utc);
|
||||
return bias;
|
||||
}
|
||||
|
||||
#define TICKS_PER_SEC 10000000
|
||||
/*
|
||||
#define SECS_PER_DAY (24 * 60 * 60)
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY)
|
||||
#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC)
|
||||
*/
|
||||
|
||||
#define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32))
|
||||
|
||||
#define SET_FILETIME(ft, v64) \
|
||||
(ft)->dwLowDateTime = (DWORD)v64; \
|
||||
(ft)->dwHighDateTime = (DWORD)(v64 >> 32);
|
||||
|
||||
|
||||
BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime)
|
||||
{
|
||||
UInt64 v = GET_TIME_64(fileTime);
|
||||
v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC);
|
||||
SET_FILETIME(localFileTime, v)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime)
|
||||
{
|
||||
UInt64 v = GET_TIME_64(localFileTime);
|
||||
v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC);
|
||||
SET_FILETIME(fileTime, v)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft)
|
||||
{
|
||||
UInt64 t = 0;
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == 0)
|
||||
{
|
||||
t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970;
|
||||
t += tv.tv_usec * 10;
|
||||
}
|
||||
SET_FILETIME(ft, t)
|
||||
}
|
||||
*/
|
||||
|
||||
DWORD WINAPI GetTickCount(VOID)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
// gettimeofday() doesn't work in some MINGWs by unknown reason
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == 0)
|
||||
{
|
||||
// tv_sec and tv_usec are (long)
|
||||
return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000);
|
||||
}
|
||||
#endif
|
||||
return (DWORD)time(NULL) * 1000;
|
||||
}
|
||||
|
||||
|
||||
#define PERIOD_4 (4 * 365 + 1)
|
||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||
|
||||
BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st)
|
||||
{
|
||||
UInt32 v;
|
||||
UInt64 v64 = GET_TIME_64(ft);
|
||||
v64 /= 10000;
|
||||
st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000;
|
||||
st->wSecond = (WORD)(v64 % 60); v64 /= 60;
|
||||
st->wMinute = (WORD)(v64 % 60); v64 /= 60;
|
||||
v = (UInt32)v64;
|
||||
st->wHour = (WORD)(v % 24); v /= 24;
|
||||
|
||||
// 1601-01-01 was Monday
|
||||
st->wDayOfWeek = (WORD)((v + 1) % 7);
|
||||
|
||||
UInt32 leaps, year, day, mon;
|
||||
leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4;
|
||||
v += 28188 + leaps;
|
||||
// leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01
|
||||
// (1959 / 64) - converts day from 03-01 to month
|
||||
year = (20 * v - 2442) / (5 * PERIOD_4);
|
||||
day = v - (year * PERIOD_4) / 4;
|
||||
mon = (64 * day) / 1959;
|
||||
st->wDay = (WORD)(day - (1959 * mon) / 64);
|
||||
mon -= 1;
|
||||
year += 1524;
|
||||
if (mon > 12)
|
||||
{
|
||||
mon -= 12;
|
||||
year++;
|
||||
}
|
||||
st->wMonth = (WORD)mon;
|
||||
st->wYear = (WORD)year;
|
||||
|
||||
/*
|
||||
unsigned year, mon;
|
||||
unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
unsigned t;
|
||||
|
||||
year = (WORD)(1601 + v / PERIOD_400 * 400);
|
||||
v %= PERIOD_400;
|
||||
|
||||
t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
|
||||
t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
|
||||
t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
|
||||
|
||||
st->wYear = (WORD)year;
|
||||
|
||||
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
|
||||
ms[1] = 29;
|
||||
for (mon = 0;; mon++)
|
||||
{
|
||||
unsigned d = ms[mon];
|
||||
if (v < d)
|
||||
break;
|
||||
v -= d;
|
||||
}
|
||||
st->wDay = (WORD)(v + 1);
|
||||
st->wMonth = (WORD)(mon + 1);
|
||||
*/
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,325 @@
|
||||
// MyWindows.h
|
||||
|
||||
#ifdef Z7_DEFINE_GUID
|
||||
#undef Z7_DEFINE_GUID
|
||||
#endif
|
||||
|
||||
#ifdef INITGUID
|
||||
#define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
EXTERN_C const GUID name; \
|
||||
EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||
#else
|
||||
#define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
EXTERN_C const GUID name
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef ZIP7_INC_MY_WINDOWS_H
|
||||
#define ZIP7_INC_MY_WINDOWS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "../../C/7zWindows.h"
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#include <stddef.h> // for wchar_t
|
||||
#include <string.h>
|
||||
// #include <stdint.h> // for uintptr_t
|
||||
|
||||
#include "../../C/7zTypes.h"
|
||||
#include "MyGuidDef.h"
|
||||
|
||||
// WINAPI is __stdcall in Windows-MSVC in windef.h
|
||||
#define WINAPI
|
||||
|
||||
typedef char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
|
||||
#undef BYTE
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
|
||||
#undef WORD
|
||||
typedef unsigned short WORD;
|
||||
typedef short VARIANT_BOOL;
|
||||
|
||||
#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
|
||||
#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
|
||||
|
||||
// MS uses long for BOOL, but long is 32-bit in MS. So we use int.
|
||||
// typedef long BOOL;
|
||||
typedef int BOOL;
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
// typedef size_t ULONG_PTR;
|
||||
// typedef size_t DWORD_PTR;
|
||||
// typedef uintptr_t UINT_PTR;
|
||||
// typedef ptrdiff_t UINT_PTR;
|
||||
|
||||
typedef Int64 LONGLONG;
|
||||
typedef UInt64 ULONGLONG;
|
||||
|
||||
typedef struct { LONGLONG QuadPart; } LARGE_INTEGER;
|
||||
typedef struct { ULONGLONG QuadPart; } ULARGE_INTEGER;
|
||||
|
||||
typedef const CHAR *LPCSTR;
|
||||
typedef CHAR TCHAR;
|
||||
typedef const TCHAR *LPCTSTR;
|
||||
typedef wchar_t WCHAR;
|
||||
typedef WCHAR OLECHAR;
|
||||
typedef const WCHAR *LPCWSTR;
|
||||
typedef OLECHAR *BSTR;
|
||||
typedef const OLECHAR *LPCOLESTR;
|
||||
typedef OLECHAR *LPOLESTR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD dwLowDateTime;
|
||||
DWORD dwHighDateTime;
|
||||
} FILETIME;
|
||||
|
||||
#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
|
||||
#define FAILED(hr) ((HRESULT)(hr) < 0)
|
||||
typedef ULONG PROPID;
|
||||
typedef LONG SCODE;
|
||||
|
||||
|
||||
#define S_OK ((HRESULT)0x00000000L)
|
||||
#define S_FALSE ((HRESULT)0x00000001L)
|
||||
#define E_NOTIMPL ((HRESULT)0x80004001L)
|
||||
#define E_NOINTERFACE ((HRESULT)0x80004002L)
|
||||
#define E_ABORT ((HRESULT)0x80004004L)
|
||||
#define E_FAIL ((HRESULT)0x80004005L)
|
||||
#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
|
||||
#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L)
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STDMETHODCALLTYPE __stdcall
|
||||
#define STDAPICALLTYPE __stdcall
|
||||
#else
|
||||
// do we need __export here?
|
||||
#define STDMETHODCALLTYPE
|
||||
#define STDAPICALLTYPE
|
||||
#endif
|
||||
|
||||
#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
|
||||
|
||||
#ifndef DECLSPEC_NOTHROW
|
||||
#define DECLSPEC_NOTHROW Z7_DECLSPEC_NOTHROW
|
||||
#endif
|
||||
|
||||
#ifndef DECLSPEC_NOVTABLE
|
||||
#define DECLSPEC_NOVTABLE Z7_DECLSPEC_NOVTABLE
|
||||
#endif
|
||||
|
||||
#ifndef COM_DECLSPEC_NOTHROW
|
||||
#ifdef COM_STDMETHOD_CAN_THROW
|
||||
#define COM_DECLSPEC_NOTHROW
|
||||
#else
|
||||
#define COM_DECLSPEC_NOTHROW DECLSPEC_NOTHROW
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DECLARE_INTERFACE(iface) struct DECLSPEC_NOVTABLE iface
|
||||
#define DECLARE_INTERFACE_(iface, baseiface) struct DECLSPEC_NOVTABLE iface : public baseiface
|
||||
|
||||
#define STDMETHOD_(t, f) virtual COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE f
|
||||
#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
|
||||
#define STDMETHODIMP_(t) COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE
|
||||
#define STDMETHODIMP STDMETHODIMP_(HRESULT)
|
||||
|
||||
|
||||
#define PURE = 0
|
||||
|
||||
// #define MIDL_INTERFACE(x) struct
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
p7zip and 7-Zip before v23 used virtual destructor in IUnknown,
|
||||
if _WIN32 is not defined.
|
||||
It used virtual destructor, because some compilers don't like virtual
|
||||
interfaces without virtual destructor.
|
||||
IUnknown in Windows (_WIN32) doesn't use virtual destructor in IUnknown.
|
||||
We still can define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,
|
||||
if we want to be compatible with old plugin interface of p7zip and 7-Zip before v23.
|
||||
|
||||
v23:
|
||||
In new 7-Zip v23 we try to be more compatible with original IUnknown from _WIN32.
|
||||
So we do not define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,
|
||||
*/
|
||||
// #define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
|
||||
|
||||
#ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
|
||||
#if defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Winconsistent-missing-destructor-override"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
DEFINE_GUID(IID_IUnknown,
|
||||
0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
|
||||
struct IUnknown
|
||||
{
|
||||
STDMETHOD(QueryInterface) (REFIID iid, void **outObject) =0;
|
||||
STDMETHOD_(ULONG, AddRef)() =0;
|
||||
STDMETHOD_(ULONG, Release)() =0;
|
||||
#ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN
|
||||
virtual ~IUnknown() {}
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef IUnknown *LPUNKNOWN;
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#define VARIANT_TRUE ((VARIANT_BOOL)-1)
|
||||
#define VARIANT_FALSE ((VARIANT_BOOL)0)
|
||||
|
||||
enum VARENUM
|
||||
{
|
||||
VT_EMPTY = 0,
|
||||
VT_NULL = 1,
|
||||
VT_I2 = 2,
|
||||
VT_I4 = 3,
|
||||
VT_R4 = 4,
|
||||
VT_R8 = 5,
|
||||
VT_CY = 6,
|
||||
VT_DATE = 7,
|
||||
VT_BSTR = 8,
|
||||
VT_DISPATCH = 9,
|
||||
VT_ERROR = 10,
|
||||
VT_BOOL = 11,
|
||||
VT_VARIANT = 12,
|
||||
VT_UNKNOWN = 13,
|
||||
VT_DECIMAL = 14,
|
||||
|
||||
VT_I1 = 16,
|
||||
VT_UI1 = 17,
|
||||
VT_UI2 = 18,
|
||||
VT_UI4 = 19,
|
||||
VT_I8 = 20,
|
||||
VT_UI8 = 21,
|
||||
VT_INT = 22,
|
||||
VT_UINT = 23,
|
||||
VT_VOID = 24,
|
||||
VT_HRESULT = 25,
|
||||
VT_FILETIME = 64
|
||||
};
|
||||
|
||||
typedef unsigned short VARTYPE;
|
||||
typedef WORD PROPVAR_PAD1;
|
||||
typedef WORD PROPVAR_PAD2;
|
||||
typedef WORD PROPVAR_PAD3;
|
||||
|
||||
typedef struct tagPROPVARIANT
|
||||
{
|
||||
VARTYPE vt;
|
||||
PROPVAR_PAD1 wReserved1;
|
||||
PROPVAR_PAD2 wReserved2;
|
||||
PROPVAR_PAD3 wReserved3;
|
||||
union
|
||||
{
|
||||
CHAR cVal;
|
||||
UCHAR bVal;
|
||||
SHORT iVal;
|
||||
USHORT uiVal;
|
||||
LONG lVal;
|
||||
ULONG ulVal;
|
||||
INT intVal;
|
||||
UINT uintVal;
|
||||
LARGE_INTEGER hVal;
|
||||
ULARGE_INTEGER uhVal;
|
||||
VARIANT_BOOL boolVal;
|
||||
SCODE scode;
|
||||
FILETIME filetime;
|
||||
BSTR bstrVal;
|
||||
};
|
||||
} PROPVARIANT;
|
||||
|
||||
typedef PROPVARIANT tagVARIANT;
|
||||
typedef tagVARIANT VARIANT;
|
||||
typedef VARIANT VARIANTARG;
|
||||
|
||||
EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
|
||||
EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src);
|
||||
|
||||
typedef struct tagSTATPROPSTG
|
||||
{
|
||||
LPOLESTR lpwstrName;
|
||||
PROPID propid;
|
||||
VARTYPE vt;
|
||||
} STATPROPSTG;
|
||||
|
||||
EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
|
||||
EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len);
|
||||
EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
|
||||
EXTERN_C void SysFreeString(BSTR bstr);
|
||||
EXTERN_C UINT SysStringByteLen(BSTR bstr);
|
||||
EXTERN_C UINT SysStringLen(BSTR bstr);
|
||||
|
||||
EXTERN_C DWORD GetLastError();
|
||||
EXTERN_C void SetLastError(DWORD dwCode);
|
||||
EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
|
||||
|
||||
EXTERN_C DWORD GetCurrentThreadId();
|
||||
EXTERN_C DWORD GetCurrentProcessId();
|
||||
|
||||
#define MAX_PATH 1024
|
||||
|
||||
#define CP_ACP 0
|
||||
#define CP_OEMCP 1
|
||||
#define CP_UTF8 65001
|
||||
|
||||
typedef enum tagSTREAM_SEEK
|
||||
{
|
||||
STREAM_SEEK_SET = 0,
|
||||
STREAM_SEEK_CUR = 1,
|
||||
STREAM_SEEK_END = 2
|
||||
} STREAM_SEEK;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD wYear;
|
||||
WORD wMonth;
|
||||
WORD wDayOfWeek;
|
||||
WORD wDay;
|
||||
WORD wHour;
|
||||
WORD wMinute;
|
||||
WORD wSecond;
|
||||
WORD wMilliseconds;
|
||||
} SYSTEMTIME;
|
||||
|
||||
BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime);
|
||||
BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime);
|
||||
BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime);
|
||||
// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime);
|
||||
|
||||
DWORD GetTickCount();
|
||||
|
||||
|
||||
/*
|
||||
#define CREATE_NEW 1
|
||||
#define CREATE_ALWAYS 2
|
||||
#define OPEN_EXISTING 3
|
||||
#define OPEN_ALWAYS 4
|
||||
#define TRUNCATE_EXISTING 5
|
||||
*/
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
// MyXml.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "MyXml.h"
|
||||
#include "StringToInt.h"
|
||||
|
||||
static bool IsValidChar(char c)
|
||||
{
|
||||
return
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9') ||
|
||||
c == '-';
|
||||
}
|
||||
|
||||
static bool IsSpaceChar(char c)
|
||||
{
|
||||
return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);
|
||||
}
|
||||
|
||||
#define SKIP_SPACES(s) while (IsSpaceChar(*s)) s++;
|
||||
|
||||
int CXmlItem::FindProp(const char *propName) const throw()
|
||||
{
|
||||
FOR_VECTOR (i, Props)
|
||||
if (Props[i].Name.IsEqualTo(propName))
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
AString CXmlItem::GetPropVal(const char *propName) const
|
||||
{
|
||||
const int index = FindProp(propName);
|
||||
if (index >= 0)
|
||||
return Props[(unsigned)index].Value;
|
||||
return AString();
|
||||
}
|
||||
|
||||
bool CXmlItem::IsTagged(const char *tag) const throw()
|
||||
{
|
||||
return (IsTag && Name.IsEqualTo(tag));
|
||||
}
|
||||
|
||||
int CXmlItem::FindSubTag(const char *tag) const throw()
|
||||
{
|
||||
FOR_VECTOR (i, SubItems)
|
||||
if (SubItems[i].IsTagged(tag))
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const CXmlItem *CXmlItem::FindSubTag_GetPtr(const char *tag) const throw()
|
||||
{
|
||||
FOR_VECTOR (i, SubItems)
|
||||
{
|
||||
const CXmlItem *p = &SubItems[i];
|
||||
if (p->IsTagged(tag))
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AString CXmlItem::GetSubString() const
|
||||
{
|
||||
if (SubItems.Size() == 1)
|
||||
{
|
||||
const CXmlItem &item = SubItems[0];
|
||||
if (!item.IsTag)
|
||||
return item.Name;
|
||||
}
|
||||
return AString();
|
||||
}
|
||||
|
||||
const AString * CXmlItem::GetSubStringPtr() const throw()
|
||||
{
|
||||
if (SubItems.Size() == 1)
|
||||
{
|
||||
const CXmlItem &item = SubItems[0];
|
||||
if (!item.IsTag)
|
||||
return &item.Name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AString CXmlItem::GetSubStringForTag(const char *tag) const
|
||||
{
|
||||
const CXmlItem *item = FindSubTag_GetPtr(tag);
|
||||
if (item)
|
||||
return item->GetSubString();
|
||||
return AString();
|
||||
}
|
||||
|
||||
const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
|
||||
{
|
||||
SKIP_SPACES(s)
|
||||
|
||||
const char *beg = s;
|
||||
for (;;)
|
||||
{
|
||||
char c;
|
||||
c = *s; if (c == 0 || c == '<') break; s++;
|
||||
c = *s; if (c == 0 || c == '<') break; s++;
|
||||
}
|
||||
if (*s == 0)
|
||||
return NULL;
|
||||
{
|
||||
const size_t num = (size_t)(s - beg);
|
||||
if (num)
|
||||
{
|
||||
IsTag = false;
|
||||
Name.SetFrom_Chars_SizeT(beg, num);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
IsTag = true;
|
||||
|
||||
s++;
|
||||
SKIP_SPACES(s)
|
||||
|
||||
beg = s;
|
||||
for (;; s++)
|
||||
if (!IsValidChar(*s))
|
||||
break;
|
||||
if (s == beg || *s == 0)
|
||||
return NULL;
|
||||
Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
beg = s;
|
||||
SKIP_SPACES(s)
|
||||
if (*s == '/')
|
||||
{
|
||||
s++;
|
||||
// SKIP_SPACES(s)
|
||||
if (*s != '>')
|
||||
return NULL;
|
||||
return s + 1;
|
||||
}
|
||||
if (*s == '>')
|
||||
{
|
||||
s++;
|
||||
if (numAllowedLevels == 0)
|
||||
return NULL;
|
||||
SubItems.Clear();
|
||||
for (;;)
|
||||
{
|
||||
SKIP_SPACES(s)
|
||||
if (s[0] == '<' && s[1] == '/')
|
||||
break;
|
||||
CXmlItem &item = SubItems.AddNew();
|
||||
s = item.ParseItem(s, numAllowedLevels - 1);
|
||||
if (!s)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s += 2;
|
||||
const unsigned len = Name.Len();
|
||||
const char *name = Name.Ptr();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (*s++ != *name++)
|
||||
return NULL;
|
||||
// s += len;
|
||||
if (s[0] != '>')
|
||||
return NULL;
|
||||
return s + 1;
|
||||
}
|
||||
if (beg == s)
|
||||
return NULL;
|
||||
|
||||
// ReadProperty
|
||||
CXmlProp &prop = Props.AddNew();
|
||||
|
||||
beg = s;
|
||||
for (;; s++)
|
||||
{
|
||||
char c = *s;
|
||||
if (!IsValidChar(c))
|
||||
break;
|
||||
}
|
||||
if (s == beg)
|
||||
return NULL;
|
||||
prop.Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
|
||||
|
||||
SKIP_SPACES(s)
|
||||
if (*s != '=')
|
||||
return NULL;
|
||||
s++;
|
||||
SKIP_SPACES(s)
|
||||
if (*s != '\"')
|
||||
return NULL;
|
||||
s++;
|
||||
|
||||
beg = s;
|
||||
for (;;)
|
||||
{
|
||||
char c = *s;
|
||||
if (c == 0)
|
||||
return NULL;
|
||||
if (c == '\"')
|
||||
break;
|
||||
s++;
|
||||
}
|
||||
prop.Value.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
static const char * SkipHeader(const char *s, const char *startString, const char *endString)
|
||||
{
|
||||
SKIP_SPACES(s)
|
||||
if (IsString1PrefixedByString2(s, startString))
|
||||
{
|
||||
s = strstr(s, endString);
|
||||
if (!s)
|
||||
return NULL;
|
||||
s += strlen(endString);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void CXmlItem::AppendTo(AString &s) const
|
||||
{
|
||||
if (IsTag)
|
||||
s += '<';
|
||||
s += Name;
|
||||
if (IsTag)
|
||||
{
|
||||
FOR_VECTOR (i, Props)
|
||||
{
|
||||
const CXmlProp &prop = Props[i];
|
||||
s.Add_Space();
|
||||
s += prop.Name;
|
||||
s += '=';
|
||||
s += '\"';
|
||||
s += prop.Value;
|
||||
s += '\"';
|
||||
}
|
||||
s += '>';
|
||||
}
|
||||
FOR_VECTOR (i, SubItems)
|
||||
{
|
||||
const CXmlItem &item = SubItems[i];
|
||||
if (i != 0 && !SubItems[i - 1].IsTag)
|
||||
s.Add_Space();
|
||||
item.AppendTo(s);
|
||||
}
|
||||
if (IsTag)
|
||||
{
|
||||
s += '<';
|
||||
s += '/';
|
||||
s += Name;
|
||||
s += '>';
|
||||
}
|
||||
}
|
||||
|
||||
bool CXml::Parse(const char *s)
|
||||
{
|
||||
s = SkipHeader(s, "<?xml", "?>"); if (!s) return false;
|
||||
s = SkipHeader(s, "<!DOCTYPE", ">"); if (!s) return false;
|
||||
|
||||
s = Root.ParseItem(s, 1000);
|
||||
if (!s || !Root.IsTag)
|
||||
return false;
|
||||
SKIP_SPACES(s)
|
||||
return *s == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void CXml::AppendTo(AString &s) const
|
||||
{
|
||||
Root.AppendTo(s);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void z7_xml_DecodeString(AString &temp)
|
||||
{
|
||||
char * const beg = temp.GetBuf();
|
||||
char *dest = beg;
|
||||
const char *p = beg;
|
||||
for (;;)
|
||||
{
|
||||
char c = *p++;
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c == '&')
|
||||
{
|
||||
if (p[0] == '#')
|
||||
{
|
||||
const char *end;
|
||||
const UInt32 number = ConvertStringToUInt32(p + 1, &end);
|
||||
if (*end == ';' && number != 0 && number <= 127)
|
||||
{
|
||||
p = end + 1;
|
||||
c = (char)number;
|
||||
}
|
||||
}
|
||||
else if (
|
||||
p[0] == 'a' &&
|
||||
p[1] == 'm' &&
|
||||
p[2] == 'p' &&
|
||||
p[3] == ';')
|
||||
{
|
||||
p += 4;
|
||||
}
|
||||
else if (
|
||||
p[0] == 'l' &&
|
||||
p[1] == 't' &&
|
||||
p[2] == ';')
|
||||
{
|
||||
p += 3;
|
||||
c = '<';
|
||||
}
|
||||
else if (
|
||||
p[0] == 'g' &&
|
||||
p[1] == 't' &&
|
||||
p[2] == ';')
|
||||
{
|
||||
p += 3;
|
||||
c = '>';
|
||||
}
|
||||
else if (
|
||||
p[0] == 'a' &&
|
||||
p[1] == 'p' &&
|
||||
p[2] == 'o' &&
|
||||
p[3] == 's' &&
|
||||
p[4] == ';')
|
||||
{
|
||||
p += 5;
|
||||
c = '\'';
|
||||
}
|
||||
else if (
|
||||
p[0] == 'q' &&
|
||||
p[1] == 'u' &&
|
||||
p[2] == 'o' &&
|
||||
p[3] == 't' &&
|
||||
p[4] == ';')
|
||||
{
|
||||
p += 5;
|
||||
c = '\"';
|
||||
}
|
||||
}
|
||||
*dest++ = c;
|
||||
}
|
||||
temp.ReleaseBuf_SetEnd((unsigned)(dest - beg));
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// MyXml.h
|
||||
|
||||
#ifndef ZIP7_INC_MY_XML_H
|
||||
#define ZIP7_INC_MY_XML_H
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
struct CXmlProp
|
||||
{
|
||||
AString Name;
|
||||
AString Value;
|
||||
};
|
||||
|
||||
class CXmlItem
|
||||
{
|
||||
public:
|
||||
AString Name;
|
||||
bool IsTag;
|
||||
CObjectVector<CXmlProp> Props;
|
||||
CObjectVector<CXmlItem> SubItems;
|
||||
|
||||
const char * ParseItem(const char *s, int numAllowedLevels);
|
||||
|
||||
bool IsTagged(const char *tag) const throw();
|
||||
int FindProp(const char *propName) const throw();
|
||||
AString GetPropVal(const char *propName) const;
|
||||
AString GetSubString() const;
|
||||
const AString * GetSubStringPtr() const throw();
|
||||
int FindSubTag(const char *tag) const throw();
|
||||
const CXmlItem *FindSubTag_GetPtr(const char *tag) const throw();
|
||||
AString GetSubStringForTag(const char *tag) const;
|
||||
void AppendTo(AString &s) const;
|
||||
};
|
||||
|
||||
struct CXml
|
||||
{
|
||||
CXmlItem Root;
|
||||
|
||||
bool Parse(const char *s);
|
||||
// void AppendTo(AString &s) const;
|
||||
};
|
||||
|
||||
void z7_xml_DecodeString(AString &s);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,340 @@
|
||||
// NewHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "NewHandler.h"
|
||||
|
||||
// #define DEBUG_MEMORY_LEAK
|
||||
|
||||
#ifndef DEBUG_MEMORY_LEAK
|
||||
|
||||
#ifdef Z7_REDEFINE_OPERATOR_NEW
|
||||
|
||||
/*
|
||||
void * my_new(size_t size)
|
||||
{
|
||||
// void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void *p = ::malloc(size);
|
||||
if (!p)
|
||||
throw CNewException();
|
||||
return p;
|
||||
}
|
||||
|
||||
void my_delete(void *p) throw()
|
||||
{
|
||||
// if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);
|
||||
::free(p);
|
||||
}
|
||||
|
||||
void * my_Realloc(void *p, size_t newSize, size_t oldSize)
|
||||
{
|
||||
void *newBuf = my_new(newSize);
|
||||
if (oldSize != 0)
|
||||
memcpy(newBuf, p, oldSize);
|
||||
my_delete(p);
|
||||
return newBuf;
|
||||
}
|
||||
*/
|
||||
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new(size_t size)
|
||||
{
|
||||
/* by C++ specification:
|
||||
if (size == 0), operator new(size) returns non_NULL pointer.
|
||||
If (operator new(0) returns NULL), it's out of specification.
|
||||
but some calling code can work correctly even in this case too. */
|
||||
// if (size == 0) return NULL; // for debug only. don't use it
|
||||
|
||||
/* malloc(0) returns non_NULL in main compilers, as we need here.
|
||||
But specification also allows malloc(0) to return NULL.
|
||||
So we change (size=0) to (size=1) here to get real non_NULL pointer */
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
// void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
|
||||
// void *p = ::MyAlloc(size); // note: MyAlloc(0) returns NULL
|
||||
void *p = ::malloc(size);
|
||||
if (!p)
|
||||
throw CNewException();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1600
|
||||
// vs2010 has no throw() by default ?
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration
|
||||
#endif
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p) throw()
|
||||
{
|
||||
// if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);
|
||||
// MyFree(p);
|
||||
::free(p);
|
||||
}
|
||||
|
||||
/* we define operator delete(void *p, size_t n) because
|
||||
vs2022 compiler uses delete(void *p, size_t n), and
|
||||
we want to mix files from different compilers:
|
||||
- old vc6 linker
|
||||
- old vc6 complier
|
||||
- new vs2022 complier
|
||||
*/
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t n) throw()
|
||||
{
|
||||
UNUSED_VAR(n)
|
||||
::free(p);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1600
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/*
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new[](size_t size)
|
||||
{
|
||||
// void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void *p = ::malloc(size);
|
||||
if (!p)
|
||||
throw CNewException();
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete[](void *p) throw()
|
||||
{
|
||||
// if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);
|
||||
::free(p);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// #pragma init_seg(lib)
|
||||
/*
|
||||
const int kDebugSize = 1000000;
|
||||
static void *a[kDebugSize];
|
||||
static int g_index = 0;
|
||||
|
||||
class CC
|
||||
{
|
||||
public:
|
||||
CC()
|
||||
{
|
||||
for (int i = 0; i < kDebugSize; i++)
|
||||
a[i] = 0;
|
||||
}
|
||||
~CC()
|
||||
{
|
||||
printf("\nDestructor: %d\n", numAllocs);
|
||||
for (int i = 0; i < kDebugSize; i++)
|
||||
if (a[i] != 0)
|
||||
return;
|
||||
}
|
||||
} g_CC;
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
static bool wasInit = false;
|
||||
static CRITICAL_SECTION cs;
|
||||
#endif
|
||||
|
||||
static int numAllocs = 0;
|
||||
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new(size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!wasInit)
|
||||
{
|
||||
InitializeCriticalSection(&cs);
|
||||
wasInit = true;
|
||||
}
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
numAllocs++;
|
||||
int loc = numAllocs;
|
||||
void *p = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
/*
|
||||
if (g_index < kDebugSize)
|
||||
{
|
||||
a[g_index] = p;
|
||||
g_index++;
|
||||
}
|
||||
*/
|
||||
printf("Alloc %6d, size = %8u\n", loc, (unsigned)size);
|
||||
LeaveCriticalSection(&cs);
|
||||
if (!p)
|
||||
throw CNewException();
|
||||
return p;
|
||||
#else
|
||||
numAllocs++;
|
||||
int loc = numAllocs;
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void *p = malloc(size);
|
||||
/*
|
||||
if (g_index < kDebugSize)
|
||||
{
|
||||
a[g_index] = p;
|
||||
g_index++;
|
||||
}
|
||||
*/
|
||||
printf("Alloc %6d, size = %8u\n", loc, (unsigned)size);
|
||||
if (!p)
|
||||
throw CNewException();
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p) throw()
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
#ifdef _WIN32
|
||||
EnterCriticalSection(&cs);
|
||||
/*
|
||||
for (int i = 0; i < g_index; i++)
|
||||
if (a[i] == p)
|
||||
a[i] = 0;
|
||||
*/
|
||||
HeapFree(GetProcessHeap(), 0, p);
|
||||
// if (numAllocs == 0) numAllocs = numAllocs; // ERROR
|
||||
numAllocs--;
|
||||
// if (numAllocs == 0) numAllocs = numAllocs; // OK: all objects were deleted
|
||||
printf("Free %d\n", numAllocs);
|
||||
LeaveCriticalSection(&cs);
|
||||
#else
|
||||
free(p);
|
||||
numAllocs--;
|
||||
printf("Free %d\n", numAllocs);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t n) throw();
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t n) throw()
|
||||
{
|
||||
UNUSED_VAR(n)
|
||||
printf("delete_WITH_SIZE=%u, ptr = %p\n", (unsigned)n, p);
|
||||
operator delete(p);
|
||||
}
|
||||
|
||||
/*
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new[](size_t size)
|
||||
{
|
||||
printf("operator_new[] : ");
|
||||
return operator new(size);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t sz) throw();
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t sz) throw()
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
printf("operator_delete_size : size=%d : ", (unsigned)sz);
|
||||
operator delete(p);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete[](void *p) throw()
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
printf("operator_delete[] : ");
|
||||
operator delete(p);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete[](void *p, size_t sz) throw();
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete[](void *p, size_t sz) throw()
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
printf("operator_delete_size[] : size=%d : ", (unsigned)sz);
|
||||
operator delete(p);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
int MemErrorVC(size_t)
|
||||
{
|
||||
throw CNewException();
|
||||
// return 1;
|
||||
}
|
||||
CNewHandlerSetter::CNewHandlerSetter()
|
||||
{
|
||||
// MemErrorOldVCFunction = _set_new_handler(MemErrorVC);
|
||||
}
|
||||
CNewHandlerSetter::~CNewHandlerSetter()
|
||||
{
|
||||
// _set_new_handler(MemErrorOldVCFunction);
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,121 @@
|
||||
// Common/NewHandler.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_NEW_HANDLER_H
|
||||
#define ZIP7_INC_COMMON_NEW_HANDLER_H
|
||||
|
||||
/*
|
||||
NewHandler.h and NewHandler.cpp allows to solve problem with compilers that
|
||||
don't throw exception in operator new().
|
||||
|
||||
This file must be included before any code that uses operators new() or delete()
|
||||
and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler.
|
||||
|
||||
DOCs:
|
||||
Since ISO C++98, operator new throws std::bad_alloc when memory allocation fails.
|
||||
MSVC 6.0 returned a null pointer on an allocation failure.
|
||||
Beginning in VS2002, operator new conforms to the standard and throws on failure.
|
||||
|
||||
By default, the compiler also generates defensive null checks to prevent
|
||||
these older-style allocators from causing an immediate crash on failure.
|
||||
The /Zc:throwingNew option tells the compiler to leave out these null checks,
|
||||
on the assumption that all linked memory allocators conform to the standard.
|
||||
|
||||
The operator new() in some MSVC versions doesn't throw exception std::bad_alloc.
|
||||
MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception.
|
||||
The code produced by some another MSVC compilers also can be linked
|
||||
to library that doesn't throw exception.
|
||||
We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc.
|
||||
For older _MSC_VER versions we redefine operator new() and operator delete().
|
||||
Our version of operator new() throws CNewException() exception on failure.
|
||||
|
||||
It's still allowed to use redefined version of operator new() from "NewHandler.cpp"
|
||||
with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions.
|
||||
But if you use some additional code (outside of 7-Zip's code), you must check
|
||||
that redefined version of operator new() is not problem for your code.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
// We can compile my_new and my_delete with _fastcall
|
||||
/*
|
||||
void * my_new(size_t size);
|
||||
void my_delete(void *p) throw();
|
||||
// void * my_Realloc(void *p, size_t newSize, size_t oldSize);
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
// If you want to use default operator new(), you can disable the following line
|
||||
#define Z7_REDEFINE_OPERATOR_NEW
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Z7_REDEFINE_OPERATOR_NEW
|
||||
|
||||
// std::bad_alloc can require additional DLL dependency.
|
||||
// So we don't define CNewException as std::bad_alloc here.
|
||||
|
||||
class CNewException {};
|
||||
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new(size_t size);
|
||||
|
||||
/*
|
||||
#if 0 && defined(_MSC_VER) && _MSC_VER == 1600
|
||||
#define Z7_OPERATOR_DELETE_SPEC_THROW0
|
||||
#else
|
||||
#define Z7_OPERATOR_DELETE_SPEC_THROW0 throw()
|
||||
#endif
|
||||
*/
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1600
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration
|
||||
#endif
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p) throw();
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete(void *p, size_t n) throw();
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1600
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#include <new>
|
||||
|
||||
#define CNewException std::bad_alloc
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
void *
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator new[](size_t size);
|
||||
|
||||
void
|
||||
#ifdef _MSC_VER
|
||||
__cdecl
|
||||
#endif
|
||||
operator delete[](void *p) throw();
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// Common/Random.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <time.h>
|
||||
#else
|
||||
#include "MyWindows.h"
|
||||
#endif
|
||||
|
||||
#include "Random.h"
|
||||
|
||||
void CRandom::Init(unsigned seed) { srand(seed); }
|
||||
|
||||
void CRandom::Init()
|
||||
{
|
||||
Init((unsigned)
|
||||
#ifdef _WIN32
|
||||
GetTickCount()
|
||||
#else
|
||||
time(NULL)
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
int CRandom::Generate() const { return rand(); }
|
||||
@@ -0,0 +1,14 @@
|
||||
// Common/Random.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_RANDOM_H
|
||||
#define ZIP7_INC_COMMON_RANDOM_H
|
||||
|
||||
class CRandom
|
||||
{
|
||||
public:
|
||||
void Init();
|
||||
void Init(unsigned seed);
|
||||
int Generate() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
// Sha1Prepare.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha1.h"
|
||||
|
||||
static struct CSha1Prepare { CSha1Prepare() { Sha1Prepare(); } } g_Sha1Prepare;
|
||||
@@ -0,0 +1,67 @@
|
||||
// Sha1Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha1.h"
|
||||
|
||||
#include "../Common/MyBuffer2.h"
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CSha1Hasher
|
||||
, IHasher
|
||||
, ICompressSetCoderProperties
|
||||
)
|
||||
CAlignedBuffer1 _buf;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7];
|
||||
|
||||
CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_buf; }
|
||||
public:
|
||||
CSha1Hasher():
|
||||
_buf(sizeof(CSha1))
|
||||
{
|
||||
Sha1_SetFunction(Sha(), 0);
|
||||
Sha1_InitState(Sha());
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha1Hasher::Init())
|
||||
{
|
||||
Sha1_InitState(Sha());
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha1Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
Sha1_Update(Sha(), (const Byte *)data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha1Hasher::Final(Byte *digest))
|
||||
{
|
||||
Sha1_Final(Sha(), digest);
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CSha1Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
|
||||
{
|
||||
unsigned algo = 0;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
if (propIDs[i] == NCoderPropID::kDefaultProp)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (prop.ulVal > 2)
|
||||
return E_NOTIMPL;
|
||||
algo = (unsigned)prop.ulVal;
|
||||
}
|
||||
}
|
||||
if (!Sha1_SetFunction(Sha(), algo))
|
||||
return E_NOTIMPL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE)
|
||||
@@ -0,0 +1,7 @@
|
||||
// Sha256Prepare.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha256.h"
|
||||
|
||||
static struct CSha256Prepare { CSha256Prepare() { Sha256Prepare(); } } g_Sha256Prepare;
|
||||
@@ -0,0 +1,67 @@
|
||||
// Sha256Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha256.h"
|
||||
|
||||
#include "../Common/MyBuffer2.h"
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CSha256Hasher
|
||||
, IHasher
|
||||
, ICompressSetCoderProperties
|
||||
)
|
||||
CAlignedBuffer1 _buf;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7];
|
||||
|
||||
CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_buf; }
|
||||
public:
|
||||
CSha256Hasher():
|
||||
_buf(sizeof(CSha256))
|
||||
{
|
||||
Sha256_SetFunction(Sha(), 0);
|
||||
Sha256_InitState(Sha());
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha256Hasher::Init())
|
||||
{
|
||||
Sha256_InitState(Sha());
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha256Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
Sha256_Update(Sha(), (const Byte *)data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha256Hasher::Final(Byte *digest))
|
||||
{
|
||||
Sha256_Final(Sha(), digest);
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CSha256Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
|
||||
{
|
||||
unsigned algo = 0;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
if (propIDs[i] == NCoderPropID::kDefaultProp)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (prop.ulVal > 2)
|
||||
return E_NOTIMPL;
|
||||
algo = (unsigned)prop.ulVal;
|
||||
}
|
||||
}
|
||||
if (!Sha256_SetFunction(Sha(), algo))
|
||||
return E_NOTIMPL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)
|
||||
@@ -0,0 +1,76 @@
|
||||
// Sha3Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha3.h"
|
||||
|
||||
#include "../Common/MyBuffer2.h"
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CSha3Hasher
|
||||
, IHasher
|
||||
)
|
||||
unsigned _digestSize;
|
||||
bool _isShake;
|
||||
CAlignedBuffer1 _buf;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7];
|
||||
|
||||
CSha3 *Sha() { return (CSha3 *)(void *)(Byte *)_buf; }
|
||||
public:
|
||||
CSha3Hasher(unsigned digestSize, bool isShake, unsigned blockSize):
|
||||
_digestSize(digestSize),
|
||||
_isShake(isShake),
|
||||
_buf(sizeof(CSha3))
|
||||
{
|
||||
CSha3 *p = Sha();
|
||||
Sha3_SET_blockSize(p, blockSize)
|
||||
Sha3_Init(Sha());
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha3Hasher::Init())
|
||||
{
|
||||
Sha3_Init(Sha());
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha3Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
Sha3_Update(Sha(), (const Byte *)data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha3Hasher::Final(Byte *digest))
|
||||
{
|
||||
Sha3_Final(Sha(), digest, _digestSize, _isShake);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(UInt32, CSha3Hasher::GetDigestSize())
|
||||
{
|
||||
return (UInt32)_digestSize;
|
||||
}
|
||||
|
||||
|
||||
#define REGISTER_SHA3_HASHER_2(cls, id, name, digestSize, isShake, digestSize_for_blockSize) \
|
||||
namespace N ## cls { \
|
||||
static IHasher *CreateHasherSpec() \
|
||||
{ return new CSha3Hasher(digestSize / 8, isShake, \
|
||||
SHA3_BLOCK_SIZE_FROM_DIGEST_SIZE(digestSize_for_blockSize / 8)); } \
|
||||
static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, digestSize / 8 }; \
|
||||
struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
|
||||
static REGISTER_HASHER_NAME(cls) g_RegisterHasher; }
|
||||
|
||||
#define REGISTER_SHA3_HASHER( cls, id, name, size, isShake) \
|
||||
REGISTER_SHA3_HASHER_2(cls, id, name, size, isShake, size)
|
||||
|
||||
// REGISTER_SHA3_HASHER (Sha3_224_Hasher, 0x230, "SHA3-224", 224, false)
|
||||
REGISTER_SHA3_HASHER (Sha3_256_Hasher, 0x231, "SHA3-256", 256, false)
|
||||
// REGISTER_SHA3_HASHER (Sha3_386_Hasher, 0x232, "SHA3-384", 384, false)
|
||||
// REGISTER_SHA3_HASHER (Sha3_512_Hasher, 0x233, "SHA3-512", 512, false)
|
||||
// REGISTER_SHA3_HASHER (Shake128_Hasher, 0x240, "SHAKE128", 128, true)
|
||||
// REGISTER_SHA3_HASHER (Shake256_Hasher, 0x241, "SHAKE256", 256, true)
|
||||
// REGISTER_SHA3_HASHER_2 (Shake128_512_Hasher, 0x248, "SHAKE128-256", 256, true, 128) // -1344 (max)
|
||||
// REGISTER_SHA3_HASHER_2 (Shake256_512_Hasher, 0x249, "SHAKE256-512", 512, true, 256) // -1088 (max)
|
||||
// Shake supports different digestSize values for same blockSize
|
||||
@@ -0,0 +1,7 @@
|
||||
// Sha512Prepare.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha512.h"
|
||||
|
||||
static struct CSha512Prepare { CSha512Prepare() { Sha512Prepare(); } } g_Sha512Prepare;
|
||||
@@ -0,0 +1,83 @@
|
||||
// Sha512Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Sha512.h"
|
||||
|
||||
#include "../Common/MyBuffer2.h"
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_2(
|
||||
CSha512Hasher
|
||||
, IHasher
|
||||
, ICompressSetCoderProperties
|
||||
)
|
||||
unsigned _digestSize;
|
||||
CAlignedBuffer1 _buf;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7];
|
||||
|
||||
CSha512 *Sha() { return (CSha512 *)(void *)(Byte *)_buf; }
|
||||
public:
|
||||
CSha512Hasher(unsigned digestSize):
|
||||
_digestSize(digestSize),
|
||||
_buf(sizeof(CSha512))
|
||||
{
|
||||
Sha512_SetFunction(Sha(), 0);
|
||||
Sha512_InitState(Sha(), _digestSize);
|
||||
}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha512Hasher::Init())
|
||||
{
|
||||
Sha512_InitState(Sha(), _digestSize);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha512Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
Sha512_Update(Sha(), (const Byte *)data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CSha512Hasher::Final(Byte *digest))
|
||||
{
|
||||
Sha512_Final(Sha(), digest, _digestSize);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(UInt32, CSha512Hasher::GetDigestSize())
|
||||
{
|
||||
return (UInt32)_digestSize;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CSha512Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))
|
||||
{
|
||||
unsigned algo = 0;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
if (propIDs[i] == NCoderPropID::kDefaultProp)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (prop.ulVal > 2)
|
||||
return E_NOTIMPL;
|
||||
algo = (unsigned)prop.ulVal;
|
||||
}
|
||||
}
|
||||
if (!Sha512_SetFunction(Sha(), algo))
|
||||
return E_NOTIMPL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#define REGISTER_SHA512_HASHER(cls, id, name, size) \
|
||||
namespace N ## cls { \
|
||||
static IHasher *CreateHasherSpec() { return new CSha512Hasher(size); } \
|
||||
static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \
|
||||
struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \
|
||||
static REGISTER_HASHER_NAME(cls) g_RegisterHasher; }
|
||||
|
||||
// REGISTER_SHA512_HASHER (Sha512_224_Hasher, 0x220, "SHA512-224", SHA512_224_DIGEST_SIZE)
|
||||
// REGISTER_SHA512_HASHER (Sha512_256_Hasher, 0x221, "SHA512-256", SHA512_256_DIGEST_SIZE)
|
||||
REGISTER_SHA512_HASHER (Sha384Hasher, 0x222, "SHA384", SHA512_384_DIGEST_SIZE)
|
||||
REGISTER_SHA512_HASHER (Sha512Hasher, 0x223, "SHA512", SHA512_DIGEST_SIZE)
|
||||
@@ -0,0 +1,8 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
// Common/StdInStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "StdInStream.h"
|
||||
#include "StringConvert.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
// #define kEOFMessage "Unexpected end of input stream"
|
||||
// #define kReadErrorMessage "Error reading input stream"
|
||||
// #define kIllegalCharMessage "Illegal zero character in input stream"
|
||||
|
||||
|
||||
CStdInStream g_StdIn(stdin);
|
||||
|
||||
/*
|
||||
#define kFileOpenMode TEXT("r")
|
||||
|
||||
bool CStdInStream::Open(LPCTSTR fileName) throw()
|
||||
{
|
||||
Close();
|
||||
_stream =
|
||||
#ifdef _WIN32
|
||||
_tfopen
|
||||
#else
|
||||
fopen
|
||||
#endif
|
||||
(fileName, kFileOpenMode);
|
||||
_streamIsOpen = (_stream != 0);
|
||||
return _streamIsOpen;
|
||||
}
|
||||
|
||||
bool CStdInStream::Close() throw()
|
||||
{
|
||||
if (!_streamIsOpen)
|
||||
return true;
|
||||
_streamIsOpen = (fclose(_stream) != 0);
|
||||
return !_streamIsOpen;
|
||||
}
|
||||
*/
|
||||
|
||||
bool CStdInStream::ScanAStringUntilNewLine(AString &s)
|
||||
{
|
||||
s.Empty();
|
||||
for (;;)
|
||||
{
|
||||
const int intChar = GetChar();
|
||||
if (intChar == EOF)
|
||||
return true;
|
||||
const char c = (char)intChar;
|
||||
if (c == 0)
|
||||
return false;
|
||||
if (c == '\n')
|
||||
return true;
|
||||
s.Add_Char(c);
|
||||
}
|
||||
}
|
||||
|
||||
bool CStdInStream::ScanUStringUntilNewLine(UString &dest)
|
||||
{
|
||||
dest.Empty();
|
||||
AString s;
|
||||
const bool res = ScanAStringUntilNewLine(s);
|
||||
int codePage = CodePage;
|
||||
if (codePage == -1)
|
||||
codePage = CP_OEMCP;
|
||||
if ((unsigned)codePage == CP_UTF8)
|
||||
ConvertUTF8ToUnicode(s, dest);
|
||||
else
|
||||
MultiByteToUnicodeString2(dest, s, (UINT)(unsigned)codePage);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CStdInStream::ReadToString(AString &resultString)
|
||||
{
|
||||
resultString.Empty();
|
||||
for (;;)
|
||||
{
|
||||
int intChar = GetChar();
|
||||
if (intChar == EOF)
|
||||
return !Error();
|
||||
char c = (char)intChar;
|
||||
if (c == 0)
|
||||
return false;
|
||||
resultString += c;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int CStdInStream::GetChar()
|
||||
{
|
||||
return fgetc(_stream); // getc() doesn't work in BeOS?
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Common/StdInStream.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_STD_IN_STREAM_H
|
||||
#define ZIP7_INC_COMMON_STD_IN_STREAM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MyString.h"
|
||||
#include "MyTypes.h"
|
||||
|
||||
class CStdInStream
|
||||
{
|
||||
FILE *_stream;
|
||||
// bool _streamIsOpen;
|
||||
public:
|
||||
int CodePage;
|
||||
|
||||
CStdInStream(FILE *stream = NULL):
|
||||
_stream(stream),
|
||||
// _streamIsOpen(false),
|
||||
CodePage(-1)
|
||||
{}
|
||||
|
||||
/*
|
||||
~CStdInStream() { Close(); }
|
||||
|
||||
bool Open(LPCTSTR fileName) throw();
|
||||
bool Close() throw();
|
||||
*/
|
||||
|
||||
// returns:
|
||||
// false, if ZERO character in stream
|
||||
// true, if EOF or '\n'
|
||||
bool ScanAStringUntilNewLine(AString &s);
|
||||
bool ScanUStringUntilNewLine(UString &s);
|
||||
// bool ReadToString(AString &resultString);
|
||||
|
||||
bool Eof() const throw() { return (feof(_stream) != 0); }
|
||||
bool Error() const throw() { return (ferror(_stream) != 0); }
|
||||
|
||||
int GetChar();
|
||||
};
|
||||
|
||||
extern CStdInStream g_StdIn;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
// Common/StdOutStream.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "IntToString.h"
|
||||
#include "StdOutStream.h"
|
||||
#include "StringConvert.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
CStdOutStream g_StdOut(stdout);
|
||||
CStdOutStream g_StdErr(stderr);
|
||||
|
||||
/*
|
||||
// #define kFileOpenMode "wt"
|
||||
|
||||
bool CStdOutStream::Open(const char *fileName) throw()
|
||||
{
|
||||
Close();
|
||||
_stream = fopen(fileName, kFileOpenMode);
|
||||
_streamIsOpen = (_stream != 0);
|
||||
return _streamIsOpen;
|
||||
}
|
||||
|
||||
bool CStdOutStream::Close() throw()
|
||||
{
|
||||
if (!_streamIsOpen)
|
||||
return true;
|
||||
if (fclose(_stream) != 0)
|
||||
return false;
|
||||
_stream = 0;
|
||||
_streamIsOpen = false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool CStdOutStream::Flush() throw()
|
||||
{
|
||||
return (fflush(_stream) == 0);
|
||||
}
|
||||
|
||||
CStdOutStream & endl(CStdOutStream & outStream) throw()
|
||||
{
|
||||
return outStream << '\n';
|
||||
}
|
||||
|
||||
CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)
|
||||
{
|
||||
AString temp;
|
||||
UString s2(s);
|
||||
PrintUString(s2, temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CStdOutStream::PrintUString(const UString &s, AString &temp)
|
||||
{
|
||||
Convert_UString_to_AString(s, temp);
|
||||
*this << (const char *)temp;
|
||||
}
|
||||
|
||||
void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest)
|
||||
{
|
||||
int codePage = CodePage;
|
||||
if (codePage == -1)
|
||||
codePage = CP_OEMCP;
|
||||
if ((unsigned)codePage == CP_UTF8)
|
||||
ConvertUnicodeToUTF8(src, dest);
|
||||
else
|
||||
UnicodeStringToMultiByte2(dest, src, (UINT)(unsigned)codePage);
|
||||
}
|
||||
|
||||
|
||||
static const wchar_t kReplaceChar = '_';
|
||||
|
||||
/*
|
||||
void CStdOutStream::Normalize_UString_LF_Allowed(UString &s)
|
||||
{
|
||||
if (!IsTerminalMode)
|
||||
return;
|
||||
|
||||
const unsigned len = s.Len();
|
||||
wchar_t *d = s.GetBuf();
|
||||
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
const wchar_t c = d[i];
|
||||
if (c == 0x1b || (c <= 13 && c >= 7 && c != '\n'))
|
||||
d[i] = kReplaceChar;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void CStdOutStream::Normalize_UString(UString &s)
|
||||
{
|
||||
const unsigned len = s.Len();
|
||||
wchar_t *d = s.GetBuf();
|
||||
|
||||
if (IsTerminalMode)
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
const wchar_t c = d[i];
|
||||
if ((c <= 13 && c >= 7) || c == 0x1b)
|
||||
d[i] = kReplaceChar;
|
||||
}
|
||||
else
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
const wchar_t c = d[i];
|
||||
if (c == '\n')
|
||||
d[i] = kReplaceChar;
|
||||
}
|
||||
}
|
||||
|
||||
void CStdOutStream::Normalize_UString_Path(UString &s)
|
||||
{
|
||||
if (ListPathSeparatorSlash.Def)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (ListPathSeparatorSlash.Val)
|
||||
s.Replace(L'\\', L'/');
|
||||
#else
|
||||
if (!ListPathSeparatorSlash.Val)
|
||||
s.Replace(L'/', L'\\');
|
||||
#endif
|
||||
}
|
||||
Normalize_UString(s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void CStdOutStream::Normalize_UString(UString &src)
|
||||
{
|
||||
const wchar_t *s = src.Ptr();
|
||||
const unsigned len = src.Len();
|
||||
unsigned i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
const wchar_t c = s[i];
|
||||
#if 0 && !defined(_WIN32)
|
||||
if (c == '\\') // IsTerminalMode &&
|
||||
break;
|
||||
#endif
|
||||
if ((unsigned)c < 0x20)
|
||||
break;
|
||||
}
|
||||
if (i == len)
|
||||
return;
|
||||
|
||||
UString temp;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
#if 0 && !defined(_WIN32)
|
||||
if (c == '\\')
|
||||
temp += (wchar_t)L'\\';
|
||||
else
|
||||
#endif
|
||||
if ((unsigned)c < 0x20)
|
||||
{
|
||||
if (c == '\n'
|
||||
|| (IsTerminalMode && (c == 0x1b || (c <= 13 && c >= 7))))
|
||||
{
|
||||
#if 1 || defined(_WIN32)
|
||||
c = (wchar_t)kReplaceChar;
|
||||
#else
|
||||
temp += (wchar_t)L'\\';
|
||||
if (c == '\n') c = L'n';
|
||||
else if (c == '\r') c = L'r';
|
||||
else if (c == '\a') c = L'a';
|
||||
else if (c == '\b') c = L'b';
|
||||
else if (c == '\t') c = L't';
|
||||
else if (c == '\v') c = L'v';
|
||||
else if (c == '\f') c = L'f';
|
||||
else
|
||||
{
|
||||
temp += (wchar_t)(L'0' + (unsigned)c / 64);
|
||||
temp += (wchar_t)(L'0' + (unsigned)c / 8 % 8);
|
||||
c = (wchar_t)(L'0' + (unsigned)c % 8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
temp += c;
|
||||
}
|
||||
src = temp;
|
||||
}
|
||||
*/
|
||||
|
||||
void CStdOutStream::NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA)
|
||||
{
|
||||
tempU = s;
|
||||
Normalize_UString_Path(tempU);
|
||||
PrintUString(tempU, tempA);
|
||||
}
|
||||
|
||||
void CStdOutStream::NormalizePrint_UString_Path(const UString &s)
|
||||
{
|
||||
UString tempU;
|
||||
AString tempA;
|
||||
NormalizePrint_UString_Path(s, tempU, tempA);
|
||||
}
|
||||
|
||||
void CStdOutStream::NormalizePrint_wstr_Path(const wchar_t *s)
|
||||
{
|
||||
UString tempU = s;
|
||||
Normalize_UString_Path(tempU);
|
||||
AString tempA;
|
||||
PrintUString(tempU, tempA);
|
||||
}
|
||||
|
||||
void CStdOutStream::NormalizePrint_UString(const UString &s)
|
||||
{
|
||||
UString tempU = s;
|
||||
Normalize_UString(tempU);
|
||||
AString tempA;
|
||||
PrintUString(tempU, tempA);
|
||||
}
|
||||
|
||||
CStdOutStream & CStdOutStream::operator<<(Int32 number) throw()
|
||||
{
|
||||
char s[32];
|
||||
ConvertInt64ToString(number, s);
|
||||
return operator<<(s);
|
||||
}
|
||||
|
||||
CStdOutStream & CStdOutStream::operator<<(Int64 number) throw()
|
||||
{
|
||||
char s[32];
|
||||
ConvertInt64ToString(number, s);
|
||||
return operator<<(s);
|
||||
}
|
||||
|
||||
CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw()
|
||||
{
|
||||
char s[16];
|
||||
ConvertUInt32ToString(number, s);
|
||||
return operator<<(s);
|
||||
}
|
||||
|
||||
CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw()
|
||||
{
|
||||
char s[32];
|
||||
ConvertUInt64ToString(number, s);
|
||||
return operator<<(s);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
// Common/StdOutStream.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_STD_OUT_STREAM_H
|
||||
#define ZIP7_INC_COMMON_STD_OUT_STREAM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MyString.h"
|
||||
#include "MyTypes.h"
|
||||
|
||||
class CStdOutStream
|
||||
{
|
||||
FILE *_stream;
|
||||
// bool _streamIsOpen;
|
||||
public:
|
||||
bool IsTerminalMode;
|
||||
CBoolPair ListPathSeparatorSlash;
|
||||
int CodePage;
|
||||
|
||||
CStdOutStream(FILE *stream = NULL):
|
||||
_stream(stream),
|
||||
// _streamIsOpen(false),
|
||||
IsTerminalMode(false),
|
||||
CodePage(-1)
|
||||
{
|
||||
ListPathSeparatorSlash.Val =
|
||||
#ifdef _WIN32
|
||||
false;
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ~CStdOutStream() { Close(); }
|
||||
|
||||
// void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; }
|
||||
// bool IsDefined() const { return _stream != NULL; }
|
||||
|
||||
operator FILE *() { return _stream; }
|
||||
/*
|
||||
bool Open(const char *fileName) throw();
|
||||
bool Close() throw();
|
||||
*/
|
||||
bool Flush() throw();
|
||||
|
||||
CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &))
|
||||
{
|
||||
(*func)(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStdOutStream & operator<<(const char *s) throw()
|
||||
{
|
||||
fputs(s, _stream);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStdOutStream & operator<<(char c) throw()
|
||||
{
|
||||
fputc((unsigned char)c, _stream);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CStdOutStream & operator<<(Int32 number) throw();
|
||||
CStdOutStream & operator<<(Int64 number) throw();
|
||||
CStdOutStream & operator<<(UInt32 number) throw();
|
||||
CStdOutStream & operator<<(UInt64 number) throw();
|
||||
|
||||
CStdOutStream & operator<<(const wchar_t *s);
|
||||
void PrintUString(const UString &s, AString &temp);
|
||||
void Convert_UString_to_AString(const UString &src, AString &dest);
|
||||
|
||||
void Normalize_UString(UString &s);
|
||||
void Normalize_UString_Path(UString &s);
|
||||
|
||||
void NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA);
|
||||
void NormalizePrint_UString_Path(const UString &s);
|
||||
void NormalizePrint_UString(const UString &s);
|
||||
void NormalizePrint_wstr_Path(const wchar_t *s);
|
||||
};
|
||||
|
||||
CStdOutStream & endl(CStdOutStream & outStream) throw();
|
||||
|
||||
extern CStdOutStream g_StdOut;
|
||||
extern CStdOutStream g_StdErr;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,762 @@
|
||||
// Common/StringConvert.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "StringConvert.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
// #include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
|
||||
#include "UTFConvert.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENV_HAVE_LOCALE
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
static const char k_DefultChar = '_';
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/*
|
||||
MultiByteToWideChar(CodePage, DWORD dwFlags,
|
||||
LPCSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPWSTR lpWideCharStr, int cchWideChar)
|
||||
|
||||
if (cbMultiByte == 0)
|
||||
return: 0. ERR: ERROR_INVALID_PARAMETER
|
||||
|
||||
if (cchWideChar == 0)
|
||||
return: the required buffer size in characters.
|
||||
|
||||
if (supplied buffer size was not large enough)
|
||||
return: 0. ERR: ERROR_INSUFFICIENT_BUFFER
|
||||
The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)
|
||||
|
||||
If there are illegal characters:
|
||||
if MB_ERR_INVALID_CHARS is set in dwFlags:
|
||||
- the function stops conversion on illegal character.
|
||||
- Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.
|
||||
|
||||
if MB_ERR_INVALID_CHARS is NOT set in dwFlags:
|
||||
before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.
|
||||
in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal
|
||||
character is converted to U+FFFD, which is REPLACEMENT CHARACTER.
|
||||
*/
|
||||
|
||||
|
||||
void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
|
||||
{
|
||||
dest.Empty();
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
{
|
||||
/*
|
||||
wchar_t *d = dest.GetBuf(src.Len());
|
||||
const char *s = (const char *)src;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0;;)
|
||||
{
|
||||
Byte c = (Byte)s[i];
|
||||
if (c >= 0x80 || c == 0)
|
||||
break;
|
||||
d[i++] = (wchar_t)c;
|
||||
}
|
||||
|
||||
if (i != src.Len())
|
||||
{
|
||||
unsigned len = MultiByteToWideChar(codePage, 0, s + i,
|
||||
src.Len() - i, d + i,
|
||||
src.Len() + 1 - i);
|
||||
if (len == 0)
|
||||
throw 282228;
|
||||
i += len;
|
||||
}
|
||||
|
||||
d[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
*/
|
||||
unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0);
|
||||
if (len == 0)
|
||||
{
|
||||
if (GetLastError() != 0)
|
||||
throw 282228;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len);
|
||||
if (len == 0)
|
||||
throw 282228;
|
||||
dest.ReleaseBuf_SetEnd(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
int WideCharToMultiByte(
|
||||
UINT CodePage, DWORD dwFlags,
|
||||
LPCWSTR lpWideCharStr, int cchWideChar,
|
||||
LPSTR lpMultiByteStr, int cbMultiByte,
|
||||
LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
|
||||
|
||||
if (lpDefaultChar == NULL),
|
||||
- it uses system default value.
|
||||
|
||||
if (CodePage == CP_UTF7 || CodePage == CP_UTF8)
|
||||
if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)
|
||||
return: 0. ERR: ERROR_INVALID_PARAMETER.
|
||||
|
||||
The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)
|
||||
|
||||
*/
|
||||
|
||||
static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
|
||||
{
|
||||
dest.Empty();
|
||||
defaultCharWasUsed = false;
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
{
|
||||
/*
|
||||
unsigned numRequiredBytes = src.Len() * 2;
|
||||
char *d = dest.GetBuf(numRequiredBytes);
|
||||
const wchar_t *s = (const wchar_t *)src;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0;;)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c >= 0x80 || c == 0)
|
||||
break;
|
||||
d[i++] = (char)c;
|
||||
}
|
||||
|
||||
if (i != src.Len())
|
||||
{
|
||||
BOOL defUsed = FALSE;
|
||||
defaultChar = defaultChar;
|
||||
|
||||
bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
|
||||
unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,
|
||||
d + i, numRequiredBytes + 1 - i,
|
||||
(isUtf ? NULL : &defaultChar),
|
||||
(isUtf ? NULL : &defUsed));
|
||||
defaultCharWasUsed = (defUsed != FALSE);
|
||||
if (len == 0)
|
||||
throw 282229;
|
||||
i += len;
|
||||
}
|
||||
|
||||
d[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
*/
|
||||
|
||||
/*
|
||||
if (codePage != CP_UTF7)
|
||||
{
|
||||
const wchar_t *s = (const wchar_t *)src;
|
||||
unsigned i;
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c >= 0x80 || c == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (s[i] == 0)
|
||||
{
|
||||
char *d = dest.GetBuf(src.Len());
|
||||
for (i = 0;;)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
d[i++] = (char)c;
|
||||
}
|
||||
d[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL);
|
||||
if (len == 0)
|
||||
{
|
||||
if (GetLastError() != 0)
|
||||
throw 282228;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL defUsed = FALSE;
|
||||
bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
|
||||
// defaultChar = defaultChar;
|
||||
len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(),
|
||||
dest.GetBuf(len), (int)len,
|
||||
(isUtf ? NULL : &defaultChar),
|
||||
(isUtf ? NULL : &defUsed)
|
||||
);
|
||||
if (!isUtf)
|
||||
defaultCharWasUsed = (defUsed != FALSE);
|
||||
if (len == 0)
|
||||
throw 282228;
|
||||
dest.ReleaseBuf_SetEnd(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#ifndef UNDER_CE
|
||||
AString SystemStringToOemString(const CSysString &src)
|
||||
{
|
||||
AString dest;
|
||||
const unsigned len = src.Len() * 2;
|
||||
CharToOem(src, dest.GetBuf(len));
|
||||
dest.ReleaseBuf_CalcLen(len);
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// #include <stdio.h>
|
||||
/*
|
||||
if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff),
|
||||
and utf-8 string contains big unicode character > 0xffff),
|
||||
then we still use 16-bit surrogate pair in UString.
|
||||
It simplifies another code where utf-16 encoding is used.
|
||||
So we use surrogate-conversion code only in is file.
|
||||
*/
|
||||
|
||||
/*
|
||||
mbstowcs() returns error if there is error in utf-8 stream,
|
||||
mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream
|
||||
*/
|
||||
|
||||
/*
|
||||
static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src)
|
||||
{
|
||||
dest.Empty();
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
|
||||
const size_t limit = ((size_t)src.Len() + 1) * 2;
|
||||
wchar_t *d = dest.GetBuf((unsigned)limit);
|
||||
const size_t len = mbstowcs(d, src, limit);
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
dest.ReleaseBuf_SetEnd((unsigned)len);
|
||||
return;
|
||||
}
|
||||
dest.ReleaseBuf_SetEnd(0);
|
||||
}
|
||||
*/
|
||||
|
||||
bool g_ForceToUTF8 = true; // false;
|
||||
|
||||
void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
|
||||
{
|
||||
dest.Empty();
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
|
||||
if (codePage == CP_UTF8 || g_ForceToUTF8)
|
||||
{
|
||||
#if 1
|
||||
ConvertUTF8ToUnicode(src, dest);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
const size_t limit = ((size_t)src.Len() + 1) * 2;
|
||||
wchar_t *d = dest.GetBuf((unsigned)limit);
|
||||
const size_t len = mbstowcs(d, src, limit);
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
dest.ReleaseBuf_SetEnd((unsigned)len);
|
||||
|
||||
#if WCHAR_MAX > 0xffff
|
||||
d = dest.GetBuf();
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
wchar_t c = d[i];
|
||||
// printf("\ni=%2d c = %4x\n", (unsigned)i, (unsigned)c);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c >= 0x10000 && c < 0x110000)
|
||||
{
|
||||
UString tempString = d + i;
|
||||
const wchar_t *t = tempString.Ptr();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
wchar_t w = *t++;
|
||||
// printf("\nchar=%x\n", w);
|
||||
if (w == 0)
|
||||
break;
|
||||
if (i == limit)
|
||||
break; // unexpected error
|
||||
if (w >= 0x10000 && w < 0x110000)
|
||||
{
|
||||
#if 1
|
||||
if (i + 1 == limit)
|
||||
break; // unexpected error
|
||||
w -= 0x10000;
|
||||
d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff);
|
||||
w = 0xdc00 + (w & 0x3ff);
|
||||
#else
|
||||
// w = '_'; // for debug
|
||||
#endif
|
||||
}
|
||||
d[i++] = w;
|
||||
}
|
||||
dest.ReleaseBuf_SetEnd((unsigned)i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr());
|
||||
printf("char: ");
|
||||
for (unsigned i = 0; i < src.Len(); i++)
|
||||
printf (" %02x", (int)(Byte)src[i]);
|
||||
printf("\n");
|
||||
printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr());
|
||||
printf("wchar_t: ");
|
||||
for (unsigned i = 0; i < dest.Len(); i++)
|
||||
{
|
||||
printf (" %02x", (int)dest[i]);
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* if there is mbstowcs() error, we have two ways:
|
||||
|
||||
1) change 0x80+ characters to some character: '_'
|
||||
in that case we lose data, but we have correct UString()
|
||||
and that scheme can show errors to user in early stages,
|
||||
when file converted back to mbs() cannot be found
|
||||
|
||||
2) transfer bad characters in some UTF-16 range.
|
||||
it can be non-original Unicode character.
|
||||
but later we still can restore original character.
|
||||
*/
|
||||
|
||||
|
||||
// printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr());
|
||||
{
|
||||
unsigned i;
|
||||
const char *s = (const char *)src;
|
||||
for (i = 0;;)
|
||||
{
|
||||
Byte c = (Byte)s[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
// we can use ascii compatibilty character '_'
|
||||
// if (c > 0x7F) c = '_'; // we replace "bad: character
|
||||
d[i++] = (wchar_t)c;
|
||||
}
|
||||
d[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src)
|
||||
{
|
||||
dest.Empty();
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
|
||||
const size_t limit = ((size_t)src.Len() + 1) * 6;
|
||||
char *d = dest.GetBuf((unsigned)limit);
|
||||
|
||||
const size_t len = wcstombs(d, src, limit);
|
||||
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
dest.ReleaseBuf_SetEnd((unsigned)len);
|
||||
return;
|
||||
}
|
||||
dest.ReleaseBuf_SetEnd(0);
|
||||
}
|
||||
|
||||
|
||||
static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
|
||||
{
|
||||
// if (codePage == 1234567) // for debug purposes
|
||||
if (codePage == CP_UTF8 || g_ForceToUTF8)
|
||||
{
|
||||
#if 1
|
||||
defaultCharWasUsed = false;
|
||||
ConvertUnicodeToUTF8(src2, dest);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
UString src = src2;
|
||||
#if WCHAR_MAX > 0xffff
|
||||
{
|
||||
src.Empty();
|
||||
for (unsigned i = 0; i < src2.Len();)
|
||||
{
|
||||
wchar_t c = src2[i++];
|
||||
if (c >= 0xd800 && c < 0xdc00 && i != src2.Len())
|
||||
{
|
||||
const wchar_t c2 = src2[i];
|
||||
if (c2 >= 0xdc00 && c2 < 0xe000)
|
||||
{
|
||||
#if 1
|
||||
// printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
|
||||
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
|
||||
// printf("%4x\n", (int)c);
|
||||
i++;
|
||||
#else
|
||||
// c = '_'; // for debug
|
||||
#endif
|
||||
}
|
||||
}
|
||||
src += c;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dest.Empty();
|
||||
defaultCharWasUsed = false;
|
||||
if (src.IsEmpty())
|
||||
return;
|
||||
|
||||
const size_t len = wcstombs(NULL, src, 0);
|
||||
|
||||
if (len != (size_t)-1)
|
||||
{
|
||||
const unsigned limit = ((unsigned)len);
|
||||
if (limit == len)
|
||||
{
|
||||
char *d = dest.GetBuf(limit);
|
||||
|
||||
/*
|
||||
{
|
||||
printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr());
|
||||
for (unsigned i = 0; i < src.Len(); i++)
|
||||
printf (" %02x", (int)src[i]);
|
||||
printf("\n");
|
||||
printf("\ndest Limit = %d \n", limit);
|
||||
}
|
||||
*/
|
||||
|
||||
const size_t len2 = wcstombs(d, src, len + 1);
|
||||
|
||||
if (len2 != (size_t)-1 && len2 <= limit)
|
||||
{
|
||||
/*
|
||||
printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr());
|
||||
for (unsigned i = 0; i < len2; i++)
|
||||
printf(" %02x", (int)(Byte)dest[i]);
|
||||
printf("\n");
|
||||
*/
|
||||
dest.ReleaseBuf_SetEnd((unsigned)len2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const wchar_t *s = (const wchar_t *)src;
|
||||
char *d = dest.GetBuf(src.Len());
|
||||
|
||||
unsigned i;
|
||||
for (i = 0;;)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (c == 0)
|
||||
break;
|
||||
if (c >=
|
||||
0x100
|
||||
// 0x80
|
||||
)
|
||||
{
|
||||
c = defaultChar;
|
||||
defaultCharWasUsed = true;
|
||||
}
|
||||
|
||||
d[i++] = (char)c;
|
||||
}
|
||||
d[i] = 0;
|
||||
dest.ReleaseBuf_SetLen(i);
|
||||
/*
|
||||
printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len());
|
||||
printf("ERROR: %s\n", dest.Ptr());
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
UString MultiByteToUnicodeString(const AString &src, UINT codePage)
|
||||
{
|
||||
UString dest;
|
||||
MultiByteToUnicodeString2(dest, src, codePage);
|
||||
return dest;
|
||||
}
|
||||
|
||||
UString MultiByteToUnicodeString(const char *src, UINT codePage)
|
||||
{
|
||||
return MultiByteToUnicodeString(AString(src), codePage);
|
||||
}
|
||||
|
||||
|
||||
void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)
|
||||
{
|
||||
bool defaultCharWasUsed;
|
||||
UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
|
||||
}
|
||||
|
||||
AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
|
||||
{
|
||||
AString dest;
|
||||
UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);
|
||||
return dest;
|
||||
}
|
||||
|
||||
AString UnicodeStringToMultiByte(const UString &src, UINT codePage)
|
||||
{
|
||||
AString dest;
|
||||
bool defaultCharWasUsed;
|
||||
UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
|
||||
|
||||
#ifdef _WIN32
|
||||
#define U_to_A(a, b, c) UnicodeStringToMultiByte2
|
||||
// #define A_to_U(a, b, c) MultiByteToUnicodeString2
|
||||
#else
|
||||
// void MultiByteToUnicodeString2_Native(UString &dest, const AString &src);
|
||||
#define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b)
|
||||
// #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b)
|
||||
#endif
|
||||
|
||||
bool IsNativeUTF8()
|
||||
{
|
||||
UString u;
|
||||
AString a, a2;
|
||||
// for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1)
|
||||
for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1)
|
||||
{
|
||||
u.Empty();
|
||||
u += (wchar_t)c;
|
||||
/*
|
||||
if (Unicode_Is_There_Utf16SurrogateError(u))
|
||||
continue;
|
||||
#ifndef _WIN32
|
||||
if (Unicode_Is_There_BmpEscape(u))
|
||||
continue;
|
||||
#endif
|
||||
*/
|
||||
ConvertUnicodeToUTF8(u, a);
|
||||
U_to_A(a2, u, CP_OEMCP);
|
||||
if (a != a2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENV_HAVE_LOCALE
|
||||
|
||||
const char *GetLocale(void)
|
||||
{
|
||||
#ifdef ENV_HAVE_LOCALE
|
||||
// printf("\n\nsetlocale(LC_CTYPE, NULL) : return : ");
|
||||
const char *s = setlocale(LC_CTYPE, NULL);
|
||||
if (!s)
|
||||
{
|
||||
// printf("[NULL]\n");
|
||||
s = "C";
|
||||
}
|
||||
else
|
||||
{
|
||||
// ubuntu returns "C" after program start
|
||||
// printf("\"%s\"\n", s);
|
||||
}
|
||||
return s;
|
||||
#elif defined(LOCALE_IS_UTF8)
|
||||
return "utf8";
|
||||
#else
|
||||
return "C";
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void Set_ForceToUTF8(bool) {}
|
||||
#else
|
||||
static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; }
|
||||
#endif
|
||||
|
||||
static bool Is_Default_Basic_Locale(const char *locale)
|
||||
{
|
||||
const AString a (locale);
|
||||
if (a.IsEqualTo_Ascii_NoCase("")
|
||||
|| a.IsEqualTo_Ascii_NoCase("C")
|
||||
|| a.IsEqualTo_Ascii_NoCase("POSIX"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Is_Default_Basic_Locale()
|
||||
{
|
||||
return Is_Default_Basic_Locale(GetLocale());
|
||||
}
|
||||
|
||||
|
||||
void MY_SetLocale()
|
||||
{
|
||||
#ifdef ENV_HAVE_LOCALE
|
||||
/*
|
||||
{
|
||||
const char *s = GetLocale();
|
||||
printf("\nGetLocale() : returned : \"%s\"\n", s);
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned start = 0;
|
||||
// unsigned lim = 0;
|
||||
unsigned lim = 3;
|
||||
|
||||
/*
|
||||
#define MY_SET_LOCALE_FLAGS__FROM_ENV 1
|
||||
#define MY_SET_LOCALE_FLAGS__TRY_UTF8 2
|
||||
|
||||
unsigned flags =
|
||||
MY_SET_LOCALE_FLAGS__FROM_ENV |
|
||||
MY_SET_LOCALE_FLAGS__TRY_UTF8
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV)
|
||||
lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1;
|
||||
else
|
||||
{
|
||||
start = 1;
|
||||
lim = 2;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (unsigned i = start; i < lim; i++)
|
||||
{
|
||||
/*
|
||||
man7: "If locale is an empty string, "", each part of the locale that
|
||||
should be modified is set according to the environment variables.
|
||||
for glibc: glibc, first from the user's environment variables:
|
||||
1) the environment variable LC_ALL,
|
||||
2) environment variable with the same name as the category (see the
|
||||
3) the environment variable LANG
|
||||
The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems.
|
||||
|
||||
for WIN32 : MSDN :
|
||||
Sets the locale to the default, which is the user-default
|
||||
ANSI code page obtained from the operating system.
|
||||
The locale name is set to the value returned by GetUserDefaultLocaleName.
|
||||
The code page is set to the value returned by GetACP
|
||||
*/
|
||||
const char *newLocale = "";
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
/* look also CFLocale
|
||||
there is no C.UTF-8 in macos
|
||||
macos has UTF-8 locale only with some language like en_US.UTF-8
|
||||
what is best way to set UTF-8 locale in macos? */
|
||||
if (i == 1)
|
||||
newLocale = "en_US.UTF-8";
|
||||
|
||||
/* file open with non-utf8 sequencies return
|
||||
#define EILSEQ 92 // "Illegal byte sequence"
|
||||
*/
|
||||
#else
|
||||
// newLocale = "C";
|
||||
if (i == 1)
|
||||
{
|
||||
newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu
|
||||
// newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime
|
||||
// newLocale = "en_US.utf8"; // supported by ubuntu ?
|
||||
// newLocale = "en_US.UTF-8";
|
||||
/* setlocale() in ubuntu allows locales with minor chracter changes in strings
|
||||
"en_US.UTF-8" / "en_US.utf8" */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale);
|
||||
|
||||
// const char *s =
|
||||
setlocale(LC_ALL, newLocale);
|
||||
|
||||
/*
|
||||
if (!s)
|
||||
printf("NULL: can't set locale");
|
||||
else
|
||||
printf("\"%s\"\n", s);
|
||||
*/
|
||||
|
||||
// request curent locale of program
|
||||
const char *locale = GetLocale();
|
||||
if (locale)
|
||||
{
|
||||
AString a (locale);
|
||||
a.MakeLower_Ascii();
|
||||
// if (a.Find("utf") >= 0)
|
||||
{
|
||||
if (IsNativeUTF8())
|
||||
{
|
||||
Set_ForceToUTF8(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!Is_Default_Basic_Locale(locale))
|
||||
{
|
||||
// if there is some non-default and non-utf locale, we want to use it
|
||||
break; // comment it for debug
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNativeUTF8())
|
||||
{
|
||||
Set_ForceToUTF8(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Is_Default_Basic_Locale())
|
||||
{
|
||||
Set_ForceToUTF8(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Set_ForceToUTF8(false);
|
||||
|
||||
#elif defined(LOCALE_IS_UTF8)
|
||||
// assume LC_CTYPE="utf8"
|
||||
#else
|
||||
// assume LC_CTYPE="C"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,110 @@
|
||||
// Common/StringConvert.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_STRING_CONVERT_H
|
||||
#define ZIP7_INC_COMMON_STRING_CONVERT_H
|
||||
|
||||
#include "MyString.h"
|
||||
#include "MyWindows.h"
|
||||
|
||||
UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP);
|
||||
UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP);
|
||||
|
||||
// optimized versions that work faster for ASCII strings
|
||||
void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP);
|
||||
// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
|
||||
void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage);
|
||||
|
||||
AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
|
||||
AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP);
|
||||
|
||||
inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; }
|
||||
inline const UString& GetUnicodeString(const UString &u) { return u; }
|
||||
|
||||
inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); }
|
||||
inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); }
|
||||
|
||||
inline UString GetUnicodeString(const AString &a, UINT codePage)
|
||||
{ return MultiByteToUnicodeString(a, codePage); }
|
||||
inline UString GetUnicodeString(const char *a, UINT codePage)
|
||||
{ return MultiByteToUnicodeString(a, codePage); }
|
||||
|
||||
inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; }
|
||||
inline const UString& GetUnicodeString(const UString &u, UINT) { return u; }
|
||||
|
||||
inline const char* GetAnsiString(const char *a) { return a; }
|
||||
inline const AString& GetAnsiString(const AString &a) { return a; }
|
||||
|
||||
inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
|
||||
inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); }
|
||||
|
||||
/*
|
||||
inline const char* GetOemString(const char* oem)
|
||||
{ return oem; }
|
||||
inline const AString& GetOemString(const AString &oem)
|
||||
{ return oem; }
|
||||
*/
|
||||
const char* GetOemString(const char* oem);
|
||||
const AString& GetOemString(const AString &oem);
|
||||
inline AString GetOemString(const UString &u)
|
||||
{ return UnicodeStringToMultiByte(u, CP_OEMCP); }
|
||||
|
||||
#ifdef _UNICODE
|
||||
inline const wchar_t* GetSystemString(const wchar_t *u) { return u;}
|
||||
inline const UString& GetSystemString(const UString &u) { return u;}
|
||||
inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;}
|
||||
inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;}
|
||||
|
||||
inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
|
||||
inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
|
||||
inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); }
|
||||
inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); }
|
||||
#else
|
||||
inline const char* GetSystemString(const char *a) { return a; }
|
||||
inline const AString& GetSystemString(const AString &a) { return a; }
|
||||
inline const char* GetSystemString(const char *a, UINT) { return a; }
|
||||
inline const AString& GetSystemString(const AString &a, UINT) { return a; }
|
||||
|
||||
inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
|
||||
inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); }
|
||||
inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
inline AString GetSystemString(const wchar_t *u)
|
||||
{
|
||||
UString s;
|
||||
s = u;
|
||||
return UnicodeStringToMultiByte(s);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef UNDER_CE
|
||||
AString SystemStringToOemString(const CSysString &src);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
/* we don't need locale functions in Windows
|
||||
but we can define ENV_HAVE_LOCALE here for debug purposes */
|
||||
// #define ENV_HAVE_LOCALE
|
||||
#else
|
||||
#define ENV_HAVE_LOCALE
|
||||
#endif
|
||||
|
||||
#ifdef ENV_HAVE_LOCALE
|
||||
void MY_SetLocale();
|
||||
const char *GetLocale(void);
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
|
||||
bool IsNativeUTF8();
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
extern bool g_ForceToUTF8;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
// Common/StringToInt.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <limits.h>
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
|
||||
#include <stdint.h> // for WCHAR_MAX in vs2022
|
||||
#endif
|
||||
|
||||
#include "StringToInt.h"
|
||||
|
||||
static const UInt32 k_UInt32_max = 0xFFFFFFFF;
|
||||
static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
|
||||
// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;
|
||||
|
||||
#define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(charTypeUnsigned)digit - '0')
|
||||
// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)digit - '0')
|
||||
// #define DIGIT_TO_VALUE(charTypeUnsigned, digit) ((unsigned)(digit - '0'))
|
||||
|
||||
#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \
|
||||
uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
|
||||
if (end) *end = s; \
|
||||
uintType res = 0; \
|
||||
for (;; s++) { \
|
||||
const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \
|
||||
if (v > 9) { if (end) *end = s; return res; } \
|
||||
if (res > (k_ ## uintType ## _max) / 10) return 0; \
|
||||
res *= 10; \
|
||||
if (res > (k_ ## uintType ## _max) - v) return 0; \
|
||||
res += v; }}
|
||||
|
||||
// arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason
|
||||
// so we don't use this branch
|
||||
#if 0 && WCHAR_MAX > UINT_MAX
|
||||
/*
|
||||
if (sizeof(wchar_t) > sizeof(unsigned)
|
||||
we must use CONVERT_STRING_TO_UINT_FUNC_SLOW
|
||||
But we just stop compiling instead.
|
||||
We need some real cases to test this code.
|
||||
*/
|
||||
#error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX
|
||||
#define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \
|
||||
uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
|
||||
if (end) *end = s; \
|
||||
uintType res = 0; \
|
||||
for (;; s++) { \
|
||||
const charTypeUnsigned c = (charTypeUnsigned)*s; \
|
||||
if (c < '0' || c > '9') { if (end) *end = s; return res; } \
|
||||
if (res > (k_ ## uintType ## _max) / 10) return 0; \
|
||||
res *= 10; \
|
||||
const unsigned v = (unsigned)(c - '0'); \
|
||||
if (res > (k_ ## uintType ## _max) - v) return 0; \
|
||||
res += v; }}
|
||||
#endif
|
||||
|
||||
|
||||
CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)
|
||||
CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)
|
||||
CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)
|
||||
CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)
|
||||
|
||||
Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
|
||||
{
|
||||
if (end)
|
||||
*end = s;
|
||||
const wchar_t *s2 = s;
|
||||
if (*s == '-')
|
||||
s2++;
|
||||
const wchar_t *end2;
|
||||
UInt32 res = ConvertStringToUInt32(s2, &end2);
|
||||
if (s2 == end2)
|
||||
return 0;
|
||||
if (s != s2)
|
||||
{
|
||||
if (res > (UInt32)1 << (32 - 1))
|
||||
return 0;
|
||||
res = 0 - res;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res & (UInt32)1 << (32 - 1))
|
||||
return 0;
|
||||
}
|
||||
if (end)
|
||||
*end = end2;
|
||||
return (Int32)res;
|
||||
}
|
||||
|
||||
|
||||
#define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \
|
||||
uintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \
|
||||
{ \
|
||||
if (end) *end = s; \
|
||||
uintType res = 0; \
|
||||
for (;; s++) { \
|
||||
const unsigned c = (unsigned)(Byte)*s - '0'; \
|
||||
if (c > 7) { \
|
||||
if (end) \
|
||||
*end = s; \
|
||||
return res; \
|
||||
} \
|
||||
if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \
|
||||
return 0; \
|
||||
res <<= 3; \
|
||||
res |= c; \
|
||||
} \
|
||||
}
|
||||
|
||||
CONVERT_OCT_STRING_TO_UINT_FUNC(UInt32)
|
||||
CONVERT_OCT_STRING_TO_UINT_FUNC(UInt64)
|
||||
|
||||
|
||||
#define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \
|
||||
uintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \
|
||||
{ \
|
||||
if (end) *end = s; \
|
||||
uintType res = 0; \
|
||||
for (;; s++) { \
|
||||
unsigned c = (unsigned)(Byte)*s; \
|
||||
Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s; return res; }) \
|
||||
if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \
|
||||
return 0; \
|
||||
res <<= 4; \
|
||||
res |= c; \
|
||||
} \
|
||||
}
|
||||
|
||||
CONVERT_HEX_STRING_TO_UINT_FUNC(UInt32)
|
||||
CONVERT_HEX_STRING_TO_UINT_FUNC(UInt64)
|
||||
|
||||
const char *FindNonHexChar(const char *s) throw()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
unsigned c = (Byte)*s++; // pointer can go 1 byte after end
|
||||
c -= '0';
|
||||
if (c <= 9)
|
||||
continue;
|
||||
c -= 'A' - '0';
|
||||
c &= ~0x20u;
|
||||
if (c > 5)
|
||||
return s - 1;
|
||||
}
|
||||
}
|
||||
|
||||
Byte *ParseHexString(const char *s, Byte *dest) throw()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
unsigned v0 = (Byte)s[0]; Z7_PARSE_HEX_DIGIT(v0, return dest;)
|
||||
unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;)
|
||||
*dest++ = (Byte)(v1 | (v0 << 4));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Common/StringToInt.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_STRING_TO_INT_H
|
||||
#define ZIP7_INC_COMMON_STRING_TO_INT_H
|
||||
|
||||
#include "MyTypes.h"
|
||||
|
||||
UInt32 ConvertStringToUInt32(const char *s, const char **end) throw();
|
||||
UInt64 ConvertStringToUInt64(const char *s, const char **end) throw();
|
||||
UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw();
|
||||
UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw();
|
||||
|
||||
// Int32 ConvertStringToInt32(const char *s, const char **end) throw();
|
||||
Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw();
|
||||
|
||||
UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw();
|
||||
UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();
|
||||
|
||||
UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();
|
||||
UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();
|
||||
|
||||
#define Z7_PARSE_HEX_DIGIT(c, err_op) \
|
||||
{ c -= '0'; \
|
||||
if (c > 9) { \
|
||||
c -= 'A' - '0'; \
|
||||
c &= ~0x20u; \
|
||||
if (c > 5) { err_op } \
|
||||
c += 10; \
|
||||
} \
|
||||
}
|
||||
|
||||
const char *FindNonHexChar(const char *s) throw();
|
||||
|
||||
// in: (dest != NULL)
|
||||
// returns: pointer in dest array after last written byte
|
||||
Byte *ParseHexString(const char *s, Byte *dest) throw();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,123 @@
|
||||
// Common/TextConfig.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "TextConfig.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
static inline bool IsDelimitChar(char c)
|
||||
{
|
||||
return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t');
|
||||
}
|
||||
|
||||
static AString GetIDString(const char *s, unsigned &finishPos)
|
||||
{
|
||||
AString result;
|
||||
for (finishPos = 0; ; finishPos++)
|
||||
{
|
||||
const char c = s[finishPos];
|
||||
if (IsDelimitChar(c) || c == '=')
|
||||
break;
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool WaitNextLine(const AString &s, unsigned &pos)
|
||||
{
|
||||
for (; pos < s.Len(); pos++)
|
||||
if (s[pos] == 0x0A)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool SkipSpaces(const AString &s, unsigned &pos)
|
||||
{
|
||||
for (; pos < s.Len(); pos++)
|
||||
{
|
||||
const char c = s[pos];
|
||||
if (!IsDelimitChar(c))
|
||||
{
|
||||
if (c != ';')
|
||||
return true;
|
||||
if (!WaitNextLine(s, pos))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)
|
||||
{
|
||||
pairs.Clear();
|
||||
unsigned pos = 0;
|
||||
|
||||
/////////////////////
|
||||
// read strings
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!SkipSpaces(s, pos))
|
||||
break;
|
||||
CTextConfigPair pair;
|
||||
unsigned finishPos;
|
||||
const AString temp (GetIDString(((const char *)s) + pos, finishPos));
|
||||
if (!ConvertUTF8ToUnicode(temp, pair.ID))
|
||||
return false;
|
||||
if (finishPos == 0)
|
||||
return false;
|
||||
pos += finishPos;
|
||||
if (!SkipSpaces(s, pos))
|
||||
return false;
|
||||
if (s[pos] != '=')
|
||||
return false;
|
||||
pos++;
|
||||
if (!SkipSpaces(s, pos))
|
||||
return false;
|
||||
if (s[pos] != '\"')
|
||||
return false;
|
||||
pos++;
|
||||
AString message;
|
||||
for (;;)
|
||||
{
|
||||
if (pos >= s.Len())
|
||||
return false;
|
||||
char c = s[pos++];
|
||||
if (c == '\"')
|
||||
break;
|
||||
if (c == '\\')
|
||||
{
|
||||
c = s[pos++];
|
||||
switch (c)
|
||||
{
|
||||
case 'n': c = '\n'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case '\\': break;
|
||||
case '\"': break;
|
||||
default: message += '\\'; break;
|
||||
}
|
||||
}
|
||||
message += c;
|
||||
}
|
||||
if (!ConvertUTF8ToUnicode(message, pair.String))
|
||||
return false;
|
||||
pairs.Add(pair);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw()
|
||||
{
|
||||
FOR_VECTOR (i, pairs)
|
||||
if (pairs[i].ID.IsEqualTo(id))
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id)
|
||||
{
|
||||
const int index = FindTextConfigItem(pairs, id);
|
||||
if (index < 0)
|
||||
return UString();
|
||||
return pairs[index].String;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Common/TextConfig.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_TEXT_CONFIG_H
|
||||
#define ZIP7_INC_COMMON_TEXT_CONFIG_H
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
struct CTextConfigPair
|
||||
{
|
||||
UString ID;
|
||||
UString String;
|
||||
};
|
||||
|
||||
bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);
|
||||
|
||||
int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw();
|
||||
UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,863 @@
|
||||
// UTFConvert.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
#include "MyTypes.h"
|
||||
#include "UTFConvert.h"
|
||||
|
||||
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
#ifndef __APPLE__
|
||||
// we define it if the system supports files with non-utf8 symbols:
|
||||
#define MY_UTF8_RAW_NON_UTF8_SUPPORTED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
MY_UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte
|
||||
|
||||
n : MY_UTF8_START(n) : Bits of code point
|
||||
|
||||
0 : 0x80 : : unused
|
||||
1 : 0xC0 : 11 :
|
||||
2 : 0xE0 : 16 : Basic Multilingual Plane
|
||||
3 : 0xF0 : 21 : Unicode space
|
||||
4 : 0xF8 : 26 :
|
||||
5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value
|
||||
6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value
|
||||
7 : 0xFF :
|
||||
*/
|
||||
|
||||
#define MY_UTF8_START(n) (0x100 - (1 << (7 - (n))))
|
||||
|
||||
#define MY_UTF8_HEAD_PARSE2(n) \
|
||||
if (c < MY_UTF8_START((n) + 1)) \
|
||||
{ numBytes = (n); val -= MY_UTF8_START(n); }
|
||||
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
|
||||
/*
|
||||
if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence,
|
||||
when we convert wchar_t strings to UTF-8:
|
||||
(_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode
|
||||
(_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4
|
||||
(_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack)
|
||||
*/
|
||||
|
||||
#define MY_UTF8_NUM_TAIL_BYTES_MAX 5
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define MY_UTF8_HEAD_PARSE \
|
||||
UInt32 val = c; \
|
||||
MY_UTF8_HEAD_PARSE2(1) \
|
||||
else MY_UTF8_HEAD_PARSE2(2) \
|
||||
else MY_UTF8_HEAD_PARSE2(3) \
|
||||
else MY_UTF8_HEAD_PARSE2(4) \
|
||||
else MY_UTF8_HEAD_PARSE2(5) \
|
||||
#if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6
|
||||
else MY_UTF8_HEAD_PARSE2(6)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#define MY_UTF8_HEAD_PARSE_MAX_3_BYTES \
|
||||
UInt32 val = c; \
|
||||
MY_UTF8_HEAD_PARSE2(1) \
|
||||
else MY_UTF8_HEAD_PARSE2(2) \
|
||||
else { numBytes = 3; val -= MY_UTF8_START(3); }
|
||||
|
||||
|
||||
#define MY_UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))
|
||||
|
||||
|
||||
#define START_POINT_FOR_SURROGATE 0x10000
|
||||
|
||||
|
||||
/* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes
|
||||
Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000)
|
||||
to simplify internal intermediate conversion in Linux:
|
||||
RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8
|
||||
*/
|
||||
|
||||
|
||||
#if defined(Z7_WCHART_IS_16BIT)
|
||||
|
||||
#define UTF_ESCAPE_PLANE 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
we can place 128 ESCAPE chars to
|
||||
ef 80 - ee be 80 (3-bytes utf-8) : similar to WSL
|
||||
ef ff - ee bf bf
|
||||
|
||||
1f ef 80 - f7 be be 80 (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode)
|
||||
1f ef ff - f7 be bf bf (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode)
|
||||
*/
|
||||
|
||||
// #define UTF_ESCAPE_PLANE_HIGH (0x1f << 16)
|
||||
// #define UTF_ESCAPE_PLANE UTF_ESCAPE_PLANE_HIGH
|
||||
#define UTF_ESCAPE_PLANE 0
|
||||
|
||||
/*
|
||||
if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is set)
|
||||
{
|
||||
if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH)
|
||||
{
|
||||
we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane.
|
||||
But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive)
|
||||
So we still need a way to extract 8-bit Escapes and BMP-Escapes-8
|
||||
from same BMP-Escapes-16 stored in 7z.
|
||||
And if we want to restore any 8-bit from 7z archive,
|
||||
we still must use Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT for (utf-8 -> utf-16)
|
||||
Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21
|
||||
}
|
||||
else (UTF_ESCAPE_PLANE == 0)
|
||||
{
|
||||
we must convert original 3-bytes utf-8 BMP-Escape point to sequence
|
||||
of 3 BMP-Escape-16 points with Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
|
||||
so we can extract original RAW-UTF-8 from UTFD-16 later.
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define UTF_ESCAPE_BASE 0xef00
|
||||
|
||||
|
||||
#ifdef UTF_ESCAPE_BASE
|
||||
#define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80)
|
||||
#endif
|
||||
|
||||
#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800)
|
||||
#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffc00) == 0xdc00)
|
||||
|
||||
|
||||
#define UTF_ERROR_UTF8_CHECK \
|
||||
{ NonUtf = true; continue; }
|
||||
|
||||
void CUtf8Check::Check_Buf(const char *src, size_t size) throw()
|
||||
{
|
||||
Clear();
|
||||
// Byte maxByte = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
const Byte c = (Byte)(*src++);
|
||||
size--;
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
ZeroChar = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
if (c > maxByte)
|
||||
maxByte = c;
|
||||
*/
|
||||
|
||||
if (c < 0x80)
|
||||
continue;
|
||||
|
||||
if (c < 0xc0 + 2)
|
||||
UTF_ERROR_UTF8_CHECK
|
||||
|
||||
unsigned numBytes;
|
||||
UInt32 val = c;
|
||||
MY_UTF8_HEAD_PARSE2(1)
|
||||
else MY_UTF8_HEAD_PARSE2(2)
|
||||
else MY_UTF8_HEAD_PARSE2(3)
|
||||
else MY_UTF8_HEAD_PARSE2(4)
|
||||
else MY_UTF8_HEAD_PARSE2(5)
|
||||
else
|
||||
{
|
||||
UTF_ERROR_UTF8_CHECK
|
||||
}
|
||||
|
||||
unsigned pos = 0;
|
||||
do
|
||||
{
|
||||
if (pos == size)
|
||||
break;
|
||||
unsigned c2 = (Byte)src[pos];
|
||||
c2 -= 0x80;
|
||||
if (c2 >= 0x40)
|
||||
break;
|
||||
val <<= 6;
|
||||
val |= c2;
|
||||
if (pos == 0)
|
||||
if (val < (((unsigned)1 << 7) >> numBytes))
|
||||
break;
|
||||
pos++;
|
||||
}
|
||||
while (--numBytes);
|
||||
|
||||
if (numBytes != 0)
|
||||
{
|
||||
if (pos == size)
|
||||
Truncated = true;
|
||||
else
|
||||
UTF_ERROR_UTF8_CHECK
|
||||
}
|
||||
|
||||
#ifdef UTF_ESCAPE_BASE
|
||||
if (IS_ESCAPE_POINT(val, 0))
|
||||
Escape = true;
|
||||
#endif
|
||||
|
||||
if (MaxHighPoint < val)
|
||||
MaxHighPoint = val;
|
||||
|
||||
if (IS_SURROGATE_POINT(val))
|
||||
SingleSurrogate = true;
|
||||
|
||||
src += pos;
|
||||
size -= pos;
|
||||
}
|
||||
|
||||
// MaxByte = maxByte;
|
||||
}
|
||||
|
||||
bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw()
|
||||
{
|
||||
CUtf8Check check;
|
||||
check.Check_Buf(src, size);
|
||||
return check.IsOK(allowReduced);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CheckUTF8_chars(const char *src, bool allowReduced) throw()
|
||||
{
|
||||
CUtf8Check check;
|
||||
check.CheckBuf(src, strlen(src));
|
||||
return check.IsOK(allowReduced);
|
||||
}
|
||||
*/
|
||||
|
||||
bool CheckUTF8_AString(const AString &s) throw()
|
||||
{
|
||||
CUtf8Check check;
|
||||
check.Check_AString(s);
|
||||
return check.IsOK();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
bool CheckUTF8(const char *src, bool allowReduced) throw()
|
||||
{
|
||||
// return Check_UTF8_Buf(src, strlen(src), allowReduced);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const Byte c = (Byte)(*src++);
|
||||
if (c == 0)
|
||||
return true;
|
||||
|
||||
if (c < 0x80)
|
||||
continue;
|
||||
if (c < 0xC0 + 2 || c >= 0xf5)
|
||||
return false;
|
||||
|
||||
unsigned numBytes;
|
||||
MY_UTF8_HEAD_PARSE
|
||||
else
|
||||
return false;
|
||||
|
||||
unsigned pos = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Byte c2 = (Byte)(*src++);
|
||||
if (c2 < 0x80 || c2 >= 0xC0)
|
||||
return allowReduced && c2 == 0;
|
||||
val <<= 6;
|
||||
val |= (c2 - 0x80);
|
||||
pos++;
|
||||
}
|
||||
while (--numBytes);
|
||||
|
||||
if (val < MY_UTF8_RANGE(pos - 1))
|
||||
return false;
|
||||
|
||||
if (val >= 0x110000)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// in case of UTF-8 error we have two ways:
|
||||
// 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version
|
||||
// 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols
|
||||
|
||||
#define UTF_REPLACEMENT_CHAR 0xfffd
|
||||
|
||||
|
||||
|
||||
#define UTF_ESCAPE(c) \
|
||||
((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) ? \
|
||||
UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR)
|
||||
|
||||
/*
|
||||
#define UTF_HARD_ERROR_UTF8
|
||||
{ if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \
|
||||
destPos++; ok = false; continue; }
|
||||
*/
|
||||
|
||||
// we ignore utf errors, and don't change (ok) variable!
|
||||
|
||||
#define UTF_ERROR_UTF8 \
|
||||
{ if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \
|
||||
destPos++; continue; }
|
||||
|
||||
// we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points:
|
||||
|
||||
// for debug puposes only we can store UTF-32 in wchar_t:
|
||||
// #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1)
|
||||
|
||||
|
||||
/*
|
||||
WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found.
|
||||
Ant it can emit single 0xfffd from 2 src bytes.
|
||||
It doesn't emit single 0xfffd from 3-4 src bytes.
|
||||
We can
|
||||
1) emit Escape point for each incorrect byte. So we can data recover later
|
||||
2) emit 0xfffd for each incorrect byte.
|
||||
That scheme is similar to Escape scheme, but we emit 0xfffd
|
||||
instead of each Escape point.
|
||||
3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme
|
||||
*/
|
||||
|
||||
static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw()
|
||||
{
|
||||
size_t destPos = 0;
|
||||
bool ok = true;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (src == srcLim)
|
||||
{
|
||||
*destLen = destPos;
|
||||
return ok;
|
||||
}
|
||||
|
||||
const Byte c = (Byte)(*src++);
|
||||
|
||||
if (c < 0x80)
|
||||
{
|
||||
if (dest)
|
||||
dest[destPos] = (wchar_t)c;
|
||||
destPos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c < 0xc0 + 2
|
||||
|| c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility
|
||||
{
|
||||
UTF_ERROR_UTF8
|
||||
}
|
||||
|
||||
unsigned numBytes;
|
||||
|
||||
MY_UTF8_HEAD_PARSE_MAX_3_BYTES
|
||||
|
||||
unsigned pos = 0;
|
||||
do
|
||||
{
|
||||
if (src + pos == srcLim)
|
||||
break;
|
||||
unsigned c2 = (Byte)src[pos];
|
||||
c2 -= 0x80;
|
||||
if (c2 >= 0x40)
|
||||
break;
|
||||
val <<= 6;
|
||||
val |= c2;
|
||||
pos++;
|
||||
if (pos == 1)
|
||||
{
|
||||
if (val < (((unsigned)1 << 7) >> numBytes))
|
||||
break;
|
||||
if (numBytes == 2)
|
||||
{
|
||||
if (flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR)
|
||||
if ((val & (0xF800 >> 6)) == (0xd800 >> 6))
|
||||
break;
|
||||
}
|
||||
else if (numBytes == 3 && val >= (0x110000 >> 12))
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (--numBytes);
|
||||
|
||||
if (numBytes != 0)
|
||||
{
|
||||
if ((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) == 0)
|
||||
{
|
||||
// the following code to emit the 0xfffd chars as win32 Utf8 function.
|
||||
// disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode
|
||||
src += pos;
|
||||
}
|
||||
UTF_ERROR_UTF8
|
||||
}
|
||||
|
||||
/*
|
||||
if (val < MY_UTF8_RANGE(pos - 1))
|
||||
UTF_ERROR_UTF8
|
||||
*/
|
||||
|
||||
#ifdef UTF_ESCAPE_BASE
|
||||
|
||||
if ((flags & Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT)
|
||||
&& IS_ESCAPE_POINT(val, 0))
|
||||
{
|
||||
// We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes)
|
||||
UTF_ERROR_UTF8
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
We don't expect virtual Escape-21 points in UTF-8 stream.
|
||||
And we don't check for Escape-21.
|
||||
So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points.
|
||||
Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases?
|
||||
*/
|
||||
|
||||
if (val < START_POINT_FOR_SURROGATE)
|
||||
{
|
||||
/*
|
||||
if ((flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR)
|
||||
&& IS_SURROGATE_POINT(val))
|
||||
{
|
||||
// We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes)
|
||||
UTF_ERROR_UTF8
|
||||
}
|
||||
*/
|
||||
if (dest)
|
||||
dest[destPos] = (wchar_t)val;
|
||||
destPos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
if (val >= 0x110000)
|
||||
{
|
||||
// We will emit utf16-Escape-16-21 point from each source byte
|
||||
UTF_ERROR_UTF8
|
||||
}
|
||||
*/
|
||||
if (dest)
|
||||
{
|
||||
dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10));
|
||||
dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff));
|
||||
}
|
||||
destPos += 2;
|
||||
}
|
||||
src += pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define MY_UTF8_HEAD(n, val) ((char)(MY_UTF8_START(n) + (val >> (6 * (n)))))
|
||||
#define MY_UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F)))
|
||||
|
||||
static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags)
|
||||
{
|
||||
size_t size = (size_t)(srcLim - src);
|
||||
for (;;)
|
||||
{
|
||||
if (src == srcLim)
|
||||
return size;
|
||||
|
||||
UInt32 val = (UInt32)(*src++);
|
||||
|
||||
if (val < 0x80)
|
||||
continue;
|
||||
|
||||
if (val < MY_UTF8_RANGE(1))
|
||||
{
|
||||
size++;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef UTF_ESCAPE_BASE
|
||||
|
||||
#if UTF_ESCAPE_PLANE != 0
|
||||
if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE)
|
||||
if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE)
|
||||
if (IS_ESCAPE_POINT(val, 0))
|
||||
continue;
|
||||
|
||||
#endif
|
||||
|
||||
if (IS_SURROGATE_POINT(val))
|
||||
{
|
||||
// it's hack to UTF-8 encoding
|
||||
|
||||
if (val < 0xdc00 && src != srcLim)
|
||||
{
|
||||
const UInt32 c2 = (UInt32)*src;
|
||||
if (c2 >= 0xdc00 && c2 < 0xe000)
|
||||
src++;
|
||||
}
|
||||
size += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef Z7_WCHART_IS_16BIT
|
||||
|
||||
size += 2;
|
||||
|
||||
#else
|
||||
|
||||
if (val < MY_UTF8_RANGE(2)) size += 2;
|
||||
else if (val < MY_UTF8_RANGE(3)) size += 3;
|
||||
else if (val < MY_UTF8_RANGE(4)) size += 4;
|
||||
else if (val < MY_UTF8_RANGE(5)) size += 5;
|
||||
else
|
||||
#if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6
|
||||
size += 6;
|
||||
#else
|
||||
size += 3;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (src == srcLim)
|
||||
return dest;
|
||||
|
||||
UInt32 val = (UInt32)*src++;
|
||||
|
||||
if (val < 0x80)
|
||||
{
|
||||
*dest++ = (char)val;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val < MY_UTF8_RANGE(1))
|
||||
{
|
||||
dest[0] = MY_UTF8_HEAD(1, val);
|
||||
dest[1] = MY_UTF8_CHAR(0, val);
|
||||
dest += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef UTF_ESCAPE_BASE
|
||||
|
||||
#if UTF_ESCAPE_PLANE != 0
|
||||
/*
|
||||
if (wchar_t is 32-bit)
|
||||
&& (Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE is set)
|
||||
&& (point is virtual escape plane)
|
||||
we extract 8-bit byte from virtual HIGH-ESCAPE PLANE.
|
||||
*/
|
||||
if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE)
|
||||
if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))
|
||||
{
|
||||
*dest++ = (char)(val);
|
||||
continue;
|
||||
}
|
||||
#endif // UTF_ESCAPE_PLANE != 0
|
||||
|
||||
/* if (Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE is defined)
|
||||
we extract 8-bit byte from BMP-ESCAPE PLANE. */
|
||||
|
||||
if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE)
|
||||
if (IS_ESCAPE_POINT(val, 0))
|
||||
{
|
||||
*dest++ = (char)(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
#endif // UTF_ESCAPE_BASE
|
||||
|
||||
if (IS_SURROGATE_POINT(val))
|
||||
{
|
||||
// it's hack to UTF-8 encoding
|
||||
if (val < 0xdc00 && src != srcLim)
|
||||
{
|
||||
const UInt32 c2 = (UInt32)*src;
|
||||
if (IS_LOW_SURROGATE_POINT(c2))
|
||||
{
|
||||
src++;
|
||||
val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000;
|
||||
dest[0] = MY_UTF8_HEAD(3, val);
|
||||
dest[1] = MY_UTF8_CHAR(2, val);
|
||||
dest[2] = MY_UTF8_CHAR(1, val);
|
||||
dest[3] = MY_UTF8_CHAR(0, val);
|
||||
dest += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (flags & Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR)
|
||||
val = UTF_REPLACEMENT_CHAR; // WIN32 function does it
|
||||
}
|
||||
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
if (val < MY_UTF8_RANGE(2))
|
||||
#endif
|
||||
{
|
||||
dest[0] = MY_UTF8_HEAD(2, val);
|
||||
dest[1] = MY_UTF8_CHAR(1, val);
|
||||
dest[2] = MY_UTF8_CHAR(0, val);
|
||||
dest += 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
|
||||
// we don't expect this case. so we can throw exception
|
||||
// throw 20210407;
|
||||
|
||||
char b;
|
||||
unsigned numBits;
|
||||
if (val < MY_UTF8_RANGE(3)) { numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); }
|
||||
else if (val < MY_UTF8_RANGE(4)) { numBits = 6 * 4; b = MY_UTF8_HEAD(4, val); }
|
||||
else if (val < MY_UTF8_RANGE(5)) { numBits = 6 * 5; b = MY_UTF8_HEAD(5, val); }
|
||||
#if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6
|
||||
else { numBits = 6 * 6; b = (char)MY_UTF8_START(6); }
|
||||
#else
|
||||
else
|
||||
{
|
||||
val = UTF_REPLACEMENT_CHAR;
|
||||
{ numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); }
|
||||
}
|
||||
#endif
|
||||
|
||||
*dest++ = b;
|
||||
|
||||
do
|
||||
{
|
||||
numBits -= 6;
|
||||
*dest++ = (char)(0x80 + ((val >> numBits) & 0x3F));
|
||||
}
|
||||
while (numBits != 0);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags)
|
||||
{
|
||||
dest.Empty();
|
||||
size_t destLen = 0;
|
||||
Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags);
|
||||
bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags);
|
||||
dest.ReleaseBuf_SetEnd((unsigned)destLen);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags)
|
||||
{
|
||||
return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest, flags);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
unsigned g_UTF8_To_Unicode_Flags =
|
||||
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
| Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
|
||||
#ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED
|
||||
| Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
bool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest)
|
||||
{
|
||||
return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);
|
||||
}
|
||||
*/
|
||||
|
||||
bool ConvertUTF8ToUnicode(const AString &src, UString &dest)
|
||||
{
|
||||
return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);
|
||||
}
|
||||
|
||||
void Print_UString(const UString &a);
|
||||
|
||||
void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags)
|
||||
{
|
||||
/*
|
||||
if (src.Len()== 24)
|
||||
throw "202104";
|
||||
*/
|
||||
dest.Empty();
|
||||
const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);
|
||||
char *destStart = dest.GetBuf((unsigned)destLen);
|
||||
const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags);
|
||||
dest.ReleaseBuf_SetEnd((unsigned)destLen);
|
||||
// printf("\nlen = %d\n", src.Len());
|
||||
if (destLen != (size_t)(destEnd - destStart))
|
||||
{
|
||||
/*
|
||||
// dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart));
|
||||
printf("\nlen = %d\n", (unsigned)destLen);
|
||||
printf("\n(destEnd - destStart) = %d\n", (unsigned)(destEnd - destStart));
|
||||
printf("\n");
|
||||
// Print_UString(src);
|
||||
printf("\n");
|
||||
// printf("\nlen = %d\n", destLen);
|
||||
*/
|
||||
throw 20210406;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned g_Unicode_To_UTF8_Flags =
|
||||
// Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE
|
||||
0
|
||||
#ifndef _WIN32
|
||||
#ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED
|
||||
| Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE
|
||||
#else
|
||||
| Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
|
||||
void ConvertUnicodeToUTF8(const UString &src, AString &dest)
|
||||
{
|
||||
ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags);
|
||||
}
|
||||
|
||||
void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest)
|
||||
{
|
||||
const unsigned flags = g_Unicode_To_UTF8_Flags;
|
||||
dest.Free();
|
||||
const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);
|
||||
dest.Alloc(destLen);
|
||||
const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags);
|
||||
if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest))
|
||||
throw 202104;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
#ifndef _WIN32
|
||||
void Convert_UTF16_To_UTF32(const UString &src, UString &dest)
|
||||
{
|
||||
dest.Empty();
|
||||
for (size_t i = 0; i < src.Len();)
|
||||
{
|
||||
wchar_t c = src[i++];
|
||||
if (c >= 0xd800 && c < 0xdc00 && i < src.Len())
|
||||
{
|
||||
const wchar_t c2 = src[i];
|
||||
if (c2 >= 0xdc00 && c2 < 0xe000)
|
||||
{
|
||||
// printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
|
||||
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
|
||||
// printf("%4x\n", (int)c);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
dest += c;
|
||||
}
|
||||
}
|
||||
|
||||
void Convert_UTF32_To_UTF16(const UString &src, UString &dest)
|
||||
{
|
||||
dest.Empty();
|
||||
for (size_t i = 0; i < src.Len();)
|
||||
{
|
||||
wchar_t w = src[i++];
|
||||
if (w >= 0x10000 && w < 0x110000)
|
||||
{
|
||||
w -= 0x10000;
|
||||
dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff));
|
||||
w = 0xdc00 + (w & 0x3ff);
|
||||
}
|
||||
dest += w;
|
||||
}
|
||||
}
|
||||
|
||||
bool UTF32_IsThere_BigPoint(const UString &src)
|
||||
{
|
||||
for (size_t i = 0; i < src.Len();)
|
||||
{
|
||||
const UInt32 c = (UInt32)src[i++];
|
||||
if (c >= 0x110000)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Unicode_IsThere_BmpEscape(const UString &src)
|
||||
{
|
||||
for (size_t i = 0; i < src.Len();)
|
||||
{
|
||||
const UInt32 c = (UInt32)src[i++];
|
||||
if (IS_ESCAPE_POINT(c, 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool Unicode_IsThere_Utf16SurrogateError(const UString &src)
|
||||
{
|
||||
for (size_t i = 0; i < src.Len();)
|
||||
{
|
||||
const UInt32 val = (UInt32)src[i++];
|
||||
if (IS_SURROGATE_POINT(val))
|
||||
{
|
||||
// it's hack to UTF-8 encoding
|
||||
if (val >= 0xdc00 || i == src.Len())
|
||||
return true;
|
||||
const UInt32 c2 = (UInt32)*src;
|
||||
if (!IS_LOW_SURROGATE_POINT(c2))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef Z7_WCHART_IS_16BIT
|
||||
|
||||
void Convert_UnicodeEsc16_To_UnicodeEscHigh
|
||||
#if UTF_ESCAPE_PLANE == 0
|
||||
(UString &) {}
|
||||
#else
|
||||
(UString &s)
|
||||
{
|
||||
const unsigned len = s.Len();
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = s[i];
|
||||
if (IS_ESCAPE_POINT(c, 0))
|
||||
{
|
||||
c += UTF_ESCAPE_PLANE;
|
||||
s.ReplaceOneCharAtPos(i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,384 @@
|
||||
// Common/UTFConvert.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_UTF_CONVERT_H
|
||||
#define ZIP7_INC_COMMON_UTF_CONVERT_H
|
||||
|
||||
#include "MyBuffer.h"
|
||||
#include "MyString.h"
|
||||
|
||||
struct CUtf8Check
|
||||
{
|
||||
// Byte MaxByte; // in original src stream
|
||||
bool NonUtf;
|
||||
bool ZeroChar;
|
||||
bool SingleSurrogate;
|
||||
bool Escape;
|
||||
bool Truncated;
|
||||
UInt32 MaxHighPoint; // only for points >= 0x80
|
||||
|
||||
CUtf8Check() { Clear(); }
|
||||
|
||||
void Clear()
|
||||
{
|
||||
// MaxByte = 0;
|
||||
NonUtf = false;
|
||||
ZeroChar = false;
|
||||
SingleSurrogate = false;
|
||||
Escape = false;
|
||||
Truncated = false;
|
||||
MaxHighPoint = 0;
|
||||
}
|
||||
|
||||
void Update(const CUtf8Check &c)
|
||||
{
|
||||
if (c.NonUtf) NonUtf = true;
|
||||
if (c.ZeroChar) ZeroChar = true;
|
||||
if (c.SingleSurrogate) SingleSurrogate = true;
|
||||
if (c.Escape) Escape = true;
|
||||
if (c.Truncated) Truncated = true;
|
||||
if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint;
|
||||
}
|
||||
|
||||
void PrintStatus(AString &s) const
|
||||
{
|
||||
s.Empty();
|
||||
|
||||
// s.Add_OptSpaced("MaxByte=");
|
||||
// s.Add_UInt32(MaxByte);
|
||||
|
||||
if (NonUtf) s.Add_OptSpaced("non-UTF8");
|
||||
if (ZeroChar) s.Add_OptSpaced("ZeroChar");
|
||||
if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate");
|
||||
if (Escape) s.Add_OptSpaced("Escape");
|
||||
if (Truncated) s.Add_OptSpaced("Truncated");
|
||||
|
||||
if (MaxHighPoint != 0)
|
||||
{
|
||||
s.Add_OptSpaced("MaxUnicode=");
|
||||
s.Add_UInt32(MaxHighPoint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool IsOK(bool allowReduced = false) const
|
||||
{
|
||||
if (NonUtf || SingleSurrogate || ZeroChar)
|
||||
return false;
|
||||
if (MaxHighPoint >= 0x110000)
|
||||
return false;
|
||||
if (Truncated && !allowReduced)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// it checks full buffer as specified in (size) and it doesn't stop on zero char
|
||||
void Check_Buf(const char *src, size_t size) throw();
|
||||
|
||||
void Check_AString(const AString &s) throw()
|
||||
{
|
||||
Check_Buf(s.Ptr(), s.Len());
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
if (allowReduced == false) - all UTF-8 character sequences must be finished.
|
||||
if (allowReduced == true) - it allows truncated last character-Utf8-sequence
|
||||
*/
|
||||
|
||||
bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw();
|
||||
bool CheckUTF8_AString(const AString &s) throw();
|
||||
|
||||
#define Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR (1 << 0)
|
||||
#define Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE (1 << 1)
|
||||
#define Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT (1 << 2)
|
||||
|
||||
/*
|
||||
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
|
||||
|
||||
if (flag is NOT set)
|
||||
{
|
||||
it processes SINGLE-SURROGATE-8 as valid Unicode point.
|
||||
it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16
|
||||
Note: some sequencies of two SINGLE-SURROGATE-8 points
|
||||
will generate correct SURROGATE-16-PAIR, and
|
||||
that SURROGATE-16-PAIR later will be converted to correct
|
||||
UTF8-SURROGATE-21 point. So we don't restore original
|
||||
STR-8 sequence in that case.
|
||||
}
|
||||
|
||||
if (flag is set)
|
||||
{
|
||||
if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is defined)
|
||||
it generates ESCAPE for SINGLE-SURROGATE-8,
|
||||
if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is not defined)
|
||||
it generates U+fffd for SINGLE-SURROGATE-8,
|
||||
}
|
||||
|
||||
|
||||
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
|
||||
|
||||
if (flag is NOT set)
|
||||
it generates (U+fffd) code for non-UTF-8 (invalid) characters
|
||||
|
||||
if (flag is set)
|
||||
{
|
||||
It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters.
|
||||
And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes.
|
||||
}
|
||||
|
||||
Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
|
||||
|
||||
if (flag is NOT set)
|
||||
{
|
||||
it process ESCAPE-8 points as another Unicode points.
|
||||
In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences,
|
||||
so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW
|
||||
}
|
||||
|
||||
if (flag is set)
|
||||
{
|
||||
it generates ESCAPE-16-21 for ESCAPE-8 points
|
||||
so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21.
|
||||
}
|
||||
|
||||
|
||||
Main USE CASES with UTF-8 <-> UTF-16 conversions:
|
||||
|
||||
WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW
|
||||
{
|
||||
set Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
|
||||
Do NOT set Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
|
||||
Do NOT set Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
|
||||
|
||||
So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8.
|
||||
}
|
||||
|
||||
Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
|
||||
{
|
||||
we want restore original UTF-8-RAW sequence later from that ESCAPE-16.
|
||||
Set the flags:
|
||||
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
|
||||
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
|
||||
Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT
|
||||
}
|
||||
|
||||
MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
|
||||
{
|
||||
we want to restore correct UTF-8 without any BMP processing:
|
||||
Set the flags:
|
||||
Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR
|
||||
Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// zero char is not allowed in (src) buf
|
||||
bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0);
|
||||
|
||||
bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0);
|
||||
bool ConvertUTF8ToUnicode(const AString &src, UString &dest);
|
||||
|
||||
#define Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR (1 << 8)
|
||||
#define Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE (1 << 9)
|
||||
// #define Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE (1 << 10)
|
||||
|
||||
/*
|
||||
Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR
|
||||
|
||||
if (flag is NOT set)
|
||||
{
|
||||
we extract SINGLE-SURROGATE as normal UTF-8
|
||||
|
||||
In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in .
|
||||
|
||||
In Linux :
|
||||
use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE,
|
||||
if (Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) is used.
|
||||
use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux)
|
||||
will generate SINGLE-SURROGATE-UTF-8 here.
|
||||
}
|
||||
|
||||
if (flag is set)
|
||||
{
|
||||
we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE
|
||||
it can be used for compatibility mode with WIN32 UTF function
|
||||
or if we want UTF-8 stream without any errors
|
||||
}
|
||||
|
||||
|
||||
Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE
|
||||
|
||||
if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16
|
||||
if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16
|
||||
|
||||
in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive):
|
||||
if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane.
|
||||
if (we don't use High-Escape-Plane), we must use Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.
|
||||
|
||||
|
||||
Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE
|
||||
// that flag affects the code only if (wchar_t is 32-bit)
|
||||
// that mode with high-escape can be disabled now in UTFConvert.cpp
|
||||
if (flag is NOT set)
|
||||
it doesn't extract raw 8-bit symbol from High-Escape-Plane
|
||||
if (flag is set)
|
||||
it extracts raw 8-bit symbol from High-Escape-Plane
|
||||
|
||||
Main use cases:
|
||||
|
||||
WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW
|
||||
{
|
||||
Do NOT set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.
|
||||
Do NOT set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR.
|
||||
So we restore original UTF-16-RAW.
|
||||
}
|
||||
|
||||
Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes
|
||||
set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive
|
||||
set Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE for intermediate UTF-16.
|
||||
Note: high esacape mode can be ignored now in UTFConvert.cpp
|
||||
|
||||
macOS:
|
||||
the system doesn't support incorrect UTF-8 in file names.
|
||||
set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR
|
||||
*/
|
||||
|
||||
extern unsigned g_Unicode_To_UTF8_Flags;
|
||||
|
||||
void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0);
|
||||
void ConvertUnicodeToUTF8(const UString &src, AString &dest);
|
||||
|
||||
void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest);
|
||||
|
||||
/*
|
||||
#ifndef _WIN32
|
||||
void Convert_UTF16_To_UTF32(const UString &src, UString &dest);
|
||||
void Convert_UTF32_To_UTF16(const UString &src, UString &dest);
|
||||
bool UTF32_IsThere_BigPoint(const UString &src);
|
||||
bool Unicode_IsThere_BmpEscape(const UString &src);
|
||||
#endif
|
||||
|
||||
bool Unicode_IsThere_Utf16SurrogateError(const UString &src);
|
||||
*/
|
||||
|
||||
#ifdef Z7_WCHART_IS_16BIT
|
||||
#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s)
|
||||
#else
|
||||
void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s);
|
||||
#endif
|
||||
|
||||
/*
|
||||
// #include "../../C/CpuArch.h"
|
||||
|
||||
// ---------- Utf16 Little endian functions ----------
|
||||
|
||||
// We store 16-bit surrogates even in 32-bit WCHARs in Linux.
|
||||
// So now we don't use the following code:
|
||||
|
||||
#if WCHAR_MAX > 0xffff
|
||||
|
||||
// void *p : pointer to src bytes stream
|
||||
// size_t len : num Utf16 characters : it can include or not include NULL character
|
||||
|
||||
inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len)
|
||||
{
|
||||
#if WCHAR_MAX > 0xffff
|
||||
size_t num_wchars = 0;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = GetUi16(p);
|
||||
p = (const void *)((const Byte *)p + 2);
|
||||
if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
|
||||
{
|
||||
wchar_t c2 = GetUi16(p);
|
||||
if (c2 >= 0xdc00 && c2 < 0xe000)
|
||||
{
|
||||
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
|
||||
p = (const void *)((const Byte *)p + 2);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
num_wchars++;
|
||||
}
|
||||
return num_wchars;
|
||||
#else
|
||||
UNUSED_VAR(p)
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
wchar_t c = GetUi16(p);
|
||||
p = (const void *)((const Byte *)p + 2);
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
if (c == L'/')
|
||||
c = WCHAR_PATH_SEPARATOR;
|
||||
#endif
|
||||
|
||||
#if WCHAR_MAX > 0xffff
|
||||
|
||||
if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
|
||||
{
|
||||
wchar_t c2 = GetUi16(p);
|
||||
if (c2 >= 0xdc00 && c2 < 0xe000)
|
||||
{
|
||||
// printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2);
|
||||
c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
|
||||
p = (const void *)((const Byte *)p + 2);
|
||||
i++;
|
||||
// printf("%4x\n", (int)c);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
*dest++ = c;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p)
|
||||
{
|
||||
size_t num = 0;
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = *p++;
|
||||
if (c == 0)
|
||||
return num;
|
||||
num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c = *p++;
|
||||
if (c == 0)
|
||||
return dest;
|
||||
if (c >= 0x10000 && c < 0x110000)
|
||||
{
|
||||
SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF)));
|
||||
SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF)));
|
||||
dest += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUi16(dest, c);
|
||||
dest += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,789 @@
|
||||
// Common/Wildcard.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "Wildcard.h"
|
||||
|
||||
extern
|
||||
bool g_CaseSensitive;
|
||||
bool g_CaseSensitive =
|
||||
#ifdef _WIN32
|
||||
false;
|
||||
#elif defined (__APPLE__)
|
||||
#ifdef TARGET_OS_IPHONE
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
|
||||
|
||||
bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
|
||||
{
|
||||
if (g_CaseSensitive)
|
||||
return IsString1PrefixedByString2(s1, s2);
|
||||
return IsString1PrefixedByString2_NoCase(s1, s2);
|
||||
}
|
||||
|
||||
// #include <stdio.h>
|
||||
|
||||
/*
|
||||
static int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c1 = *s1++;
|
||||
wchar_t c2 = *s2++;
|
||||
if (c1 != c2)
|
||||
{
|
||||
if (c1 == 0) return -1;
|
||||
if (c2 == 0) return 1;
|
||||
if (c1 == '/') c1 = 0;
|
||||
if (c2 == '/') c2 = 0;
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
continue;
|
||||
}
|
||||
if (c1 == 0) return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c1 = *s1++;
|
||||
wchar_t c2 = *s2++;
|
||||
if (c1 != c2)
|
||||
{
|
||||
if (c1 == 0) return -1;
|
||||
if (c2 == 0) return 1;
|
||||
if (IS_PATH_SEPAR(c1)) c1 = 0;
|
||||
if (IS_PATH_SEPAR(c2)) c2 = 0;
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
continue;
|
||||
}
|
||||
if (c1 == 0) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
wchar_t c1 = *s1++;
|
||||
wchar_t c2 = *s2++;
|
||||
if (c1 != c2)
|
||||
{
|
||||
if (c1 == 0) return -1;
|
||||
if (c2 == 0) return 1;
|
||||
if (IS_PATH_SEPAR(c1)) c1 = 0;
|
||||
if (IS_PATH_SEPAR(c2)) c2 = 0;
|
||||
c1 = MyCharUpper(c1);
|
||||
c2 = MyCharUpper(c2);
|
||||
if (c1 < c2) return -1;
|
||||
if (c1 > c2) return 1;
|
||||
continue;
|
||||
}
|
||||
if (c1 == 0) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
|
||||
{
|
||||
/*
|
||||
printf("\nCompareFileNames");
|
||||
printf("\n S1: %ls", s1);
|
||||
printf("\n S2: %ls", s2);
|
||||
printf("\n");
|
||||
*/
|
||||
// 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1
|
||||
if (g_CaseSensitive)
|
||||
return MyStringCompare_Path(s1, s2);
|
||||
return MyStringCompareNoCase_Path(s1, s2);
|
||||
}
|
||||
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
int CompareFileNames(const char *s1, const char *s2)
|
||||
{
|
||||
const UString u1 = fs2us(s1);
|
||||
const UString u2 = fs2us(s2);
|
||||
return CompareFileNames(u1, u2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------
|
||||
// this function compares name with mask
|
||||
// ? - any char
|
||||
// * - any char or empty
|
||||
|
||||
static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
const wchar_t m = *mask;
|
||||
const wchar_t c = *name;
|
||||
if (m == 0)
|
||||
return (c == 0);
|
||||
if (m == '*')
|
||||
{
|
||||
if (EnhancedMaskTest(mask + 1, name))
|
||||
return true;
|
||||
if (c == 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m == '?')
|
||||
{
|
||||
if (c == 0)
|
||||
return false;
|
||||
}
|
||||
else if (m != c)
|
||||
if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))
|
||||
return false;
|
||||
mask++;
|
||||
}
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// Splits path to strings
|
||||
|
||||
void SplitPathToParts(const UString &path, UStringVector &pathParts)
|
||||
{
|
||||
pathParts.Clear();
|
||||
unsigned len = path.Len();
|
||||
if (len == 0)
|
||||
return;
|
||||
UString name;
|
||||
unsigned prev = 0;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
if (IsPathSepar(path[i]))
|
||||
{
|
||||
name.SetFrom(path.Ptr(prev), i - prev);
|
||||
pathParts.Add(name);
|
||||
prev = i + 1;
|
||||
}
|
||||
name.SetFrom(path.Ptr(prev), len - prev);
|
||||
pathParts.Add(name);
|
||||
}
|
||||
|
||||
void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)
|
||||
{
|
||||
const wchar_t *start = path;
|
||||
const wchar_t *p = start + path.Len();
|
||||
for (; p != start; p--)
|
||||
if (IsPathSepar(*(p - 1)))
|
||||
break;
|
||||
dirPrefix.SetFrom(path, (unsigned)(p - start));
|
||||
name = p;
|
||||
}
|
||||
|
||||
void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)
|
||||
{
|
||||
const wchar_t *start = path;
|
||||
const wchar_t *p = start + path.Len();
|
||||
if (p != start)
|
||||
{
|
||||
if (IsPathSepar(*(p - 1)))
|
||||
p--;
|
||||
for (; p != start; p--)
|
||||
if (IsPathSepar(*(p - 1)))
|
||||
break;
|
||||
}
|
||||
dirPrefix.SetFrom(path, (unsigned)(p - start));
|
||||
name = p;
|
||||
}
|
||||
|
||||
/*
|
||||
UString ExtractDirPrefixFromPath(const UString &path)
|
||||
{
|
||||
return path.Left(path.ReverseFind_PathSepar() + 1));
|
||||
}
|
||||
*/
|
||||
|
||||
UString ExtractFileNameFromPath(const UString &path)
|
||||
{
|
||||
return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1)));
|
||||
}
|
||||
|
||||
|
||||
bool DoesWildcardMatchName(const UString &mask, const UString &name)
|
||||
{
|
||||
return EnhancedMaskTest(mask, name);
|
||||
}
|
||||
|
||||
bool DoesNameContainWildcard(const UString &path)
|
||||
{
|
||||
for (unsigned i = 0; i < path.Len(); i++)
|
||||
{
|
||||
wchar_t c = path[i];
|
||||
if (c == '*' || c == '?')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------'
|
||||
// NWildcard
|
||||
|
||||
namespace NWildcard {
|
||||
|
||||
/*
|
||||
|
||||
M = MaskParts.Size();
|
||||
N = TestNameParts.Size();
|
||||
|
||||
File Dir
|
||||
ForFile rec M<=N [N-M, N) -
|
||||
!ForDir nonrec M=N [0, M) -
|
||||
|
||||
ForDir rec M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File
|
||||
!ForFile nonrec [0, M) same as ForBoth-File
|
||||
|
||||
ForFile rec m<=N [0, M) ... [N-M, N) same as ForBoth-File
|
||||
ForDir nonrec [0, M) same as ForBoth-File
|
||||
|
||||
*/
|
||||
|
||||
bool CItem::AreAllAllowed() const
|
||||
{
|
||||
return ForFile && ForDir && WildcardMatching
|
||||
&& PathParts.Size() == 1 && PathParts.Front().IsEqualTo("*");
|
||||
}
|
||||
|
||||
bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
|
||||
{
|
||||
if (!isFile && !ForDir)
|
||||
return false;
|
||||
|
||||
/*
|
||||
if (PathParts.IsEmpty())
|
||||
{
|
||||
// PathParts.IsEmpty() means all items (universal wildcard)
|
||||
if (!isFile)
|
||||
return true;
|
||||
if (pathParts.Size() <= 1)
|
||||
return ForFile;
|
||||
return (ForDir || Recursive && ForFile);
|
||||
}
|
||||
*/
|
||||
|
||||
int delta = (int)pathParts.Size() - (int)PathParts.Size();
|
||||
if (delta < 0)
|
||||
return false;
|
||||
int start = 0;
|
||||
int finish = 0;
|
||||
|
||||
if (isFile)
|
||||
{
|
||||
if (!ForDir)
|
||||
{
|
||||
if (Recursive)
|
||||
start = delta;
|
||||
else if (delta !=0)
|
||||
return false;
|
||||
}
|
||||
if (!ForFile && delta == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Recursive)
|
||||
{
|
||||
finish = delta;
|
||||
if (isFile && !ForFile)
|
||||
finish = delta - 1;
|
||||
}
|
||||
|
||||
for (int d = start; d <= finish; d++)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < PathParts.Size(); i++)
|
||||
{
|
||||
if (WildcardMatching)
|
||||
{
|
||||
if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d]))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == PathParts.Size())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCensorNode::AreAllAllowed() const
|
||||
{
|
||||
if (!Name.IsEmpty() ||
|
||||
!SubNodes.IsEmpty() ||
|
||||
!ExcludeItems.IsEmpty() ||
|
||||
IncludeItems.Size() != 1)
|
||||
return false;
|
||||
return IncludeItems.Front().AreAllAllowed();
|
||||
}
|
||||
|
||||
int CCensorNode::FindSubNode(const UString &name) const
|
||||
{
|
||||
FOR_VECTOR (i, SubNodes)
|
||||
if (CompareFileNames(SubNodes[i].Name, name) == 0)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CCensorNode::AddItemSimple(bool include, CItem &item)
|
||||
{
|
||||
CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)
|
||||
{
|
||||
if (item.PathParts.Size() <= 1)
|
||||
{
|
||||
if (item.PathParts.Size() != 0 && item.WildcardMatching)
|
||||
{
|
||||
if (!DoesNameContainWildcard(item.PathParts.Front()))
|
||||
item.WildcardMatching = false;
|
||||
}
|
||||
AddItemSimple(include, item);
|
||||
return;
|
||||
}
|
||||
|
||||
const UString &front = item.PathParts.Front();
|
||||
|
||||
// WIN32 doesn't support wildcards in file names
|
||||
if (item.WildcardMatching
|
||||
&& ignoreWildcardIndex != 0
|
||||
&& DoesNameContainWildcard(front))
|
||||
{
|
||||
AddItemSimple(include, item);
|
||||
return;
|
||||
}
|
||||
CCensorNode &subNode = Find_SubNode_Or_Add_New(front);
|
||||
item.PathParts.Delete(0);
|
||||
subNode.AddItem(include, item, ignoreWildcardIndex - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
void CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props)
|
||||
{
|
||||
CItem item;
|
||||
SplitPathToParts(path, item.PathParts);
|
||||
item.Recursive = props.Recursive;
|
||||
item.ForFile = props.ForFile;
|
||||
item.ForDir = props.ForDir;
|
||||
item.WildcardMatching = props.WildcardMatching;
|
||||
AddItem(include, item);
|
||||
}
|
||||
*/
|
||||
|
||||
bool CCensorNode::NeedCheckSubDirs() const
|
||||
{
|
||||
FOR_VECTOR (i, IncludeItems)
|
||||
{
|
||||
const CItem &item = IncludeItems[i];
|
||||
if (item.Recursive || item.PathParts.Size() > 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCensorNode::AreThereIncludeItems() const
|
||||
{
|
||||
if (IncludeItems.Size() > 0)
|
||||
return true;
|
||||
FOR_VECTOR (i, SubNodes)
|
||||
if (SubNodes[i].AreThereIncludeItems())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const
|
||||
{
|
||||
const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
|
||||
FOR_VECTOR (i, items)
|
||||
if (items[i].CheckPath(pathParts, isFile))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const
|
||||
{
|
||||
if (CheckPathCurrent(false, pathParts, isFile))
|
||||
{
|
||||
include = false;
|
||||
return true;
|
||||
}
|
||||
if (pathParts.Size() > 1)
|
||||
{
|
||||
int index = FindSubNode(pathParts.Front());
|
||||
if (index >= 0)
|
||||
{
|
||||
UStringVector pathParts2 = pathParts;
|
||||
pathParts2.Delete(0);
|
||||
if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool finded = CheckPathCurrent(true, pathParts, isFile);
|
||||
include = finded; // if (!finded), then (true) is allowed also
|
||||
return finded;
|
||||
}
|
||||
|
||||
/*
|
||||
bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const
|
||||
{
|
||||
UStringVector pathParts;
|
||||
SplitPathToParts(path, pathParts);
|
||||
if (CheckPathVect(pathParts, isFile, include))
|
||||
{
|
||||
if (!include || !isAltStream)
|
||||
return true;
|
||||
}
|
||||
if (isAltStream && !pathParts.IsEmpty())
|
||||
{
|
||||
UString &back = pathParts.Back();
|
||||
int pos = back.Find(L':');
|
||||
if (pos > 0)
|
||||
{
|
||||
back.DeleteFrom(pos);
|
||||
return CheckPathVect(pathParts, isFile, include);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const
|
||||
{
|
||||
bool include;
|
||||
if (CheckPath2(isAltStream, path, isFile, include))
|
||||
return include;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const
|
||||
{
|
||||
if (CheckPathCurrent(include, pathParts, isFile))
|
||||
return true;
|
||||
if (!Parent)
|
||||
return false;
|
||||
pathParts.Insert(0, Name);
|
||||
return Parent->CheckPathToRoot_Change(include, pathParts, isFile);
|
||||
}
|
||||
|
||||
bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const
|
||||
{
|
||||
if (CheckPathCurrent(include, pathParts, isFile))
|
||||
return true;
|
||||
if (!Parent)
|
||||
return false;
|
||||
UStringVector pathParts2;
|
||||
pathParts2.Add(Name);
|
||||
pathParts2 += pathParts;
|
||||
return Parent->CheckPathToRoot_Change(include, pathParts2, isFile);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const
|
||||
{
|
||||
UStringVector pathParts;
|
||||
SplitPathToParts(path, pathParts);
|
||||
return CheckPathToRoot(include, pathParts, isFile);
|
||||
}
|
||||
*/
|
||||
|
||||
void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)
|
||||
{
|
||||
ExcludeItems += fromNodes.ExcludeItems;
|
||||
FOR_VECTOR (i, fromNodes.SubNodes)
|
||||
{
|
||||
const CCensorNode &node = fromNodes.SubNodes[i];
|
||||
Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node);
|
||||
}
|
||||
}
|
||||
|
||||
int CCensor::FindPairForPrefix(const UString &prefix) const
|
||||
{
|
||||
FOR_VECTOR (i, Pairs)
|
||||
if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool IsDriveColonName(const wchar_t *s)
|
||||
{
|
||||
unsigned c = s[0];
|
||||
c |= 0x20;
|
||||
c -= 'a';
|
||||
return c <= (unsigned)('z' - 'a') && s[1] == ':' && s[2] == 0;
|
||||
}
|
||||
|
||||
unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)
|
||||
{
|
||||
if (pathParts.IsEmpty())
|
||||
return 0;
|
||||
|
||||
unsigned testIndex = 0;
|
||||
if (pathParts[0].IsEmpty())
|
||||
{
|
||||
if (pathParts.Size() < 4
|
||||
|| !pathParts[1].IsEmpty()
|
||||
|| !pathParts[2].IsEqualTo("?"))
|
||||
return 0;
|
||||
testIndex = 3;
|
||||
}
|
||||
if (NWildcard::IsDriveColonName(pathParts[testIndex]))
|
||||
return testIndex + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static unsigned GetNumPrefixParts(const UStringVector &pathParts)
|
||||
{
|
||||
if (pathParts.IsEmpty())
|
||||
return 0;
|
||||
|
||||
/* empty last part could be removed already from (pathParts),
|
||||
if there was tail path separator (slash) in original full path string. */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
if (IsDriveColonName(pathParts[0]))
|
||||
return 1;
|
||||
if (!pathParts[0].IsEmpty())
|
||||
return 0;
|
||||
|
||||
if (pathParts.Size() == 1)
|
||||
return 1;
|
||||
if (!pathParts[1].IsEmpty())
|
||||
return 1;
|
||||
if (pathParts.Size() == 2)
|
||||
return 2;
|
||||
if (pathParts[2].IsEqualTo("."))
|
||||
return 3;
|
||||
|
||||
unsigned networkParts = 2;
|
||||
if (pathParts[2].IsEqualTo("?"))
|
||||
{
|
||||
if (pathParts.Size() == 3)
|
||||
return 3;
|
||||
if (IsDriveColonName(pathParts[3]))
|
||||
return 4;
|
||||
if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))
|
||||
return 3;
|
||||
networkParts = 4;
|
||||
}
|
||||
|
||||
networkParts +=
|
||||
// 2; // server/share
|
||||
1; // server
|
||||
if (pathParts.Size() <= networkParts)
|
||||
return pathParts.Size();
|
||||
return networkParts;
|
||||
|
||||
#else
|
||||
|
||||
return pathParts[0].IsEmpty() ? 1 : 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path,
|
||||
const CCensorPathProps &props)
|
||||
{
|
||||
if (path.IsEmpty())
|
||||
throw "Empty file path";
|
||||
|
||||
UStringVector pathParts;
|
||||
SplitPathToParts(path, pathParts);
|
||||
|
||||
CCensorPathProps props2 = props;
|
||||
|
||||
bool forFile = true;
|
||||
bool forDir = true;
|
||||
const UString &back = pathParts.Back();
|
||||
if (back.IsEmpty())
|
||||
{
|
||||
// we have tail path separator. So it's directory.
|
||||
// we delete tail path separator here even for "\" and "c:\"
|
||||
forFile = false;
|
||||
pathParts.DeleteBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (props.MarkMode == kMark_StrictFile
|
||||
|| (props.MarkMode == kMark_StrictFile_IfWildcard
|
||||
&& DoesNameContainWildcard(back)))
|
||||
forDir = false;
|
||||
}
|
||||
|
||||
|
||||
UString prefix;
|
||||
|
||||
int ignoreWildcardIndex = -1;
|
||||
|
||||
// #ifdef _WIN32
|
||||
// we ignore "?" wildcard in "\\?\" prefix.
|
||||
if (pathParts.Size() >= 3
|
||||
&& pathParts[0].IsEmpty()
|
||||
&& pathParts[1].IsEmpty()
|
||||
&& pathParts[2].IsEqualTo("?"))
|
||||
ignoreWildcardIndex = 2;
|
||||
// #endif
|
||||
|
||||
if (pathMode != k_AbsPath)
|
||||
{
|
||||
// detection of the number of Skip Parts for prefix
|
||||
ignoreWildcardIndex = -1;
|
||||
|
||||
const unsigned numPrefixParts = GetNumPrefixParts(pathParts);
|
||||
unsigned numSkipParts = numPrefixParts;
|
||||
|
||||
if (pathMode != k_FullPath)
|
||||
{
|
||||
// if absolute path, then all parts before last part will be in prefix
|
||||
if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)
|
||||
numSkipParts = pathParts.Size() - 1;
|
||||
}
|
||||
{
|
||||
int dotsIndex = -1;
|
||||
for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)
|
||||
{
|
||||
const UString &part = pathParts[i];
|
||||
if (part.IsEqualTo("..") || part.IsEqualTo("."))
|
||||
dotsIndex = (int)i;
|
||||
}
|
||||
|
||||
if (dotsIndex >= 0)
|
||||
{
|
||||
if (dotsIndex == (int)pathParts.Size() - 1)
|
||||
numSkipParts = pathParts.Size();
|
||||
else
|
||||
numSkipParts = pathParts.Size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// we split (pathParts) to (prefix) and (pathParts).
|
||||
for (unsigned i = 0; i < numSkipParts; i++)
|
||||
{
|
||||
{
|
||||
const UString &front = pathParts.Front();
|
||||
// WIN32 doesn't support wildcards in file names
|
||||
if (props.WildcardMatching)
|
||||
if (i >= numPrefixParts && DoesNameContainWildcard(front))
|
||||
break;
|
||||
prefix += front;
|
||||
prefix.Add_PathSepar();
|
||||
}
|
||||
pathParts.Delete(0);
|
||||
}
|
||||
}
|
||||
|
||||
int index = FindPairForPrefix(prefix);
|
||||
if (index < 0)
|
||||
{
|
||||
index = (int)Pairs.Size();
|
||||
Pairs.AddNew().Prefix = prefix;
|
||||
}
|
||||
|
||||
if (pathMode != k_AbsPath)
|
||||
{
|
||||
if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty()))
|
||||
{
|
||||
// we create universal item, if we skip all parts as prefix (like \ or L:\ )
|
||||
pathParts.Clear();
|
||||
pathParts.Add(UString("*"));
|
||||
forFile = true;
|
||||
forDir = true;
|
||||
props2.WildcardMatching = true;
|
||||
props2.Recursive = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// not possible now
|
||||
if (!forDir && !forFile)
|
||||
{
|
||||
UString s ("file path was blocked for files and directories: ");
|
||||
s += path;
|
||||
throw s;
|
||||
// return; // for debug : ignore item (don't create Item)
|
||||
}
|
||||
*/
|
||||
|
||||
CItem item;
|
||||
item.PathParts = pathParts;
|
||||
item.ForDir = forDir;
|
||||
item.ForFile = forFile;
|
||||
item.Recursive = props2.Recursive;
|
||||
item.WildcardMatching = props2.WildcardMatching;
|
||||
Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const
|
||||
{
|
||||
bool finded = false;
|
||||
FOR_VECTOR (i, Pairs)
|
||||
{
|
||||
bool include;
|
||||
if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))
|
||||
{
|
||||
if (!include)
|
||||
return false;
|
||||
finded = true;
|
||||
}
|
||||
}
|
||||
return finded;
|
||||
}
|
||||
*/
|
||||
|
||||
void CCensor::ExtendExclude()
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < Pairs.Size(); i++)
|
||||
if (Pairs[i].Prefix.IsEmpty())
|
||||
break;
|
||||
if (i == Pairs.Size())
|
||||
return;
|
||||
unsigned index = i;
|
||||
for (i = 0; i < Pairs.Size(); i++)
|
||||
if (index != i)
|
||||
Pairs[i].Head.ExtendExclude(Pairs[index].Head);
|
||||
}
|
||||
|
||||
void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)
|
||||
{
|
||||
FOR_VECTOR(i, CensorPaths)
|
||||
{
|
||||
const CCensorPath &cp = CensorPaths[i];
|
||||
AddItem(censorPathMode, cp.Include, cp.Path, cp.Props);
|
||||
}
|
||||
CensorPaths.Clear();
|
||||
}
|
||||
|
||||
void CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props)
|
||||
{
|
||||
CCensorPath &cp = CensorPaths.AddNew();
|
||||
cp.Path = path;
|
||||
cp.Include = include;
|
||||
cp.Props = props;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
// Common/Wildcard.h
|
||||
|
||||
#ifndef ZIP7_INC_COMMON_WILDCARD_H
|
||||
#define ZIP7_INC_COMMON_WILDCARD_H
|
||||
|
||||
#include "MyString.h"
|
||||
|
||||
int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;
|
||||
#ifndef USE_UNICODE_FSTRING
|
||||
int CompareFileNames(const char *s1, const char *s2);
|
||||
#endif
|
||||
|
||||
bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);
|
||||
|
||||
void SplitPathToParts(const UString &path, UStringVector &pathParts);
|
||||
void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);
|
||||
void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)
|
||||
|
||||
UString ExtractDirPrefixFromPath(const UString &path);
|
||||
UString ExtractFileNameFromPath(const UString &path);
|
||||
|
||||
bool DoesNameContainWildcard(const UString &path);
|
||||
bool DoesWildcardMatchName(const UString &mask, const UString &name);
|
||||
|
||||
namespace NWildcard {
|
||||
|
||||
#ifdef _WIN32
|
||||
// returns true, if name is like "a:", "c:", ...
|
||||
bool IsDriveColonName(const wchar_t *s);
|
||||
unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);
|
||||
#endif
|
||||
|
||||
struct CItem
|
||||
{
|
||||
UStringVector PathParts;
|
||||
bool Recursive;
|
||||
bool ForFile;
|
||||
bool ForDir;
|
||||
bool WildcardMatching;
|
||||
|
||||
#ifdef _WIN32
|
||||
bool IsDriveItem() const
|
||||
{
|
||||
return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// CItem(): WildcardMatching(true) {}
|
||||
|
||||
bool AreAllAllowed() const;
|
||||
bool CheckPath(const UStringVector &pathParts, bool isFile) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const Byte kMark_FileOrDir = 0;
|
||||
const Byte kMark_StrictFile = 1;
|
||||
const Byte kMark_StrictFile_IfWildcard = 2;
|
||||
|
||||
struct CCensorPathProps
|
||||
{
|
||||
bool Recursive;
|
||||
bool WildcardMatching;
|
||||
Byte MarkMode;
|
||||
|
||||
CCensorPathProps():
|
||||
Recursive(false),
|
||||
WildcardMatching(true),
|
||||
MarkMode(kMark_FileOrDir)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
class CCensorNode MY_UNCOPYABLE
|
||||
{
|
||||
CCensorNode *Parent;
|
||||
|
||||
bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
|
||||
void AddItemSimple(bool include, CItem &item);
|
||||
public:
|
||||
// bool ExcludeDirItems;
|
||||
|
||||
CCensorNode():
|
||||
Parent(NULL)
|
||||
// , ExcludeDirItems(false)
|
||||
{}
|
||||
|
||||
CCensorNode(const UString &name, CCensorNode *parent):
|
||||
Parent(parent)
|
||||
// , ExcludeDirItems(false)
|
||||
, Name(name)
|
||||
{}
|
||||
|
||||
UString Name; // WIN32 doesn't support wildcards in file names
|
||||
CObjectVector<CCensorNode> SubNodes;
|
||||
CObjectVector<CItem> IncludeItems;
|
||||
CObjectVector<CItem> ExcludeItems;
|
||||
|
||||
CCensorNode &Find_SubNode_Or_Add_New(const UString &name)
|
||||
{
|
||||
int i = FindSubNode(name);
|
||||
if (i >= 0)
|
||||
return SubNodes[(unsigned)i];
|
||||
// return SubNodes.Add(CCensorNode(name, this));
|
||||
CCensorNode &node = SubNodes.AddNew();
|
||||
node.Parent = this;
|
||||
node.Name = name;
|
||||
return node;
|
||||
}
|
||||
|
||||
bool AreAllAllowed() const;
|
||||
|
||||
int FindSubNode(const UString &path) const;
|
||||
|
||||
void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);
|
||||
// void AddItem(bool include, const UString &path, const CCensorPathProps &props);
|
||||
void Add_Wildcard()
|
||||
{
|
||||
CItem item;
|
||||
item.PathParts.Add(L"*");
|
||||
item.Recursive = false;
|
||||
item.ForFile = true;
|
||||
item.ForDir = true;
|
||||
item.WildcardMatching = true;
|
||||
AddItem(
|
||||
true // include
|
||||
, item);
|
||||
}
|
||||
|
||||
// NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs
|
||||
bool NeedCheckSubDirs() const;
|
||||
bool AreThereIncludeItems() const;
|
||||
|
||||
/*
|
||||
CheckPathVect() doesn't check path in Parent CCensorNode
|
||||
so use CheckPathVect() for root CCensorNode
|
||||
OUT:
|
||||
returns (true) && (include = false) - file in exlude list
|
||||
returns (true) && (include = true) - file in include list and is not in exlude list
|
||||
returns (false) - file is not in (include/exlude) list
|
||||
*/
|
||||
bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;
|
||||
|
||||
// bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;
|
||||
// bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
|
||||
|
||||
// CheckPathToRoot_Change() changes pathParts !!!
|
||||
bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const;
|
||||
bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const;
|
||||
|
||||
// bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;
|
||||
void ExtendExclude(const CCensorNode &fromNodes);
|
||||
};
|
||||
|
||||
|
||||
struct CPair MY_UNCOPYABLE
|
||||
{
|
||||
UString Prefix;
|
||||
CCensorNode Head;
|
||||
|
||||
// CPair(const UString &prefix): Prefix(prefix) { };
|
||||
};
|
||||
|
||||
|
||||
enum ECensorPathMode
|
||||
{
|
||||
k_RelatPath, // absolute prefix as Prefix, remain path in Tree
|
||||
k_FullPath, // drive prefix as Prefix, remain path in Tree
|
||||
k_AbsPath // full path in Tree
|
||||
};
|
||||
|
||||
|
||||
struct CCensorPath
|
||||
{
|
||||
UString Path;
|
||||
bool Include;
|
||||
CCensorPathProps Props;
|
||||
|
||||
CCensorPath():
|
||||
Include(true)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
class CCensor MY_UNCOPYABLE
|
||||
{
|
||||
int FindPairForPrefix(const UString &prefix) const;
|
||||
public:
|
||||
CObjectVector<CPair> Pairs;
|
||||
|
||||
bool ExcludeDirItems;
|
||||
bool ExcludeFileItems;
|
||||
|
||||
CCensor():
|
||||
ExcludeDirItems(false),
|
||||
ExcludeFileItems(false)
|
||||
{}
|
||||
|
||||
CObjectVector<NWildcard::CCensorPath> CensorPaths;
|
||||
|
||||
bool AllAreRelative() const
|
||||
{ return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }
|
||||
|
||||
void AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props);
|
||||
// bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
|
||||
void ExtendExclude();
|
||||
|
||||
void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);
|
||||
void AddPreItem(bool include, const UString &path, const CCensorPathProps &props);
|
||||
|
||||
void AddPreItem_NoWildcard(const UString &path)
|
||||
{
|
||||
CCensorPathProps props;
|
||||
props.WildcardMatching = false;
|
||||
AddPreItem(
|
||||
true, // include
|
||||
path, props);
|
||||
}
|
||||
void AddPreItem_Wildcard()
|
||||
{
|
||||
CCensorPathProps props;
|
||||
// props.WildcardMatching = true;
|
||||
AddPreItem(
|
||||
true, // include
|
||||
UString("*"), props);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
// Xxh64Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/Xxh64.h"
|
||||
#include "../../C/CpuArch.h"
|
||||
|
||||
// #define Z7_USE_HHX64_ORIGINAL
|
||||
#ifdef Z7_USE_HHX64_ORIGINAL
|
||||
#ifdef __clang__
|
||||
#include "../../C/zstd7z/7z_zstd_cmpl.h"
|
||||
#pragma GCC diagnostic ignored "-Wlanguage-extension-token"
|
||||
#endif
|
||||
#define XXH_STATIC_LINKING_ONLY
|
||||
#include "../../C/zstd7z/common/xxhash.h"
|
||||
#endif
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CXxh64Hasher
|
||||
, IHasher
|
||||
)
|
||||
CXxh64 _state;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
|
||||
CXxh64Hasher() { Init(); }
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Init())
|
||||
{
|
||||
Xxh64_Init(&_state);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
#if 1
|
||||
Xxh64_Update(&_state, data, size);
|
||||
#else // for debug:
|
||||
for (;;)
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
UInt32 size2 = (size * 0x85EBCA87) % size / 8;
|
||||
if (size2 == 0)
|
||||
size2 = 1;
|
||||
Xxh64_Update(&_state, data, size2);
|
||||
data = (const void *)((const Byte *)data + size2);
|
||||
size -= size2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Final(Byte *digest))
|
||||
{
|
||||
const UInt64 val = Xxh64_Digest(&_state);
|
||||
SetUi64(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CXxh64Hasher, 0x211, "XXH64", 8)
|
||||
|
||||
|
||||
|
||||
#ifdef Z7_USE_HHX64_ORIGINAL
|
||||
namespace NOriginal
|
||||
{
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CXxh64Hasher
|
||||
, IHasher
|
||||
)
|
||||
XXH64_state_t _state;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
|
||||
CXxh64Hasher() { Init(); }
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Init())
|
||||
{
|
||||
XXH64_reset(&_state, 0);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
XXH64_update(&_state, data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXxh64Hasher::Final(Byte *digest))
|
||||
{
|
||||
const UInt64 val = XXH64_digest(&_state);
|
||||
SetUi64(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CXxh64Hasher, 0x212, "XXH64a", 8)
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
// XzCrc64Init.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/XzCrc64.h"
|
||||
|
||||
static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
|
||||
@@ -0,0 +1,39 @@
|
||||
// XzCrc64Reg.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../C/CpuArch.h"
|
||||
#include "../../C/XzCrc64.h"
|
||||
|
||||
#include "../Common/MyCom.h"
|
||||
|
||||
#include "../7zip/Common/RegisterCodec.h"
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CXzCrc64Hasher
|
||||
, IHasher
|
||||
)
|
||||
UInt64 _crc;
|
||||
public:
|
||||
Byte _mtDummy[1 << 7]; // it's public to eliminate clang warning: unused private field
|
||||
|
||||
CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}
|
||||
};
|
||||
|
||||
Z7_COM7F_IMF2(void, CXzCrc64Hasher::Init())
|
||||
{
|
||||
_crc = CRC64_INIT_VAL;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXzCrc64Hasher::Update(const void *data, UInt32 size))
|
||||
{
|
||||
_crc = Crc64Update(_crc, data, size);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF2(void, CXzCrc64Hasher::Final(Byte *digest))
|
||||
{
|
||||
const UInt64 val = CRC64_GET_DIGEST(_crc);
|
||||
SetUi64(digest, val)
|
||||
}
|
||||
|
||||
REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)
|
||||
Reference in New Issue
Block a user