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:
Simone
2026-04-29 14:07:51 +02:00
commit d074cc7c07
3848 changed files with 1076682 additions and 0 deletions
+46
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
// Common/CRC.cpp
#include "StdAfx.h"
#include "../../C/7zCrc.h"
static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;
+3
View File
@@ -0,0 +1,3 @@
// Common/C_FileIO.cpp
#include "StdAfx.h"
+6
View File
@@ -0,0 +1,6 @@
// Common/C_FileIO.h
#ifndef ZIP7_INC_COMMON_C_FILEIO_H
#define ZIP7_INC_COMMON_C_FILEIO_H
#endif
+55
View File
@@ -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)
+21
View File
@@ -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
+28
View File
@@ -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
+330
View File
@@ -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"
+77
View File
@@ -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)
+16
View File
@@ -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
+93
View File
@@ -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;
}
+41
View File
@@ -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
+76
View File
@@ -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
+215
View File
@@ -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;
}
+54
View File
@@ -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
+173
View File
@@ -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];
}
+30
View File
@@ -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
+150
View File
@@ -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;
}
+18
View File
@@ -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;
+44
View File
@@ -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)
+297
View File
@@ -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
+185
View File
@@ -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
+693
View File
@@ -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
+14
View File
@@ -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
+63
View File
@@ -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
+57
View File
@@ -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
+75
View File
@@ -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
+140
View File
@@ -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];
}
}
+28
View File
@@ -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
+38
View File
@@ -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
+8
View File
@@ -0,0 +1,8 @@
// MyUnknown.h
#ifndef ZIP7_INC_MY_UNKNOWN_H
#define ZIP7_INC_MY_UNKNOWN_H
#include "MyWindows.h"
#endif
+3
View File
@@ -0,0 +1,3 @@
// Common/MyVector.cpp
#include "StdAfx.h"
+724
View File
@@ -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
+292
View File
@@ -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
+325
View File
@@ -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
+349
View File
@@ -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));
}
+45
View File
@@ -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
+340
View File
@@ -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);
}
*/
+121
View File
@@ -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
+28
View File
@@ -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(); }
+14
View File
@@ -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;
+67
View File
@@ -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;
+67
View File
@@ -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)
+76
View File
@@ -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;
+83
View File
@@ -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)
+8
View File
@@ -0,0 +1,8 @@
// StdAfx.h
#ifndef ZIP7_INC_STDAFX_H
#define ZIP7_INC_STDAFX_H
#include "Common.h"
#endif
+98
View File
@@ -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?
}
+46
View File
@@ -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
+248
View File
@@ -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);
}
+87
View File
@@ -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
+762
View File
@@ -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
+110
View File
@@ -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
+154
View File
@@ -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));
}
}
+38
View File
@@ -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
+123
View File
@@ -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;
}
+19
View File
@@ -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
+863
View File
@@ -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
+384
View File
@@ -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
+789
View File
@@ -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;
}
}
+231
View File
@@ -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
+97
View File
@@ -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;
+39
View File
@@ -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)