aboutsummaryrefslogtreecommitdiff
path: root/CPP/Common
diff options
context:
space:
mode:
authorIgor Pavlov <87184205+ip7z@users.noreply.github.com>2021-12-27 00:00:00 +0000
committerIgor Pavlov <87184205+ip7z@users.noreply.github.com>2022-03-18 15:35:13 +0500
commitf19f813537c7aea1c20749c914e756b54a9c3cf5 (patch)
tree816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /CPP/Common
parent98e06a519b63b81986abe76d28887f6984a7732b (diff)
download7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.gz
7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.tar.bz2
7zip-f19f813537c7aea1c20749c914e756b54a9c3cf5.zip
'21.07'21.07
Diffstat (limited to 'CPP/Common')
-rw-r--r--CPP/Common/AutoPtr.h35
-rw-r--r--CPP/Common/CRC.cpp7
-rw-r--r--CPP/Common/C_FileIO.cpp3
-rw-r--r--CPP/Common/C_FileIO.h6
-rw-r--r--CPP/Common/CksumReg.cpp60
-rw-r--r--CPP/Common/ComTry.h21
-rw-r--r--CPP/Common/CommandLineParser.cpp197
-rw-r--r--CPP/Common/CommandLineParser.h63
-rw-r--r--CPP/Common/Common.h57
-rw-r--r--CPP/Common/CrcReg.cpp95
-rw-r--r--CPP/Common/Defs.h16
-rw-r--r--CPP/Common/DynLimBuf.cpp93
-rw-r--r--CPP/Common/DynLimBuf.h41
-rw-r--r--CPP/Common/DynamicBuffer.h64
-rw-r--r--CPP/Common/IntToString.cpp192
-rw-r--r--CPP/Common/IntToString.h30
-rw-r--r--CPP/Common/Lang.cpp163
-rw-r--r--CPP/Common/Lang.h23
-rw-r--r--CPP/Common/ListFileUtils.cpp150
-rw-r--r--CPP/Common/ListFileUtils.h18
-rw-r--r--CPP/Common/LzFindPrepare.cpp7
-rw-r--r--CPP/Common/MyBuffer.h277
-rw-r--r--CPP/Common/MyBuffer2.h139
-rw-r--r--CPP/Common/MyCom.h306
-rw-r--r--CPP/Common/MyException.h14
-rw-r--r--CPP/Common/MyGuidDef.h57
-rw-r--r--CPP/Common/MyInitGuid.h49
-rw-r--r--CPP/Common/MyLinux.h42
-rw-r--r--CPP/Common/MyMap.cpp140
-rw-r--r--CPP/Common/MyMap.h28
-rw-r--r--CPP/Common/MyString.cpp1756
-rw-r--r--CPP/Common/MyString.h1012
-rw-r--r--CPP/Common/MyTypes.h52
-rw-r--r--CPP/Common/MyUnknown.h17
-rw-r--r--CPP/Common/MyVector.cpp3
-rw-r--r--CPP/Common/MyVector.h634
-rw-r--r--CPP/Common/MyWindows.cpp292
-rw-r--r--CPP/Common/MyWindows.h268
-rw-r--r--CPP/Common/MyXml.cpp260
-rw-r--r--CPP/Common/MyXml.h43
-rw-r--r--CPP/Common/NewHandler.cpp163
-rw-r--r--CPP/Common/NewHandler.h88
-rw-r--r--CPP/Common/Random.cpp28
-rw-r--r--CPP/Common/Random.h14
-rw-r--r--CPP/Common/Sha1Prepare.cpp7
-rw-r--r--CPP/Common/Sha1Reg.cpp70
-rw-r--r--CPP/Common/Sha256Prepare.cpp7
-rw-r--r--CPP/Common/Sha256Reg.cpp70
-rw-r--r--CPP/Common/StdAfx.h8
-rw-r--r--CPP/Common/StdInStream.cpp95
-rw-r--r--CPP/Common/StdInStream.h44
-rw-r--r--CPP/Common/StdOutStream.cpp158
-rw-r--r--CPP/Common/StdOutStream.h76
-rw-r--r--CPP/Common/StringConvert.cpp757
-rw-r--r--CPP/Common/StringConvert.h110
-rw-r--r--CPP/Common/StringToInt.cpp144
-rw-r--r--CPP/Common/StringToInt.h21
-rw-r--r--CPP/Common/TextConfig.cpp124
-rw-r--r--CPP/Common/TextConfig.h19
-rw-r--r--CPP/Common/UTFConvert.cpp863
-rw-r--r--CPP/Common/UTFConvert.h384
-rw-r--r--CPP/Common/Wildcard.cpp790
-rw-r--r--CPP/Common/Wildcard.h231
-rw-r--r--CPP/Common/XzCrc64Init.cpp7
-rw-r--r--CPP/Common/XzCrc64Reg.cpp42
65 files changed, 11050 insertions, 0 deletions
diff --git a/CPP/Common/AutoPtr.h b/CPP/Common/AutoPtr.h
new file mode 100644
index 0000000..006d315
--- /dev/null
+++ b/CPP/Common/AutoPtr.h
@@ -0,0 +1,35 @@
1// Common/AutoPtr.h
2
3#ifndef __COMMON_AUTOPTR_H
4#define __COMMON_AUTOPTR_H
5
6template<class T> class CMyAutoPtr
7{
8 T *_p;
9public:
10 CMyAutoPtr(T *p = 0) : _p(p) {}
11 CMyAutoPtr(CMyAutoPtr<T>& p): _p(p.release()) {}
12 CMyAutoPtr<T>& operator=(CMyAutoPtr<T>& p)
13 {
14 reset(p.release());
15 return (*this);
16 }
17 ~CMyAutoPtr() { delete _p; }
18 T& operator*() const { return *_p; }
19 // T* operator->() const { return (&**this); }
20 T* get() const { return _p; }
21 T* release()
22 {
23 T *tmp = _p;
24 _p = 0;
25 return tmp;
26 }
27 void reset(T* p = 0)
28 {
29 if (p != _p)
30 delete _p;
31 _p = p;
32 }
33};
34
35#endif
diff --git a/CPP/Common/CRC.cpp b/CPP/Common/CRC.cpp
new file mode 100644
index 0000000..c6b7d5e
--- /dev/null
+++ b/CPP/Common/CRC.cpp
@@ -0,0 +1,7 @@
1// Common/CRC.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/7zCrc.h"
6
7static struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;
diff --git a/CPP/Common/C_FileIO.cpp b/CPP/Common/C_FileIO.cpp
new file mode 100644
index 0000000..4bd3fad
--- /dev/null
+++ b/CPP/Common/C_FileIO.cpp
@@ -0,0 +1,3 @@
1// Common/C_FileIO.cpp
2
3#include "StdAfx.h"
diff --git a/CPP/Common/C_FileIO.h b/CPP/Common/C_FileIO.h
new file mode 100644
index 0000000..6818558
--- /dev/null
+++ b/CPP/Common/C_FileIO.h
@@ -0,0 +1,6 @@
1// Common/C_FileIO.h
2
3#ifndef __COMMON_C_FILEIO_H
4#define __COMMON_C_FILEIO_H
5
6#endif
diff --git a/CPP/Common/CksumReg.cpp b/CPP/Common/CksumReg.cpp
new file mode 100644
index 0000000..29d9f82
--- /dev/null
+++ b/CPP/Common/CksumReg.cpp
@@ -0,0 +1,60 @@
1// CksumReg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "../Common/MyCom.h"
8
9#include "../7zip/Common/RegisterCodec.h"
10
11#include "../7zip/Compress/BZip2Crc.h"
12
13class CCksumHasher:
14 public IHasher,
15 public CMyUnknownImp
16{
17 CBZip2Crc _crc;
18 UInt64 _size;
19 Byte mtDummy[1 << 7];
20
21public:
22 CCksumHasher()
23 {
24 _crc.Init(0);
25 _size = 0;
26 }
27
28 MY_UNKNOWN_IMP1(IHasher)
29 INTERFACE_IHasher(;)
30};
31
32STDMETHODIMP_(void) CCksumHasher::Init() throw()
33{
34 _crc.Init(0);
35 _size = 0;
36}
37
38STDMETHODIMP_(void) CCksumHasher::Update(const void *data, UInt32 size) throw()
39{
40 _size += size;
41 CBZip2Crc crc = _crc;
42 for (UInt32 i = 0; i < size; i++)
43 crc.UpdateByte(((const Byte *)data)[i]);
44 _crc = crc;
45}
46
47STDMETHODIMP_(void) CCksumHasher::Final(Byte *digest) throw()
48{
49 UInt64 size = _size;
50 CBZip2Crc crc = _crc;
51 while (size)
52 {
53 crc.UpdateByte((Byte)size);
54 size >>= 8;
55 }
56 const UInt32 val = crc.GetDigest();
57 SetUi32(digest, val);
58}
59
60REGISTER_HASHER(CCksumHasher, 0x203, "CKSUM", 4)
diff --git a/CPP/Common/ComTry.h b/CPP/Common/ComTry.h
new file mode 100644
index 0000000..297c407
--- /dev/null
+++ b/CPP/Common/ComTry.h
@@ -0,0 +1,21 @@
1// ComTry.h
2
3#ifndef __COM_TRY_H
4#define __COM_TRY_H
5
6#include "MyWindows.h"
7// #include "Exception.h"
8// #include "NewHandler.h"
9
10#define COM_TRY_BEGIN try {
11#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }
12
13/*
14#define COM_TRY_END } \
15 catch(const CNewException &) { return E_OUTOFMEMORY; } \
16 catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \
17*/
18 // catch(const CSystemException &e) { return e.ErrorCode; }
19 // catch(...) { return E_FAIL; }
20
21#endif
diff --git a/CPP/Common/CommandLineParser.cpp b/CPP/Common/CommandLineParser.cpp
new file mode 100644
index 0000000..465e0fd
--- /dev/null
+++ b/CPP/Common/CommandLineParser.cpp
@@ -0,0 +1,197 @@
1// CommandLineParser.cpp
2
3#include "StdAfx.h"
4
5#include "CommandLineParser.h"
6
7namespace NCommandLineParser {
8
9bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
10{
11 dest1.Empty();
12 dest2.Empty();
13 bool quoteMode = false;
14 unsigned i;
15 for (i = 0; i < src.Len(); i++)
16 {
17 wchar_t c = src[i];
18 if ((c == L' ' || c == L'\t') && !quoteMode)
19 {
20 dest2 = src.Ptr(i + 1);
21 return i != 0;
22 }
23 if (c == L'\"')
24 quoteMode = !quoteMode;
25 else
26 dest1 += c;
27 }
28 return i != 0;
29}
30
31void SplitCommandLine(const UString &s, UStringVector &parts)
32{
33 UString sTemp (s);
34 sTemp.Trim();
35 parts.Clear();
36 for (;;)
37 {
38 UString s1, s2;
39 if (SplitCommandLine(sTemp, s1, s2))
40 parts.Add(s1);
41 if (s2.IsEmpty())
42 break;
43 sTemp = s2;
44 }
45}
46
47
48static const char * const kStopSwitchParsing = "--";
49
50static bool inline IsItSwitchChar(wchar_t c)
51{
52 return (c == '-');
53}
54
55CParser::CParser():
56 _switches(NULL),
57 StopSwitchIndex(-1)
58{
59}
60
61CParser::~CParser()
62{
63 delete []_switches;
64}
65
66
67// if (s) contains switch then function updates switch structures
68// out: true, if (s) is a switch
69bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)
70{
71 if (s.IsEmpty() || !IsItSwitchChar(s[0]))
72 return false;
73
74 unsigned pos = 1;
75 unsigned switchIndex = 0;
76 int maxLen = -1;
77
78 for (unsigned i = 0; i < numSwitches; i++)
79 {
80 const char * const key = switchForms[i].Key;
81 unsigned switchLen = MyStringLen(key);
82 if ((int)switchLen <= maxLen || pos + switchLen > s.Len())
83 continue;
84 if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))
85 {
86 switchIndex = i;
87 maxLen = (int)switchLen;
88 }
89 }
90
91 if (maxLen < 0)
92 {
93 ErrorMessage = "Unknown switch:";
94 return false;
95 }
96
97 pos += (unsigned)maxLen;
98
99 CSwitchResult &sw = _switches[switchIndex];
100 const CSwitchForm &form = switchForms[switchIndex];
101
102 if (!form.Multi && sw.ThereIs)
103 {
104 ErrorMessage = "Multiple instances for switch:";
105 return false;
106 }
107
108 sw.ThereIs = true;
109
110 const unsigned rem = s.Len() - pos;
111 if (rem < form.MinLen)
112 {
113 ErrorMessage = "Too short switch:";
114 return false;
115 }
116
117 sw.WithMinus = false;
118 sw.PostCharIndex = -1;
119
120 switch (form.Type)
121 {
122 case NSwitchType::kMinus:
123 if (rem == 1)
124 {
125 sw.WithMinus = (s[pos] == '-');
126 if (sw.WithMinus)
127 return true;
128 ErrorMessage = "Incorrect switch postfix:";
129 return false;
130 }
131 break;
132
133 case NSwitchType::kChar:
134 if (rem == 1)
135 {
136 wchar_t c = s[pos];
137 if (c <= 0x7F)
138 {
139 sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);
140 if (sw.PostCharIndex >= 0)
141 return true;
142 }
143 ErrorMessage = "Incorrect switch postfix:";
144 return false;
145 }
146 break;
147
148 case NSwitchType::kString:
149 {
150 sw.PostStrings.Add(s.Ptr(pos));
151 return true;
152 }
153 }
154
155 if (pos != s.Len())
156 {
157 ErrorMessage = "Too long switch:";
158 return false;
159 }
160 return true;
161}
162
163
164bool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)
165{
166 StopSwitchIndex = -1;
167 ErrorMessage.Empty();
168 ErrorLine.Empty();
169 NonSwitchStrings.Clear();
170 delete []_switches;
171 _switches = NULL;
172 _switches = new CSwitchResult[numSwitches];
173
174 FOR_VECTOR (i, commandStrings)
175 {
176 const UString &s = commandStrings[i];
177 if (StopSwitchIndex < 0)
178 {
179 if (s.IsEqualTo(kStopSwitchParsing))
180 {
181 StopSwitchIndex = (int)NonSwitchStrings.Size();
182 continue;
183 }
184 if (!s.IsEmpty() && IsItSwitchChar(s[0]))
185 {
186 if (ParseString(s, switchForms, numSwitches))
187 continue;
188 ErrorLine = s;
189 return false;
190 }
191 }
192 NonSwitchStrings.Add(s);
193 }
194 return true;
195}
196
197}
diff --git a/CPP/Common/CommandLineParser.h b/CPP/Common/CommandLineParser.h
new file mode 100644
index 0000000..fbd4fa5
--- /dev/null
+++ b/CPP/Common/CommandLineParser.h
@@ -0,0 +1,63 @@
1// Common/CommandLineParser.h
2
3#ifndef __COMMON_COMMAND_LINE_PARSER_H
4#define __COMMON_COMMAND_LINE_PARSER_H
5
6#include "MyString.h"
7
8namespace NCommandLineParser {
9
10bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);
11void SplitCommandLine(const UString &s, UStringVector &parts);
12
13namespace NSwitchType
14{
15 enum EEnum
16 {
17 kSimple,
18 kMinus,
19 kString,
20 kChar
21 };
22}
23
24struct CSwitchForm
25{
26 const char *Key;
27 Byte Type;
28 bool Multi;
29 Byte MinLen;
30 // int MaxLen;
31 const char *PostCharSet;
32};
33
34struct CSwitchResult
35{
36 bool ThereIs;
37 bool WithMinus;
38 int PostCharIndex;
39 UStringVector PostStrings;
40
41 CSwitchResult(): ThereIs(false) {}
42};
43
44class CParser
45{
46 CSwitchResult *_switches;
47
48 bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches);
49public:
50 UStringVector NonSwitchStrings;
51 int StopSwitchIndex; // NonSwitchStrings[StopSwitchIndex+] are after "--"
52 AString ErrorMessage;
53 UString ErrorLine;
54
55 CParser();
56 ~CParser();
57 bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings);
58 const CSwitchResult& operator[](unsigned index) const { return _switches[index]; }
59};
60
61}
62
63#endif
diff --git a/CPP/Common/Common.h b/CPP/Common/Common.h
new file mode 100644
index 0000000..8dac613
--- /dev/null
+++ b/CPP/Common/Common.h
@@ -0,0 +1,57 @@
1// Common.h
2
3#ifndef __COMMON_COMMON_H
4#define __COMMON_COMMON_H
5
6/*
7This file is included to all cpp files in 7-Zip.
8Each folder contains StdAfx.h file that includes "Common.h".
9So 7-Zip includes "Common.h" in both modes:
10 with precompiled StdAfx.h
11and
12 without precompiled StdAfx.h
13
14If you use 7-Zip code, you must include "Common.h" before other h files of 7-zip.
15If you don't need some things that are used in 7-Zip,
16you can change this h file or h files included in this file.
17*/
18
19// compiler pragmas to disable some warnings
20#include "../../C/Compiler.h"
21
22// it's <windows.h> or code that defines windows things, if it's not _WIN32
23#include "MyWindows.h"
24
25// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers
26#include "NewHandler.h"
27
28
29
30#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
31
32
33/* There is BUG in MSVC 6.0 compiler for operator new[]:
34 It doesn't check overflow, when it calculates size in bytes for allocated array.
35 So we can use MY_ARRAY_NEW macro instead of new[] operator. */
36
37#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)
38 #define MY_ARRAY_NEW(p, T, size) p = new T[(size > (unsigned)0xFFFFFFFF / sizeof(T)) ? (unsigned)0xFFFFFFFF / sizeof(T) : size];
39#else
40 #define MY_ARRAY_NEW(p, T, size) p = new T[size];
41#endif
42
43#if (defined(__GNUC__) && (__GNUC__ >= 8))
44 #define MY_ATTR_NORETURN __attribute__((noreturn))
45#elif (defined(__clang__) && (__clang_major__ >= 3))
46 #if __has_feature(cxx_attributes)
47 #define MY_ATTR_NORETURN [[noreturn]]
48 #else
49 #define MY_ATTR_NORETURN __attribute__ ((noreturn))
50 #endif
51#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
52 #define MY_ATTR_NORETURN [[noreturn]]
53#else
54 #define MY_ATTR_NORETURN
55#endif
56
57#endif
diff --git a/CPP/Common/CrcReg.cpp b/CPP/Common/CrcReg.cpp
new file mode 100644
index 0000000..fdbba77
--- /dev/null
+++ b/CPP/Common/CrcReg.cpp
@@ -0,0 +1,95 @@
1// CrcReg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/7zCrc.h"
6#include "../../C/CpuArch.h"
7
8#include "../Common/MyCom.h"
9
10#include "../7zip/Common/RegisterCodec.h"
11
12EXTERN_C_BEGIN
13
14typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
15
16UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);
17
18extern CRC_FUNC g_CrcUpdate;
19extern CRC_FUNC g_CrcUpdateT4;
20extern CRC_FUNC g_CrcUpdateT8;
21extern CRC_FUNC g_CrcUpdateT0_32;
22extern CRC_FUNC g_CrcUpdateT0_64;
23
24EXTERN_C_END
25
26class CCrcHasher:
27 public IHasher,
28 public ICompressSetCoderProperties,
29 public CMyUnknownImp
30{
31 UInt32 _crc;
32 CRC_FUNC _updateFunc;
33 Byte mtDummy[1 << 7];
34
35 bool SetFunctions(UInt32 tSize);
36public:
37 CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }
38
39 MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties)
40 INTERFACE_IHasher(;)
41 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
42};
43
44bool CCrcHasher::SetFunctions(UInt32 tSize)
45{
46 CRC_FUNC f = NULL;
47 if (tSize == 0) f = g_CrcUpdate;
48 else if (tSize == 1) f = CrcUpdateT1;
49 else if (tSize == 4) f = g_CrcUpdateT4;
50 else if (tSize == 8) f = g_CrcUpdateT8;
51 else if (tSize == 32) f = g_CrcUpdateT0_32;
52 else if (tSize == 64) f = g_CrcUpdateT0_64;
53
54 if (!f)
55 {
56 _updateFunc = g_CrcUpdate;
57 return false;
58 }
59 _updateFunc = f;
60 return true;
61}
62
63STDMETHODIMP CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
64{
65 for (UInt32 i = 0; i < numProps; i++)
66 {
67 const PROPVARIANT &prop = coderProps[i];
68 if (propIDs[i] == NCoderPropID::kDefaultProp)
69 {
70 if (prop.vt != VT_UI4)
71 return E_INVALIDARG;
72 if (!SetFunctions(prop.ulVal))
73 return E_NOTIMPL;
74 }
75 }
76 return S_OK;
77}
78
79STDMETHODIMP_(void) CCrcHasher::Init() throw()
80{
81 _crc = CRC_INIT_VAL;
82}
83
84STDMETHODIMP_(void) CCrcHasher::Update(const void *data, UInt32 size) throw()
85{
86 _crc = _updateFunc(_crc, data, size, g_CrcTable);
87}
88
89STDMETHODIMP_(void) CCrcHasher::Final(Byte *digest) throw()
90{
91 UInt32 val = CRC_GET_DIGEST(_crc);
92 SetUi32(digest, val);
93}
94
95REGISTER_HASHER(CCrcHasher, 0x1, "CRC32", 4)
diff --git a/CPP/Common/Defs.h b/CPP/Common/Defs.h
new file mode 100644
index 0000000..9adb88c
--- /dev/null
+++ b/CPP/Common/Defs.h
@@ -0,0 +1,16 @@
1// Common/Defs.h
2
3#ifndef __COMMON_DEFS_H
4#define __COMMON_DEFS_H
5
6template <class T> inline T MyMin(T a, T b) { return a < b ? a : b; }
7template <class T> inline T MyMax(T a, T b) { return a > b ? a : b; }
8
9template <class T> inline int MyCompare(T a, T b)
10 { return a == b ? 0 : (a < b ? -1 : 1); }
11
12inline int BoolToInt(bool v) { return (v ? 1 : 0); }
13inline unsigned BoolToUInt(bool v) { return (v ? (unsigned)1 : (unsigned)0); }
14inline bool IntToBool(int v) { return (v != 0); }
15
16#endif
diff --git a/CPP/Common/DynLimBuf.cpp b/CPP/Common/DynLimBuf.cpp
new file mode 100644
index 0000000..7914104
--- /dev/null
+++ b/CPP/Common/DynLimBuf.cpp
@@ -0,0 +1,93 @@
1// Common/DynLimBuf.cpp
2
3#include "StdAfx.h"
4
5#include "DynLimBuf.h"
6#include "MyString.h"
7
8CDynLimBuf::CDynLimBuf(size_t limit) throw()
9{
10 _chars = 0;
11 _pos = 0;
12 _size = 0;
13 _sizeLimit = limit;
14 _error = true;
15 unsigned size = 1 << 4;
16 if (size > limit)
17 size = (unsigned)limit;
18 _chars = (Byte *)MyAlloc(size);
19 if (_chars)
20 {
21 _size = size;
22 _error = false;
23 }
24}
25
26CDynLimBuf & CDynLimBuf::operator+=(char c) throw()
27{
28 if (_error)
29 return *this;
30 if (_size == _pos)
31 {
32 size_t n = _sizeLimit - _size;
33 if (n == 0)
34 {
35 _error = true;
36 return *this;
37 }
38 if (n > _size)
39 n = _size;
40
41 n += _pos;
42
43 Byte *newBuf = (Byte *)MyAlloc(n);
44 if (!newBuf)
45 {
46 _error = true;
47 return *this;
48 }
49 memcpy(newBuf, _chars, _pos);
50 MyFree(_chars);
51 _chars = newBuf;
52 _size = n;
53 }
54 _chars[_pos++] = (Byte)c;
55 return *this;
56}
57
58CDynLimBuf &CDynLimBuf::operator+=(const char *s) throw()
59{
60 if (_error)
61 return *this;
62 unsigned len = MyStringLen(s);
63 size_t rem = _sizeLimit - _pos;
64 if (rem < len)
65 {
66 len = (unsigned)rem;
67 _error = true;
68 }
69 if (_size - _pos < len)
70 {
71 size_t n = _pos + len;
72 if (n - _size < _size)
73 {
74 n = _sizeLimit;
75 if (n - _size > _size)
76 n = _size * 2;
77 }
78
79 Byte *newBuf = (Byte *)MyAlloc(n);
80 if (!newBuf)
81 {
82 _error = true;
83 return *this;
84 }
85 memcpy(newBuf, _chars, _pos);
86 MyFree(_chars);
87 _chars = newBuf;
88 _size = n;
89 }
90 memcpy(_chars + _pos, s, len);
91 _pos += len;
92 return *this;
93}
diff --git a/CPP/Common/DynLimBuf.h b/CPP/Common/DynLimBuf.h
new file mode 100644
index 0000000..e80a7e7
--- /dev/null
+++ b/CPP/Common/DynLimBuf.h
@@ -0,0 +1,41 @@
1// Common/DynLimBuf.h
2
3#ifndef __COMMON_DYN_LIM_BUF_H
4#define __COMMON_DYN_LIM_BUF_H
5
6#include <string.h>
7
8#include "../../C/Alloc.h"
9
10#include "MyString.h"
11
12class CDynLimBuf
13{
14 Byte *_chars;
15 size_t _pos;
16 size_t _size;
17 size_t _sizeLimit;
18 bool _error;
19
20 CDynLimBuf(const CDynLimBuf &s);
21
22 // ---------- forbidden functions ----------
23 CDynLimBuf &operator+=(wchar_t c);
24
25public:
26 CDynLimBuf(size_t limit) throw();
27 ~CDynLimBuf() { MyFree(_chars); }
28
29 size_t Len() const { return _pos; }
30 bool IsError() const { return _error; }
31 void Empty() { _pos = 0; _error = false; }
32
33 operator const Byte *() const { return _chars; }
34 // const char *Ptr() const { return _chars; }
35
36 CDynLimBuf &operator+=(char c) throw();
37 CDynLimBuf &operator+=(const char *s) throw();
38};
39
40
41#endif
diff --git a/CPP/Common/DynamicBuffer.h b/CPP/Common/DynamicBuffer.h
new file mode 100644
index 0000000..f6f6b15
--- /dev/null
+++ b/CPP/Common/DynamicBuffer.h
@@ -0,0 +1,64 @@
1// Common/DynamicBuffer.h
2
3#ifndef __COMMON_DYNAMIC_BUFFER_H
4#define __COMMON_DYNAMIC_BUFFER_H
5
6template <class T> class CDynamicBuffer
7{
8 T *_items;
9 size_t _size;
10 size_t _pos;
11
12 CDynamicBuffer(const CDynamicBuffer &buffer);
13 void operator=(const CDynamicBuffer &buffer);
14
15 void Grow(size_t size)
16 {
17 size_t delta = _size >= 64 ? _size : 64;
18 if (delta < size)
19 delta = size;
20 size_t newCap = _size + delta;
21 if (newCap < delta)
22 {
23 newCap = _size + size;
24 if (newCap < size)
25 throw 20120116;
26 }
27
28 T *newBuffer = new T[newCap];
29 if (_pos != 0)
30 memcpy(newBuffer, _items, _pos * sizeof(T));
31 delete []_items;
32 _items = newBuffer;
33 _size = newCap;
34 }
35
36public:
37 CDynamicBuffer(): _items(0), _size(0), _pos(0) {}
38 // operator T *() { return _items; }
39 operator const T *() const { return _items; }
40 ~CDynamicBuffer() { delete []_items; }
41
42 T *GetCurPtrAndGrow(size_t addSize)
43 {
44 size_t rem = _size - _pos;
45 if (rem < addSize)
46 Grow(addSize - rem);
47 T *res = _items + _pos;
48 _pos += addSize;
49 return res;
50 }
51
52 void AddData(const T *data, size_t size)
53 {
54 memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));
55 }
56
57 size_t GetPos() const { return _pos; }
58
59 // void Empty() { _pos = 0; }
60};
61
62typedef CDynamicBuffer<unsigned char> CByteDynamicBuffer;
63
64#endif
diff --git a/CPP/Common/IntToString.cpp b/CPP/Common/IntToString.cpp
new file mode 100644
index 0000000..c87643c
--- /dev/null
+++ b/CPP/Common/IntToString.cpp
@@ -0,0 +1,192 @@
1// Common/IntToString.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "IntToString.h"
8
9#define CONVERT_INT_TO_STR(charType, tempSize) \
10 unsigned char temp[tempSize]; unsigned i = 0; \
11 while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \
12 *s++ = (charType)('0' + (unsigned)val); \
13 while (i != 0) { i--; *s++ = (charType)temp[i]; } \
14 *s = 0; \
15 return s;
16
17char * ConvertUInt32ToString(UInt32 val, char *s) throw()
18{
19 CONVERT_INT_TO_STR(char, 16);
20}
21
22char * ConvertUInt64ToString(UInt64 val, char *s) throw()
23{
24 if (val <= (UInt32)0xFFFFFFFF)
25 {
26 return ConvertUInt32ToString((UInt32)val, s);
27 }
28 CONVERT_INT_TO_STR(char, 24);
29}
30
31void ConvertUInt64ToOct(UInt64 val, char *s) throw()
32{
33 UInt64 v = val;
34 unsigned i;
35 for (i = 1;; i++)
36 {
37 v >>= 3;
38 if (v == 0)
39 break;
40 }
41 s[i] = 0;
42 do
43 {
44 unsigned t = (unsigned)(val & 0x7);
45 val >>= 3;
46 s[--i] = (char)('0' + t);
47 }
48 while (i);
49}
50
51
52#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))
53
54static inline char GetHexChar(unsigned t) { return GET_HEX_CHAR(t); }
55
56
57void ConvertUInt32ToHex(UInt32 val, char *s) throw()
58{
59 UInt32 v = val;
60 unsigned i;
61 for (i = 1;; i++)
62 {
63 v >>= 4;
64 if (v == 0)
65 break;
66 }
67 s[i] = 0;
68 do
69 {
70 unsigned t = (unsigned)(val & 0xF);
71 val >>= 4;
72 s[--i] = GET_HEX_CHAR(t);
73 }
74 while (i);
75}
76
77
78void ConvertUInt64ToHex(UInt64 val, char *s) throw()
79{
80 UInt64 v = val;
81 unsigned i;
82 for (i = 1;; i++)
83 {
84 v >>= 4;
85 if (v == 0)
86 break;
87 }
88 s[i] = 0;
89 do
90 {
91 unsigned t = (unsigned)(val & 0xF);
92 val >>= 4;
93 s[--i] = GET_HEX_CHAR(t);
94 }
95 while (i);
96}
97
98void ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()
99{
100 s[8] = 0;
101 for (int i = 7; i >= 0; i--)
102 {
103 unsigned t = val & 0xF;
104 val >>= 4;
105 s[i] = GET_HEX_CHAR(t);;
106 }
107}
108
109/*
110void ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s)
111{
112 s[8] = 0;
113 for (int i = 7; i >= 0; i--)
114 {
115 unsigned t = val & 0xF;
116 val >>= 4;
117 s[i] = (wchar_t)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));
118 }
119}
120*/
121
122wchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()
123{
124 CONVERT_INT_TO_STR(wchar_t, 16);
125}
126
127wchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()
128{
129 if (val <= (UInt32)0xFFFFFFFF)
130 {
131 return ConvertUInt32ToString((UInt32)val, s);
132 }
133 CONVERT_INT_TO_STR(wchar_t, 24);
134}
135
136void ConvertInt64ToString(Int64 val, char *s) throw()
137{
138 if (val < 0)
139 {
140 *s++ = '-';
141 val = -val;
142 }
143 ConvertUInt64ToString((UInt64)val, s);
144}
145
146void ConvertInt64ToString(Int64 val, wchar_t *s) throw()
147{
148 if (val < 0)
149 {
150 *s++ = L'-';
151 val = -val;
152 }
153 ConvertUInt64ToString((UInt64)val, s);
154}
155
156
157static void ConvertByteToHex2Digits(unsigned v, char *s) throw()
158{
159 s[0] = GetHexChar(v >> 4);
160 s[1] = GetHexChar(v & 0xF);
161}
162
163static void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()
164{
165 ConvertByteToHex2Digits(val >> 8, s);
166 ConvertByteToHex2Digits(val & 0xFF, s + 2);
167}
168
169char *RawLeGuidToString(const Byte *g, char *s) throw()
170{
171 ConvertUInt32ToHex8Digits(GetUi32(g ), s); s += 8; *s++ = '-';
172 ConvertUInt16ToHex4Digits(GetUi16(g + 4), s); s += 4; *s++ = '-';
173 ConvertUInt16ToHex4Digits(GetUi16(g + 6), s); s += 4; *s++ = '-';
174 for (unsigned i = 0; i < 8; i++)
175 {
176 if (i == 2)
177 *s++ = '-';
178 ConvertByteToHex2Digits(g[8 + i], s);
179 s += 2;
180 }
181 *s = 0;
182 return s;
183}
184
185char *RawLeGuidToString_Braced(const Byte *g, char *s) throw()
186{
187 *s++ = '{';
188 s = RawLeGuidToString(g, s);
189 *s++ = '}';
190 *s = 0;
191 return s;
192}
diff --git a/CPP/Common/IntToString.h b/CPP/Common/IntToString.h
new file mode 100644
index 0000000..d0a96ef
--- /dev/null
+++ b/CPP/Common/IntToString.h
@@ -0,0 +1,30 @@
1// Common/IntToString.h
2
3#ifndef __COMMON_INT_TO_STRING_H
4#define __COMMON_INT_TO_STRING_H
5
6#include "MyTypes.h"
7
8// return: the pointer to the "terminating" null character after written characters
9
10char * ConvertUInt32ToString(UInt32 value, char *s) throw();
11char * ConvertUInt64ToString(UInt64 value, char *s) throw();
12
13wchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();
14wchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();
15
16void ConvertUInt64ToOct(UInt64 value, char *s) throw();
17
18void ConvertUInt32ToHex(UInt32 value, char *s) throw();
19void ConvertUInt64ToHex(UInt64 value, char *s) throw();
20void ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();
21// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();
22
23void ConvertInt64ToString(Int64 value, char *s) throw();
24void ConvertInt64ToString(Int64 value, wchar_t *s) throw();
25
26// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.
27char *RawLeGuidToString(const Byte *guid, char *s) throw();
28char *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();
29
30#endif
diff --git a/CPP/Common/Lang.cpp b/CPP/Common/Lang.cpp
new file mode 100644
index 0000000..35d3752
--- /dev/null
+++ b/CPP/Common/Lang.cpp
@@ -0,0 +1,163 @@
1// Common/Lang.cpp
2
3#include "StdAfx.h"
4
5#include "Lang.h"
6#include "StringToInt.h"
7#include "UTFConvert.h"
8
9#include "../Windows/FileIO.h"
10
11void CLang::Clear() throw()
12{
13 _ids.Clear();
14 _offsets.Clear();
15 delete []_text;
16 _text = 0;
17}
18
19static const char * const kLangSignature = ";!@Lang2@!UTF-8!";
20
21bool CLang::OpenFromString(const AString &s2)
22{
23 UString s;
24 if (!ConvertUTF8ToUnicode(s2, s))
25 return false;
26 unsigned i = 0;
27 if (s.IsEmpty())
28 return false;
29 if (s[0] == 0xFEFF)
30 i++;
31
32 for (const char *p = kLangSignature;; i++)
33 {
34 Byte c = (Byte)(*p++);
35 if (c == 0)
36 break;
37 if (s[i] != c)
38 return false;
39 }
40
41 _text = new wchar_t[s.Len() - i + 1];
42 wchar_t *text = _text;
43
44 Int32 id = -100;
45 UInt32 pos = 0;
46
47 while (i < s.Len())
48 {
49 unsigned start = pos;
50 do
51 {
52 wchar_t c = s[i++];
53 if (c == '\n')
54 break;
55 if (c == '\\')
56 {
57 if (i == s.Len())
58 return false;
59 c = s[i++];
60 switch (c)
61 {
62 case '\n': return false;
63 case 'n': c = '\n'; break;
64 case 't': c = '\t'; break;
65 case '\\': c = '\\'; break;
66 default: text[pos++] = L'\\'; break;
67 }
68 }
69 text[pos++] = c;
70 }
71 while (i < s.Len());
72
73 {
74 unsigned j = start;
75 for (; j < pos; j++)
76 if (text[j] != ' ')
77 break;
78 if (j == pos)
79 {
80 id++;
81 continue;
82 }
83 }
84 if (text[start] == ';')
85 {
86 pos = start;
87 id++;
88 continue;
89 }
90
91 text[pos++] = 0;
92 const wchar_t *end;
93 UInt32 id32 = ConvertStringToUInt32(text + start, &end);
94 if (*end == 0)
95 {
96 if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id)
97 return false;
98 id = (Int32)id32;
99 pos = start;
100 continue;
101 }
102
103 if (id < 0)
104 return false;
105 _ids.Add((UInt32)id++);
106 _offsets.Add(start);
107 }
108
109 return true;
110}
111
112bool CLang::Open(CFSTR fileName, const char *id)
113{
114 Clear();
115 NWindows::NFile::NIO::CInFile file;
116 if (!file.Open(fileName))
117 return false;
118 UInt64 length;
119 if (!file.GetLength(length))
120 return false;
121 if (length > (1 << 20))
122 return false;
123
124 AString s;
125 const unsigned len = (unsigned)length;
126 char *p = s.GetBuf(len);
127 size_t processed;
128 if (!file.ReadFull(p, len, processed))
129 return false;
130 file.Close();
131 if (len != processed)
132 return false;
133
134 char *p2 = p;
135 for (unsigned i = 0; i < len; i++)
136 {
137 char c = p[i];
138 if (c == 0)
139 break;
140 if (c != 0x0D)
141 *p2++ = c;
142 }
143 *p2 = 0;
144 s.ReleaseBuf_SetLen((unsigned)(p2 - p));
145
146 if (OpenFromString(s))
147 {
148 const wchar_t *name = Get(0);
149 if (name && StringsAreEqual_Ascii(name, id))
150 return true;
151 }
152
153 Clear();
154 return false;
155}
156
157const wchar_t *CLang::Get(UInt32 id) const throw()
158{
159 int index = _ids.FindInSorted(id);
160 if (index < 0)
161 return NULL;
162 return _text + (size_t)_offsets[(unsigned)index];
163}
diff --git a/CPP/Common/Lang.h b/CPP/Common/Lang.h
new file mode 100644
index 0000000..cc66677
--- /dev/null
+++ b/CPP/Common/Lang.h
@@ -0,0 +1,23 @@
1// Common/Lang.h
2
3#ifndef __COMMON_LANG_H
4#define __COMMON_LANG_H
5
6#include "MyString.h"
7
8class CLang
9{
10 wchar_t *_text;
11 CRecordVector<UInt32> _ids;
12 CRecordVector<UInt32> _offsets;
13
14 bool OpenFromString(const AString &s);
15public:
16 CLang(): _text(0) {}
17 ~CLang() { Clear(); }
18 bool Open(CFSTR fileName, const char *id);
19 void Clear() throw();
20 const wchar_t *Get(UInt32 id) const throw();
21};
22
23#endif
diff --git a/CPP/Common/ListFileUtils.cpp b/CPP/Common/ListFileUtils.cpp
new file mode 100644
index 0000000..b361b37
--- /dev/null
+++ b/CPP/Common/ListFileUtils.cpp
@@ -0,0 +1,150 @@
1// Common/ListFileUtils.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "ListFileUtils.h"
8#include "MyBuffer.h"
9#include "StringConvert.h"
10#include "UTFConvert.h"
11
12#include "../Windows/FileIO.h"
13
14#define CSysInFile NWindows::NFile::NIO::CInFile
15#define MY_GET_LAST_ERROR ::GetLastError()
16
17
18#define kQuoteChar '\"'
19
20
21static void AddName(UStringVector &strings, UString &s)
22{
23 s.Trim();
24 if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar)
25 {
26 s.DeleteBack();
27 s.Delete(0);
28 }
29 if (!s.IsEmpty())
30 strings.Add(s);
31}
32
33
34static bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError)
35{
36 size_t processed;
37 if (!file.ReadFull(data, size, processed))
38 {
39 lastError = MY_GET_LAST_ERROR;
40 return false;
41 }
42 if (processed != size)
43 {
44 lastError = 1; // error: size of listfile was changed
45 return false;
46 }
47 return true;
48}
49
50
51bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError)
52{
53 lastError = 0;
54 CSysInFile file;
55 if (!file.Open(fileName))
56 {
57 lastError = MY_GET_LAST_ERROR;
58 return false;
59 }
60 UInt64 fileSize;
61 if (!file.GetLength(fileSize))
62 {
63 lastError = MY_GET_LAST_ERROR;
64 return false;
65 }
66 if (fileSize >= ((UInt32)1 << 31) - 32)
67 return false;
68 UString u;
69 if (codePage == MY__CP_UTF16 || codePage == MY__CP_UTF16BE)
70 {
71 if ((fileSize & 1) != 0)
72 return false;
73 CByteArr buf((size_t)fileSize);
74
75 if (!My_File_Read(file, buf, (size_t)fileSize, lastError))
76 return false;
77
78 file.Close();
79 const unsigned num = (unsigned)fileSize / 2;
80 wchar_t *p = u.GetBuf(num);
81 if (codePage == MY__CP_UTF16)
82 for (unsigned i = 0; i < num; i++)
83 {
84 wchar_t c = GetUi16(buf + (size_t)i * 2);
85 if (c == 0)
86 return false;
87 p[i] = c;
88 }
89 else
90 for (unsigned i = 0; i < num; i++)
91 {
92 wchar_t c = (wchar_t)GetBe16(buf + (size_t)i * 2);
93 if (c == 0)
94 return false;
95 p[i] = c;
96 }
97 p[num] = 0;
98 u.ReleaseBuf_SetLen(num);
99 }
100 else
101 {
102 AString s;
103 char *p = s.GetBuf((unsigned)fileSize);
104
105 if (!My_File_Read(file, p, (size_t)fileSize, lastError))
106 return false;
107
108 file.Close();
109 s.ReleaseBuf_CalcLen((unsigned)fileSize);
110 if (s.Len() != fileSize)
111 return false;
112
113 // #ifdef CP_UTF8
114 if (codePage == CP_UTF8)
115 {
116 // we must check UTF8 here, if convert function doesn't check
117 if (!CheckUTF8_AString(s))
118 return false;
119 if (!ConvertUTF8ToUnicode(s, u))
120 return false;
121 }
122 else
123 // #endif
124 MultiByteToUnicodeString2(u, s, codePage);
125 }
126
127 const wchar_t kGoodBOM = 0xFEFF;
128 // const wchar_t kBadBOM = 0xFFFE;
129
130 UString s;
131 unsigned i = 0;
132 for (; i < u.Len() && u[i] == kGoodBOM; i++);
133 for (; i < u.Len(); i++)
134 {
135 wchar_t c = u[i];
136 /*
137 if (c == kGoodBOM || c == kBadBOM)
138 return false;
139 */
140 if (c == '\n' || c == 0xD)
141 {
142 AddName(strings, s);
143 s.Empty();
144 }
145 else
146 s += c;
147 }
148 AddName(strings, s);
149 return true;
150}
diff --git a/CPP/Common/ListFileUtils.h b/CPP/Common/ListFileUtils.h
new file mode 100644
index 0000000..a91e4b1
--- /dev/null
+++ b/CPP/Common/ListFileUtils.h
@@ -0,0 +1,18 @@
1// Common/ListFileUtils.h
2
3#ifndef __COMMON_LIST_FILE_UTILS_H
4#define __COMMON_LIST_FILE_UTILS_H
5
6#include "MyString.h"
7#include "MyTypes.h"
8
9#define MY__CP_UTF16 1200
10#define MY__CP_UTF16BE 1201
11
12// bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);
13
14 // = CP_OEMCP
15bool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage,
16 DWORD &lastError);
17
18#endif
diff --git a/CPP/Common/LzFindPrepare.cpp b/CPP/Common/LzFindPrepare.cpp
new file mode 100644
index 0000000..8845e4a
--- /dev/null
+++ b/CPP/Common/LzFindPrepare.cpp
@@ -0,0 +1,7 @@
1// Sha256Prepare.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/LzFind.h"
6
7static struct CLzFindPrepare { CLzFindPrepare() { LzFindPrepare(); } } g_CLzFindPrepare;
diff --git a/CPP/Common/MyBuffer.h b/CPP/Common/MyBuffer.h
new file mode 100644
index 0000000..18ab6fa
--- /dev/null
+++ b/CPP/Common/MyBuffer.h
@@ -0,0 +1,277 @@
1// Common/MyBuffer.h
2
3#ifndef __COMMON_MY_BUFFER_H
4#define __COMMON_MY_BUFFER_H
5
6#include "Defs.h"
7#include "MyTypes.h"
8
9/* 7-Zip now uses CBuffer only as CByteBuffer.
10 So there is no need to use MY_ARRAY_NEW macro in CBuffer code. */
11
12template <class T> class CBuffer
13{
14 T *_items;
15 size_t _size;
16
17public:
18 void Free()
19 {
20 if (_items)
21 {
22 delete []_items;
23 _items = 0;
24 }
25 _size = 0;
26 }
27
28 CBuffer(): _items(0), _size(0) {};
29 CBuffer(size_t size): _items(0), _size(0) { _items = new T[size]; _size = size; }
30 CBuffer(const CBuffer &buffer): _items(0), _size(0)
31 {
32 size_t size = buffer._size;
33 if (size != 0)
34 {
35 _items = new T[size];
36 memcpy(_items, buffer._items, size * sizeof(T));
37 _size = size;
38 }
39 }
40
41 ~CBuffer() { delete []_items; }
42
43 operator T *() { return _items; }
44 operator const T *() const { return _items; }
45 size_t Size() const { return _size; }
46
47 void Alloc(size_t size)
48 {
49 if (size != _size)
50 {
51 Free();
52 if (size != 0)
53 {
54 _items = new T[size];
55 _size = size;
56 }
57 }
58 }
59
60 void AllocAtLeast(size_t size)
61 {
62 if (size > _size)
63 {
64 Free();
65 _items = new T[size];
66 _size = size;
67 }
68 }
69
70 void CopyFrom(const T *data, size_t size)
71 {
72 Alloc(size);
73 if (size != 0)
74 memcpy(_items, data, size * sizeof(T));
75 }
76
77 void ChangeSize_KeepData(size_t newSize, size_t keepSize)
78 {
79 if (newSize == _size)
80 return;
81 T *newBuffer = NULL;
82 if (newSize != 0)
83 {
84 newBuffer = new T[newSize];
85 if (keepSize > _size)
86 keepSize = _size;
87 if (keepSize != 0)
88 memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T));
89 }
90 delete []_items;
91 _items = newBuffer;
92 _size = newSize;
93 }
94
95 void Wipe()
96 {
97 if (_size != 0)
98 memset(_items, 0, _size * sizeof(T));
99 }
100
101 CBuffer& operator=(const CBuffer &buffer)
102 {
103 if (&buffer != this)
104 CopyFrom(buffer, buffer._size);
105 return *this;
106 }
107};
108
109template <class T>
110bool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)
111{
112 size_t size1 = b1.Size();
113 if (size1 != b2.Size())
114 return false;
115 if (size1 == 0)
116 return true;
117 return memcmp(b1, b2, size1 * sizeof(T)) == 0;
118}
119
120template <class T>
121bool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)
122{
123 size_t size1 = b1.Size();
124 if (size1 != b2.Size())
125 return true;
126 if (size1 == 0)
127 return false;
128 return memcmp(b1, b2, size1 * sizeof(T)) != 0;
129}
130
131
132// typedef CBuffer<char> CCharBuffer;
133// typedef CBuffer<wchar_t> CWCharBuffer;
134typedef CBuffer<unsigned char> CByteBuffer;
135
136
137class CByteBuffer_Wipe: public CByteBuffer
138{
139 CLASS_NO_COPY(CByteBuffer_Wipe)
140public:
141 // CByteBuffer_Wipe(): CBuffer<unsigned char>() {}
142 CByteBuffer_Wipe(size_t size): CBuffer<unsigned char>(size) {}
143 ~CByteBuffer_Wipe() { Wipe(); }
144};
145
146
147
148template <class T> class CObjArray
149{
150protected:
151 T *_items;
152private:
153 // we disable copy
154 CObjArray(const CObjArray &buffer);
155 void operator=(const CObjArray &buffer);
156public:
157 void Free()
158 {
159 delete []_items;
160 _items = 0;
161 }
162 CObjArray(size_t size): _items(0)
163 {
164 if (size != 0)
165 {
166 MY_ARRAY_NEW(_items, T, size)
167 // _items = new T[size];
168 }
169 }
170 CObjArray(): _items(0) {};
171 ~CObjArray() { delete []_items; }
172
173 operator T *() { return _items; }
174 operator const T *() const { return _items; }
175
176 void Alloc(size_t newSize)
177 {
178 delete []_items;
179 _items = 0;
180 MY_ARRAY_NEW(_items, T, newSize)
181 // _items = new T[newSize];
182 }
183};
184
185typedef CObjArray<unsigned char> CByteArr;
186typedef CObjArray<bool> CBoolArr;
187typedef CObjArray<int> CIntArr;
188typedef CObjArray<unsigned> CUIntArr;
189
190
191template <class T> class CObjArray2
192{
193 T *_items;
194 unsigned _size;
195
196 // we disable copy
197 CObjArray2(const CObjArray2 &buffer);
198 void operator=(const CObjArray2 &buffer);
199public:
200
201 void Free()
202 {
203 delete []_items;
204 _items = 0;
205 _size = 0;
206 }
207 CObjArray2(): _items(0), _size(0) {};
208 /*
209 CObjArray2(const CObjArray2 &buffer): _items(0), _size(0)
210 {
211 size_t newSize = buffer._size;
212 if (newSize != 0)
213 {
214 T *newBuffer = new T[newSize];;
215 _items = newBuffer;
216 _size = newSize;
217 const T *src = buffer;
218 for (size_t i = 0; i < newSize; i++)
219 newBuffer[i] = src[i];
220 }
221 }
222 */
223 /*
224 CObjArray2(size_t size): _items(0), _size(0)
225 {
226 if (size != 0)
227 {
228 _items = new T[size];
229 _size = size;
230 }
231 }
232 */
233
234 ~CObjArray2() { delete []_items; }
235
236 operator T *() { return _items; }
237 operator const T *() const { return _items; }
238
239 unsigned Size() const { return (unsigned)_size; }
240 bool IsEmpty() const { return _size == 0; }
241
242 // SetSize doesn't keep old items. It allocates new array if size is not equal
243 void SetSize(unsigned size)
244 {
245 if (size == _size)
246 return;
247 T *newBuffer = NULL;
248 if (size != 0)
249 {
250 MY_ARRAY_NEW(newBuffer, T, size)
251 // newBuffer = new T[size];
252 }
253 delete []_items;
254 _items = newBuffer;
255 _size = size;
256 }
257
258 /*
259 CObjArray2& operator=(const CObjArray2 &buffer)
260 {
261 Free();
262 size_t newSize = buffer._size;
263 if (newSize != 0)
264 {
265 T *newBuffer = new T[newSize];;
266 _items = newBuffer;
267 _size = newSize;
268 const T *src = buffer;
269 for (size_t i = 0; i < newSize; i++)
270 newBuffer[i] = src[i];
271 }
272 return *this;
273 }
274 */
275};
276
277#endif
diff --git a/CPP/Common/MyBuffer2.h b/CPP/Common/MyBuffer2.h
new file mode 100644
index 0000000..372d478
--- /dev/null
+++ b/CPP/Common/MyBuffer2.h
@@ -0,0 +1,139 @@
1// Common/MyBuffer2.h
2
3#ifndef __COMMON_MY_BUFFER2_H
4#define __COMMON_MY_BUFFER2_H
5
6#include "../../C/Alloc.h"
7
8#include "MyTypes.h"
9
10class CMidBuffer
11{
12 Byte *_data;
13 size_t _size;
14
15 CLASS_NO_COPY(CMidBuffer)
16
17public:
18 CMidBuffer(): _data(NULL), _size(0) {}
19 ~CMidBuffer() { ::MidFree(_data); }
20
21 void Free() { ::MidFree(_data); _data = NULL; _size = 0; }
22
23 bool IsAllocated() const { return _data != NULL; }
24 operator Byte *() { return _data; }
25 operator const Byte *() const { return _data; }
26 size_t Size() const { return _size; }
27
28 void Alloc(size_t size)
29 {
30 if (!_data || size != _size)
31 {
32 ::MidFree(_data);
33 _size = 0;
34 _data = NULL;
35 _data = (Byte *)::MidAlloc(size);
36 if (_data)
37 _size = size;
38 }
39 }
40
41 void AllocAtLeast(size_t size)
42 {
43 if (!_data || size > _size)
44 {
45 ::MidFree(_data);
46 const size_t kMinSize = (size_t)1 << 16;
47 if (size < kMinSize)
48 size = kMinSize;
49 _size = 0;
50 _data = NULL;
51 _data = (Byte *)::MidAlloc(size);
52 if (_data)
53 _size = size;
54 }
55 }
56};
57
58
59class CAlignedBuffer
60{
61 Byte *_data;
62 size_t _size;
63
64 CLASS_NO_COPY(CAlignedBuffer)
65
66public:
67 CAlignedBuffer(): _data(NULL), _size(0) {}
68 ~CAlignedBuffer()
69 {
70 ISzAlloc_Free(&g_AlignedAlloc, _data);
71 }
72
73 CAlignedBuffer(size_t size): _size(0)
74 {
75 _data = NULL;
76 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size);
77 if (!_data)
78 throw 1;
79 _size = size;
80 }
81
82 void Free()
83 {
84 ISzAlloc_Free(&g_AlignedAlloc, _data);
85 _data = NULL;
86 _size = 0;
87 }
88
89 bool IsAllocated() const { return _data != NULL; }
90 operator Byte *() { return _data; }
91 operator const Byte *() const { return _data; }
92 size_t Size() const { return _size; }
93
94 void Alloc(size_t size)
95 {
96 if (!_data || size != _size)
97 {
98 ISzAlloc_Free(&g_AlignedAlloc, _data);
99 _size = 0;
100 _data = NULL;
101 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size);
102 if (_data)
103 _size = size;
104 }
105 }
106
107 void AllocAtLeast(size_t size)
108 {
109 if (!_data || size > _size)
110 {
111 ISzAlloc_Free(&g_AlignedAlloc, _data);
112 _size = 0;
113 _data = NULL;
114 _data = (Byte *)ISzAlloc_Alloc(&g_AlignedAlloc, size);
115 if (_data)
116 _size = size;
117 }
118 }
119};
120
121/*
122 CMidAlignedBuffer must return aligned pointer.
123 - in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc()
124 VirtualAlloc(): Memory allocated is automatically initialized to zero.
125 MidAlloc(0) returns NULL
126 - in non-Windows systems it uses g_AlignedAlloc.
127 g_AlignedAlloc::Alloc(size = 0) can return non NULL.
128*/
129
130typedef
131#ifdef _WIN32
132 CMidBuffer
133#else
134 CAlignedBuffer
135#endif
136 CMidAlignedBuffer;
137
138
139#endif
diff --git a/CPP/Common/MyCom.h b/CPP/Common/MyCom.h
new file mode 100644
index 0000000..ce2f0dd
--- /dev/null
+++ b/CPP/Common/MyCom.h
@@ -0,0 +1,306 @@
1// MyCom.h
2
3#ifndef __MY_COM_H
4#define __MY_COM_H
5
6#include "MyWindows.h"
7#include "MyTypes.h"
8
9#ifndef RINOK
10#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; }
11#endif
12
13template <class T>
14class CMyComPtr
15{
16 T* _p;
17public:
18 CMyComPtr(): _p(NULL) {}
19 CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }
20 CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }
21 ~CMyComPtr() { if (_p) _p->Release(); }
22 void Release() { if (_p) { _p->Release(); _p = NULL; } }
23 operator T*() const { return (T*)_p; }
24 // T& operator*() const { return *_p; }
25 T** operator&() { return &_p; }
26 T* operator->() const { return _p; }
27 T* operator=(T* p)
28 {
29 if (p)
30 p->AddRef();
31 if (_p)
32 _p->Release();
33 _p = p;
34 return p;
35 }
36 T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }
37 bool operator!() const { return (_p == NULL); }
38 // bool operator==(T* pT) const { return _p == pT; }
39 void Attach(T* p2)
40 {
41 Release();
42 _p = p2;
43 }
44 T* Detach()
45 {
46 T* pt = _p;
47 _p = NULL;
48 return pt;
49 }
50 #ifdef _WIN32
51 HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
52 {
53 return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);
54 }
55 #endif
56 /*
57 HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
58 {
59 CLSID clsid;
60 HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
61 ATLASSERT(_p == NULL);
62 if (SUCCEEDED(hr))
63 hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);
64 return hr;
65 }
66 */
67 template <class Q>
68 HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()
69 {
70 return _p->QueryInterface(iid, (void**)pp);
71 }
72};
73
74//////////////////////////////////////////////////////////
75
76inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)
77{
78 *bstr = ::SysAllocString(src);
79 return (*bstr) ? S_OK : E_OUTOFMEMORY;
80}
81
82class CMyComBSTR
83{
84 BSTR m_str;
85 CLASS_NO_COPY(CMyComBSTR)
86public:
87 CMyComBSTR(): m_str(NULL) {}
88 ~CMyComBSTR() { ::SysFreeString(m_str); }
89 BSTR* operator&() { return &m_str; }
90 operator LPCOLESTR() const { return m_str; }
91 // operator bool() const { return m_str != NULL; }
92 // bool operator!() const { return m_str == NULL; }
93
94 void Wipe_and_Free()
95 {
96 if (m_str)
97 {
98 memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));
99 Empty();
100 }
101 }
102
103private:
104 // operator BSTR() const { return m_str; }
105
106 CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }
107 // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }
108 // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); }
109 // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }
110
111 /*
112 CMyComBSTR(REFGUID src)
113 {
114 LPOLESTR szGuid;
115 StringFromCLSID(src, &szGuid);
116 m_str = ::SysAllocString(szGuid);
117 CoTaskMemFree(szGuid);
118 }
119 */
120
121 /*
122 CMyComBSTR& operator=(const CMyComBSTR& src)
123 {
124 if (m_str != src.m_str)
125 {
126 if (m_str)
127 ::SysFreeString(m_str);
128 m_str = src.MyCopy();
129 }
130 return *this;
131 }
132 */
133
134 CMyComBSTR& operator=(LPCOLESTR src)
135 {
136 ::SysFreeString(m_str);
137 m_str = ::SysAllocString(src);
138 return *this;
139 }
140
141 unsigned Len() const { return ::SysStringLen(m_str); }
142
143 BSTR MyCopy() const
144 {
145 // We don't support Byte BSTRs here
146 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
147 /*
148 UINT byteLen = ::SysStringByteLen(m_str);
149 BSTR res = ::SysAllocStringByteLen(NULL, byteLen);
150 if (res && byteLen != 0 && m_str)
151 memcpy(res, m_str, byteLen);
152 return res;
153 */
154 }
155
156 /*
157 void Attach(BSTR src) { m_str = src; }
158 BSTR Detach()
159 {
160 BSTR s = m_str;
161 m_str = NULL;
162 return s;
163 }
164 */
165
166 void Empty()
167 {
168 ::SysFreeString(m_str);
169 m_str = NULL;
170 }
171};
172
173
174class CMyComBSTR_Wipe: public CMyComBSTR
175{
176 CLASS_NO_COPY(CMyComBSTR_Wipe)
177public:
178 CMyComBSTR_Wipe(): CMyComBSTR() {}
179 ~CMyComBSTR_Wipe() { Wipe_and_Free(); }
180};
181
182
183
184/*
185 If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.
186 But if some class_1 derived from CMyUnknownImp
187 uses MY_ADDREF_RELEASE and IUnknown::Release()
188 and some another class_2 is derived from class_1,
189 then class_1 must use virtual destructor:
190 virtual ~class_1();
191 In that case, class_1::Release() calls correct destructor of class_2.
192
193 We use virtual ~CMyUnknownImp() to disable warning
194 "class has virtual functions, but destructor is not virtual".
195
196 also we can use virtual ~IUnknown() {} in MyWindows.h
197*/
198
199class CMyUnknownImp
200{
201 CLASS_NO_COPY(CMyUnknownImp)
202public:
203 ULONG __m_RefCount;
204 CMyUnknownImp(): __m_RefCount(0) {}
205
206 #ifdef _WIN32
207 #if defined(__GNUC__) || defined(__clang__)
208 virtual // to disable GCC/CLANG varnings
209 #endif
210 #endif
211 ~CMyUnknownImp() {}
212};
213
214
215
216#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \
217(REFGUID iid, void **outObject) throw() { *outObject = NULL;
218
219#define MY_QUERYINTERFACE_ENTRY(i) else if (iid == IID_ ## i) \
220 { *outObject = (void *)(i *)this; }
221
222#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \
223 { *outObject = (void *)(IUnknown *)(i *)this; }
224
225#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \
226 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
227 MY_QUERYINTERFACE_ENTRY(i)
228
229#define MY_QUERYINTERFACE_END else return E_NOINTERFACE; ++__m_RefCount; /* AddRef(); */ return S_OK; }
230
231#define MY_ADDREF_RELEASE \
232STDMETHOD_(ULONG, AddRef)() throw() { return ++__m_RefCount; } \
233STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) return __m_RefCount; \
234 delete this; return 0; }
235
236#define MY_UNKNOWN_IMP_SPEC(i) \
237 MY_QUERYINTERFACE_BEGIN \
238 i \
239 MY_QUERYINTERFACE_END \
240 MY_ADDREF_RELEASE
241
242
243#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \
244 MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \
245 MY_QUERYINTERFACE_END \
246 MY_ADDREF_RELEASE
247
248#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \
249 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \
250 MY_QUERYINTERFACE_ENTRY(i) \
251 )
252
253#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \
254 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
255 MY_QUERYINTERFACE_ENTRY(i1) \
256 MY_QUERYINTERFACE_ENTRY(i2) \
257 )
258
259#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \
260 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
261 MY_QUERYINTERFACE_ENTRY(i1) \
262 MY_QUERYINTERFACE_ENTRY(i2) \
263 MY_QUERYINTERFACE_ENTRY(i3) \
264 )
265
266#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \
267 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
268 MY_QUERYINTERFACE_ENTRY(i1) \
269 MY_QUERYINTERFACE_ENTRY(i2) \
270 MY_QUERYINTERFACE_ENTRY(i3) \
271 MY_QUERYINTERFACE_ENTRY(i4) \
272 )
273
274#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \
275 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
276 MY_QUERYINTERFACE_ENTRY(i1) \
277 MY_QUERYINTERFACE_ENTRY(i2) \
278 MY_QUERYINTERFACE_ENTRY(i3) \
279 MY_QUERYINTERFACE_ENTRY(i4) \
280 MY_QUERYINTERFACE_ENTRY(i5) \
281 )
282
283#define MY_UNKNOWN_IMP6(i1, i2, i3, i4, i5, i6) MY_UNKNOWN_IMP_SPEC( \
284 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
285 MY_QUERYINTERFACE_ENTRY(i1) \
286 MY_QUERYINTERFACE_ENTRY(i2) \
287 MY_QUERYINTERFACE_ENTRY(i3) \
288 MY_QUERYINTERFACE_ENTRY(i4) \
289 MY_QUERYINTERFACE_ENTRY(i5) \
290 MY_QUERYINTERFACE_ENTRY(i6) \
291 )
292
293#define MY_UNKNOWN_IMP7(i1, i2, i3, i4, i5, i6, i7) MY_UNKNOWN_IMP_SPEC( \
294 MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \
295 MY_QUERYINTERFACE_ENTRY(i1) \
296 MY_QUERYINTERFACE_ENTRY(i2) \
297 MY_QUERYINTERFACE_ENTRY(i3) \
298 MY_QUERYINTERFACE_ENTRY(i4) \
299 MY_QUERYINTERFACE_ENTRY(i5) \
300 MY_QUERYINTERFACE_ENTRY(i6) \
301 MY_QUERYINTERFACE_ENTRY(i7) \
302 )
303
304const HRESULT k_My_HRESULT_WritingWasCut = 0x20000010;
305
306#endif
diff --git a/CPP/Common/MyException.h b/CPP/Common/MyException.h
new file mode 100644
index 0000000..f0ad111
--- /dev/null
+++ b/CPP/Common/MyException.h
@@ -0,0 +1,14 @@
1// Common/Exception.h
2
3#ifndef __COMMON_EXCEPTION_H
4#define __COMMON_EXCEPTION_H
5
6#include "MyWindows.h"
7
8struct CSystemException
9{
10 HRESULT ErrorCode;
11 CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}
12};
13
14#endif
diff --git a/CPP/Common/MyGuidDef.h b/CPP/Common/MyGuidDef.h
new file mode 100644
index 0000000..38aad6e
--- /dev/null
+++ b/CPP/Common/MyGuidDef.h
@@ -0,0 +1,57 @@
1// Common/MyGuidDef.h
2
3#ifndef GUID_DEFINED
4#define GUID_DEFINED
5
6#include "MyTypes.h"
7
8typedef struct {
9 UInt32 Data1;
10 UInt16 Data2;
11 UInt16 Data3;
12 unsigned char Data4[8];
13} GUID;
14
15#ifdef __cplusplus
16#define REFGUID const GUID &
17#else
18#define REFGUID const GUID *
19#endif
20
21// typedef GUID IID;
22typedef GUID CLSID;
23
24#define REFCLSID REFGUID
25#define REFIID REFGUID
26
27#ifdef __cplusplus
28inline int operator==(REFGUID g1, REFGUID g2)
29{
30 for (int i = 0; i < (int)sizeof(g1); i++)
31 if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i])
32 return 0;
33 return 1;
34}
35inline int operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); }
36#endif
37
38#ifdef __cplusplus
39 #define MY_EXTERN_C extern "C"
40#else
41 #define MY_EXTERN_C extern
42#endif
43
44#endif
45
46
47#ifdef DEFINE_GUID
48#undef DEFINE_GUID
49#endif
50
51#ifdef INITGUID
52 #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
53 MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
54#else
55 #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
56 MY_EXTERN_C const GUID name
57#endif
diff --git a/CPP/Common/MyInitGuid.h b/CPP/Common/MyInitGuid.h
new file mode 100644
index 0000000..04d77e2
--- /dev/null
+++ b/CPP/Common/MyInitGuid.h
@@ -0,0 +1,49 @@
1// Common/MyInitGuid.h
2
3#ifndef __COMMON_MY_INITGUID_H
4#define __COMMON_MY_INITGUID_H
5
6/*
7This file must be included only to one C++ file in project before
8declarations of COM interfaces with DEFINE_GUID macro.
9
10Each GUID must be initialized exactly once in project.
11There are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h):
12 - if INITGUID is not defined: DEFINE_GUID declares an external reference to the symbol name.
13 - if INITGUID is defined: DEFINE_GUID initializes the symbol name to the value of the GUID.
14
15Also we need IID_IUnknown that is initialized in some file for linking:
16 MSVC: by default the linker uses some lib file that contains IID_IUnknown
17 MinGW: add -luuid switch for linker
18 WinCE: we define IID_IUnknown in this file
19 Other: we define IID_IUnknown in this file
20*/
21
22#ifdef __clang__
23 #pragma clang diagnostic ignored "-Wmissing-variable-declarations"
24#endif
25
26#ifdef _WIN32
27
28#ifdef UNDER_CE
29#include <basetyps.h>
30#endif
31
32#include <InitGuid.h>
33
34#ifdef UNDER_CE
35DEFINE_GUID(IID_IUnknown,
360x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
37#endif
38
39#else
40
41#define INITGUID
42#include "MyGuidDef.h"
43DEFINE_GUID(IID_IUnknown,
440x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
45
46#endif
47
48
49#endif
diff --git a/CPP/Common/MyLinux.h b/CPP/Common/MyLinux.h
new file mode 100644
index 0000000..1a91899
--- /dev/null
+++ b/CPP/Common/MyLinux.h
@@ -0,0 +1,42 @@
1// MyLinux.h
2
3#ifndef __MY_LIN_LINUX_H
4#define __MY_LIN_LINUX_H
5
6#define MY_LIN_S_IFMT 00170000
7#define MY_LIN_S_IFSOCK 0140000
8#define MY_LIN_S_IFLNK 0120000
9#define MY_LIN_S_IFREG 0100000
10#define MY_LIN_S_IFBLK 0060000
11#define MY_LIN_S_IFDIR 0040000
12#define MY_LIN_S_IFCHR 0020000
13#define MY_LIN_S_IFIFO 0010000
14
15#define MY_LIN_S_ISLNK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK)
16#define MY_LIN_S_ISREG(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG)
17#define MY_LIN_S_ISDIR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR)
18#define MY_LIN_S_ISCHR(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR)
19#define MY_LIN_S_ISBLK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK)
20#define MY_LIN_S_ISFIFO(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO)
21#define MY_LIN_S_ISSOCK(m) (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK)
22
23#define MY_LIN_S_ISUID 0004000
24#define MY_LIN_S_ISGID 0002000
25#define MY_LIN_S_ISVTX 0001000
26
27#define MY_LIN_S_IRWXU 00700
28#define MY_LIN_S_IRUSR 00400
29#define MY_LIN_S_IWUSR 00200
30#define MY_LIN_S_IXUSR 00100
31
32#define MY_LIN_S_IRWXG 00070
33#define MY_LIN_S_IRGRP 00040
34#define MY_LIN_S_IWGRP 00020
35#define MY_LIN_S_IXGRP 00010
36
37#define MY_LIN_S_IRWXO 00007
38#define MY_LIN_S_IROTH 00004
39#define MY_LIN_S_IWOTH 00002
40#define MY_LIN_S_IXOTH 00001
41
42#endif
diff --git a/CPP/Common/MyMap.cpp b/CPP/Common/MyMap.cpp
new file mode 100644
index 0000000..923846a
--- /dev/null
+++ b/CPP/Common/MyMap.cpp
@@ -0,0 +1,140 @@
1// MyMap.cpp
2
3#include "StdAfx.h"
4
5#include "MyMap.h"
6
7static const unsigned kNumBitsMax = sizeof(UInt32) * 8;
8
9static UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) throw()
10{
11 if (startPos == sizeof(value) * 8)
12 return 0;
13 value >>= startPos;
14 if (numBits == sizeof(value) * 8)
15 return value;
16 return value & (((UInt32)1 << numBits) - 1);
17}
18
19static inline unsigned GetSubBit(UInt32 v, unsigned n) { return (unsigned)(v >> n) & 1; }
20
21bool CMap32::Find(UInt32 key, UInt32 &valueRes) const throw()
22{
23 valueRes = (UInt32)(Int32)-1;
24 if (Nodes.Size() == 0)
25 return false;
26 if (Nodes.Size() == 1)
27 {
28 const CNode &n = Nodes[0];
29 if (n.Len == kNumBitsMax)
30 {
31 valueRes = n.Values[0];
32 return (key == n.Key);
33 }
34 }
35
36 unsigned cur = 0;
37 unsigned bitPos = kNumBitsMax;
38 for (;;)
39 {
40 const CNode &n = Nodes[cur];
41 bitPos -= n.Len;
42 if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))
43 return false;
44 unsigned bit = GetSubBit(key, --bitPos);
45 if (n.IsLeaf[bit])
46 {
47 valueRes = n.Values[bit];
48 return (key == n.Keys[bit]);
49 }
50 cur = (unsigned)n.Keys[bit];
51 }
52}
53
54bool CMap32::Set(UInt32 key, UInt32 value)
55{
56 if (Nodes.Size() == 0)
57 {
58 CNode n;
59 n.Key = n.Keys[0] = n.Keys[1] = key;
60 n.Values[0] = n.Values[1] = value;
61 n.IsLeaf[0] = n.IsLeaf[1] = 1;
62 n.Len = kNumBitsMax;
63 Nodes.Add(n);
64 return false;
65 }
66 if (Nodes.Size() == 1)
67 {
68 CNode &n = Nodes[0];
69 if (n.Len == kNumBitsMax)
70 {
71 if (key == n.Key)
72 {
73 n.Values[0] = n.Values[1] = value;
74 return true;
75 }
76 unsigned i = kNumBitsMax - 1;
77 for (; GetSubBit(key, i) == GetSubBit(n.Key, i); i--);
78 n.Len = (UInt16)(kNumBitsMax - (1 + i));
79 unsigned newBit = GetSubBit(key, i);
80 n.Values[newBit] = value;
81 n.Keys[newBit] = key;
82 return false;
83 }
84 }
85
86 unsigned cur = 0;
87 unsigned bitPos = kNumBitsMax;
88 for (;;)
89 {
90 CNode &n = Nodes[cur];
91 bitPos -= n.Len;
92 if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))
93 {
94 unsigned i = n.Len - 1;
95 for (; GetSubBit(key, bitPos + i) == GetSubBit(n.Key, bitPos + i); i--);
96
97 CNode e2(n);
98 e2.Len = (UInt16)i;
99
100 n.Len = (UInt16)(n.Len - (1 + i));
101 unsigned newBit = GetSubBit(key, bitPos + i);
102 n.Values[newBit] = value;
103 n.IsLeaf[newBit] = 1;
104 n.IsLeaf[1 - newBit] = 0;
105 n.Keys[newBit] = key;
106 n.Keys[1 - newBit] = Nodes.Size();
107 Nodes.Add(e2);
108 return false;
109 }
110 unsigned bit = GetSubBit(key, --bitPos);
111
112 if (n.IsLeaf[bit])
113 {
114 if (key == n.Keys[bit])
115 {
116 n.Values[bit] = value;
117 return true;
118 }
119 unsigned i = bitPos - 1;
120 for (; GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--);
121
122 CNode e2;
123
124 unsigned newBit = GetSubBit(key, i);
125 e2.Values[newBit] = value;
126 e2.Values[1 - newBit] = n.Values[bit];
127 e2.IsLeaf[newBit] = e2.IsLeaf[1 - newBit] = 1;
128 e2.Keys[newBit] = key;
129 e2.Keys[1 - newBit] = e2.Key = n.Keys[bit];
130 e2.Len = (UInt16)(bitPos - (1 + i));
131
132 n.IsLeaf[bit] = 0;
133 n.Keys[bit] = Nodes.Size();
134
135 Nodes.Add(e2);
136 return false;
137 }
138 cur = (unsigned)n.Keys[bit];
139 }
140}
diff --git a/CPP/Common/MyMap.h b/CPP/Common/MyMap.h
new file mode 100644
index 0000000..cbcbadd
--- /dev/null
+++ b/CPP/Common/MyMap.h
@@ -0,0 +1,28 @@
1// MyMap.h
2
3#ifndef __COMMON_MYMAP_H
4#define __COMMON_MYMAP_H
5
6#include "MyTypes.h"
7#include "MyVector.h"
8
9class CMap32
10{
11 struct CNode
12 {
13 UInt32 Key;
14 UInt32 Keys[2];
15 UInt32 Values[2];
16 UInt16 Len;
17 Byte IsLeaf[2];
18 };
19 CRecordVector<CNode> Nodes;
20
21public:
22
23 void Clear() { Nodes.Clear(); }
24 bool Find(UInt32 key, UInt32 &valueRes) const throw();
25 bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already
26};
27
28#endif
diff --git a/CPP/Common/MyString.cpp b/CPP/Common/MyString.cpp
new file mode 100644
index 0000000..db202f4
--- /dev/null
+++ b/CPP/Common/MyString.cpp
@@ -0,0 +1,1756 @@
1// Common/MyString.cpp
2
3#include "StdAfx.h"
4
5#ifdef _WIN32
6#include <wchar.h>
7#else
8#include <ctype.h>
9#endif
10
11#include "IntToString.h"
12
13#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)
14#include "StringConvert.h"
15#endif
16
17#include "MyString.h"
18
19#define MY_STRING_NEW(_T_, _size_) new _T_[_size_]
20// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))
21
22/*
23inline const char* MyStringGetNextCharPointer(const char *p) throw()
24{
25 #if defined(_WIN32) && !defined(UNDER_CE)
26 return CharNextA(p);
27 #else
28 return p + 1;
29 #endif
30}
31*/
32
33#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, _size_)
34#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, _size_)
35
36
37int FindCharPosInString(const char *s, char c) throw()
38{
39 for (const char *p = s;; p++)
40 {
41 if (*p == c)
42 return (int)(p - s);
43 if (*p == 0)
44 return -1;
45 // MyStringGetNextCharPointer(p);
46 }
47}
48
49int FindCharPosInString(const wchar_t *s, wchar_t c) throw()
50{
51 for (const wchar_t *p = s;; p++)
52 {
53 if (*p == c)
54 return (int)(p - s);
55 if (*p == 0)
56 return -1;
57 }
58}
59
60/*
61void MyStringUpper_Ascii(char *s) throw()
62{
63 for (;;)
64 {
65 char c = *s;
66 if (c == 0)
67 return;
68 *s++ = MyCharUpper_Ascii(c);
69 }
70}
71
72void MyStringUpper_Ascii(wchar_t *s) throw()
73{
74 for (;;)
75 {
76 wchar_t c = *s;
77 if (c == 0)
78 return;
79 *s++ = MyCharUpper_Ascii(c);
80 }
81}
82*/
83
84void MyStringLower_Ascii(char *s) throw()
85{
86 for (;;)
87 {
88 char c = *s;
89 if (c == 0)
90 return;
91 *s++ = MyCharLower_Ascii(c);
92 }
93}
94
95void MyStringLower_Ascii(wchar_t *s) throw()
96{
97 for (;;)
98 {
99 wchar_t c = *s;
100 if (c == 0)
101 return;
102 *s++ = MyCharLower_Ascii(c);
103 }
104}
105
106#ifdef _WIN32
107
108#ifdef _UNICODE
109
110// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }
111// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }
112// for WinCE - FString - char
113// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }
114
115#else
116
117// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }
118// char * MyStringUpper(char *s) { return CharUpperA(s); }
119// char * MyStringLower(char *s) { return CharLowerA(s); }
120
121wchar_t MyCharUpper_WIN(wchar_t c) throw()
122{
123 wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
124 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
125 return (wchar_t)(unsigned)(UINT_PTR)res;
126 const int kBufSize = 4;
127 char s[kBufSize + 1];
128 int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
129 if (numChars == 0 || numChars > kBufSize)
130 return c;
131 s[numChars] = 0;
132 ::CharUpperA(s);
133 ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
134 return c;
135}
136
137/*
138wchar_t MyCharLower_WIN(wchar_t c)
139{
140 wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
141 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
142 return (wchar_t)(unsigned)(UINT_PTR)res;
143 const int kBufSize = 4;
144 char s[kBufSize + 1];
145 int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);
146 if (numChars == 0 || numChars > kBufSize)
147 return c;
148 s[numChars] = 0;
149 ::CharLowerA(s);
150 ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);
151 return c;
152}
153*/
154
155/*
156wchar_t * MyStringUpper(wchar_t *s)
157{
158 if (s == 0)
159 return 0;
160 wchar_t *res = CharUpperW(s);
161 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
162 return res;
163 AString a = UnicodeStringToMultiByte(s);
164 a.MakeUpper();
165 MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
166 return s;
167}
168*/
169
170/*
171wchar_t * MyStringLower(wchar_t *s)
172{
173 if (s == 0)
174 return 0;
175 wchar_t *res = CharLowerW(s);
176 if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
177 return res;
178 AString a = UnicodeStringToMultiByte(s);
179 a.MakeLower();
180 MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));
181 return s;
182}
183*/
184
185#endif
186
187#endif
188
189bool IsString1PrefixedByString2(const char *s1, const char *s2) throw()
190{
191 for (;;)
192 {
193 unsigned char c2 = (unsigned char)*s2++; if (c2 == 0) return true;
194 unsigned char c1 = (unsigned char)*s1++; if (c1 != c2) return false;
195 }
196}
197
198bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()
199{
200 for (;;)
201 {
202 wchar_t c1 = *s1++;
203 wchar_t c2 = *s2++;
204 if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;
205 if (c1 == 0) return true;
206 }
207}
208
209// ---------- ASCII ----------
210
211bool AString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
212{
213 const char *s1 = _chars;
214 for (;;)
215 {
216 char c2 = *s++;
217 if (c2 == 0)
218 return true;
219 char c1 = *s1++;
220 if (MyCharLower_Ascii(c1) !=
221 MyCharLower_Ascii(c2))
222 return false;
223 }
224}
225
226bool UString::IsPrefixedBy_Ascii_NoCase(const char *s) const throw()
227{
228 const wchar_t *s1 = _chars;
229 for (;;)
230 {
231 char c2 = *s++;
232 if (c2 == 0)
233 return true;
234 wchar_t c1 = *s1++;
235 if (MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
236 return false;
237 }
238}
239
240bool StringsAreEqual_Ascii(const char *u, const char *a) throw()
241{
242 for (;;)
243 {
244 char c = *a;
245 if (c != *u)
246 return false;
247 if (c == 0)
248 return true;
249 a++;
250 u++;
251 }
252}
253
254bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()
255{
256 for (;;)
257 {
258 unsigned char c = (unsigned char)*a;
259 if (c != *u)
260 return false;
261 if (c == 0)
262 return true;
263 a++;
264 u++;
265 }
266}
267
268bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()
269{
270 for (;;)
271 {
272 char c1 = *s1++;
273 char c2 = *s2++;
274 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
275 return false;
276 if (c1 == 0)
277 return true;
278 }
279}
280
281bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()
282{
283 for (;;)
284 {
285 wchar_t c1 = *s1++;
286 wchar_t c2 = *s2++;
287 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
288 return false;
289 if (c1 == 0)
290 return true;
291 }
292}
293
294bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()
295{
296 for (;;)
297 {
298 wchar_t c1 = *s1++;
299 char c2 = *s2++;
300 if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))
301 return false;
302 if (c1 == 0)
303 return true;
304 }
305}
306
307bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()
308{
309 for (;;)
310 {
311 wchar_t c2 = *s2++; if (c2 == 0) return true;
312 wchar_t c1 = *s1++; if (c1 != c2) return false;
313 }
314}
315
316bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()
317{
318 for (;;)
319 {
320 unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;
321 wchar_t c1 = *s1++; if (c1 != c2) return false;
322 }
323}
324
325bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw()
326{
327 for (;;)
328 {
329 char c2 = *s2++; if (c2 == 0) return true;
330 char c1 = *s1++;
331 if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))
332 return false;
333 }
334}
335
336bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()
337{
338 for (;;)
339 {
340 char c2 = *s2++; if (c2 == 0) return true;
341 wchar_t c1 = *s1++;
342 if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))
343 return false;
344 }
345}
346
347bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()
348{
349 for (;;)
350 {
351 wchar_t c2 = *s2++; if (c2 == 0) return true;
352 wchar_t c1 = *s1++;
353 if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))
354 return false;
355 }
356}
357
358// NTFS order: uses upper case
359int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()
360{
361 for (;;)
362 {
363 wchar_t c1 = *s1++;
364 wchar_t c2 = *s2++;
365 if (c1 != c2)
366 {
367 wchar_t u1 = MyCharUpper(c1);
368 wchar_t u2 = MyCharUpper(c2);
369 if (u1 < u2) return -1;
370 if (u1 > u2) return 1;
371 }
372 if (c1 == 0) return 0;
373 }
374}
375
376/*
377int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)
378{
379 for (; num != 0; num--)
380 {
381 wchar_t c1 = *s1++;
382 wchar_t c2 = *s2++;
383 if (c1 != c2)
384 {
385 wchar_t u1 = MyCharUpper(c1);
386 wchar_t u2 = MyCharUpper(c2);
387 if (u1 < u2) return -1;
388 if (u1 > u2) return 1;
389 }
390 if (c1 == 0) return 0;
391 }
392 return 0;
393}
394*/
395
396// ---------- AString ----------
397
398void AString::InsertSpace(unsigned &index, unsigned size)
399{
400 Grow(size);
401 MoveItems(index + size, index);
402}
403
404#define k_Alloc_Len_Limit 0x40000000
405
406void AString::ReAlloc(unsigned newLimit)
407{
408 if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130220;
409 // MY_STRING_REALLOC(_chars, char, newLimit + 1, _len + 1);
410 char *newBuf = MY_STRING_NEW_char(newLimit + 1);
411 memcpy(newBuf, _chars, (size_t)(_len + 1));
412 MY_STRING_DELETE(_chars);
413 _chars = newBuf;
414 _limit = newLimit;
415}
416
417void AString::ReAlloc2(unsigned newLimit)
418{
419 if (newLimit >= k_Alloc_Len_Limit) throw 20130220;
420 // MY_STRING_REALLOC(_chars, char, newLimit + 1, 0);
421 char *newBuf = MY_STRING_NEW_char(newLimit + 1);
422 newBuf[0] = 0;
423 MY_STRING_DELETE(_chars);
424 _chars = newBuf;
425 _limit = newLimit;
426}
427
428void AString::SetStartLen(unsigned len)
429{
430 _chars = 0;
431 _chars = MY_STRING_NEW_char(len + 1);
432 _len = len;
433 _limit = len;
434}
435
436void AString::Grow_1()
437{
438 unsigned next = _len;
439 next += next / 2;
440 next += 16;
441 next &= ~(unsigned)15;
442 ReAlloc(next - 1);
443}
444
445void AString::Grow(unsigned n)
446{
447 unsigned freeSize = _limit - _len;
448 if (n <= freeSize)
449 return;
450
451 unsigned next = _len + n;
452 next += next / 2;
453 next += 16;
454 next &= ~(unsigned)15;
455 ReAlloc(next - 1);
456}
457
458AString::AString(unsigned num, const char *s)
459{
460 unsigned len = MyStringLen(s);
461 if (num > len)
462 num = len;
463 SetStartLen(num);
464 memcpy(_chars, s, num);
465 _chars[num] = 0;
466}
467
468AString::AString(unsigned num, const AString &s)
469{
470 if (num > s._len)
471 num = s._len;
472 SetStartLen(num);
473 memcpy(_chars, s._chars, num);
474 _chars[num] = 0;
475}
476
477AString::AString(const AString &s, char c)
478{
479 SetStartLen(s.Len() + 1);
480 char *chars = _chars;
481 unsigned len = s.Len();
482 memcpy(chars, s, len);
483 chars[len] = c;
484 chars[(size_t)len + 1] = 0;
485}
486
487AString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)
488{
489 SetStartLen(num1 + num2);
490 char *chars = _chars;
491 memcpy(chars, s1, num1);
492 memcpy(chars + num1, s2, num2 + 1);
493}
494
495AString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }
496AString operator+(const AString &s1, const char *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }
497AString operator+(const char *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }
498
499static const unsigned kStartStringCapacity = 4;
500
501AString::AString()
502{
503 _chars = 0;
504 _chars = MY_STRING_NEW_char(kStartStringCapacity);
505 _len = 0;
506 _limit = kStartStringCapacity - 1;
507 _chars[0] = 0;
508}
509
510AString::AString(char c)
511{
512 SetStartLen(1);
513 char *chars = _chars;
514 chars[0] = c;
515 chars[1] = 0;
516}
517
518AString::AString(const char *s)
519{
520 SetStartLen(MyStringLen(s));
521 MyStringCopy(_chars, s);
522}
523
524AString::AString(const AString &s)
525{
526 SetStartLen(s._len);
527 MyStringCopy(_chars, s._chars);
528}
529
530AString &AString::operator=(char c)
531{
532 if (1 > _limit)
533 {
534 char *newBuf = MY_STRING_NEW_char(1 + 1);
535 MY_STRING_DELETE(_chars);
536 _chars = newBuf;
537 _limit = 1;
538 }
539 _len = 1;
540 char *chars = _chars;
541 chars[0] = c;
542 chars[1] = 0;
543 return *this;
544}
545
546AString &AString::operator=(const char *s)
547{
548 unsigned len = MyStringLen(s);
549 if (len > _limit)
550 {
551 char *newBuf = MY_STRING_NEW_char(len + 1);
552 MY_STRING_DELETE(_chars);
553 _chars = newBuf;
554 _limit = len;
555 }
556 _len = len;
557 MyStringCopy(_chars, s);
558 return *this;
559}
560
561AString &AString::operator=(const AString &s)
562{
563 if (&s == this)
564 return *this;
565 unsigned len = s._len;
566 if (len > _limit)
567 {
568 char *newBuf = MY_STRING_NEW_char(len + 1);
569 MY_STRING_DELETE(_chars);
570 _chars = newBuf;
571 _limit = len;
572 }
573 _len = len;
574 MyStringCopy(_chars, s._chars);
575 return *this;
576}
577
578void AString::SetFromWStr_if_Ascii(const wchar_t *s)
579{
580 unsigned len = 0;
581 {
582 for (;; len++)
583 {
584 wchar_t c = s[len];
585 if (c == 0)
586 break;
587 if (c >= 0x80)
588 return;
589 }
590 }
591 if (len > _limit)
592 {
593 char *newBuf = MY_STRING_NEW_char(len + 1);
594 MY_STRING_DELETE(_chars);
595 _chars = newBuf;
596 _limit = len;
597 }
598 _len = len;
599 char *dest = _chars;
600 unsigned i;
601 for (i = 0; i < len; i++)
602 dest[i] = (char)s[i];
603 dest[i] = 0;
604}
605
606/*
607void AString::SetFromBstr_if_Ascii(BSTR s)
608{
609 unsigned len = ::SysStringLen(s);
610 {
611 for (unsigned i = 0; i < len; i++)
612 if (s[i] <= 0 || s[i] >= 0x80)
613 return;
614 }
615 if (len > _limit)
616 {
617 char *newBuf = MY_STRING_NEW_char(len + 1);
618 MY_STRING_DELETE(_chars);
619 _chars = newBuf;
620 _limit = len;
621 }
622 _len = len;
623 char *dest = _chars;
624 unsigned i;
625 for (i = 0; i < len; i++)
626 dest[i] = (char)s[i];
627 dest[i] = 0;
628}
629*/
630
631void AString::Add_Space() { operator+=(' '); }
632void AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
633void AString::Add_LF() { operator+=('\n'); }
634
635AString &AString::operator+=(const char *s)
636{
637 unsigned len = MyStringLen(s);
638 Grow(len);
639 MyStringCopy(_chars + _len, s);
640 _len += len;
641 return *this;
642}
643
644void AString::Add_OptSpaced(const char *s)
645{
646 Add_Space_if_NotEmpty();
647 (*this) += s;
648}
649
650AString &AString::operator+=(const AString &s)
651{
652 Grow(s._len);
653 MyStringCopy(_chars + _len, s._chars);
654 _len += s._len;
655 return *this;
656}
657
658void AString::Add_UInt32(UInt32 v)
659{
660 Grow(10);
661 _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
662}
663
664void UString::Add_UInt64(UInt64 v)
665{
666 Grow(20);
667 _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
668}
669
670void AString::SetFrom(const char *s, unsigned len) // no check
671{
672 if (len > _limit)
673 {
674 char *newBuf = MY_STRING_NEW_char(len + 1);
675 MY_STRING_DELETE(_chars);
676 _chars = newBuf;
677 _limit = len;
678 }
679 if (len != 0)
680 memcpy(_chars, s, len);
681 _chars[len] = 0;
682 _len = len;
683}
684
685void AString::SetFrom_CalcLen(const char *s, unsigned len) // no check
686{
687 unsigned i;
688 for (i = 0; i < len; i++)
689 if (s[i] == 0)
690 break;
691 SetFrom(s, i);
692}
693
694int AString::Find(const char *s, unsigned startIndex) const throw()
695{
696 const char *fs = strstr(_chars + startIndex, s);
697 if (!fs)
698 return -1;
699 return (int)(fs - _chars);
700
701 /*
702 if (s[0] == 0)
703 return startIndex;
704 unsigned len = MyStringLen(s);
705 const char *p = _chars + startIndex;
706 for (;; p++)
707 {
708 const char c = *p;
709 if (c != s[0])
710 {
711 if (c == 0)
712 return -1;
713 continue;
714 }
715 unsigned i;
716 for (i = 1; i < len; i++)
717 if (p[i] != s[i])
718 break;
719 if (i == len)
720 return (int)(p - _chars);
721 }
722 */
723}
724
725int AString::ReverseFind(char c) const throw()
726{
727 if (_len == 0)
728 return -1;
729 const char *p = _chars + _len - 1;
730 for (;;)
731 {
732 if (*p == c)
733 return (int)(p - _chars);
734 if (p == _chars)
735 return -1;
736 p--; // p = GetPrevCharPointer(_chars, p);
737 }
738}
739
740int AString::ReverseFind_PathSepar() const throw()
741{
742 if (_len == 0)
743 return -1;
744 const char *p = _chars + _len - 1;
745 for (;;)
746 {
747 char c = *p;
748 if (IS_PATH_SEPAR(c))
749 return (int)(p - _chars);
750 if (p == _chars)
751 return -1;
752 p--;
753 }
754}
755
756void AString::TrimLeft() throw()
757{
758 const char *p = _chars;
759 for (;; p++)
760 {
761 char c = *p;
762 if (c != ' ' && c != '\n' && c != '\t')
763 break;
764 }
765 unsigned pos = (unsigned)(p - _chars);
766 if (pos != 0)
767 {
768 MoveItems(0, pos);
769 _len -= pos;
770 }
771}
772
773void AString::TrimRight() throw()
774{
775 const char *p = _chars;
776 unsigned i;
777 for (i = _len; i != 0; i--)
778 {
779 char c = p[(size_t)i - 1];
780 if (c != ' ' && c != '\n' && c != '\t')
781 break;
782 }
783 if (i != _len)
784 {
785 _chars[i] = 0;
786 _len = i;
787 }
788}
789
790void AString::InsertAtFront(char c)
791{
792 if (_limit == _len)
793 Grow_1();
794 MoveItems(1, 0);
795 _chars[0] = c;
796 _len++;
797}
798
799/*
800void AString::Insert(unsigned index, char c)
801{
802 InsertSpace(index, 1);
803 _chars[index] = c;
804 _len++;
805}
806*/
807
808void AString::Insert(unsigned index, const char *s)
809{
810 unsigned num = MyStringLen(s);
811 if (num != 0)
812 {
813 InsertSpace(index, num);
814 memcpy(_chars + index, s, num);
815 _len += num;
816 }
817}
818
819void AString::Insert(unsigned index, const AString &s)
820{
821 unsigned num = s.Len();
822 if (num != 0)
823 {
824 InsertSpace(index, num);
825 memcpy(_chars + index, s, num);
826 _len += num;
827 }
828}
829
830void AString::RemoveChar(char ch) throw()
831{
832 char *src = _chars;
833
834 for (;;)
835 {
836 char c = *src++;
837 if (c == 0)
838 return;
839 if (c == ch)
840 break;
841 }
842
843 char *dest = src - 1;
844
845 for (;;)
846 {
847 char c = *src++;
848 if (c == 0)
849 break;
850 if (c != ch)
851 *dest++ = c;
852 }
853
854 *dest = 0;
855 _len = (unsigned)(dest - _chars);
856}
857
858// !!!!!!!!!!!!!!! test it if newChar = '\0'
859void AString::Replace(char oldChar, char newChar) throw()
860{
861 if (oldChar == newChar)
862 return; // 0;
863 // unsigned number = 0;
864 int pos = 0;
865 char *chars = _chars;
866 while ((unsigned)pos < _len)
867 {
868 pos = Find(oldChar, (unsigned)pos);
869 if (pos < 0)
870 break;
871 chars[(unsigned)pos] = newChar;
872 pos++;
873 // number++;
874 }
875 return; // number;
876}
877
878void AString::Replace(const AString &oldString, const AString &newString)
879{
880 if (oldString.IsEmpty())
881 return; // 0;
882 if (oldString == newString)
883 return; // 0;
884 unsigned oldLen = oldString.Len();
885 unsigned newLen = newString.Len();
886 // unsigned number = 0;
887 int pos = 0;
888 while ((unsigned)pos < _len)
889 {
890 pos = Find(oldString, (unsigned)pos);
891 if (pos < 0)
892 break;
893 Delete((unsigned)pos, oldLen);
894 Insert((unsigned)pos, newString);
895 pos += newLen;
896 // number++;
897 }
898 // return number;
899}
900
901void AString::Delete(unsigned index) throw()
902{
903 MoveItems(index, index + 1);
904 _len--;
905}
906
907void AString::Delete(unsigned index, unsigned count) throw()
908{
909 if (index + count > _len)
910 count = _len - index;
911 if (count > 0)
912 {
913 MoveItems(index, index + count);
914 _len -= count;
915 }
916}
917
918void AString::DeleteFrontal(unsigned num) throw()
919{
920 if (num != 0)
921 {
922 MoveItems(0, num);
923 _len -= num;
924 }
925}
926
927/*
928AString operator+(const AString &s1, const AString &s2)
929{
930 AString result(s1);
931 result += s2;
932 return result;
933}
934
935AString operator+(const AString &s, const char *chars)
936{
937 AString result(s);
938 result += chars;
939 return result;
940}
941
942AString operator+(const char *chars, const AString &s)
943{
944 AString result(chars);
945 result += s;
946 return result;
947}
948
949AString operator+(const AString &s, char c)
950{
951 AString result(s);
952 result += c;
953 return result;
954}
955*/
956
957/*
958AString operator+(char c, const AString &s)
959{
960 AString result(c);
961 result += s;
962 return result;
963}
964*/
965
966
967
968
969// ---------- UString ----------
970
971void UString::InsertSpace(unsigned index, unsigned size)
972{
973 Grow(size);
974 MoveItems(index + size, index);
975}
976
977void UString::ReAlloc(unsigned newLimit)
978{
979 if (newLimit < _len || newLimit >= k_Alloc_Len_Limit) throw 20130221;
980 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, _len + 1);
981 wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
982 wmemcpy(newBuf, _chars, _len + 1);
983 MY_STRING_DELETE(_chars);
984 _chars = newBuf;
985 _limit = newLimit;
986}
987
988void UString::ReAlloc2(unsigned newLimit)
989{
990 if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
991 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
992 wchar_t *newBuf = MY_STRING_NEW_wchar_t(newLimit + 1);
993 newBuf[0] = 0;
994 MY_STRING_DELETE(_chars);
995 _chars = newBuf;
996 _limit = newLimit;
997}
998
999void UString::SetStartLen(unsigned len)
1000{
1001 _chars = 0;
1002 _chars = MY_STRING_NEW_wchar_t(len + 1);
1003 _len = len;
1004 _limit = len;
1005}
1006
1007void UString::Grow_1()
1008{
1009 unsigned next = _len;
1010 next += next / 2;
1011 next += 16;
1012 next &= ~(unsigned)15;
1013 ReAlloc(next - 1);
1014}
1015
1016void UString::Grow(unsigned n)
1017{
1018 unsigned freeSize = _limit - _len;
1019 if (n <= freeSize)
1020 return;
1021
1022 unsigned next = _len + n;
1023 next += next / 2;
1024 next += 16;
1025 next &= ~(unsigned)15;
1026 ReAlloc(next - 1);
1027}
1028
1029
1030UString::UString(unsigned num, const wchar_t *s)
1031{
1032 unsigned len = MyStringLen(s);
1033 if (num > len)
1034 num = len;
1035 SetStartLen(num);
1036 wmemcpy(_chars, s, num);
1037 _chars[num] = 0;
1038}
1039
1040
1041UString::UString(unsigned num, const UString &s)
1042{
1043 if (num > s._len)
1044 num = s._len;
1045 SetStartLen(num);
1046 wmemcpy(_chars, s._chars, num);
1047 _chars[num] = 0;
1048}
1049
1050UString::UString(const UString &s, wchar_t c)
1051{
1052 SetStartLen(s.Len() + 1);
1053 wchar_t *chars = _chars;
1054 unsigned len = s.Len();
1055 wmemcpy(chars, s, len);
1056 chars[len] = c;
1057 chars[(size_t)len + 1] = 0;
1058}
1059
1060UString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)
1061{
1062 SetStartLen(num1 + num2);
1063 wchar_t *chars = _chars;
1064 wmemcpy(chars, s1, num1);
1065 wmemcpy(chars + num1, s2, num2 + 1);
1066}
1067
1068UString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }
1069UString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }
1070UString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }
1071
1072UString::UString()
1073{
1074 _chars = 0;
1075 _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);
1076 _len = 0;
1077 _limit = kStartStringCapacity - 1;
1078 _chars[0] = 0;
1079}
1080
1081UString::UString(wchar_t c)
1082{
1083 SetStartLen(1);
1084 wchar_t *chars = _chars;
1085 chars[0] = c;
1086 chars[1] = 0;
1087}
1088
1089UString::UString(char c)
1090{
1091 SetStartLen(1);
1092 wchar_t *chars = _chars;
1093 chars[0] = (unsigned char)c;
1094 chars[1] = 0;
1095}
1096
1097UString::UString(const wchar_t *s)
1098{
1099 const unsigned len = MyStringLen(s);
1100 SetStartLen(len);
1101 wmemcpy(_chars, s, len + 1);
1102}
1103
1104UString::UString(const char *s)
1105{
1106 const unsigned len = MyStringLen(s);
1107 SetStartLen(len);
1108 wchar_t *chars = _chars;
1109 for (unsigned i = 0; i < len; i++)
1110 chars[i] = (unsigned char)s[i];
1111 chars[len] = 0;
1112}
1113
1114UString::UString(const AString &s)
1115{
1116 const unsigned len = s.Len();
1117 SetStartLen(len);
1118 wchar_t *chars = _chars;
1119 const char *s2 = s.Ptr();
1120 for (unsigned i = 0; i < len; i++)
1121 chars[i] = (unsigned char)s2[i];
1122 chars[len] = 0;
1123}
1124
1125UString::UString(const UString &s)
1126{
1127 SetStartLen(s._len);
1128 wmemcpy(_chars, s._chars, s._len + 1);
1129}
1130
1131UString &UString::operator=(wchar_t c)
1132{
1133 if (1 > _limit)
1134 {
1135 wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1136 MY_STRING_DELETE(_chars);
1137 _chars = newBuf;
1138 _limit = 1;
1139 }
1140 _len = 1;
1141 wchar_t *chars = _chars;
1142 chars[0] = c;
1143 chars[1] = 0;
1144 return *this;
1145}
1146
1147UString &UString::operator=(const wchar_t *s)
1148{
1149 unsigned len = MyStringLen(s);
1150 if (len > _limit)
1151 {
1152 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1153 MY_STRING_DELETE(_chars);
1154 _chars = newBuf;
1155 _limit = len;
1156 }
1157 _len = len;
1158 wmemcpy(_chars, s, len + 1);
1159 return *this;
1160}
1161
1162UString &UString::operator=(const UString &s)
1163{
1164 if (&s == this)
1165 return *this;
1166 unsigned len = s._len;
1167 if (len > _limit)
1168 {
1169 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1170 MY_STRING_DELETE(_chars);
1171 _chars = newBuf;
1172 _limit = len;
1173 }
1174 _len = len;
1175 wmemcpy(_chars, s._chars, len + 1);
1176 return *this;
1177}
1178
1179void UString::SetFrom(const wchar_t *s, unsigned len) // no check
1180{
1181 if (len > _limit)
1182 {
1183 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1184 MY_STRING_DELETE(_chars);
1185 _chars = newBuf;
1186 _limit = len;
1187 }
1188 if (len != 0)
1189 wmemcpy(_chars, s, len);
1190 _chars[len] = 0;
1191 _len = len;
1192}
1193
1194void UString::SetFromBstr(LPCOLESTR s)
1195{
1196 unsigned len = ::SysStringLen((BSTR)(void *)(s));
1197
1198 /*
1199 #if WCHAR_MAX > 0xffff
1200 size_t num_wchars = 0;
1201 for (size_t i = 0; i < len;)
1202 {
1203 wchar_t c = s[i++];
1204 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1205 {
1206 wchar_t c2 = s[i];
1207 if (c2 >= 0xdc00 && c2 < 0x10000)
1208 {
1209 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1210 i++;
1211 }
1212 }
1213 num_wchars++;
1214 }
1215 len = num_wchars;
1216 #endif
1217 */
1218
1219 if (len > _limit)
1220 {
1221 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1222 MY_STRING_DELETE(_chars);
1223 _chars = newBuf;
1224 _limit = len;
1225 }
1226 _len = len;
1227
1228 /*
1229 #if WCHAR_MAX > 0xffff
1230
1231 wchar_t *chars = _chars;
1232 for (size_t i = 0; i <= len; i++)
1233 {
1234 wchar_t c = *s++;
1235 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
1236 {
1237 wchar_t c2 = *s;
1238 if (c2 >= 0xdc00 && c2 < 0x10000)
1239 {
1240 s++;
1241 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
1242 }
1243 }
1244 chars[i] = c;
1245 }
1246
1247 #else
1248 */
1249
1250 // if (s)
1251 wmemcpy(_chars, s, len + 1);
1252
1253 // #endif
1254}
1255
1256UString &UString::operator=(const char *s)
1257{
1258 unsigned len = MyStringLen(s);
1259 if (len > _limit)
1260 {
1261 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1262 MY_STRING_DELETE(_chars);
1263 _chars = newBuf;
1264 _limit = len;
1265 }
1266 wchar_t *chars = _chars;
1267 for (unsigned i = 0; i < len; i++)
1268 chars[i] = (unsigned char)s[i];
1269 chars[len] = 0;
1270 _len = len;
1271 return *this;
1272}
1273
1274void UString::Add_Space() { operator+=(L' '); }
1275void UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }
1276
1277void UString::Add_LF()
1278{
1279 if (_limit == _len)
1280 Grow_1();
1281 unsigned len = _len;
1282 wchar_t *chars = _chars;
1283 chars[len++] = L'\n';
1284 chars[len] = 0;
1285 _len = len;
1286}
1287
1288UString &UString::operator+=(const wchar_t *s)
1289{
1290 unsigned len = MyStringLen(s);
1291 Grow(len);
1292 wmemcpy(_chars + _len, s, len + 1);
1293 _len += len;
1294 return *this;
1295}
1296
1297UString &UString::operator+=(const UString &s)
1298{
1299 Grow(s._len);
1300 wmemcpy(_chars + _len, s._chars, s._len + 1);
1301 _len += s._len;
1302 return *this;
1303}
1304
1305UString &UString::operator+=(const char *s)
1306{
1307 unsigned len = MyStringLen(s);
1308 Grow(len);
1309 wchar_t *chars = _chars + _len;
1310 for (unsigned i = 0; i < len; i++)
1311 chars[i] = (unsigned char)s[i];
1312 chars[len] = 0;
1313 _len += len;
1314 return *this;
1315}
1316
1317
1318void UString::Add_UInt32(UInt32 v)
1319{
1320 Grow(10);
1321 _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);
1322}
1323
1324void AString::Add_UInt64(UInt64 v)
1325{
1326 Grow(20);
1327 _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);
1328}
1329
1330
1331int UString::Find(const wchar_t *s, unsigned startIndex) const throw()
1332{
1333 const wchar_t *fs = wcsstr(_chars + startIndex, s);
1334 if (!fs)
1335 return -1;
1336 return (int)(fs - _chars);
1337
1338 /*
1339 if (s[0] == 0)
1340 return startIndex;
1341 unsigned len = MyStringLen(s);
1342 const wchar_t *p = _chars + startIndex;
1343 for (;; p++)
1344 {
1345 const wchar_t c = *p;
1346 if (c != s[0])
1347 {
1348 if (c == 0)
1349 return -1;
1350 continue;
1351 }
1352 unsigned i;
1353 for (i = 1; i < len; i++)
1354 if (p[i] != s[i])
1355 break;
1356 if (i == len)
1357 return (int)(p - _chars);
1358 }
1359 */
1360}
1361
1362int UString::ReverseFind(wchar_t c) const throw()
1363{
1364 if (_len == 0)
1365 return -1;
1366 const wchar_t *p = _chars + _len - 1;
1367 for (;;)
1368 {
1369 if (*p == c)
1370 return (int)(p - _chars);
1371 if (p == _chars)
1372 return -1;
1373 p--;
1374 }
1375}
1376
1377int UString::ReverseFind_PathSepar() const throw()
1378{
1379 if (_len == 0)
1380 return -1;
1381 const wchar_t *p = _chars + _len - 1;
1382 for (;;)
1383 {
1384 wchar_t c = *p;
1385 if (IS_PATH_SEPAR(c))
1386 return (int)(p - _chars);
1387 if (p == _chars)
1388 return -1;
1389 p--;
1390 }
1391}
1392
1393void UString::TrimLeft() throw()
1394{
1395 const wchar_t *p = _chars;
1396 for (;; p++)
1397 {
1398 wchar_t c = *p;
1399 if (c != ' ' && c != '\n' && c != '\t')
1400 break;
1401 }
1402 unsigned pos = (unsigned)(p - _chars);
1403 if (pos != 0)
1404 {
1405 MoveItems(0, pos);
1406 _len -= pos;
1407 }
1408}
1409
1410void UString::TrimRight() throw()
1411{
1412 const wchar_t *p = _chars;
1413 unsigned i;
1414 for (i = _len; i != 0; i--)
1415 {
1416 wchar_t c = p[(size_t)i - 1];
1417 if (c != ' ' && c != '\n' && c != '\t')
1418 break;
1419 }
1420 if (i != _len)
1421 {
1422 _chars[i] = 0;
1423 _len = i;
1424 }
1425}
1426
1427void UString::InsertAtFront(wchar_t c)
1428{
1429 if (_limit == _len)
1430 Grow_1();
1431 MoveItems(1, 0);
1432 _chars[0] = c;
1433 _len++;
1434}
1435
1436/*
1437void UString::Insert_wchar_t(unsigned index, wchar_t c)
1438{
1439 InsertSpace(index, 1);
1440 _chars[index] = c;
1441 _len++;
1442}
1443*/
1444
1445void UString::Insert(unsigned index, const wchar_t *s)
1446{
1447 unsigned num = MyStringLen(s);
1448 if (num != 0)
1449 {
1450 InsertSpace(index, num);
1451 wmemcpy(_chars + index, s, num);
1452 _len += num;
1453 }
1454}
1455
1456void UString::Insert(unsigned index, const UString &s)
1457{
1458 unsigned num = s.Len();
1459 if (num != 0)
1460 {
1461 InsertSpace(index, num);
1462 wmemcpy(_chars + index, s, num);
1463 _len += num;
1464 }
1465}
1466
1467void UString::RemoveChar(wchar_t ch) throw()
1468{
1469 wchar_t *src = _chars;
1470
1471 for (;;)
1472 {
1473 wchar_t c = *src++;
1474 if (c == 0)
1475 return;
1476 if (c == ch)
1477 break;
1478 }
1479
1480 wchar_t *dest = src - 1;
1481
1482 for (;;)
1483 {
1484 wchar_t c = *src++;
1485 if (c == 0)
1486 break;
1487 if (c != ch)
1488 *dest++ = c;
1489 }
1490
1491 *dest = 0;
1492 _len = (unsigned)(dest - _chars);
1493}
1494
1495// !!!!!!!!!!!!!!! test it if newChar = '\0'
1496void UString::Replace(wchar_t oldChar, wchar_t newChar) throw()
1497{
1498 if (oldChar == newChar)
1499 return; // 0;
1500 // unsigned number = 0;
1501 int pos = 0;
1502 wchar_t *chars = _chars;
1503 while ((unsigned)pos < _len)
1504 {
1505 pos = Find(oldChar, (unsigned)pos);
1506 if (pos < 0)
1507 break;
1508 chars[(unsigned)pos] = newChar;
1509 pos++;
1510 // number++;
1511 }
1512 return; // number;
1513}
1514
1515void UString::Replace(const UString &oldString, const UString &newString)
1516{
1517 if (oldString.IsEmpty())
1518 return; // 0;
1519 if (oldString == newString)
1520 return; // 0;
1521 unsigned oldLen = oldString.Len();
1522 unsigned newLen = newString.Len();
1523 // unsigned number = 0;
1524 int pos = 0;
1525 while ((unsigned)pos < _len)
1526 {
1527 pos = Find(oldString, (unsigned)pos);
1528 if (pos < 0)
1529 break;
1530 Delete((unsigned)pos, oldLen);
1531 Insert((unsigned)pos, newString);
1532 pos += newLen;
1533 // number++;
1534 }
1535 // return number;
1536}
1537
1538void UString::Delete(unsigned index) throw()
1539{
1540 MoveItems(index, index + 1);
1541 _len--;
1542}
1543
1544void UString::Delete(unsigned index, unsigned count) throw()
1545{
1546 if (index + count > _len)
1547 count = _len - index;
1548 if (count > 0)
1549 {
1550 MoveItems(index, index + count);
1551 _len -= count;
1552 }
1553}
1554
1555void UString::DeleteFrontal(unsigned num) throw()
1556{
1557 if (num != 0)
1558 {
1559 MoveItems(0, num);
1560 _len -= num;
1561 }
1562}
1563
1564
1565// ---------- UString2 ----------
1566
1567void UString2::ReAlloc2(unsigned newLimit)
1568{
1569 if (newLimit >= k_Alloc_Len_Limit) throw 20130221;
1570 // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);
1571 _chars = MY_STRING_NEW_wchar_t(newLimit + 1);
1572}
1573
1574void UString2::SetStartLen(unsigned len)
1575{
1576 _chars = 0;
1577 _chars = MY_STRING_NEW_wchar_t(len + 1);
1578 _len = len;
1579}
1580
1581
1582/*
1583UString2::UString2(wchar_t c)
1584{
1585 SetStartLen(1);
1586 wchar_t *chars = _chars;
1587 chars[0] = c;
1588 chars[1] = 0;
1589}
1590*/
1591
1592UString2::UString2(const wchar_t *s)
1593{
1594 unsigned len = MyStringLen(s);
1595 SetStartLen(len);
1596 wmemcpy(_chars, s, len + 1);
1597}
1598
1599UString2::UString2(const UString2 &s): _chars(NULL), _len(0)
1600{
1601 if (s._chars)
1602 {
1603 SetStartLen(s._len);
1604 wmemcpy(_chars, s._chars, s._len + 1);
1605 }
1606}
1607
1608/*
1609UString2 &UString2::operator=(wchar_t c)
1610{
1611 if (1 > _len)
1612 {
1613 wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);
1614 if (_chars)
1615 MY_STRING_DELETE(_chars);
1616 _chars = newBuf;
1617 }
1618 _len = 1;
1619 wchar_t *chars = _chars;
1620 chars[0] = c;
1621 chars[1] = 0;
1622 return *this;
1623}
1624*/
1625
1626UString2 &UString2::operator=(const wchar_t *s)
1627{
1628 unsigned len = MyStringLen(s);
1629 if (len > _len)
1630 {
1631 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1632 if (_chars)
1633 MY_STRING_DELETE(_chars);
1634 _chars = newBuf;
1635 }
1636 _len = len;
1637 MyStringCopy(_chars, s);
1638 return *this;
1639}
1640
1641void UString2::SetFromAscii(const char *s)
1642{
1643 unsigned len = MyStringLen(s);
1644 if (len > _len)
1645 {
1646 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1647 if (_chars)
1648 MY_STRING_DELETE(_chars);
1649 _chars = newBuf;
1650 }
1651 wchar_t *chars = _chars;
1652 for (unsigned i = 0; i < len; i++)
1653 chars[i] = (unsigned char)s[i];
1654 chars[len] = 0;
1655 _len = len;
1656}
1657
1658UString2 &UString2::operator=(const UString2 &s)
1659{
1660 if (&s == this)
1661 return *this;
1662 unsigned len = s._len;
1663 if (len > _len)
1664 {
1665 wchar_t *newBuf = MY_STRING_NEW_wchar_t(len + 1);
1666 if (_chars)
1667 MY_STRING_DELETE(_chars);
1668 _chars = newBuf;
1669 }
1670 _len = len;
1671 MyStringCopy(_chars, s._chars);
1672 return *this;
1673}
1674
1675bool operator==(const UString2 &s1, const UString2 &s2)
1676{
1677 return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);
1678}
1679
1680bool operator==(const UString2 &s1, const wchar_t *s2)
1681{
1682 if (s1.IsEmpty())
1683 return (*s2 == 0);
1684 return wcscmp(s1.GetRawPtr(), s2) == 0;
1685}
1686
1687bool operator==(const wchar_t *s1, const UString2 &s2)
1688{
1689 if (s2.IsEmpty())
1690 return (*s1 == 0);
1691 return wcscmp(s1, s2.GetRawPtr()) == 0;
1692}
1693
1694
1695
1696// ----------------------------------------
1697
1698/*
1699int MyStringCompareNoCase(const char *s1, const char *s2)
1700{
1701 return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));
1702}
1703*/
1704
1705#if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE)
1706
1707static inline UINT GetCurrentCodePage()
1708{
1709 #if defined(UNDER_CE) || !defined(_WIN32)
1710 return CP_ACP;
1711 #else
1712 return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1713 #endif
1714}
1715
1716#endif
1717
1718#ifdef USE_UNICODE_FSTRING
1719
1720#ifndef _UNICODE
1721
1722AString fs2fas(CFSTR s)
1723{
1724 return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1725}
1726
1727FString fas2fs(const char *s)
1728{
1729 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1730}
1731
1732FString fas2fs(const AString &s)
1733{
1734 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1735}
1736
1737#endif // _UNICODE
1738
1739#else // USE_UNICODE_FSTRING
1740
1741UString fs2us(const FChar *s)
1742{
1743 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1744}
1745
1746UString fs2us(const FString &s)
1747{
1748 return MultiByteToUnicodeString(s, GetCurrentCodePage());
1749}
1750
1751FString us2fs(const wchar_t *s)
1752{
1753 return UnicodeStringToMultiByte(s, GetCurrentCodePage());
1754}
1755
1756#endif // USE_UNICODE_FSTRING
diff --git a/CPP/Common/MyString.h b/CPP/Common/MyString.h
new file mode 100644
index 0000000..aa3c301
--- /dev/null
+++ b/CPP/Common/MyString.h
@@ -0,0 +1,1012 @@
1// Common/MyString.h
2
3#ifndef __COMMON_MY_STRING_H
4#define __COMMON_MY_STRING_H
5
6#include <string.h>
7
8#ifndef _WIN32
9#include <wctype.h>
10#include <wchar.h>
11#endif
12
13#include "MyWindows.h"
14#include "MyTypes.h"
15#include "MyVector.h"
16
17
18/* if (DEBUG_FSTRING_INHERITS_ASTRING is defined), then
19 FString inherits from AString, so we can find bugs related to FString at compile time.
20 DON'T define DEBUG_FSTRING_INHERITS_ASTRING in release code */
21
22// #define DEBUG_FSTRING_INHERITS_ASTRING
23
24#ifdef DEBUG_FSTRING_INHERITS_ASTRING
25class FString;
26#endif
27
28
29#ifdef _MSC_VER
30 #ifdef _NATIVE_WCHAR_T_DEFINED
31 #define MY_NATIVE_WCHAR_T_DEFINED
32 #endif
33#else
34 #define MY_NATIVE_WCHAR_T_DEFINED
35#endif
36
37/*
38 native support for wchar_t:
39 _MSC_VER == 1600 : /Zc:wchar_t is not supported
40 _MSC_VER == 1310 (VS2003)
41 ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short
42 /Zc:wchar_t : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED
43 _MSC_VER > 1400 (VS2008+)
44 /Zc:wchar_t[-]
45 /Zc:wchar_t is on by default
46*/
47
48#ifdef _WIN32
49#define IS_PATH_SEPAR(c) ((c) == '\\' || (c) == '/')
50#else
51#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)
52#endif
53
54inline bool IsPathSepar(char c) { return IS_PATH_SEPAR(c); }
55inline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }
56
57inline unsigned MyStringLen(const char *s)
58{
59 unsigned i;
60 for (i = 0; s[i] != 0; i++);
61 return i;
62}
63
64inline void MyStringCopy(char *dest, const char *src)
65{
66 while ((*dest++ = *src++) != 0);
67}
68
69inline char *MyStpCpy(char *dest, const char *src)
70{
71 for (;;)
72 {
73 char c = *src;
74 *dest = c;
75 if (c == 0)
76 return dest;
77 src++;
78 dest++;
79 }
80}
81
82inline unsigned MyStringLen(const wchar_t *s)
83{
84 unsigned i;
85 for (i = 0; s[i] != 0; i++);
86 return i;
87}
88
89inline void MyStringCopy(wchar_t *dest, const wchar_t *src)
90{
91 while ((*dest++ = *src++) != 0);
92}
93
94inline void MyStringCat(wchar_t *dest, const wchar_t *src)
95{
96 MyStringCopy(dest + MyStringLen(dest), src);
97}
98
99
100/*
101inline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)
102{
103 for (;;)
104 {
105 wchar_t c = *src;
106 *dest = c;
107 if (c == 0)
108 return dest;
109 src++;
110 dest++;
111 }
112}
113*/
114
115int FindCharPosInString(const char *s, char c) throw();
116int FindCharPosInString(const wchar_t *s, wchar_t c) throw();
117
118#ifdef _WIN32
119 #ifndef _UNICODE
120 #define STRING_UNICODE_THROW
121 #endif
122#endif
123
124#ifndef STRING_UNICODE_THROW
125 #define STRING_UNICODE_THROW throw()
126#endif
127
128
129inline char MyCharUpper_Ascii(char c)
130{
131 if (c >= 'a' && c <= 'z')
132 return (char)((unsigned char)c - 0x20);
133 return c;
134}
135
136/*
137inline wchar_t MyCharUpper_Ascii(wchar_t c)
138{
139 if (c >= 'a' && c <= 'z')
140 return (wchar_t)(c - 0x20);
141 return c;
142}
143*/
144
145inline char MyCharLower_Ascii(char c)
146{
147 if (c >= 'A' && c <= 'Z')
148 return (char)((unsigned char)c + 0x20);
149 return c;
150}
151
152inline wchar_t MyCharLower_Ascii(wchar_t c)
153{
154 if (c >= 'A' && c <= 'Z')
155 return (wchar_t)(c + 0x20);
156 return c;
157}
158
159wchar_t MyCharUpper_WIN(wchar_t c) throw();
160
161inline wchar_t MyCharUpper(wchar_t c) throw()
162{
163 if (c < 'a') return c;
164 if (c <= 'z') return (wchar_t)(c - 0x20);
165 if (c <= 0x7F) return c;
166 #ifdef _WIN32
167 #ifdef _UNICODE
168 return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);
169 #else
170 return (wchar_t)MyCharUpper_WIN(c);
171 #endif
172 #else
173 return (wchar_t)towupper((wint_t)c);
174 #endif
175}
176
177/*
178wchar_t MyCharLower_WIN(wchar_t c) throw();
179
180inline wchar_t MyCharLower(wchar_t c) throw()
181{
182 if (c < 'A') return c;
183 if (c <= 'Z') return (wchar_t)(c + 0x20);
184 if (c <= 0x7F) return c;
185 #ifdef _WIN32
186 #ifdef _UNICODE
187 return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);
188 #else
189 return (wchar_t)MyCharLower_WIN(c);
190 #endif
191 #else
192 return (wchar_t)tolower(c);
193 #endif
194}
195*/
196
197// char *MyStringUpper(char *s) throw();
198// char *MyStringLower(char *s) throw();
199
200// void MyStringUpper_Ascii(char *s) throw();
201// void MyStringUpper_Ascii(wchar_t *s) throw();
202void MyStringLower_Ascii(char *s) throw();
203void MyStringLower_Ascii(wchar_t *s) throw();
204// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;
205// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;
206
207bool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();
208
209bool IsString1PrefixedByString2(const char *s1, const char *s2) throw();
210bool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();
211bool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();
212bool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw();
213bool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();
214bool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();
215
216#define MyStringCompare(s1, s2) wcscmp(s1, s2)
217int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();
218// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();
219
220// ---------- ASCII ----------
221// char values in ASCII strings must be less then 128
222bool StringsAreEqual_Ascii(const char *u, const char *a) throw();
223bool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();
224bool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();
225bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();
226bool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();
227
228#define MY_STRING_DELETE(_p_) delete []_p_;
229// #define MY_STRING_DELETE(_p_) my_delete(_p_);
230
231
232#define FORBID_STRING_OPS_2(cls, t) \
233 void Find(t) const; \
234 void Find(t, unsigned startIndex) const; \
235 void ReverseFind(t) const; \
236 void InsertAtFront(t); \
237 void RemoveChar(t); \
238 void Replace(t, t); \
239
240#define FORBID_STRING_OPS(cls, t) \
241 explicit cls(t); \
242 explicit cls(const t *); \
243 cls &operator=(t); \
244 cls &operator=(const t *); \
245 cls &operator+=(t); \
246 cls &operator+=(const t *); \
247 FORBID_STRING_OPS_2(cls, t) \
248
249/*
250 cls &operator+(t); \
251 cls &operator+(const t *); \
252*/
253
254#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t)
255#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t)
256#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t)
257
258class AString
259{
260 char *_chars;
261 unsigned _len;
262 unsigned _limit;
263
264 void MoveItems(unsigned dest, unsigned src)
265 {
266 memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));
267 }
268
269 void InsertSpace(unsigned &index, unsigned size);
270
271 void ReAlloc(unsigned newLimit);
272 void ReAlloc2(unsigned newLimit);
273 void SetStartLen(unsigned len);
274 void Grow_1();
275 void Grow(unsigned n);
276
277 AString(unsigned num, const char *s);
278 AString(unsigned num, const AString &s);
279 AString(const AString &s, char c); // it's for String + char
280 AString(const char *s1, unsigned num1, const char *s2, unsigned num2);
281
282 friend AString operator+(const AString &s, char c) { return AString(s, c); }
283 // friend AString operator+(char c, const AString &s); // is not supported
284
285 friend AString operator+(const AString &s1, const AString &s2);
286 friend AString operator+(const AString &s1, const char *s2);
287 friend AString operator+(const char *s1, const AString &s2);
288
289 // ---------- forbidden functions ----------
290
291 #ifdef MY_NATIVE_WCHAR_T_DEFINED
292 FORBID_STRING_OPS_AString(wchar_t)
293 #endif
294
295 FORBID_STRING_OPS_AString(signed char)
296 FORBID_STRING_OPS_AString(unsigned char)
297 FORBID_STRING_OPS_AString(short)
298 FORBID_STRING_OPS_AString(unsigned short)
299 FORBID_STRING_OPS_AString(int)
300 FORBID_STRING_OPS_AString(unsigned)
301 FORBID_STRING_OPS_AString(long)
302 FORBID_STRING_OPS_AString(unsigned long)
303
304 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
305 AString(const FString &s);
306 AString &operator=(const FString &s);
307 AString &operator+=(const FString &s);
308 #endif
309
310public:
311 explicit AString();
312 explicit AString(char c);
313 explicit AString(const char *s);
314 AString(const AString &s);
315 ~AString() { MY_STRING_DELETE(_chars); }
316
317 unsigned Len() const { return _len; }
318 bool IsEmpty() const { return _len == 0; }
319 void Empty() { _len = 0; _chars[0] = 0; }
320
321 operator const char *() const { return _chars; }
322 char *Ptr_non_const() const { return _chars; }
323 const char *Ptr() const { return _chars; }
324 const char *Ptr(unsigned pos) const { return _chars + pos; }
325 const char *RightPtr(unsigned num) const { return _chars + _len - num; }
326 char Back() const { return _chars[(size_t)_len - 1]; }
327
328 void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }
329
330 char *GetBuf() { return _chars; }
331 /* GetBuf(minLen): provides the buffer that can store
332 at least (minLen) characters and additional null terminator.
333 9.35: GetBuf doesn't preserve old characters and terminator */
334 char *GetBuf(unsigned minLen)
335 {
336 if (minLen > _limit)
337 ReAlloc2(minLen);
338 return _chars;
339 }
340 char *GetBuf_SetEnd(unsigned minLen)
341 {
342 if (minLen > _limit)
343 ReAlloc2(minLen);
344 char *chars = _chars;
345 chars[minLen] = 0;
346 _len = minLen;
347 return chars;
348 }
349
350 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
351 void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
352 void ReleaseBuf_CalcLen(unsigned maxLen)
353 {
354 char *chars = _chars;
355 chars[maxLen] = 0;
356 _len = MyStringLen(chars);
357 }
358
359 AString &operator=(char c);
360 AString &operator=(const char *s);
361 AString &operator=(const AString &s);
362 void SetFromWStr_if_Ascii(const wchar_t *s);
363 // void SetFromBstr_if_Ascii(BSTR s);
364
365 AString &operator+=(char c)
366 {
367 if (_limit == _len)
368 Grow_1();
369 unsigned len = _len;
370 char *chars = _chars;
371 chars[len++] = c;
372 chars[len] = 0;
373 _len = len;
374 return *this;
375 }
376
377 void Add_Space();
378 void Add_Space_if_NotEmpty();
379 void Add_OptSpaced(const char *s);
380 void Add_LF();
381 void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }
382
383 AString &operator+=(const char *s);
384 AString &operator+=(const AString &s);
385
386 void Add_UInt32(UInt32 v);
387 void Add_UInt64(UInt64 v);
388
389 void SetFrom(const char *s, unsigned len); // no check
390 void SetFrom_CalcLen(const char *s, unsigned len);
391
392 AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }
393 AString Left(unsigned count) const { return AString(count, *this); }
394
395 // void MakeUpper() { MyStringUpper(_chars); }
396 // void MakeLower() { MyStringLower(_chars); }
397 void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
398
399
400 bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }
401 bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
402 // int Compare(const char *s) const { return MyStringCompare(_chars, s); }
403 // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }
404 // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }
405 // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
406 bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }
407 bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
408
409 bool IsAscii() const
410 {
411 unsigned len = Len();
412 const char *s = _chars;
413 for (unsigned i = 0; i < len; i++)
414 if ((unsigned char)s[i] >= 0x80)
415 return false;
416 return true;
417 }
418 int Find(char c) const { return FindCharPosInString(_chars, c); }
419 int Find(char c, unsigned startIndex) const
420 {
421 int pos = FindCharPosInString(_chars + startIndex, c);
422 return pos < 0 ? -1 : (int)startIndex + pos;
423 }
424
425 int ReverseFind(char c) const throw();
426 int ReverseFind_Dot() const throw() { return ReverseFind('.'); }
427 int ReverseFind_PathSepar() const throw();
428
429 int Find(const char *s) const { return Find(s, 0); }
430 int Find(const char *s, unsigned startIndex) const throw();
431
432 void TrimLeft() throw();
433 void TrimRight() throw();
434 void Trim()
435 {
436 TrimRight();
437 TrimLeft();
438 }
439
440 void InsertAtFront(char c);
441 // void Insert(unsigned index, char c);
442 void Insert(unsigned index, const char *s);
443 void Insert(unsigned index, const AString &s);
444
445 void RemoveChar(char ch) throw();
446
447 void Replace(char oldChar, char newChar) throw();
448 void Replace(const AString &oldString, const AString &newString);
449
450 void Delete(unsigned index) throw();
451 void Delete(unsigned index, unsigned count) throw();
452 void DeleteFrontal(unsigned num) throw();
453 void DeleteBack() { _chars[--_len] = 0; }
454 void DeleteFrom(unsigned index)
455 {
456 if (index < _len)
457 {
458 _len = index;
459 _chars[index] = 0;
460 }
461 }
462
463 void Wipe_and_Empty()
464 {
465 if (_chars)
466 {
467 memset(_chars, 0, (_limit + 1) * sizeof(*_chars));
468 _len = 0;
469 }
470 }
471};
472
473
474class AString_Wipe: public AString
475{
476 CLASS_NO_COPY(AString_Wipe)
477public:
478 AString_Wipe(): AString() {}
479 // AString_Wipe(const AString &s): AString(s) {}
480 // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; }
481 // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; }
482 ~AString_Wipe() { Wipe_and_Empty(); }
483};
484
485
486bool operator<(const AString &s1, const AString &s2);
487bool operator>(const AString &s1, const AString &s2);
488
489/*
490bool operator==(const AString &s1, const AString &s2);
491bool operator==(const AString &s1, const char *s2);
492bool operator==(const char *s1, const AString &s2);
493
494bool operator!=(const AString &s1, const AString &s2);
495bool operator!=(const AString &s1, const char *s2);
496bool operator!=(const char *s1, const AString &s2);
497*/
498
499inline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }
500inline bool operator==(const AString &s1, const char *s2) { return strcmp(s1, s2) == 0; }
501inline bool operator==(const char *s1, const AString &s2) { return strcmp(s1, s2) == 0; }
502
503inline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }
504inline bool operator!=(const AString &s1, const char *s2) { return strcmp(s1, s2) != 0; }
505inline bool operator!=(const char *s1, const AString &s2) { return strcmp(s1, s2) != 0; }
506
507// ---------- forbidden functions ----------
508
509void operator==(char c1, const AString &s2);
510void operator==(const AString &s1, char c2);
511
512void operator+(char c, const AString &s); // this function can be OK, but we don't use it
513
514void operator+(const AString &s, int c);
515void operator+(const AString &s, unsigned c);
516void operator+(int c, const AString &s);
517void operator+(unsigned c, const AString &s);
518void operator-(const AString &s, int c);
519void operator-(const AString &s, unsigned c);
520
521
522class UString
523{
524 wchar_t *_chars;
525 unsigned _len;
526 unsigned _limit;
527
528 void MoveItems(unsigned dest, unsigned src)
529 {
530 memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));
531 }
532
533 void InsertSpace(unsigned index, unsigned size);
534
535 void ReAlloc(unsigned newLimit);
536 void ReAlloc2(unsigned newLimit);
537 void SetStartLen(unsigned len);
538 void Grow_1();
539 void Grow(unsigned n);
540
541 UString(unsigned num, const wchar_t *s); // for Mid
542 UString(unsigned num, const UString &s); // for Left
543 UString(const UString &s, wchar_t c); // it's for String + char
544 UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);
545
546 friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); }
547 // friend UString operator+(wchar_t c, const UString &s); // is not supported
548
549 friend UString operator+(const UString &s1, const UString &s2);
550 friend UString operator+(const UString &s1, const wchar_t *s2);
551 friend UString operator+(const wchar_t *s1, const UString &s2);
552
553 // ---------- forbidden functions ----------
554
555 FORBID_STRING_OPS_UString(signed char)
556 FORBID_STRING_OPS_UString(unsigned char)
557 FORBID_STRING_OPS_UString(short)
558
559 #ifdef MY_NATIVE_WCHAR_T_DEFINED
560 FORBID_STRING_OPS_UString(unsigned short)
561 #endif
562
563 FORBID_STRING_OPS_UString(int)
564 FORBID_STRING_OPS_UString(unsigned)
565 FORBID_STRING_OPS_UString(long)
566 FORBID_STRING_OPS_UString(unsigned long)
567
568 FORBID_STRING_OPS_2(UString, char)
569
570 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
571 UString(const FString &s);
572 UString &operator=(const FString &s);
573 UString &operator+=(const FString &s);
574 #endif
575
576public:
577 UString();
578 explicit UString(wchar_t c);
579 explicit UString(char c);
580 explicit UString(const char *s);
581 explicit UString(const AString &s);
582 UString(const wchar_t *s);
583 UString(const UString &s);
584 ~UString() { MY_STRING_DELETE(_chars); }
585
586 unsigned Len() const { return _len; }
587 bool IsEmpty() const { return _len == 0; }
588 void Empty() { _len = 0; _chars[0] = 0; }
589
590 operator const wchar_t *() const { return _chars; }
591 wchar_t *Ptr_non_const() const { return _chars; }
592 const wchar_t *Ptr() const { return _chars; }
593 const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }
594 const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }
595 wchar_t Back() const { return _chars[(size_t)_len - 1]; }
596
597 void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }
598
599 wchar_t *GetBuf() { return _chars; }
600
601 wchar_t *GetBuf(unsigned minLen)
602 {
603 if (minLen > _limit)
604 ReAlloc2(minLen);
605 return _chars;
606 }
607 wchar_t *GetBuf_SetEnd(unsigned minLen)
608 {
609 if (minLen > _limit)
610 ReAlloc2(minLen);
611 wchar_t *chars = _chars;
612 chars[minLen] = 0;
613 _len = minLen;
614 return chars;
615 }
616
617 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
618 void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }
619 void ReleaseBuf_CalcLen(unsigned maxLen)
620 {
621 wchar_t *chars = _chars;
622 chars[maxLen] = 0;
623 _len = MyStringLen(chars);
624 }
625
626 UString &operator=(wchar_t c);
627 UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); }
628 UString &operator=(const wchar_t *s);
629 UString &operator=(const UString &s);
630 void SetFrom(const wchar_t *s, unsigned len); // no check
631 void SetFromBstr(LPCOLESTR s);
632 UString &operator=(const char *s);
633 UString &operator=(const AString &s) { return operator=(s.Ptr()); }
634
635 UString &operator+=(wchar_t c)
636 {
637 if (_limit == _len)
638 Grow_1();
639 unsigned len = _len;
640 wchar_t *chars = _chars;
641 chars[len++] = c;
642 chars[len] = 0;
643 _len = len;
644 return *this;
645 }
646
647 UString &operator+=(char c) { return (*this)+=((wchar_t)(unsigned char)c); }
648
649 void Add_Space();
650 void Add_Space_if_NotEmpty();
651 void Add_LF();
652 void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }
653
654 UString &operator+=(const wchar_t *s);
655 UString &operator+=(const UString &s);
656 UString &operator+=(const char *s);
657 UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }
658
659 void Add_UInt32(UInt32 v);
660 void Add_UInt64(UInt64 v);
661
662 UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }
663 UString Left(unsigned count) const { return UString(count, *this); }
664
665 // void MakeUpper() { MyStringUpper(_chars); }
666 // void MakeUpper() { MyStringUpper_Ascii(_chars); }
667 // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }
668 void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }
669
670 bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }
671 bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }
672 bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }
673 int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
674 // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }
675 // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }
676 // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }
677 bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }
678 bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }
679 bool IsPrefixedBy_Ascii_NoCase(const char *s) const throw();
680
681 bool IsAscii() const
682 {
683 unsigned len = Len();
684 const wchar_t *s = _chars;
685 for (unsigned i = 0; i < len; i++)
686 if (s[i] >= 0x80)
687 return false;
688 return true;
689 }
690 int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }
691 int Find(wchar_t c, unsigned startIndex) const
692 {
693 int pos = FindCharPosInString(_chars + startIndex, c);
694 return pos < 0 ? -1 : (int)startIndex + pos;
695 }
696
697 int ReverseFind(wchar_t c) const throw();
698 int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }
699 int ReverseFind_PathSepar() const throw();
700
701 int Find(const wchar_t *s) const { return Find(s, 0); }
702 int Find(const wchar_t *s, unsigned startIndex) const throw();
703
704 void TrimLeft() throw();
705 void TrimRight() throw();
706 void Trim()
707 {
708 TrimRight();
709 TrimLeft();
710 }
711
712 void InsertAtFront(wchar_t c);
713 // void Insert_wchar_t(unsigned index, wchar_t c);
714 void Insert(unsigned index, const wchar_t *s);
715 void Insert(unsigned index, const UString &s);
716
717 void RemoveChar(wchar_t ch) throw();
718
719 void Replace(wchar_t oldChar, wchar_t newChar) throw();
720 void Replace(const UString &oldString, const UString &newString);
721
722 void Delete(unsigned index) throw();
723 void Delete(unsigned index, unsigned count) throw();
724 void DeleteFrontal(unsigned num) throw();
725 void DeleteBack() { _chars[--_len] = 0; }
726 void DeleteFrom(unsigned index)
727 {
728 if (index < _len)
729 {
730 _len = index;
731 _chars[index] = 0;
732 }
733 }
734
735 void Wipe_and_Empty()
736 {
737 if (_chars)
738 {
739 memset(_chars, 0, (_limit + 1) * sizeof(*_chars));
740 _len = 0;
741 }
742 }
743};
744
745
746class UString_Wipe: public UString
747{
748 CLASS_NO_COPY(UString_Wipe)
749public:
750 UString_Wipe(): UString() {}
751 // UString_Wipe(const UString &s): UString(s) {}
752 // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; }
753 // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; }
754 ~UString_Wipe() { Wipe_and_Empty(); }
755};
756
757
758bool operator<(const UString &s1, const UString &s2);
759bool operator>(const UString &s1, const UString &s2);
760
761inline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }
762inline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }
763inline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }
764
765inline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }
766inline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }
767inline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }
768
769
770// ---------- forbidden functions ----------
771
772void operator==(wchar_t c1, const UString &s2);
773void operator==(const UString &s1, wchar_t c2);
774
775void operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it
776
777void operator+(const AString &s1, const UString &s2);
778void operator+(const UString &s1, const AString &s2);
779
780void operator+(const UString &s1, const char *s2);
781void operator+(const char *s1, const UString &s2);
782
783void operator+(const UString &s, char c);
784void operator+(const UString &s, unsigned char c);
785void operator+(char c, const UString &s);
786void operator+(unsigned char c, const UString &s);
787void operator-(const UString &s1, wchar_t c);
788
789#ifdef _WIN32
790// can we forbid these functions, if wchar_t is 32-bit ?
791void operator+(const UString &s, int c);
792void operator+(const UString &s, unsigned c);
793void operator+(int c, const UString &s);
794void operator+(unsigned c, const UString &s);
795void operator-(const UString &s1, int c);
796void operator-(const UString &s1, unsigned c);
797#endif
798
799
800
801
802
803
804
805class UString2
806{
807 wchar_t *_chars;
808 unsigned _len;
809
810 void ReAlloc2(unsigned newLimit);
811 void SetStartLen(unsigned len);
812
813 // ---------- forbidden functions ----------
814
815 FORBID_STRING_OPS_UString2(char)
816 FORBID_STRING_OPS_UString2(signed char)
817 FORBID_STRING_OPS_UString2(unsigned char)
818 FORBID_STRING_OPS_UString2(short)
819
820 UString2 &operator=(wchar_t c);
821
822 UString2(const AString &s);
823 UString2 &operator=(const AString &s);
824 UString2 &operator+=(const AString &s);
825
826 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
827 UString2(const FString &s);
828 UString2 &operator=(const FString &s);
829 UString2 &operator+=(const FString &s);
830 #endif
831
832public:
833 UString2(): _chars(NULL), _len(0) {}
834 UString2(const wchar_t *s);
835 UString2(const UString2 &s);
836 ~UString2() { if (_chars) MY_STRING_DELETE(_chars); }
837
838 unsigned Len() const { return _len; }
839 bool IsEmpty() const { return _len == 0; }
840 // void Empty() { _len = 0; _chars[0] = 0; }
841
842 // operator const wchar_t *() const { return _chars; }
843 const wchar_t *GetRawPtr() const { return _chars; }
844
845 int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }
846
847 wchar_t *GetBuf(unsigned minLen)
848 {
849 if (!_chars || minLen > _len)
850 ReAlloc2(minLen);
851 return _chars;
852 }
853 void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }
854
855 UString2 &operator=(const wchar_t *s);
856 UString2 &operator=(const UString2 &s);
857 void SetFromAscii(const char *s);
858};
859
860bool operator==(const UString2 &s1, const UString2 &s2);
861bool operator==(const UString2 &s1, const wchar_t *s2);
862bool operator==(const wchar_t *s1, const UString2 &s2);
863
864inline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }
865inline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }
866inline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }
867
868
869// ---------- forbidden functions ----------
870
871void operator==(wchar_t c1, const UString2 &s2);
872void operator==(const UString2 &s1, wchar_t c2);
873bool operator<(const UString2 &s1, const UString2 &s2);
874bool operator>(const UString2 &s1, const UString2 &s2);
875
876void operator+(const UString2 &s1, const UString2 &s2);
877void operator+(const UString2 &s1, const wchar_t *s2);
878void operator+(const wchar_t *s1, const UString2 &s2);
879void operator+(wchar_t c, const UString2 &s);
880void operator+(const UString2 &s, wchar_t c);
881void operator+(const UString2 &s, char c);
882void operator+(const UString2 &s, unsigned char c);
883void operator+(char c, const UString2 &s);
884void operator+(unsigned char c, const UString2 &s);
885void operator-(const UString2 &s1, wchar_t c);
886
887
888
889
890
891
892typedef CObjectVector<AString> AStringVector;
893typedef CObjectVector<UString> UStringVector;
894
895#ifdef _UNICODE
896 typedef UString CSysString;
897#else
898 typedef AString CSysString;
899#endif
900
901typedef CObjectVector<CSysString> CSysStringVector;
902
903
904// ---------- FString ----------
905
906#ifndef DEBUG_FSTRING_INHERITS_ASTRING
907#ifdef _WIN32
908 #define USE_UNICODE_FSTRING
909#endif
910#endif
911
912#ifdef USE_UNICODE_FSTRING
913
914 #define __FTEXT(quote) L##quote
915
916 typedef wchar_t FChar;
917 typedef UString FString;
918
919 #define fs2us(_x_) (_x_)
920 #define us2fs(_x_) (_x_)
921 FString fas2fs(const char *s);
922 FString fas2fs(const AString &s);
923 AString fs2fas(const FChar *s);
924
925#else
926
927 #define __FTEXT(quote) quote
928
929 typedef char FChar;
930
931 #ifdef DEBUG_FSTRING_INHERITS_ASTRING
932
933 class FString: public AString
934 {
935 // FString &operator=(const char *s);
936 FString &operator=(const AString &s);
937 // FString &operator+=(const AString &s);
938 public:
939 FString(const AString &s): AString(s.Ptr()) {}
940 FString(const FString &s): AString(s.Ptr()) {}
941 FString(const char *s): AString(s) {}
942 FString() {}
943 FString &operator=(const FString &s) { AString::operator=((const AString &)s); return *this; }
944 FString &operator=(char c) { AString::operator=(c); return *this; }
945 FString &operator+=(char c) { AString::operator+=(c); return *this; }
946 FString &operator+=(const FString &s) { AString::operator+=((const AString &)s); return *this; }
947 FString Left(unsigned count) const { return FString(AString::Left(count)); }
948 };
949 void operator+(const AString &s1, const FString &s2);
950 void operator+(const FString &s1, const AString &s2);
951
952 inline FString operator+(const FString &s1, const FString &s2)
953 {
954 AString s =(const AString &)s1 + (const AString &)s2;
955 return FString(s.Ptr());
956 // return FString((const AString &)s1 + (const AString &)s2);
957 }
958 inline FString operator+(const FString &s1, const FChar *s2)
959 {
960 return s1 + (FString)s2;
961 }
962 /*
963 inline FString operator+(const FChar *s1, const FString &s2)
964 {
965 return (FString)s1 + s2;
966 }
967 */
968
969 inline FString fas2fs(const char *s) { return FString(s); }
970
971 #else // DEBUG_FSTRING_INHERITS_ASTRING
972 typedef AString FString;
973 #define fas2fs(_x_) (_x_)
974 #endif // DEBUG_FSTRING_INHERITS_ASTRING
975
976 UString fs2us(const FChar *s);
977 UString fs2us(const FString &s);
978 FString us2fs(const wchar_t *s);
979 #define fs2fas(_x_) (_x_)
980
981#endif
982
983#define FTEXT(quote) __FTEXT(quote)
984
985#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)
986#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)
987
988// #define FCHAR_ANY_MASK FTEXT('*')
989// #define FSTRING_ANY_MASK FTEXT("*")
990
991typedef const FChar *CFSTR;
992
993typedef CObjectVector<FString> FStringVector;
994
995#endif
996
997
998
999#if defined(_WIN32)
1000 // #include <wchar.h>
1001 // WCHAR_MAX is defined as ((wchar_t)-1)
1002 #define _WCHART_IS_16BIT 1
1003#elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \
1004 || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2))
1005 #define _WCHART_IS_16BIT 1
1006#endif
1007
1008#if WCHAR_PATH_SEPARATOR == L'\\'
1009// WSL scheme
1010#define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\'))
1011// #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT '_'
1012#endif
diff --git a/CPP/Common/MyTypes.h b/CPP/Common/MyTypes.h
new file mode 100644
index 0000000..71b8e7f
--- /dev/null
+++ b/CPP/Common/MyTypes.h
@@ -0,0 +1,52 @@
1// Common/MyTypes.h
2
3#ifndef __COMMON_MY_TYPES_H
4#define __COMMON_MY_TYPES_H
5
6#include "../../C/7zTypes.h"
7
8typedef int HRes;
9
10struct CBoolPair
11{
12 bool Val;
13 bool Def;
14
15 CBoolPair(): Val(false), Def(false) {}
16
17 void Init()
18 {
19 Val = false;
20 Def = false;
21 }
22
23 void SetTrueTrue()
24 {
25 Val = true;
26 Def = true;
27 }
28
29 void SetVal_as_Defined(bool val)
30 {
31 Val = val;
32 Def = true;
33 }
34};
35
36#define CLASS_NO_COPY(cls) \
37 private: \
38 cls(const cls &); \
39 cls &operator=(const cls &);
40
41class CUncopyable
42{
43protected:
44 CUncopyable() {} // allow constructor
45 // ~CUncopyable() {}
46CLASS_NO_COPY(CUncopyable)
47};
48
49#define MY_UNCOPYABLE :private CUncopyable
50// #define MY_UNCOPYABLE
51
52#endif
diff --git a/CPP/Common/MyUnknown.h b/CPP/Common/MyUnknown.h
new file mode 100644
index 0000000..ff025cb
--- /dev/null
+++ b/CPP/Common/MyUnknown.h
@@ -0,0 +1,17 @@
1// MyUnknown.h
2
3#ifndef __MY_UNKNOWN_H
4#define __MY_UNKNOWN_H
5
6#include "MyWindows.h"
7
8/*
9#ifdef _WIN32
10#include <basetyps.h>
11#include <unknwn.h>
12#else
13#include "MyWindows.h"
14#endif
15*/
16
17#endif
diff --git a/CPP/Common/MyVector.cpp b/CPP/Common/MyVector.cpp
new file mode 100644
index 0000000..0b1baf4
--- /dev/null
+++ b/CPP/Common/MyVector.cpp
@@ -0,0 +1,3 @@
1// Common/MyVector.cpp
2
3#include "StdAfx.h"
diff --git a/CPP/Common/MyVector.h b/CPP/Common/MyVector.h
new file mode 100644
index 0000000..c851234
--- /dev/null
+++ b/CPP/Common/MyVector.h
@@ -0,0 +1,634 @@
1// Common/MyVector.h
2
3#ifndef __COMMON_MY_VECTOR_H
4#define __COMMON_MY_VECTOR_H
5
6#include <string.h>
7
8template <class T>
9class CRecordVector
10{
11 T *_items;
12 unsigned _size;
13 unsigned _capacity;
14
15 void MoveItems(unsigned destIndex, unsigned srcIndex)
16 {
17 memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));
18 }
19
20 void ReserveOnePosition()
21 {
22 if (_size == _capacity)
23 {
24 unsigned newCapacity = _capacity + (_capacity >> 2) + 1;
25 T *p;
26 MY_ARRAY_NEW(p, T, newCapacity);
27 // p = new T[newCapacity];
28 if (_size != 0)
29 memcpy(p, _items, (size_t)_size * sizeof(T));
30 delete []_items;
31 _items = p;
32 _capacity = newCapacity;
33 }
34 }
35
36public:
37
38 CRecordVector(): _items(NULL), _size(0), _capacity(0) {}
39
40 CRecordVector(const CRecordVector &v): _items(0), _size(0), _capacity(0)
41 {
42 unsigned size = v.Size();
43 if (size != 0)
44 {
45 _items = new T[size];
46 _size = size;
47 _capacity = size;
48 memcpy(_items, v._items, (size_t)size * sizeof(T));
49 }
50 }
51
52 unsigned Size() const { return _size; }
53 bool IsEmpty() const { return _size == 0; }
54
55 void ConstructReserve(unsigned size)
56 {
57 if (size != 0)
58 {
59 MY_ARRAY_NEW(_items, T, size)
60 // _items = new T[size];
61 _capacity = size;
62 }
63 }
64
65 void Reserve(unsigned newCapacity)
66 {
67 if (newCapacity > _capacity)
68 {
69 T *p;
70 MY_ARRAY_NEW(p, T, newCapacity);
71 // p = new T[newCapacity];
72 if (_size != 0)
73 memcpy(p, _items, (size_t)_size * sizeof(T));
74 delete []_items;
75 _items = p;
76 _capacity = newCapacity;
77 }
78 }
79
80 void ClearAndReserve(unsigned newCapacity)
81 {
82 Clear();
83 if (newCapacity > _capacity)
84 {
85 delete []_items;
86 _items = NULL;
87 _capacity = 0;
88 MY_ARRAY_NEW(_items, T, newCapacity)
89 // _items = new T[newCapacity];
90 _capacity = newCapacity;
91 }
92 }
93
94 void ClearAndSetSize(unsigned newSize)
95 {
96 ClearAndReserve(newSize);
97 _size = newSize;
98 }
99
100 void ChangeSize_KeepData(unsigned newSize)
101 {
102 if (newSize > _capacity)
103 {
104 T *p;
105 MY_ARRAY_NEW(p, T, newSize)
106 // p = new T[newSize];
107 if (_size != 0)
108 memcpy(p, _items, (size_t)_size * sizeof(T));
109 delete []_items;
110 _items = p;
111 _capacity = newSize;
112 }
113 _size = newSize;
114 }
115
116 void ReserveDown()
117 {
118 if (_size == _capacity)
119 return;
120 T *p = NULL;
121 if (_size != 0)
122 {
123 p = new T[_size];
124 memcpy(p, _items, (size_t)_size * sizeof(T));
125 }
126 delete []_items;
127 _items = p;
128 _capacity = _size;
129 }
130
131 ~CRecordVector() { delete []_items; }
132
133 void ClearAndFree()
134 {
135 delete []_items;
136 _items = NULL;
137 _size = 0;
138 _capacity = 0;
139 }
140
141 void Clear() { _size = 0; }
142
143 void DeleteBack() { _size--; }
144
145 void DeleteFrom(unsigned index)
146 {
147 // if (index <= _size)
148 _size = index;
149 }
150
151 void DeleteFrontal(unsigned num)
152 {
153 if (num != 0)
154 {
155 MoveItems(0, num);
156 _size -= num;
157 }
158 }
159
160 void Delete(unsigned index)
161 {
162 MoveItems(index, index + 1);
163 _size -= 1;
164 }
165
166 /*
167 void Delete(unsigned index, unsigned num)
168 {
169 if (num > 0)
170 {
171 MoveItems(index, index + num);
172 _size -= num;
173 }
174 }
175 */
176
177 CRecordVector& operator=(const CRecordVector &v)
178 {
179 if (&v == this)
180 return *this;
181 unsigned size = v.Size();
182 if (size > _capacity)
183 {
184 delete []_items;
185 _capacity = 0;
186 _size = 0;
187 _items = NULL;
188 _items = new T[size];
189 _capacity = size;
190 }
191 _size = size;
192 if (size != 0)
193 memcpy(_items, v._items, (size_t)size * sizeof(T));
194 return *this;
195 }
196
197 CRecordVector& operator+=(const CRecordVector &v)
198 {
199 unsigned size = v.Size();
200 Reserve(_size + size);
201 if (size != 0)
202 memcpy(_items + _size, v._items, (size_t)size * sizeof(T));
203 _size += size;
204 return *this;
205 }
206
207 unsigned Add(const T item)
208 {
209 ReserveOnePosition();
210 _items[_size] = item;
211 return _size++;
212 }
213
214 void AddInReserved(const T item)
215 {
216 _items[_size++] = item;
217 }
218
219 void Insert(unsigned index, const T item)
220 {
221 ReserveOnePosition();
222 MoveItems(index + 1, index);
223 _items[index] = item;
224 _size++;
225 }
226
227 void MoveToFront(unsigned index)
228 {
229 if (index != 0)
230 {
231 T temp = _items[index];
232 memmove(_items + 1, _items, (size_t)index * sizeof(T));
233 _items[0] = temp;
234 }
235 }
236
237 const T& operator[](unsigned index) const { return _items[index]; }
238 T& operator[](unsigned index) { return _items[index]; }
239 const T& Front() const { return _items[0]; }
240 T& Front() { return _items[0]; }
241 const T& Back() const { return _items[(size_t)_size - 1]; }
242 T& Back() { return _items[(size_t)_size - 1]; }
243
244 /*
245 void Swap(unsigned i, unsigned j)
246 {
247 T temp = _items[i];
248 _items[i] = _items[j];
249 _items[j] = temp;
250 }
251 */
252
253 int FindInSorted(const T item, unsigned left, unsigned right) const
254 {
255 while (left != right)
256 {
257 unsigned mid = (left + right) / 2;
258 const T midVal = (*this)[mid];
259 if (item == midVal)
260 return (int)mid;
261 if (item < midVal)
262 right = mid;
263 else
264 left = mid + 1;
265 }
266 return -1;
267 }
268
269 int FindInSorted2(const T &item, unsigned left, unsigned right) const
270 {
271 while (left != right)
272 {
273 unsigned mid = (left + right) / 2;
274 const T& midVal = (*this)[mid];
275 int comp = item.Compare(midVal);
276 if (comp == 0)
277 return (int)mid;
278 if (comp < 0)
279 right = mid;
280 else
281 left = mid + 1;
282 }
283 return -1;
284 }
285
286 int FindInSorted(const T item) const
287 {
288 return FindInSorted(item, 0, _size);
289 }
290
291 int FindInSorted2(const T &item) const
292 {
293 return FindInSorted2(item, 0, _size);
294 }
295
296 unsigned AddToUniqueSorted(const T item)
297 {
298 unsigned left = 0, right = _size;
299 while (left != right)
300 {
301 unsigned mid = (left + right) / 2;
302 const T midVal = (*this)[mid];
303 if (item == midVal)
304 return mid;
305 if (item < midVal)
306 right = mid;
307 else
308 left = mid + 1;
309 }
310 Insert(right, item);
311 return right;
312 }
313
314 unsigned AddToUniqueSorted2(const T &item)
315 {
316 unsigned left = 0, right = _size;
317 while (left != right)
318 {
319 unsigned mid = (left + right) / 2;
320 const T& midVal = (*this)[mid];
321 int comp = item.Compare(midVal);
322 if (comp == 0)
323 return mid;
324 if (comp < 0)
325 right = mid;
326 else
327 left = mid + 1;
328 }
329 Insert(right, item);
330 return right;
331 }
332
333 static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)
334 {
335 T temp = p[k];
336 for (;;)
337 {
338 unsigned s = (k << 1);
339 if (s > size)
340 break;
341 if (s < size && compare(p + s + 1, p + s, param) > 0)
342 s++;
343 if (compare(&temp, p + s, param) >= 0)
344 break;
345 p[k] = p[s];
346 k = s;
347 }
348 p[k] = temp;
349 }
350
351 void Sort(int (*compare)(const T*, const T*, void *), void *param)
352 {
353 unsigned size = _size;
354 if (size <= 1)
355 return;
356 T* p = (&Front()) - 1;
357 {
358 unsigned i = size >> 1;
359 do
360 SortRefDown(p, i, size, compare, param);
361 while (--i != 0);
362 }
363 do
364 {
365 T temp = p[size];
366 p[size--] = p[1];
367 p[1] = temp;
368 SortRefDown(p, 1, size, compare, param);
369 }
370 while (size > 1);
371 }
372
373 static void SortRefDown2(T* p, unsigned k, unsigned size)
374 {
375 T temp = p[k];
376 for (;;)
377 {
378 unsigned s = (k << 1);
379 if (s > size)
380 break;
381 if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0)
382 s++;
383 if (temp.Compare(p[s]) >= 0)
384 break;
385 p[k] = p[s];
386 k = s;
387 }
388 p[k] = temp;
389 }
390
391 void Sort2()
392 {
393 unsigned size = _size;
394 if (size <= 1)
395 return;
396 T* p = (&Front()) - 1;
397 {
398 unsigned i = size >> 1;
399 do
400 SortRefDown2(p, i, size);
401 while (--i != 0);
402 }
403 do
404 {
405 T temp = p[size];
406 p[size--] = p[1];
407 p[1] = temp;
408 SortRefDown2(p, 1, size);
409 }
410 while (size > 1);
411 }
412};
413
414typedef CRecordVector<int> CIntVector;
415typedef CRecordVector<unsigned int> CUIntVector;
416typedef CRecordVector<bool> CBoolVector;
417typedef CRecordVector<unsigned char> CByteVector;
418typedef CRecordVector<void *> CPointerVector;
419
420template <class T>
421class CObjectVector
422{
423 CPointerVector _v;
424public:
425 unsigned Size() const { return _v.Size(); }
426 bool IsEmpty() const { return _v.IsEmpty(); }
427 void ReserveDown() { _v.ReserveDown(); }
428 // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); }
429 void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); }
430
431 CObjectVector() {}
432 CObjectVector(const CObjectVector &v)
433 {
434 unsigned size = v.Size();
435 _v.ConstructReserve(size);
436 for (unsigned i = 0; i < size; i++)
437 _v.AddInReserved(new T(v[i]));
438 }
439 CObjectVector& operator=(const CObjectVector &v)
440 {
441 if (&v == this)
442 return *this;
443 Clear();
444 unsigned size = v.Size();
445 _v.Reserve(size);
446 for (unsigned i = 0; i < size; i++)
447 _v.AddInReserved(new T(v[i]));
448 return *this;
449 }
450
451 CObjectVector& operator+=(const CObjectVector &v)
452 {
453 unsigned size = v.Size();
454 _v.Reserve(Size() + size);
455 for (unsigned i = 0; i < size; i++)
456 _v.AddInReserved(new T(v[i]));
457 return *this;
458 }
459
460 const T& operator[](unsigned index) const { return *((T *)_v[index]); }
461 T& operator[](unsigned index) { return *((T *)_v[index]); }
462 const T& Front() const { return operator[](0); }
463 T& Front() { return operator[](0); }
464 const T& Back() const { return *(T *)_v.Back(); }
465 T& Back() { return *(T *)_v.Back(); }
466
467 void MoveToFront(unsigned index) { _v.MoveToFront(index); }
468
469 unsigned Add(const T& item) { return _v.Add(new T(item)); }
470
471 void AddInReserved(const T& item) { _v.AddInReserved(new T(item)); }
472
473 T& AddNew()
474 {
475 T *p = new T;
476 _v.Add(p);
477 return *p;
478 }
479
480 T& AddNewInReserved()
481 {
482 T *p = new T;
483 _v.AddInReserved(p);
484 return *p;
485 }
486
487 void Insert(unsigned index, const T& item) { _v.Insert(index, new T(item)); }
488
489 T& InsertNew(unsigned index)
490 {
491 T *p = new T;
492 _v.Insert(index, p);
493 return *p;
494 }
495
496 ~CObjectVector()
497 {
498 for (unsigned i = _v.Size(); i != 0;)
499 delete (T *)_v[--i];
500 }
501
502 void ClearAndFree()
503 {
504 Clear();
505 _v.ClearAndFree();
506 }
507
508 void Clear()
509 {
510 for (unsigned i = _v.Size(); i != 0;)
511 delete (T *)_v[--i];
512 _v.Clear();
513 }
514
515 void DeleteFrom(unsigned index)
516 {
517 unsigned size = _v.Size();
518 for (unsigned i = index; i < size; i++)
519 delete (T *)_v[i];
520 _v.DeleteFrom(index);
521 }
522
523 void DeleteFrontal(unsigned num)
524 {
525 for (unsigned i = 0; i < num; i++)
526 delete (T *)_v[i];
527 _v.DeleteFrontal(num);
528 }
529
530 void DeleteBack()
531 {
532 delete (T *)_v.Back();
533 _v.DeleteBack();
534 }
535
536 void Delete(unsigned index)
537 {
538 delete (T *)_v[index];
539 _v.Delete(index);
540 }
541
542 /*
543 void Delete(unsigned index, unsigned num)
544 {
545 for (unsigned i = 0; i < num; i++)
546 delete (T *)_v[index + i];
547 _v.Delete(index, num);
548 }
549 */
550
551 /*
552 int Find(const T& item) const
553 {
554 unsigned size = Size();
555 for (unsigned i = 0; i < size; i++)
556 if (item == (*this)[i])
557 return i;
558 return -1;
559 }
560 */
561
562 int FindInSorted(const T& item) const
563 {
564 unsigned left = 0, right = Size();
565 while (left != right)
566 {
567 unsigned mid = (left + right) / 2;
568 const T& midVal = (*this)[mid];
569 int comp = item.Compare(midVal);
570 if (comp == 0)
571 return (int)mid;
572 if (comp < 0)
573 right = mid;
574 else
575 left = mid + 1;
576 }
577 return -1;
578 }
579
580 unsigned AddToUniqueSorted(const T& item)
581 {
582 unsigned left = 0, right = Size();
583 while (left != right)
584 {
585 unsigned mid = (left + right) / 2;
586 const T& midVal = (*this)[mid];
587 int comp = item.Compare(midVal);
588 if (comp == 0)
589 return mid;
590 if (comp < 0)
591 right = mid;
592 else
593 left = mid + 1;
594 }
595 Insert(right, item);
596 return right;
597 }
598
599 /*
600 unsigned AddToSorted(const T& item)
601 {
602 unsigned left = 0, right = Size();
603 while (left != right)
604 {
605 unsigned mid = (left + right) / 2;
606 const T& midVal = (*this)[mid];
607 int comp = item.Compare(midVal);
608 if (comp == 0)
609 {
610 right = mid + 1;
611 break;
612 }
613 if (comp < 0)
614 right = mid;
615 else
616 left = mid + 1;
617 }
618 Insert(right, item);
619 return right;
620 }
621 */
622
623 void Sort(int (*compare)(void *const *, void *const *, void *), void *param)
624 { _v.Sort(compare, param); }
625
626 static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)
627 { return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); }
628
629 void Sort() { _v.Sort(CompareObjectItems, NULL); }
630};
631
632#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++)
633
634#endif
diff --git a/CPP/Common/MyWindows.cpp b/CPP/Common/MyWindows.cpp
new file mode 100644
index 0000000..88f312f
--- /dev/null
+++ b/CPP/Common/MyWindows.cpp
@@ -0,0 +1,292 @@
1// MyWindows.cpp
2
3#include "StdAfx.h"
4
5#ifndef _WIN32
6
7#include <stdlib.h>
8#include <time.h>
9#ifdef __GNUC__
10#include <sys/time.h>
11#endif
12
13#include "MyWindows.h"
14
15static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); }
16static inline void FreeForBSTR(void *pv) { ::free(pv);}
17
18/* Win32 uses DWORD (32-bit) type to store size of string before (OLECHAR *) string.
19 We must select CBstrSizeType for another systems (not Win32):
20
21 if (CBstrSizeType is UINT32),
22 then we support only strings smaller than 4 GB.
23 Win32 version always has that limitation.
24
25 if (CBstrSizeType is UINT),
26 (UINT can be 16/32/64-bit)
27 We can support strings larger than 4 GB (if UINT is 64-bit),
28 but sizeof(UINT) can be different in parts compiled by
29 different compilers/settings,
30 and we can't send such BSTR strings between such parts.
31*/
32
33typedef UINT32 CBstrSizeType;
34// typedef UINT CBstrSizeType;
35
36#define k_BstrSize_Max 0xFFFFFFFF
37// #define k_BstrSize_Max UINT_MAX
38// #define k_BstrSize_Max ((UINT)(INT)-1)
39
40BSTR SysAllocStringByteLen(LPCSTR s, UINT len)
41{
42 /* Original SysAllocStringByteLen in Win32 maybe fills only unaligned null OLECHAR at the end.
43 We provide also aligned null OLECHAR at the end. */
44
45 if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)))
46 return NULL;
47
48 UINT size = (len + (UINT)sizeof(OLECHAR) + (UINT)sizeof(OLECHAR) - 1) & ~((UINT)sizeof(OLECHAR) - 1);
49 void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType));
50 if (!p)
51 return NULL;
52 *(CBstrSizeType *)p = (CBstrSizeType)len;
53 BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
54 if (s)
55 memcpy(bstr, s, len);
56 for (; len < size; len++)
57 ((Byte *)bstr)[len] = 0;
58 return bstr;
59}
60
61BSTR SysAllocStringLen(const OLECHAR *s, UINT len)
62{
63 if (len >= (k_BstrSize_Max - (UINT)sizeof(OLECHAR) - (UINT)sizeof(CBstrSizeType)) / (UINT)sizeof(OLECHAR))
64 return NULL;
65
66 UINT size = len * (UINT)sizeof(OLECHAR);
67 void *p = AllocateForBSTR(size + (UINT)sizeof(CBstrSizeType) + (UINT)sizeof(OLECHAR));
68 if (!p)
69 return NULL;
70 *(CBstrSizeType *)p = (CBstrSizeType)size;
71 BSTR bstr = (BSTR)((CBstrSizeType *)p + 1);
72 if (s)
73 memcpy(bstr, s, size);
74 bstr[len] = 0;
75 return bstr;
76}
77
78BSTR SysAllocString(const OLECHAR *s)
79{
80 if (!s)
81 return 0;
82 const OLECHAR *s2 = s;
83 while (*s2 != 0)
84 s2++;
85 return SysAllocStringLen(s, (UINT)(s2 - s));
86}
87
88void SysFreeString(BSTR bstr)
89{
90 if (bstr)
91 FreeForBSTR((CBstrSizeType *)bstr - 1);
92}
93
94UINT SysStringByteLen(BSTR bstr)
95{
96 if (!bstr)
97 return 0;
98 return *((CBstrSizeType *)bstr - 1);
99}
100
101UINT SysStringLen(BSTR bstr)
102{
103 if (!bstr)
104 return 0;
105 return *((CBstrSizeType *)bstr - 1) / (UINT)sizeof(OLECHAR);
106}
107
108
109HRESULT VariantClear(VARIANTARG *prop)
110{
111 if (prop->vt == VT_BSTR)
112 SysFreeString(prop->bstrVal);
113 prop->vt = VT_EMPTY;
114 return S_OK;
115}
116
117HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src)
118{
119 HRESULT res = ::VariantClear(dest);
120 if (res != S_OK)
121 return res;
122 if (src->vt == VT_BSTR)
123 {
124 dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal,
125 SysStringByteLen(src->bstrVal));
126 if (!dest->bstrVal)
127 return E_OUTOFMEMORY;
128 dest->vt = VT_BSTR;
129 }
130 else
131 *dest = *src;
132 return S_OK;
133}
134
135LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2)
136{
137 if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1;
138 if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1;
139 if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1;
140 if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1;
141 return 0;
142}
143
144DWORD GetLastError()
145{
146 return (DWORD)errno;
147}
148
149void SetLastError(DWORD dw)
150{
151 errno = (int)dw;
152}
153
154
155static LONG TIME_GetBias()
156{
157 time_t utc = time(NULL);
158 struct tm *ptm = localtime(&utc);
159 int localdaylight = ptm->tm_isdst; /* daylight for local timezone */
160 ptm = gmtime(&utc);
161 ptm->tm_isdst = localdaylight; /* use local daylight, not that of Greenwich */
162 LONG bias = (int)(mktime(ptm)-utc);
163 return bias;
164}
165
166#define TICKS_PER_SEC 10000000
167/*
168#define SECS_PER_DAY (24 * 60 * 60)
169#define SECS_1601_TO_1970 ((369 * 365 + 89) * (UInt64)SECS_PER_DAY)
170#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKS_PER_SEC)
171*/
172
173#define GET_TIME_64(pft) ((pft)->dwLowDateTime | ((UInt64)(pft)->dwHighDateTime << 32))
174
175#define SET_FILETIME(ft, v64) \
176 (ft)->dwLowDateTime = (DWORD)v64; \
177 (ft)->dwHighDateTime = (DWORD)(v64 >> 32);
178
179
180BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime)
181{
182 UInt64 v = GET_TIME_64(fileTime);
183 v = (UInt64)((Int64)v - (Int64)TIME_GetBias() * TICKS_PER_SEC);
184 SET_FILETIME(localFileTime, v);
185 return TRUE;
186}
187
188BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime)
189{
190 UInt64 v = GET_TIME_64(localFileTime);
191 v = (UInt64)((Int64)v + (Int64)TIME_GetBias() * TICKS_PER_SEC);
192 SET_FILETIME(fileTime, v);
193 return TRUE;
194}
195
196/*
197VOID WINAPI GetSystemTimeAsFileTime(FILETIME *ft)
198{
199 UInt64 t = 0;
200 timeval tv;
201 if (gettimeofday(&tv, NULL) == 0)
202 {
203 t = tv.tv_sec * (UInt64)TICKS_PER_SEC + TICKS_1601_TO_1970;
204 t += tv.tv_usec * 10;
205 }
206 SET_FILETIME(ft, t);
207}
208*/
209
210DWORD WINAPI GetTickCount(VOID)
211{
212 #ifndef _WIN32
213 // gettimeofday() doesn't work in some MINGWs by unknown reason
214 timeval tv;
215 if (gettimeofday(&tv, NULL) == 0)
216 {
217 // tv_sec and tv_usec are (long)
218 return (DWORD)((UInt64)(Int64)tv.tv_sec * (UInt64)1000 + (UInt64)(Int64)tv.tv_usec / 1000);
219 }
220 #endif
221 return (DWORD)time(NULL) * 1000;
222}
223
224
225#define PERIOD_4 (4 * 365 + 1)
226#define PERIOD_100 (PERIOD_4 * 25 - 1)
227#define PERIOD_400 (PERIOD_100 * 4 + 1)
228
229BOOL WINAPI FileTimeToSystemTime(const FILETIME *ft, SYSTEMTIME *st)
230{
231 UInt32 v;
232 UInt64 v64 = GET_TIME_64(ft);
233 v64 /= 10000;
234 st->wMilliseconds = (WORD)(v64 % 1000); v64 /= 1000;
235 st->wSecond = (WORD)(v64 % 60); v64 /= 60;
236 st->wMinute = (WORD)(v64 % 60); v64 /= 60;
237 v = (UInt32)v64;
238 st->wHour = (WORD)(v % 24); v /= 24;
239
240 // 1601-01-01 was Monday
241 st->wDayOfWeek = (WORD)((v + 1) % 7);
242
243 UInt32 leaps, year, day, mon;
244 leaps = (3 * ((4 * v + (365 - 31 - 28) * 4 + 3) / PERIOD_400) + 3) / 4;
245 v += 28188 + leaps;
246 // leaps - the number of exceptions from PERIOD_4 rules starting from 1600-03-01
247 // (1959 / 64) - converts day from 03-01 to month
248 year = (20 * v - 2442) / (5 * PERIOD_4);
249 day = v - (year * PERIOD_4) / 4;
250 mon = (64 * day) / 1959;
251 st->wDay = (WORD)(day - (1959 * mon) / 64);
252 mon -= 1;
253 year += 1524;
254 if (mon > 12)
255 {
256 mon -= 12;
257 year++;
258 }
259 st->wMonth = (WORD)mon;
260 st->wYear = (WORD)year;
261
262 /*
263 unsigned year, mon;
264 unsigned char ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
265 unsigned t;
266
267 year = (WORD)(1601 + v / PERIOD_400 * 400);
268 v %= PERIOD_400;
269
270 t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100;
271 t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4;
272 t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365;
273
274 st->wYear = (WORD)year;
275
276 if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
277 ms[1] = 29;
278 for (mon = 0;; mon++)
279 {
280 unsigned d = ms[mon];
281 if (v < d)
282 break;
283 v -= d;
284 }
285 st->wDay = (WORD)(v + 1);
286 st->wMonth = (WORD)(mon + 1);
287 */
288
289 return TRUE;
290}
291
292#endif
diff --git a/CPP/Common/MyWindows.h b/CPP/Common/MyWindows.h
new file mode 100644
index 0000000..0664a5e
--- /dev/null
+++ b/CPP/Common/MyWindows.h
@@ -0,0 +1,268 @@
1// MyWindows.h
2
3#ifndef __MY_WINDOWS_H
4#define __MY_WINDOWS_H
5
6#ifdef _WIN32
7
8#include <Windows.h>
9
10#ifdef UNDER_CE
11 #undef VARIANT_TRUE
12 #define VARIANT_TRUE ((VARIANT_BOOL)-1)
13#endif
14
15#else // _WIN32
16
17#include <stddef.h> // for wchar_t
18#include <string.h>
19// #include <stdint.h> // for uintptr_t
20
21#include "MyGuidDef.h"
22
23// WINAPI is __stdcall in Windows-MSVC in windef.h
24#define WINAPI
25#define EXTERN_C MY_EXTERN_C
26
27typedef char CHAR;
28typedef unsigned char UCHAR;
29
30#undef BYTE
31typedef unsigned char BYTE;
32
33typedef short SHORT;
34typedef unsigned short USHORT;
35
36#undef WORD
37typedef unsigned short WORD;
38typedef short VARIANT_BOOL;
39
40#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))
41#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))
42
43// MS uses long for BOOL, but long is 32-bit in MS. So we use int.
44// typedef long BOOL;
45typedef int BOOL;
46
47#ifndef FALSE
48 #define FALSE 0
49 #define TRUE 1
50#endif
51
52// typedef size_t ULONG_PTR;
53// typedef size_t DWORD_PTR;
54// typedef uintptr_t UINT_PTR;
55// typedef ptrdiff_t UINT_PTR;
56
57typedef Int64 LONGLONG;
58typedef UInt64 ULONGLONG;
59
60typedef struct _LARGE_INTEGER { LONGLONG QuadPart; } LARGE_INTEGER;
61typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart; } ULARGE_INTEGER;
62
63typedef const CHAR *LPCSTR;
64typedef CHAR TCHAR;
65typedef const TCHAR *LPCTSTR;
66typedef wchar_t WCHAR;
67typedef WCHAR OLECHAR;
68typedef const WCHAR *LPCWSTR;
69typedef OLECHAR *BSTR;
70typedef const OLECHAR *LPCOLESTR;
71typedef OLECHAR *LPOLESTR;
72
73typedef struct _FILETIME
74{
75 DWORD dwLowDateTime;
76 DWORD dwHighDateTime;
77} FILETIME;
78
79#define HRESULT LONG
80#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
81#define FAILED(hr) ((HRESULT)(hr) < 0)
82typedef ULONG PROPID;
83typedef LONG SCODE;
84
85
86#define S_OK ((HRESULT)0x00000000L)
87#define S_FALSE ((HRESULT)0x00000001L)
88#define E_NOTIMPL ((HRESULT)0x80004001L)
89#define E_NOINTERFACE ((HRESULT)0x80004002L)
90#define E_ABORT ((HRESULT)0x80004004L)
91#define E_FAIL ((HRESULT)0x80004005L)
92#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L)
93#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L)
94
95
96#ifdef _MSC_VER
97#define STDMETHODCALLTYPE __stdcall
98#define STDAPICALLTYPE __stdcall
99#else
100// do we need __export here?
101#define STDMETHODCALLTYPE
102#define STDAPICALLTYPE
103#endif
104
105#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
106
107#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f
108#define STDMETHOD(f) STDMETHOD_(HRESULT, f)
109#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
110#define STDMETHODIMP STDMETHODIMP_(HRESULT)
111
112#define PURE = 0
113
114#define MIDL_INTERFACE(x) struct
115
116#ifdef __cplusplus
117
118DEFINE_GUID(IID_IUnknown,
1190x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
120struct IUnknown
121{
122 STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE;
123 STDMETHOD_(ULONG, AddRef)() PURE;
124 STDMETHOD_(ULONG, Release)() PURE;
125 virtual ~IUnknown() {}
126 // We use virtual ~IUnknown() here for binary compatibility with 7z.so from p7zip
127};
128
129typedef IUnknown *LPUNKNOWN;
130
131#endif
132
133#define VARIANT_TRUE ((VARIANT_BOOL)-1)
134#define VARIANT_FALSE ((VARIANT_BOOL)0)
135
136enum VARENUM
137{
138 VT_EMPTY = 0,
139 VT_NULL = 1,
140 VT_I2 = 2,
141 VT_I4 = 3,
142 VT_R4 = 4,
143 VT_R8 = 5,
144 VT_CY = 6,
145 VT_DATE = 7,
146 VT_BSTR = 8,
147 VT_DISPATCH = 9,
148 VT_ERROR = 10,
149 VT_BOOL = 11,
150 VT_VARIANT = 12,
151 VT_UNKNOWN = 13,
152 VT_DECIMAL = 14,
153 VT_I1 = 16,
154 VT_UI1 = 17,
155 VT_UI2 = 18,
156 VT_UI4 = 19,
157 VT_I8 = 20,
158 VT_UI8 = 21,
159 VT_INT = 22,
160 VT_UINT = 23,
161 VT_VOID = 24,
162 VT_HRESULT = 25,
163 VT_FILETIME = 64
164};
165
166typedef unsigned short VARTYPE;
167typedef WORD PROPVAR_PAD1;
168typedef WORD PROPVAR_PAD2;
169typedef WORD PROPVAR_PAD3;
170
171typedef struct tagPROPVARIANT
172{
173 VARTYPE vt;
174 PROPVAR_PAD1 wReserved1;
175 PROPVAR_PAD2 wReserved2;
176 PROPVAR_PAD3 wReserved3;
177 union
178 {
179 CHAR cVal;
180 UCHAR bVal;
181 SHORT iVal;
182 USHORT uiVal;
183 LONG lVal;
184 ULONG ulVal;
185 INT intVal;
186 UINT uintVal;
187 LARGE_INTEGER hVal;
188 ULARGE_INTEGER uhVal;
189 VARIANT_BOOL boolVal;
190 SCODE scode;
191 FILETIME filetime;
192 BSTR bstrVal;
193 };
194} PROPVARIANT;
195
196typedef PROPVARIANT tagVARIANT;
197typedef tagVARIANT VARIANT;
198typedef VARIANT VARIANTARG;
199
200MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop);
201MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src);
202
203typedef struct tagSTATPROPSTG
204{
205 LPOLESTR lpwstrName;
206 PROPID propid;
207 VARTYPE vt;
208} STATPROPSTG;
209
210MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);
211MY_EXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len);
212MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz);
213MY_EXTERN_C void SysFreeString(BSTR bstr);
214MY_EXTERN_C UINT SysStringByteLen(BSTR bstr);
215MY_EXTERN_C UINT SysStringLen(BSTR bstr);
216
217MY_EXTERN_C DWORD GetLastError();
218MY_EXTERN_C void SetLastError(DWORD dwCode);
219MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);
220
221MY_EXTERN_C DWORD GetCurrentThreadId();
222MY_EXTERN_C DWORD GetCurrentProcessId();
223
224#define MAX_PATH 1024
225
226#define CP_ACP 0
227#define CP_OEMCP 1
228#define CP_UTF8 65001
229
230typedef enum tagSTREAM_SEEK
231{
232 STREAM_SEEK_SET = 0,
233 STREAM_SEEK_CUR = 1,
234 STREAM_SEEK_END = 2
235} STREAM_SEEK;
236
237
238
239typedef struct _SYSTEMTIME
240{
241 WORD wYear;
242 WORD wMonth;
243 WORD wDayOfWeek;
244 WORD wDay;
245 WORD wHour;
246 WORD wMinute;
247 WORD wSecond;
248 WORD wMilliseconds;
249} SYSTEMTIME;
250
251BOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime);
252BOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime);
253BOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime);
254// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime);
255
256DWORD GetTickCount();
257
258
259#define CREATE_NEW 1
260#define CREATE_ALWAYS 2
261#define OPEN_EXISTING 3
262#define OPEN_ALWAYS 4
263#define TRUNCATE_EXISTING 5
264
265
266#endif // _WIN32
267
268#endif
diff --git a/CPP/Common/MyXml.cpp b/CPP/Common/MyXml.cpp
new file mode 100644
index 0000000..e014518
--- /dev/null
+++ b/CPP/Common/MyXml.cpp
@@ -0,0 +1,260 @@
1// MyXml.cpp
2
3#include "StdAfx.h"
4
5#include "MyXml.h"
6
7static bool IsValidChar(char c)
8{
9 return
10 (c >= 'a' && c <= 'z') ||
11 (c >= 'A' && c <= 'Z') ||
12 (c >= '0' && c <= '9') ||
13 c == '-';
14}
15
16static bool IsSpaceChar(char c)
17{
18 return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);
19}
20
21#define SKIP_SPACES(s) while (IsSpaceChar(*s)) s++;
22
23int CXmlItem::FindProp(const char *propName) const throw()
24{
25 FOR_VECTOR (i, Props)
26 if (Props[i].Name == propName)
27 return (int)i;
28 return -1;
29}
30
31AString CXmlItem::GetPropVal(const char *propName) const
32{
33 int index = FindProp(propName);
34 if (index >= 0)
35 return Props[(unsigned)index].Value;
36 return AString();
37}
38
39bool CXmlItem::IsTagged(const char *tag) const throw()
40{
41 return (IsTag && Name == tag);
42}
43
44int CXmlItem::FindSubTag(const char *tag) const throw()
45{
46 FOR_VECTOR (i, SubItems)
47 if (SubItems[i].IsTagged(tag))
48 return (int)i;
49 return -1;
50}
51
52AString CXmlItem::GetSubString() const
53{
54 if (SubItems.Size() == 1)
55 {
56 const CXmlItem &item = SubItems[0];
57 if (!item.IsTag)
58 return item.Name;
59 }
60 return AString();
61}
62
63const AString * CXmlItem::GetSubStringPtr() const throw()
64{
65 if (SubItems.Size() == 1)
66 {
67 const CXmlItem &item = SubItems[0];
68 if (!item.IsTag)
69 return &item.Name;
70 }
71 return NULL;
72}
73
74AString CXmlItem::GetSubStringForTag(const char *tag) const
75{
76 int index = FindSubTag(tag);
77 if (index >= 0)
78 return SubItems[(unsigned)index].GetSubString();
79 return AString();
80}
81
82const char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)
83{
84 SKIP_SPACES(s);
85
86 const char *beg = s;
87 for (;;)
88 {
89 char c;
90 c = *s; if (c == 0 || c == '<') break; s++;
91 c = *s; if (c == 0 || c == '<') break; s++;
92 }
93 if (*s == 0)
94 return NULL;
95 if (s != beg)
96 {
97 IsTag = false;
98 Name.SetFrom(beg, (unsigned)(s - beg));
99 return s;
100 }
101
102 IsTag = true;
103
104 s++;
105 SKIP_SPACES(s);
106
107 beg = s;
108 for (;; s++)
109 if (!IsValidChar(*s))
110 break;
111 if (s == beg || *s == 0)
112 return NULL;
113 Name.SetFrom(beg, (unsigned)(s - beg));
114
115 for (;;)
116 {
117 beg = s;
118 SKIP_SPACES(s);
119 if (*s == '/')
120 {
121 s++;
122 // SKIP_SPACES(s);
123 if (*s != '>')
124 return NULL;
125 return s + 1;
126 }
127 if (*s == '>')
128 {
129 s++;
130 if (numAllowedLevels == 0)
131 return NULL;
132 SubItems.Clear();
133 for (;;)
134 {
135 SKIP_SPACES(s);
136 if (s[0] == '<' && s[1] == '/')
137 break;
138 CXmlItem &item = SubItems.AddNew();
139 s = item.ParseItem(s, numAllowedLevels - 1);
140 if (!s)
141 return NULL;
142 }
143
144 s += 2;
145 unsigned len = Name.Len();
146 for (unsigned i = 0; i < len; i++)
147 if (s[i] != Name[i])
148 return NULL;
149 s += len;
150 if (s[0] != '>')
151 return NULL;
152 return s + 1;
153 }
154 if (beg == s)
155 return NULL;
156
157 // ReadProperty
158 CXmlProp &prop = Props.AddNew();
159
160 beg = s;
161 for (;; s++)
162 {
163 char c = *s;
164 if (!IsValidChar(c))
165 break;
166 }
167 if (s == beg)
168 return NULL;
169 prop.Name.SetFrom(beg, (unsigned)(s - beg));
170
171 SKIP_SPACES(s);
172 if (*s != '=')
173 return NULL;
174 s++;
175 SKIP_SPACES(s);
176 if (*s != '\"')
177 return NULL;
178 s++;
179
180 beg = s;
181 for (;;)
182 {
183 char c = *s;
184 if (c == 0)
185 return NULL;
186 if (c == '\"')
187 break;
188 s++;
189 }
190 prop.Value.SetFrom(beg, (unsigned)(s - beg));
191 s++;
192 }
193}
194
195static const char * SkipHeader(const char *s, const char *startString, const char *endString)
196{
197 SKIP_SPACES(s);
198 if (IsString1PrefixedByString2(s, startString))
199 {
200 s = strstr(s, endString);
201 if (!s)
202 return NULL;
203 s += strlen(endString);
204 }
205 return s;
206}
207
208void CXmlItem::AppendTo(AString &s) const
209{
210 if (IsTag)
211 s += '<';
212 s += Name;
213 if (IsTag)
214 {
215 FOR_VECTOR (i, Props)
216 {
217 const CXmlProp &prop = Props[i];
218 s += ' ';
219 s += prop.Name;
220 s += '=';
221 s += '\"';
222 s += prop.Value;
223 s += '\"';
224 }
225 s += '>';
226 }
227 FOR_VECTOR (i, SubItems)
228 {
229 const CXmlItem &item = SubItems[i];
230 if (i != 0 && !SubItems[i - 1].IsTag)
231 s += ' ';
232 item.AppendTo(s);
233 }
234 if (IsTag)
235 {
236 s += '<';
237 s += '/';
238 s += Name;
239 s += '>';
240 }
241}
242
243bool CXml::Parse(const char *s)
244{
245 s = SkipHeader(s, "<?xml", "?>"); if (!s) return false;
246 s = SkipHeader(s, "<!DOCTYPE", ">"); if (!s) return false;
247
248 s = Root.ParseItem(s, 1000);
249 if (!s || !Root.IsTag)
250 return false;
251 SKIP_SPACES(s);
252 return *s == 0;
253}
254
255/*
256void CXml::AppendTo(AString &s) const
257{
258 Root.AppendTo(s);
259}
260*/
diff --git a/CPP/Common/MyXml.h b/CPP/Common/MyXml.h
new file mode 100644
index 0000000..00b7113
--- /dev/null
+++ b/CPP/Common/MyXml.h
@@ -0,0 +1,43 @@
1// MyXml.h
2
3#ifndef __MY_XML_H
4#define __MY_XML_H
5
6#include "MyString.h"
7
8struct CXmlProp
9{
10 AString Name;
11 AString Value;
12};
13
14class CXmlItem
15{
16public:
17 AString Name;
18 bool IsTag;
19 CObjectVector<CXmlProp> Props;
20 CObjectVector<CXmlItem> SubItems;
21
22 const char * ParseItem(const char *s, int numAllowedLevels);
23
24 bool IsTagged(const char *tag) const throw();
25 int FindProp(const char *propName) const throw();
26 AString GetPropVal(const char *propName) const;
27 AString GetSubString() const;
28 const AString * GetSubStringPtr() const throw();
29 int FindSubTag(const char *tag) const throw();
30 AString GetSubStringForTag(const char *tag) const;
31
32 void AppendTo(AString &s) const;
33};
34
35struct CXml
36{
37 CXmlItem Root;
38
39 bool Parse(const char *s);
40 // void AppendTo(AString &s) const;
41};
42
43#endif
diff --git a/CPP/Common/NewHandler.cpp b/CPP/Common/NewHandler.cpp
new file mode 100644
index 0000000..7e5b1d4
--- /dev/null
+++ b/CPP/Common/NewHandler.cpp
@@ -0,0 +1,163 @@
1// NewHandler.cpp
2
3#include "StdAfx.h"
4
5#include <stdlib.h>
6
7#include "NewHandler.h"
8
9// #define DEBUG_MEMORY_LEAK
10
11#ifndef DEBUG_MEMORY_LEAK
12
13#ifdef _7ZIP_REDEFINE_OPERATOR_NEW
14
15/*
16void * my_new(size_t size)
17{
18 // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
19 void *p = ::malloc(size);
20 if (p == 0)
21 throw CNewException();
22 return p;
23}
24
25void my_delete(void *p) throw()
26{
27 // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);
28 ::free(p);
29}
30
31void * my_Realloc(void *p, size_t newSize, size_t oldSize)
32{
33 void *newBuf = my_new(newSize);
34 if (oldSize != 0)
35 memcpy(newBuf, p, oldSize);
36 my_delete(p);
37 return newBuf;
38}
39*/
40
41void *
42#ifdef _MSC_VER
43__cdecl
44#endif
45operator new(size_t size)
46{
47 // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
48 void *p = ::malloc(size);
49 if (p == 0)
50 throw CNewException();
51 return p;
52}
53
54void
55#ifdef _MSC_VER
56__cdecl
57#endif
58operator delete(void *p) throw()
59{
60 // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);
61 ::free(p);
62}
63
64/*
65void *
66#ifdef _MSC_VER
67__cdecl
68#endif
69operator new[](size_t size)
70{
71 // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);
72 void *p = ::malloc(size);
73 if (p == 0)
74 throw CNewException();
75 return p;
76}
77
78void
79#ifdef _MSC_VER
80__cdecl
81#endif
82operator delete[](void *p) throw()
83{
84 // if (p == 0) return; ::HeapFree(::GetProcessHeap(), 0, p);
85 ::free(p);
86}
87*/
88
89#endif
90
91#else
92
93#include <stdio.h>
94
95// #pragma init_seg(lib)
96const int kDebugSize = 1000000;
97static void *a[kDebugSize];
98static int index = 0;
99
100static int numAllocs = 0;
101void * __cdecl operator new(size_t size)
102{
103 numAllocs++;
104 void *p = HeapAlloc(GetProcessHeap(), 0, size);
105 if (index < kDebugSize)
106 {
107 a[index] = p;
108 index++;
109 }
110 if (p == 0)
111 throw CNewException();
112 printf("Alloc %6d, size = %8u\n", numAllocs, (unsigned)size);
113 return p;
114}
115
116class CC
117{
118public:
119 CC()
120 {
121 for (int i = 0; i < kDebugSize; i++)
122 a[i] = 0;
123 }
124 ~CC()
125 {
126 for (int i = 0; i < kDebugSize; i++)
127 if (a[i] != 0)
128 return;
129 }
130} g_CC;
131
132
133void __cdecl operator delete(void *p)
134{
135 if (p == 0)
136 return;
137 /*
138 for (int i = 0; i < index; i++)
139 if (a[i] == p)
140 a[i] = 0;
141 */
142 HeapFree(GetProcessHeap(), 0, p);
143 numAllocs--;
144 printf("Free %d\n", numAllocs);
145}
146
147#endif
148
149/*
150int MemErrorVC(size_t)
151{
152 throw CNewException();
153 // return 1;
154}
155CNewHandlerSetter::CNewHandlerSetter()
156{
157 // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);
158}
159CNewHandlerSetter::~CNewHandlerSetter()
160{
161 // _set_new_handler(MemErrorOldVCFunction);
162}
163*/
diff --git a/CPP/Common/NewHandler.h b/CPP/Common/NewHandler.h
new file mode 100644
index 0000000..aedeca6
--- /dev/null
+++ b/CPP/Common/NewHandler.h
@@ -0,0 +1,88 @@
1// Common/NewHandler.h
2
3#ifndef __COMMON_NEW_HANDLER_H
4#define __COMMON_NEW_HANDLER_H
5
6/*
7NewHandler.h and NewHandler.cpp allows to solve problem with compilers that
8don't throw exception in operator new().
9
10This file must be included before any code that uses operators new() or delete()
11and you must compile and link "NewHandler.cpp", if you use some old MSVC compiler.
12
13The operator new() in some MSVC versions doesn't throw exception std::bad_alloc.
14MSVC 6.0 (_MSC_VER == 1200) doesn't throw exception.
15The code produced by some another MSVC compilers also can be linked
16to library that doesn't throw exception.
17We suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc.
18For older _MSC_VER versions we redefine operator new() and operator delete().
19Our version of operator new() throws CNewException() exception on failure.
20
21It's still allowed to use redefined version of operator new() from "NewHandler.cpp"
22with any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions.
23But if you use some additional code (outside of 7-Zip's code), you must check
24that redefined version of operator new() is not problem for your code.
25*/
26
27#include <stddef.h>
28
29#ifdef _WIN32
30// We can compile my_new and my_delete with _fastcall
31/*
32void * my_new(size_t size);
33void my_delete(void *p) throw();
34// void * my_Realloc(void *p, size_t newSize, size_t oldSize);
35*/
36#endif
37
38
39#if defined(_MSC_VER) && (_MSC_VER < 1900)
40 // If you want to use default operator new(), you can disable the following line
41 #define _7ZIP_REDEFINE_OPERATOR_NEW
42#endif
43
44
45#ifdef _7ZIP_REDEFINE_OPERATOR_NEW
46
47// std::bad_alloc can require additional DLL dependency.
48// So we don't define CNewException as std::bad_alloc here.
49
50class CNewException {};
51
52void *
53#ifdef _MSC_VER
54__cdecl
55#endif
56operator new(size_t size);
57
58void
59#ifdef _MSC_VER
60__cdecl
61#endif
62operator delete(void *p) throw();
63
64#else
65
66#include <new>
67
68#define CNewException std::bad_alloc
69
70#endif
71
72/*
73#ifdef _WIN32
74void *
75#ifdef _MSC_VER
76__cdecl
77#endif
78operator new[](size_t size);
79
80void
81#ifdef _MSC_VER
82__cdecl
83#endif
84operator delete[](void *p) throw();
85#endif
86*/
87
88#endif
diff --git a/CPP/Common/Random.cpp b/CPP/Common/Random.cpp
new file mode 100644
index 0000000..fbdb8c9
--- /dev/null
+++ b/CPP/Common/Random.cpp
@@ -0,0 +1,28 @@
1// Common/Random.cpp
2
3#include "StdAfx.h"
4
5#include <stdlib.h>
6
7#ifndef _WIN32
8#include <time.h>
9#else
10#include "MyWindows.h"
11#endif
12
13#include "Random.h"
14
15void CRandom::Init(unsigned int seed) { srand(seed); }
16
17void CRandom::Init()
18{
19 Init((unsigned int)
20 #ifdef _WIN32
21 GetTickCount()
22 #else
23 time(NULL)
24 #endif
25 );
26}
27
28int CRandom::Generate() const { return rand(); }
diff --git a/CPP/Common/Random.h b/CPP/Common/Random.h
new file mode 100644
index 0000000..e784e98
--- /dev/null
+++ b/CPP/Common/Random.h
@@ -0,0 +1,14 @@
1// Common/Random.h
2
3#ifndef __COMMON_RANDOM_H
4#define __COMMON_RANDOM_H
5
6class CRandom
7{
8public:
9 void Init();
10 void Init(unsigned int seed);
11 int Generate() const;
12};
13
14#endif
diff --git a/CPP/Common/Sha1Prepare.cpp b/CPP/Common/Sha1Prepare.cpp
new file mode 100644
index 0000000..2652f00
--- /dev/null
+++ b/CPP/Common/Sha1Prepare.cpp
@@ -0,0 +1,7 @@
1// Sha1Prepare.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/Sha1.h"
6
7static struct CSha1Prepare { CSha1Prepare() { Sha1Prepare(); } } g_Sha1Prepare;
diff --git a/CPP/Common/Sha1Reg.cpp b/CPP/Common/Sha1Reg.cpp
new file mode 100644
index 0000000..0cb2baf
--- /dev/null
+++ b/CPP/Common/Sha1Reg.cpp
@@ -0,0 +1,70 @@
1// Sha1Reg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/Sha1.h"
6
7#include "../Common/MyBuffer2.h"
8#include "../Common/MyCom.h"
9
10#include "../7zip/Common/RegisterCodec.h"
11
12class CSha1Hasher:
13 public IHasher,
14 public ICompressSetCoderProperties,
15 public CMyUnknownImp
16{
17 CAlignedBuffer _buf;
18 Byte mtDummy[1 << 7];
19
20 CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_buf; }
21public:
22 CSha1Hasher():
23 _buf(sizeof(CSha1))
24 {
25 Sha1_SetFunction(Sha(), 0);
26 Sha1_InitState(Sha());
27 }
28
29 MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties)
30 INTERFACE_IHasher(;)
31 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
32};
33
34STDMETHODIMP_(void) CSha1Hasher::Init() throw()
35{
36 Sha1_InitState(Sha());
37}
38
39STDMETHODIMP_(void) CSha1Hasher::Update(const void *data, UInt32 size) throw()
40{
41 Sha1_Update(Sha(), (const Byte *)data, size);
42}
43
44STDMETHODIMP_(void) CSha1Hasher::Final(Byte *digest) throw()
45{
46 Sha1_Final(Sha(), digest);
47}
48
49
50STDMETHODIMP CSha1Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
51{
52 unsigned algo = 0;
53 for (UInt32 i = 0; i < numProps; i++)
54 {
55 const PROPVARIANT &prop = coderProps[i];
56 if (propIDs[i] == NCoderPropID::kDefaultProp)
57 {
58 if (prop.vt != VT_UI4)
59 return E_INVALIDARG;
60 if (prop.ulVal > 2)
61 return E_NOTIMPL;
62 algo = (unsigned)prop.ulVal;
63 }
64 }
65 if (!Sha1_SetFunction(Sha(), algo))
66 return E_NOTIMPL;
67 return S_OK;
68}
69
70REGISTER_HASHER(CSha1Hasher, 0x201, "SHA1", SHA1_DIGEST_SIZE)
diff --git a/CPP/Common/Sha256Prepare.cpp b/CPP/Common/Sha256Prepare.cpp
new file mode 100644
index 0000000..1ec242b
--- /dev/null
+++ b/CPP/Common/Sha256Prepare.cpp
@@ -0,0 +1,7 @@
1// Sha256Prepare.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/Sha256.h"
6
7static struct CSha256Prepare { CSha256Prepare() { Sha256Prepare(); } } g_Sha256Prepare;
diff --git a/CPP/Common/Sha256Reg.cpp b/CPP/Common/Sha256Reg.cpp
new file mode 100644
index 0000000..5f3a35b
--- /dev/null
+++ b/CPP/Common/Sha256Reg.cpp
@@ -0,0 +1,70 @@
1// Sha256Reg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/Sha256.h"
6
7#include "../Common/MyBuffer2.h"
8#include "../Common/MyCom.h"
9
10#include "../7zip/Common/RegisterCodec.h"
11
12class CSha256Hasher:
13 public IHasher,
14 public ICompressSetCoderProperties,
15 public CMyUnknownImp
16{
17 CAlignedBuffer _buf;
18 Byte mtDummy[1 << 7];
19
20 CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_buf; }
21public:
22 CSha256Hasher():
23 _buf(sizeof(CSha256))
24 {
25 Sha256_SetFunction(Sha(), 0);
26 Sha256_InitState(Sha());
27 }
28
29 MY_UNKNOWN_IMP2(IHasher, ICompressSetCoderProperties)
30 INTERFACE_IHasher(;)
31 STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
32};
33
34STDMETHODIMP_(void) CSha256Hasher::Init() throw()
35{
36 Sha256_InitState(Sha());
37}
38
39STDMETHODIMP_(void) CSha256Hasher::Update(const void *data, UInt32 size) throw()
40{
41 Sha256_Update(Sha(), (const Byte *)data, size);
42}
43
44STDMETHODIMP_(void) CSha256Hasher::Final(Byte *digest) throw()
45{
46 Sha256_Final(Sha(), digest);
47}
48
49
50STDMETHODIMP CSha256Hasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
51{
52 unsigned algo = 0;
53 for (UInt32 i = 0; i < numProps; i++)
54 {
55 const PROPVARIANT &prop = coderProps[i];
56 if (propIDs[i] == NCoderPropID::kDefaultProp)
57 {
58 if (prop.vt != VT_UI4)
59 return E_INVALIDARG;
60 if (prop.ulVal > 2)
61 return E_NOTIMPL;
62 algo = (unsigned)prop.ulVal;
63 }
64 }
65 if (!Sha256_SetFunction(Sha(), algo))
66 return E_NOTIMPL;
67 return S_OK;
68}
69
70REGISTER_HASHER(CSha256Hasher, 0xA, "SHA256", SHA256_DIGEST_SIZE)
diff --git a/CPP/Common/StdAfx.h b/CPP/Common/StdAfx.h
new file mode 100644
index 0000000..420f5c3
--- /dev/null
+++ b/CPP/Common/StdAfx.h
@@ -0,0 +1,8 @@
1// StdAfx.h
2
3#ifndef __STDAFX_H
4#define __STDAFX_H
5
6#include "Common.h"
7
8#endif
diff --git a/CPP/Common/StdInStream.cpp b/CPP/Common/StdInStream.cpp
new file mode 100644
index 0000000..abad34b
--- /dev/null
+++ b/CPP/Common/StdInStream.cpp
@@ -0,0 +1,95 @@
1// Common/StdInStream.cpp
2
3#include "StdAfx.h"
4
5#ifdef _WIN32
6#include <tchar.h>
7#endif
8
9#include "StdInStream.h"
10#include "StringConvert.h"
11#include "UTFConvert.h"
12
13// #define kEOFMessage "Unexpected end of input stream"
14// #define kReadErrorMessage "Error reading input stream"
15// #define kIllegalCharMessage "Illegal zero character in input stream"
16
17#define kFileOpenMode TEXT("r")
18
19CStdInStream g_StdIn(stdin);
20
21bool CStdInStream::Open(LPCTSTR fileName) throw()
22{
23 Close();
24 _stream =
25 #ifdef _WIN32
26 _tfopen
27 #else
28 fopen
29 #endif
30 (fileName, kFileOpenMode);
31 _streamIsOpen = (_stream != 0);
32 return _streamIsOpen;
33}
34
35bool CStdInStream::Close() throw()
36{
37 if (!_streamIsOpen)
38 return true;
39 _streamIsOpen = (fclose(_stream) != 0);
40 return !_streamIsOpen;
41}
42
43bool CStdInStream::ScanAStringUntilNewLine(AString &s)
44{
45 s.Empty();
46 for (;;)
47 {
48 int intChar = GetChar();
49 if (intChar == EOF)
50 return true;
51 char c = (char)intChar;
52 if (c == 0)
53 return false;
54 if (c == '\n')
55 return true;
56 s += c;
57 }
58}
59
60bool CStdInStream::ScanUStringUntilNewLine(UString &dest)
61{
62 dest.Empty();
63 AString s;
64 bool res = ScanAStringUntilNewLine(s);
65 int codePage = CodePage;
66 if (codePage == -1)
67 codePage = CP_OEMCP;
68 if (codePage == CP_UTF8)
69 ConvertUTF8ToUnicode(s, dest);
70 else
71 MultiByteToUnicodeString2(dest, s, (UINT)codePage);
72 return res;
73}
74
75/*
76bool CStdInStream::ReadToString(AString &resultString)
77{
78 resultString.Empty();
79 for (;;)
80 {
81 int intChar = GetChar();
82 if (intChar == EOF)
83 return !Error();
84 char c = (char)intChar;
85 if (c == 0)
86 return false;
87 resultString += c;
88 }
89}
90*/
91
92int CStdInStream::GetChar()
93{
94 return fgetc(_stream); // getc() doesn't work in BeOS?
95}
diff --git a/CPP/Common/StdInStream.h b/CPP/Common/StdInStream.h
new file mode 100644
index 0000000..71578eb
--- /dev/null
+++ b/CPP/Common/StdInStream.h
@@ -0,0 +1,44 @@
1// Common/StdInStream.h
2
3#ifndef __COMMON_STD_IN_STREAM_H
4#define __COMMON_STD_IN_STREAM_H
5
6#include <stdio.h>
7
8#include "MyString.h"
9#include "MyTypes.h"
10
11class CStdInStream
12{
13 FILE *_stream;
14 bool _streamIsOpen;
15public:
16 int CodePage;
17
18 CStdInStream(FILE *stream = NULL):
19 _stream(stream),
20 _streamIsOpen(false),
21 CodePage(-1)
22 {};
23
24 ~CStdInStream() { Close(); }
25
26 bool Open(LPCTSTR fileName) throw();
27 bool Close() throw();
28
29 // returns:
30 // false, if ZERO character in stream
31 // true, if EOF or '\n'
32 bool ScanAStringUntilNewLine(AString &s);
33 bool ScanUStringUntilNewLine(UString &s);
34 // bool ReadToString(AString &resultString);
35
36 bool Eof() const throw() { return (feof(_stream) != 0); }
37 bool Error() const throw() { return (ferror(_stream) != 0); }
38
39 int GetChar();
40};
41
42extern CStdInStream g_StdIn;
43
44#endif
diff --git a/CPP/Common/StdOutStream.cpp b/CPP/Common/StdOutStream.cpp
new file mode 100644
index 0000000..40799e2
--- /dev/null
+++ b/CPP/Common/StdOutStream.cpp
@@ -0,0 +1,158 @@
1// Common/StdOutStream.cpp
2
3#include "StdAfx.h"
4
5#ifdef _WIN32
6#include <tchar.h>
7#endif
8
9#include "IntToString.h"
10#include "StdOutStream.h"
11#include "StringConvert.h"
12#include "UTFConvert.h"
13
14#define kFileOpenMode "wt"
15
16CStdOutStream g_StdOut(stdout);
17CStdOutStream g_StdErr(stderr);
18
19bool CStdOutStream::Open(const char *fileName) throw()
20{
21 Close();
22 _stream = fopen(fileName, kFileOpenMode);
23 _streamIsOpen = (_stream != 0);
24 return _streamIsOpen;
25}
26
27bool CStdOutStream::Close() throw()
28{
29 if (!_streamIsOpen)
30 return true;
31 if (fclose(_stream) != 0)
32 return false;
33 _stream = 0;
34 _streamIsOpen = false;
35 return true;
36}
37
38bool CStdOutStream::Flush() throw()
39{
40 return (fflush(_stream) == 0);
41}
42
43CStdOutStream & endl(CStdOutStream & outStream) throw()
44{
45 return outStream << '\n';
46}
47
48CStdOutStream & CStdOutStream::operator<<(const wchar_t *s)
49{
50 AString temp;
51 UString s2(s);
52 PrintUString(s2, temp);
53 return *this;
54}
55
56void CStdOutStream::PrintUString(const UString &s, AString &temp)
57{
58 Convert_UString_to_AString(s, temp);
59 *this << (const char *)temp;
60}
61
62void CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest)
63{
64 int codePage = CodePage;
65 if (codePage == -1)
66 codePage = CP_OEMCP;
67 if (codePage == CP_UTF8)
68 ConvertUnicodeToUTF8(src, dest);
69 else
70 UnicodeStringToMultiByte2(dest, src, (UINT)codePage);
71}
72
73
74static const wchar_t kReplaceChar = '_';
75
76void CStdOutStream::Normalize_UString__LF_Allowed(UString &s)
77{
78 unsigned len = s.Len();
79 wchar_t *d = s.GetBuf();
80
81 if (IsTerminalMode)
82 for (unsigned i = 0; i < len; i++)
83 {
84 wchar_t c = d[i];
85 if (c <= 13 && c >= 7 && c != '\n')
86 d[i] = kReplaceChar;
87 }
88}
89
90void CStdOutStream::Normalize_UString(UString &s)
91{
92 unsigned len = s.Len();
93 wchar_t *d = s.GetBuf();
94
95 if (IsTerminalMode)
96 for (unsigned i = 0; i < len; i++)
97 {
98 wchar_t c = d[i];
99 if (c <= 13 && c >= 7)
100 d[i] = kReplaceChar;
101 }
102 else
103 for (unsigned i = 0; i < len; i++)
104 {
105 wchar_t c = d[i];
106 if (c == '\n')
107 d[i] = kReplaceChar;
108 }
109}
110
111void CStdOutStream::NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA)
112{
113 tempU = s;
114 Normalize_UString(tempU);
115 PrintUString(tempU, tempA);
116}
117
118void CStdOutStream::NormalizePrint_UString(const UString &s)
119{
120 NormalizePrint_wstr(s);
121}
122
123void CStdOutStream::NormalizePrint_wstr(const wchar_t *s)
124{
125 UString tempU = s;
126 Normalize_UString(tempU);
127 AString tempA;
128 PrintUString(tempU, tempA);
129}
130
131
132CStdOutStream & CStdOutStream::operator<<(Int32 number) throw()
133{
134 char s[32];
135 ConvertInt64ToString(number, s);
136 return operator<<(s);
137}
138
139CStdOutStream & CStdOutStream::operator<<(Int64 number) throw()
140{
141 char s[32];
142 ConvertInt64ToString(number, s);
143 return operator<<(s);
144}
145
146CStdOutStream & CStdOutStream::operator<<(UInt32 number) throw()
147{
148 char s[16];
149 ConvertUInt32ToString(number, s);
150 return operator<<(s);
151}
152
153CStdOutStream & CStdOutStream::operator<<(UInt64 number) throw()
154{
155 char s[32];
156 ConvertUInt64ToString(number, s);
157 return operator<<(s);
158}
diff --git a/CPP/Common/StdOutStream.h b/CPP/Common/StdOutStream.h
new file mode 100644
index 0000000..93f1dfa
--- /dev/null
+++ b/CPP/Common/StdOutStream.h
@@ -0,0 +1,76 @@
1// Common/StdOutStream.h
2
3#ifndef __COMMON_STD_OUT_STREAM_H
4#define __COMMON_STD_OUT_STREAM_H
5
6#include <stdio.h>
7
8#include "MyString.h"
9#include "MyTypes.h"
10
11class CStdOutStream
12{
13 FILE *_stream;
14 bool _streamIsOpen;
15public:
16 bool IsTerminalMode;
17 int CodePage;
18
19 CStdOutStream(FILE *stream = 0):
20 _stream(stream),
21 _streamIsOpen(false),
22 IsTerminalMode(false),
23 CodePage(-1)
24 {};
25
26 ~CStdOutStream() { Close(); }
27
28 // void AttachStdStream(FILE *stream) { _stream = stream; _streamIsOpen = false; }
29 // bool IsDefined() const { return _stream != NULL; }
30
31 operator FILE *() { return _stream; }
32 bool Open(const char *fileName) throw();
33 bool Close() throw();
34 bool Flush() throw();
35
36 CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream &))
37 {
38 (*func)(*this);
39 return *this;
40 }
41
42 CStdOutStream & operator<<(const char *s) throw()
43 {
44 fputs(s, _stream);
45 return *this;
46 }
47
48 CStdOutStream & operator<<(char c) throw()
49 {
50 fputc((unsigned char)c, _stream);
51 return *this;
52 }
53
54 CStdOutStream & operator<<(Int32 number) throw();
55 CStdOutStream & operator<<(Int64 number) throw();
56 CStdOutStream & operator<<(UInt32 number) throw();
57 CStdOutStream & operator<<(UInt64 number) throw();
58
59 CStdOutStream & operator<<(const wchar_t *s);
60 void PrintUString(const UString &s, AString &temp);
61 void Convert_UString_to_AString(const UString &src, AString &dest);
62
63 void Normalize_UString__LF_Allowed(UString &s);
64 void Normalize_UString(UString &s);
65
66 void NormalizePrint_UString(const UString &s, UString &tempU, AString &tempA);
67 void NormalizePrint_UString(const UString &s);
68 void NormalizePrint_wstr(const wchar_t *s);
69};
70
71CStdOutStream & endl(CStdOutStream & outStream) throw();
72
73extern CStdOutStream g_StdOut;
74extern CStdOutStream g_StdErr;
75
76#endif
diff --git a/CPP/Common/StringConvert.cpp b/CPP/Common/StringConvert.cpp
new file mode 100644
index 0000000..c0bde0f
--- /dev/null
+++ b/CPP/Common/StringConvert.cpp
@@ -0,0 +1,757 @@
1// Common/StringConvert.cpp
2
3#include "StdAfx.h"
4
5#include "StringConvert.h"
6
7#ifndef _WIN32
8// #include <stdio.h>
9#include <stdlib.h>
10#endif
11
12#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
13#include "UTFConvert.h"
14#endif
15
16#ifdef ENV_HAVE_LOCALE
17#include <locale.h>
18#endif
19
20static const char k_DefultChar = '_';
21
22#ifdef _WIN32
23
24/*
25MultiByteToWideChar(CodePage, DWORD dwFlags,
26 LPCSTR lpMultiByteStr, int cbMultiByte,
27 LPWSTR lpWideCharStr, int cchWideChar)
28
29 if (cbMultiByte == 0)
30 return: 0. ERR: ERROR_INVALID_PARAMETER
31
32 if (cchWideChar == 0)
33 return: the required buffer size in characters.
34
35 if (supplied buffer size was not large enough)
36 return: 0. ERR: ERROR_INSUFFICIENT_BUFFER
37 The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)
38
39 If there are illegal characters:
40 if MB_ERR_INVALID_CHARS is set in dwFlags:
41 - the function stops conversion on illegal character.
42 - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.
43
44 if MB_ERR_INVALID_CHARS is NOT set in dwFlags:
45 before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.
46 in Vista+: illegal character is not dropped (MSDN). Undocumented: illegal
47 character is converted to U+FFFD, which is REPLACEMENT CHARACTER.
48*/
49
50
51void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
52{
53 dest.Empty();
54 if (src.IsEmpty())
55 return;
56 {
57 /*
58 wchar_t *d = dest.GetBuf(src.Len());
59 const char *s = (const char *)src;
60 unsigned i;
61
62 for (i = 0;;)
63 {
64 Byte c = (Byte)s[i];
65 if (c >= 0x80 || c == 0)
66 break;
67 d[i++] = (wchar_t)c;
68 }
69
70 if (i != src.Len())
71 {
72 unsigned len = MultiByteToWideChar(codePage, 0, s + i,
73 src.Len() - i, d + i,
74 src.Len() + 1 - i);
75 if (len == 0)
76 throw 282228;
77 i += len;
78 }
79
80 d[i] = 0;
81 dest.ReleaseBuf_SetLen(i);
82 */
83 unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0);
84 if (len == 0)
85 {
86 if (GetLastError() != 0)
87 throw 282228;
88 }
89 else
90 {
91 len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len);
92 if (len == 0)
93 throw 282228;
94 dest.ReleaseBuf_SetEnd(len);
95 }
96 }
97}
98
99/*
100 int WideCharToMultiByte(
101 UINT CodePage, DWORD dwFlags,
102 LPCWSTR lpWideCharStr, int cchWideChar,
103 LPSTR lpMultiByteStr, int cbMultiByte,
104 LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);
105
106if (lpDefaultChar == NULL),
107 - it uses system default value.
108
109if (CodePage == CP_UTF7 || CodePage == CP_UTF8)
110 if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)
111 return: 0. ERR: ERROR_INVALID_PARAMETER.
112
113The function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)
114
115*/
116
117static void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
118{
119 dest.Empty();
120 defaultCharWasUsed = false;
121 if (src.IsEmpty())
122 return;
123 {
124 /*
125 unsigned numRequiredBytes = src.Len() * 2;
126 char *d = dest.GetBuf(numRequiredBytes);
127 const wchar_t *s = (const wchar_t *)src;
128 unsigned i;
129
130 for (i = 0;;)
131 {
132 wchar_t c = s[i];
133 if (c >= 0x80 || c == 0)
134 break;
135 d[i++] = (char)c;
136 }
137
138 if (i != src.Len())
139 {
140 BOOL defUsed = FALSE;
141 defaultChar = defaultChar;
142
143 bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
144 unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,
145 d + i, numRequiredBytes + 1 - i,
146 (isUtf ? NULL : &defaultChar),
147 (isUtf ? NULL : &defUsed));
148 defaultCharWasUsed = (defUsed != FALSE);
149 if (len == 0)
150 throw 282229;
151 i += len;
152 }
153
154 d[i] = 0;
155 dest.ReleaseBuf_SetLen(i);
156 */
157
158 /*
159 if (codePage != CP_UTF7)
160 {
161 const wchar_t *s = (const wchar_t *)src;
162 unsigned i;
163 for (i = 0;; i++)
164 {
165 wchar_t c = s[i];
166 if (c >= 0x80 || c == 0)
167 break;
168 }
169
170 if (s[i] == 0)
171 {
172 char *d = dest.GetBuf(src.Len());
173 for (i = 0;;)
174 {
175 wchar_t c = s[i];
176 if (c == 0)
177 break;
178 d[i++] = (char)c;
179 }
180 d[i] = 0;
181 dest.ReleaseBuf_SetLen(i);
182 return;
183 }
184 }
185 */
186
187 unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL);
188 if (len == 0)
189 {
190 if (GetLastError() != 0)
191 throw 282228;
192 }
193 else
194 {
195 BOOL defUsed = FALSE;
196 bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);
197 // defaultChar = defaultChar;
198 len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(),
199 dest.GetBuf(len), (int)len,
200 (isUtf ? NULL : &defaultChar),
201 (isUtf ? NULL : &defUsed)
202 );
203 if (!isUtf)
204 defaultCharWasUsed = (defUsed != FALSE);
205 if (len == 0)
206 throw 282228;
207 dest.ReleaseBuf_SetEnd(len);
208 }
209 }
210}
211
212/*
213#ifndef UNDER_CE
214AString SystemStringToOemString(const CSysString &src)
215{
216 AString dest;
217 const unsigned len = src.Len() * 2;
218 CharToOem(src, dest.GetBuf(len));
219 dest.ReleaseBuf_CalcLen(len);
220 return dest;
221}
222#endif
223*/
224
225#else // _WIN32
226
227// #include <stdio.h>
228/*
229 if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff),
230 and utf-8 string contains big unicode character > 0xffff),
231 then we still use 16-bit surrogate pair in UString.
232 It simplifies another code where utf-16 encoding is used.
233 So we use surrogate-conversion code only in is file.
234*/
235
236/*
237 mbstowcs() returns error if there is error in utf-8 stream,
238 mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream
239*/
240
241/*
242static void MultiByteToUnicodeString2_Native(UString &dest, const AString &src)
243{
244 dest.Empty();
245 if (src.IsEmpty())
246 return;
247
248 const size_t limit = ((size_t)src.Len() + 1) * 2;
249 wchar_t *d = dest.GetBuf((unsigned)limit);
250 const size_t len = mbstowcs(d, src, limit);
251 if (len != (size_t)-1)
252 {
253 dest.ReleaseBuf_SetEnd((unsigned)len);
254 return;
255 }
256 dest.ReleaseBuf_SetEnd(0);
257}
258*/
259
260bool g_ForceToUTF8 = true; // false;
261
262void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)
263{
264 dest.Empty();
265 if (src.IsEmpty())
266 return;
267
268 if (codePage == CP_UTF8 || g_ForceToUTF8)
269 {
270 ConvertUTF8ToUnicode(src, dest);
271 return;
272 }
273
274 const size_t limit = ((size_t)src.Len() + 1) * 2;
275 wchar_t *d = dest.GetBuf((unsigned)limit);
276 const size_t len = mbstowcs(d, src, limit);
277 if (len != (size_t)-1)
278 {
279 dest.ReleaseBuf_SetEnd((unsigned)len);
280
281 #if WCHAR_MAX > 0xffff
282 d = dest.GetBuf();
283 for (size_t i = 0;; i++)
284 {
285 // wchar_t c = dest[i];
286 wchar_t c = d[i];
287 if (c == 0)
288 break;
289 if (c >= 0x10000 && c < 0x110000)
290 {
291 /*
292 c -= 0x10000;
293 unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);
294 dest.ReplaceOneCharAtPos(i, c0);
295 i++;
296 c = 0xdc00 + (c & 0x3FF);
297 dest.Insert_wchar_t(i, c);
298 */
299 UString temp = d + i;
300
301 for (size_t t = 0;; t++)
302 {
303 wchar_t w = temp[t];
304 if (w == 0)
305 break;
306 if (i == limit)
307 break; // unexpected error
308 if (w >= 0x10000 && w < 0x110000)
309 {
310 if (i + 1 == limit)
311 break; // unexpected error
312 w -= 0x10000;
313 d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3FF);
314 w = 0xdc00 + (w & 0x3FF);
315 }
316 d[i++] = w;
317 }
318 dest.ReleaseBuf_SetEnd((unsigned)i);
319 }
320 }
321
322 #endif
323
324 /*
325 printf("\nMultiByteToUnicodeString2 (%d) %s\n", (int)src.Len(), src.Ptr());
326 printf("char: ");
327 for (unsigned i = 0; i < src.Len(); i++)
328 printf (" %02x", (int)(Byte)src[i]);
329 printf("\n");
330 printf("\n-> (%d) %ls\n", (int)dest.Len(), dest.Ptr());
331 printf("wchar_t: ");
332 for (unsigned i = 0; i < dest.Len(); i++)
333 {
334 printf (" %02x", (int)dest[i]);
335 }
336 printf("\n");
337 */
338
339 return;
340 }
341
342 /* if there is mbstowcs() error, we have two ways:
343
344 1) change 0x80+ characters to some character: '_'
345 in that case we lose data, but we have correct UString()
346 and that scheme can show errors to user in early stages,
347 when file converted back to mbs() cannot be found
348
349 2) transfer bad characters in some UTF-16 range.
350 it can be non-original Unicode character.
351 but later we still can restore original character.
352 */
353
354
355 // printf("\nmbstowcs ERROR !!!!!! s=%s\n", src.Ptr());
356 {
357 unsigned i;
358 const char *s = (const char *)src;
359 for (i = 0;;)
360 {
361 Byte c = (Byte)s[i];
362 if (c == 0)
363 break;
364 // we can use ascii compatibilty character '_'
365 // if (c > 0x7F) c = '_'; // we replace "bad: character
366 d[i++] = (wchar_t)c;
367 }
368 d[i] = 0;
369 dest.ReleaseBuf_SetLen(i);
370 }
371}
372
373static void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src)
374{
375 dest.Empty();
376 if (src.IsEmpty())
377 return;
378
379 const size_t limit = ((size_t)src.Len() + 1) * 6;
380 char *d = dest.GetBuf((unsigned)limit);
381
382 const size_t len = wcstombs(d, src, limit);
383
384 if (len != (size_t)-1)
385 {
386 dest.ReleaseBuf_SetEnd((unsigned)len);
387 return;
388 }
389 dest.ReleaseBuf_SetEnd(0);
390}
391
392
393static void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
394{
395 // if (codePage == 1234567) // for debug purposes
396 if (codePage == CP_UTF8 || g_ForceToUTF8)
397 {
398 defaultCharWasUsed = false;
399 ConvertUnicodeToUTF8(src2, dest);
400 return;
401 }
402
403 UString src = src2;
404 #if WCHAR_MAX > 0xffff
405 {
406 src.Empty();
407 for (unsigned i = 0; i < src2.Len();)
408 {
409 wchar_t c = src2[i];
410 if (c >= 0xd800 && c < 0xdc00 && i + 1 != src2.Len())
411 {
412 const wchar_t c2 = src2[i + 1];
413 if (c2 >= 0xdc00 && c2 < 0x10000)
414 {
415 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
416 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
417 // printf("%4x\n", (int)c);
418 i++;
419 }
420 }
421 src += c;
422 i++;
423 }
424 }
425 #endif
426
427 dest.Empty();
428 defaultCharWasUsed = false;
429 if (src.IsEmpty())
430 return;
431
432 const size_t len = wcstombs(NULL, src, 0);
433
434 if (len != (size_t)-1)
435 {
436 const unsigned limit = ((unsigned)len);
437 if (limit == len)
438 {
439 char *d = dest.GetBuf(limit);
440
441 /*
442 {
443 printf("\nwcstombs; len = %d %ls \n", (int)src.Len(), src.Ptr());
444 for (unsigned i = 0; i < src.Len(); i++)
445 printf (" %02x", (int)src[i]);
446 printf("\n");
447 printf("\ndest Limit = %d \n", limit);
448 }
449 */
450
451 const size_t len2 = wcstombs(d, src, len + 1);
452
453 if (len2 != (size_t)-1 && len2 <= limit)
454 {
455 /*
456 printf("\nOK : destLen = %d : %s\n", (int)len, dest.Ptr());
457 for (unsigned i = 0; i < len2; i++)
458 printf(" %02x", (int)(Byte)dest[i]);
459 printf("\n");
460 */
461 dest.ReleaseBuf_SetEnd((unsigned)len2);
462 return;
463 }
464 }
465 }
466
467 {
468 const wchar_t *s = (const wchar_t *)src;
469 char *d = dest.GetBuf(src.Len());
470
471 unsigned i;
472 for (i = 0;;)
473 {
474 wchar_t c = s[i];
475 if (c == 0)
476 break;
477 if (c >=
478 0x100
479 // 0x80
480 )
481 {
482 c = defaultChar;
483 defaultCharWasUsed = true;
484 }
485
486 d[i++] = (char)c;
487 }
488 d[i] = 0;
489 dest.ReleaseBuf_SetLen(i);
490 /*
491 printf("\nUnicodeStringToMultiByte2; len = %d \n", (int)src.Len());
492 printf("ERROR: %s\n", dest.Ptr());
493 */
494 }
495}
496
497#endif // _WIN32
498
499
500UString MultiByteToUnicodeString(const AString &src, UINT codePage)
501{
502 UString dest;
503 MultiByteToUnicodeString2(dest, src, codePage);
504 return dest;
505}
506
507UString MultiByteToUnicodeString(const char *src, UINT codePage)
508{
509 return MultiByteToUnicodeString(AString(src), codePage);
510}
511
512
513void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)
514{
515 bool defaultCharWasUsed;
516 UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
517}
518
519AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)
520{
521 AString dest;
522 UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);
523 return dest;
524}
525
526AString UnicodeStringToMultiByte(const UString &src, UINT codePage)
527{
528 AString dest;
529 bool defaultCharWasUsed;
530 UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);
531 return dest;
532}
533
534
535
536
537
538#ifdef _WIN32
539#define U_to_A(a, b, c) UnicodeStringToMultiByte2
540// #define A_to_U(a, b, c) MultiByteToUnicodeString2
541#else
542// void MultiByteToUnicodeString2_Native(UString &dest, const AString &src);
543#define U_to_A(a, b, c) UnicodeStringToMultiByte2_Native(a, b)
544// #define A_to_U(a, b, c) MultiByteToUnicodeString2_Native(a, b)
545#endif
546
547#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
548
549bool IsNativeUTF8()
550{
551 UString u;
552 AString a, a2;
553 // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1)
554 for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1)
555 {
556 u.Empty();
557 u += (wchar_t)c;
558 /*
559 if (Unicode_Is_There_Utf16SurrogateError(u))
560 continue;
561 #ifndef _WIN32
562 if (Unicode_Is_There_BmpEscape(u))
563 continue;
564 #endif
565 */
566 ConvertUnicodeToUTF8(u, a);
567 U_to_A(a2, u, CP_OEMCP);
568 if (a != a2)
569 return false;
570 }
571 return true;
572}
573
574#endif
575
576
577#ifdef ENV_HAVE_LOCALE
578
579const char *GetLocale(void)
580{
581 #ifdef ENV_HAVE_LOCALE
582 // printf("\n\nsetlocale(LC_CTYPE, NULL) : return : ");
583 const char *s = setlocale(LC_CTYPE, NULL);
584 if (!s)
585 {
586 // printf("[NULL]\n");
587 s = "C";
588 }
589 else
590 {
591 // ubuntu returns "C" after program start
592 // printf("\"%s\"\n", s);
593 }
594 return s;
595 #elif defined(LOCALE_IS_UTF8)
596 return "utf8";
597 #else
598 return "C";
599 #endif
600}
601
602#ifdef _WIN32
603 static void Set_ForceToUTF8(bool) {}
604#else
605 static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; }
606#endif
607
608static bool Is_Default_Basic_Locale(const char *locale)
609{
610 const AString a (locale);
611 if (a.IsEqualTo_Ascii_NoCase("")
612 || a.IsEqualTo_Ascii_NoCase("C")
613 || a.IsEqualTo_Ascii_NoCase("POSIX"))
614 return true;
615 return false;
616}
617
618static bool Is_Default_Basic_Locale()
619{
620 return Is_Default_Basic_Locale(GetLocale());
621}
622
623
624void MY_SetLocale()
625{
626 #ifdef ENV_HAVE_LOCALE
627 /*
628 {
629 const char *s = GetLocale();
630 printf("\nGetLocale() : returned : \"%s\"\n", s);
631 }
632 */
633
634 unsigned start = 0;
635 // unsigned lim = 0;
636 unsigned lim = 3;
637
638 /*
639 #define MY_SET_LOCALE_FLAGS__FROM_ENV 1
640 #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2
641
642 unsigned flags =
643 MY_SET_LOCALE_FLAGS__FROM_ENV |
644 MY_SET_LOCALE_FLAGS__TRY_UTF8
645
646 if (flags != 0)
647 {
648 if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV)
649 lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1;
650 else
651 {
652 start = 1;
653 lim = 2;
654 }
655 }
656 */
657
658 for (unsigned i = start; i < lim; i++)
659 {
660 /*
661 man7: "If locale is an empty string, "", each part of the locale that
662 should be modified is set according to the environment variables.
663 for glibc: glibc, first from the user's environment variables:
664 1) the environment variable LC_ALL,
665 2) environment variable with the same name as the category (see the
666 3) the environment variable LANG
667 The locale "C" or "POSIX" is a portable locale; it exists on all conforming systems.
668
669 for WIN32 : MSDN :
670 Sets the locale to the default, which is the user-default
671 ANSI code page obtained from the operating system.
672 The locale name is set to the value returned by GetUserDefaultLocaleName.
673 The code page is set to the value returned by GetACP
674 */
675 const char *newLocale = "";
676
677 #ifdef __APPLE__
678
679 /* look also CFLocale
680 there is no C.UTF-8 in macos
681 macos has UTF-8 locale only with some language like en_US.UTF-8
682 what is best way to set UTF-8 locale in macos? */
683 if (i == 1)
684 newLocale = "en_US.UTF-8";
685
686 /* file open with non-utf8 sequencies return
687 #define EILSEQ 92 // "Illegal byte sequence"
688 */
689#else
690 // newLocale = "C";
691 if (i == 1)
692 {
693 newLocale = "C.UTF-8"; // main UTF-8 locale in ubuntu
694 // newLocale = ".utf8"; // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime
695 // newLocale = "en_US.utf8"; // supported by ubuntu ?
696 // newLocale = "en_US.UTF-8";
697 /* setlocale() in ubuntu allows locales with minor chracter changes in strings
698 "en_US.UTF-8" / "en_US.utf8" */
699 }
700
701#endif
702
703 // printf("\nsetlocale(LC_ALL, \"%s\") : returned: ", newLocale);
704
705 // const char *s =
706 setlocale(LC_ALL, newLocale);
707
708 /*
709 if (!s)
710 printf("NULL: can't set locale");
711 else
712 printf("\"%s\"\n", s);
713 */
714
715 // request curent locale of program
716 const char *locale = GetLocale();
717 if (locale)
718 {
719 AString a (locale);
720 a.MakeLower_Ascii();
721 // if (a.Find("utf") >= 0)
722 {
723 if (IsNativeUTF8())
724 {
725 Set_ForceToUTF8(true);
726 return;
727 }
728 }
729 if (!Is_Default_Basic_Locale(locale))
730 {
731 // if there is some non-default and non-utf locale, we want to use it
732 break; // comment it for debug
733 }
734 }
735 }
736
737 if (IsNativeUTF8())
738 {
739 Set_ForceToUTF8(true);
740 return;
741 }
742
743 if (Is_Default_Basic_Locale())
744 {
745 Set_ForceToUTF8(true);
746 return;
747 }
748
749 Set_ForceToUTF8(false);
750
751 #elif defined(LOCALE_IS_UTF8)
752 // assume LC_CTYPE="utf8"
753 #else
754 // assume LC_CTYPE="C"
755 #endif
756}
757#endif
diff --git a/CPP/Common/StringConvert.h b/CPP/Common/StringConvert.h
new file mode 100644
index 0000000..865c025
--- /dev/null
+++ b/CPP/Common/StringConvert.h
@@ -0,0 +1,110 @@
1// Common/StringConvert.h
2
3#ifndef __COMMON_STRING_CONVERT_H
4#define __COMMON_STRING_CONVERT_H
5
6#include "MyString.h"
7#include "MyWindows.h"
8
9UString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP);
10UString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP);
11
12// optimized versions that work faster for ASCII strings
13void MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP);
14// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
15void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage);
16
17AString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed);
18AString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP);
19
20inline const wchar_t* GetUnicodeString(const wchar_t *u) { return u; }
21inline const UString& GetUnicodeString(const UString &u) { return u; }
22
23inline UString GetUnicodeString(const AString &a) { return MultiByteToUnicodeString(a); }
24inline UString GetUnicodeString(const char *a) { return MultiByteToUnicodeString(a); }
25
26inline UString GetUnicodeString(const AString &a, UINT codePage)
27 { return MultiByteToUnicodeString(a, codePage); }
28inline UString GetUnicodeString(const char *a, UINT codePage)
29 { return MultiByteToUnicodeString(a, codePage); }
30
31inline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; }
32inline const UString& GetUnicodeString(const UString &u, UINT) { return u; }
33
34inline const char* GetAnsiString(const char *a) { return a; }
35inline const AString& GetAnsiString(const AString &a) { return a; }
36
37inline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
38inline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); }
39
40/*
41inline const char* GetOemString(const char* oem)
42 { return oem; }
43inline const AString& GetOemString(const AString &oem)
44 { return oem; }
45*/
46const char* GetOemString(const char* oem);
47const AString& GetOemString(const AString &oem);
48inline AString GetOemString(const UString &u)
49 { return UnicodeStringToMultiByte(u, CP_OEMCP); }
50
51#ifdef _UNICODE
52 inline const wchar_t* GetSystemString(const wchar_t *u) { return u;}
53 inline const UString& GetSystemString(const UString &u) { return u;}
54 inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;}
55 inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;}
56
57 inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
58 inline UString GetSystemString(const char *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }
59 inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); }
60 inline UString GetSystemString(const char *a) { return MultiByteToUnicodeString(a); }
61#else
62 inline const char* GetSystemString(const char *a) { return a; }
63 inline const AString& GetSystemString(const AString &a) { return a; }
64 inline const char* GetSystemString(const char *a, UINT) { return a; }
65 inline const AString& GetSystemString(const AString &a, UINT) { return a; }
66
67 inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }
68 inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); }
69 inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); }
70
71
72
73 /*
74 inline AString GetSystemString(const wchar_t *u)
75 {
76 UString s;
77 s = u;
78 return UnicodeStringToMultiByte(s);
79 }
80 */
81
82#endif
83
84#ifndef UNDER_CE
85AString SystemStringToOemString(const CSysString &src);
86#endif
87
88
89#ifdef _WIN32
90/* we don't need locale functions in Windows
91 but we can define ENV_HAVE_LOCALE here for debug purposes */
92// #define ENV_HAVE_LOCALE
93#else
94#define ENV_HAVE_LOCALE
95#endif
96
97#ifdef ENV_HAVE_LOCALE
98void MY_SetLocale();
99const char *GetLocale(void);
100#endif
101
102#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)
103bool IsNativeUTF8();
104#endif
105
106#ifndef _WIN32
107extern bool g_ForceToUTF8;
108#endif
109
110#endif
diff --git a/CPP/Common/StringToInt.cpp b/CPP/Common/StringToInt.cpp
new file mode 100644
index 0000000..839867a
--- /dev/null
+++ b/CPP/Common/StringToInt.cpp
@@ -0,0 +1,144 @@
1// Common/StringToInt.cpp
2
3#include "StdAfx.h"
4
5#include "StringToInt.h"
6
7static const UInt32 k_UInt32_max = 0xFFFFFFFF;
8static const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);
9// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;
10
11#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \
12 uintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \
13 if (end) *end = s; \
14 uintType res = 0; \
15 for (;; s++) { \
16 charTypeUnsigned c = (charTypeUnsigned)*s; \
17 if (c < '0' || c > '9') { if (end) *end = s; return res; } \
18 if (res > (k_ ## uintType ## _max) / 10) return 0; \
19 res *= 10; \
20 unsigned v = (unsigned)(c - '0'); \
21 if (res > (k_ ## uintType ## _max) - v) return 0; \
22 res += v; }}
23
24CONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)
25CONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)
26CONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)
27CONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)
28
29Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()
30{
31 if (end)
32 *end = s;
33 const wchar_t *s2 = s;
34 if (*s == '-')
35 s2++;
36 if (*s2 == 0)
37 return 0;
38 const wchar_t *end2;
39 UInt32 res = ConvertStringToUInt32(s2, &end2);
40 if (*s == '-')
41 {
42 if (res > ((UInt32)1 << (32 - 1)))
43 return 0;
44 }
45 else if ((res & ((UInt32)1 << (32 - 1))) != 0)
46 return 0;
47 if (end)
48 *end = end2;
49 if (*s == '-')
50 return -(Int32)res;
51 return (Int32)res;
52}
53
54UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw()
55{
56 if (end)
57 *end = s;
58 UInt32 res = 0;
59 for (;; s++)
60 {
61 unsigned c = (unsigned char)*s;
62 if (c < '0' || c > '7')
63 {
64 if (end)
65 *end = s;
66 return res;
67 }
68 if ((res & (UInt32)7 << (32 - 3)) != 0)
69 return 0;
70 res <<= 3;
71 res |= (unsigned)(c - '0');
72 }
73}
74
75UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw()
76{
77 if (end)
78 *end = s;
79 UInt64 res = 0;
80 for (;; s++)
81 {
82 unsigned c = (unsigned char)*s;
83 if (c < '0' || c > '7')
84 {
85 if (end)
86 *end = s;
87 return res;
88 }
89 if ((res & (UInt64)7 << (64 - 3)) != 0)
90 return 0;
91 res <<= 3;
92 res |= (unsigned)(c - '0');
93 }
94}
95
96UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw()
97{
98 if (end)
99 *end = s;
100 UInt32 res = 0;
101 for (;; s++)
102 {
103 unsigned c = (Byte)*s;
104 unsigned v;
105 if (c >= '0' && c <= '9') v = (c - '0');
106 else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
107 else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
108 else
109 {
110 if (end)
111 *end = s;
112 return res;
113 }
114 if ((res & (UInt32)0xF << (32 - 4)) != 0)
115 return 0;
116 res <<= 4;
117 res |= v;
118 }
119}
120
121UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw()
122{
123 if (end)
124 *end = s;
125 UInt64 res = 0;
126 for (;; s++)
127 {
128 unsigned c = (Byte)*s;
129 unsigned v;
130 if (c >= '0' && c <= '9') v = (c - '0');
131 else if (c >= 'A' && c <= 'F') v = 10 + (c - 'A');
132 else if (c >= 'a' && c <= 'f') v = 10 + (c - 'a');
133 else
134 {
135 if (end)
136 *end = s;
137 return res;
138 }
139 if ((res & (UInt64)0xF << (64 - 4)) != 0)
140 return 0;
141 res <<= 4;
142 res |= v;
143 }
144}
diff --git a/CPP/Common/StringToInt.h b/CPP/Common/StringToInt.h
new file mode 100644
index 0000000..5c5d7d7
--- /dev/null
+++ b/CPP/Common/StringToInt.h
@@ -0,0 +1,21 @@
1// Common/StringToInt.h
2
3#ifndef __COMMON_STRING_TO_INT_H
4#define __COMMON_STRING_TO_INT_H
5
6#include "MyTypes.h"
7
8UInt32 ConvertStringToUInt32(const char *s, const char **end) throw();
9UInt64 ConvertStringToUInt64(const char *s, const char **end) throw();
10UInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw();
11UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw();
12
13Int32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw();
14
15UInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw();
16UInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();
17
18UInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();
19UInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();
20
21#endif
diff --git a/CPP/Common/TextConfig.cpp b/CPP/Common/TextConfig.cpp
new file mode 100644
index 0000000..1428aab
--- /dev/null
+++ b/CPP/Common/TextConfig.cpp
@@ -0,0 +1,124 @@
1// Common/TextConfig.cpp
2
3#include "StdAfx.h"
4
5#include "TextConfig.h"
6#include "UTFConvert.h"
7
8static inline bool IsDelimitChar(char c)
9{
10 return (c == ' ' || c == 0x0A || c == 0x0D || c == '\0' || c == '\t');
11}
12
13static AString GetIDString(const char *s, unsigned &finishPos)
14{
15 AString result;
16 for (finishPos = 0; ; finishPos++)
17 {
18 char c = s[finishPos];
19 if (IsDelimitChar(c) || c == '=')
20 break;
21 result += c;
22 }
23 return result;
24}
25
26static bool WaitNextLine(const AString &s, unsigned &pos)
27{
28 for (; pos < s.Len(); pos++)
29 if (s[pos] == 0x0A)
30 return true;
31 return false;
32}
33
34static bool SkipSpaces(const AString &s, unsigned &pos)
35{
36 for (; pos < s.Len(); pos++)
37 {
38 char c = s[pos];
39 if (!IsDelimitChar(c))
40 {
41 if (c != ';')
42 return true;
43 if (!WaitNextLine(s, pos))
44 return false;
45 }
46 }
47 return false;
48}
49
50bool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)
51{
52 pairs.Clear();
53 unsigned pos = 0;
54
55 /////////////////////
56 // read strings
57
58 for (;;)
59 {
60 if (!SkipSpaces(s, pos))
61 break;
62 CTextConfigPair pair;
63 unsigned finishPos;
64 const AString temp (GetIDString(((const char *)s) + pos, finishPos));
65 if (!ConvertUTF8ToUnicode(temp, pair.ID))
66 return false;
67 if (finishPos == 0)
68 return false;
69 pos += finishPos;
70 if (!SkipSpaces(s, pos))
71 return false;
72 if (s[pos] != '=')
73 return false;
74 pos++;
75 if (!SkipSpaces(s, pos))
76 return false;
77 if (s[pos] != '\"')
78 return false;
79 pos++;
80 AString message;
81 for (;;)
82 {
83 if (pos >= s.Len())
84 return false;
85 char c = s[pos++];
86 if (c == '\"')
87 break;
88 if (c == '\\')
89 {
90 c = s[pos++];
91 switch (c)
92 {
93 case 'n': message += '\n'; break;
94 case 't': message += '\t'; break;
95 case '\\': message += '\\'; break;
96 case '\"': message += '\"'; break;
97 default: message += '\\'; message += c; break;
98 }
99 }
100 else
101 message += c;
102 }
103 if (!ConvertUTF8ToUnicode(message, pair.String))
104 return false;
105 pairs.Add(pair);
106 }
107 return true;
108}
109
110int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw()
111{
112 FOR_VECTOR (i, pairs)
113 if (pairs[i].ID.IsEqualTo(id))
114 return i;
115 return -1;
116}
117
118UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id)
119{
120 int index = FindTextConfigItem(pairs, id);
121 if (index < 0)
122 return UString();
123 return pairs[index].String;
124}
diff --git a/CPP/Common/TextConfig.h b/CPP/Common/TextConfig.h
new file mode 100644
index 0000000..cc7ce41
--- /dev/null
+++ b/CPP/Common/TextConfig.h
@@ -0,0 +1,19 @@
1// Common/TextConfig.h
2
3#ifndef __COMMON_TEXT_CONFIG_H
4#define __COMMON_TEXT_CONFIG_H
5
6#include "MyString.h"
7
8struct CTextConfigPair
9{
10 UString ID;
11 UString String;
12};
13
14bool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);
15
16int FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw();
17UString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id);
18
19#endif
diff --git a/CPP/Common/UTFConvert.cpp b/CPP/Common/UTFConvert.cpp
new file mode 100644
index 0000000..ac069db
--- /dev/null
+++ b/CPP/Common/UTFConvert.cpp
@@ -0,0 +1,863 @@
1// UTFConvert.cpp
2
3#include "StdAfx.h"
4
5// #include <stdio.h>
6
7#include "MyTypes.h"
8#include "UTFConvert.h"
9
10
11#ifndef _WCHART_IS_16BIT
12#ifndef __APPLE__
13 // we define it if the system supports files with non-utf8 symbols:
14 #define _UTF8_RAW_NON_UTF8_SUPPORTED
15#endif
16#endif
17
18/*
19 _UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte
20
21 n : _UTF8_START(n) : Bits of code point
22
23 0 : 0x80 : : unused
24 1 : 0xC0 : 11 :
25 2 : 0xE0 : 16 : Basic Multilingual Plane
26 3 : 0xF0 : 21 : Unicode space
27 4 : 0xF8 : 26 :
28 5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value
29 6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value
30 7 : 0xFF :
31*/
32
33#define _UTF8_START(n) (0x100 - (1 << (7 - (n))))
34
35#define _UTF8_HEAD_PARSE2(n) \
36 if (c < _UTF8_START((n) + 1)) \
37 { numBytes = (n); val -= _UTF8_START(n); }
38
39#ifndef _WCHART_IS_16BIT
40
41/*
42 if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence,
43 when we convert wchar_t strings to UTF-8:
44 (_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode
45 (_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4
46 (_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack)
47*/
48
49#define _UTF8_NUM_TAIL_BYTES_MAX 5
50#endif
51
52/*
53#define _UTF8_HEAD_PARSE \
54 UInt32 val = c; \
55 _UTF8_HEAD_PARSE2(1) \
56 else _UTF8_HEAD_PARSE2(2) \
57 else _UTF8_HEAD_PARSE2(3) \
58 else _UTF8_HEAD_PARSE2(4) \
59 else _UTF8_HEAD_PARSE2(5) \
60 #if _UTF8_NUM_TAIL_BYTES_MAX >= 6
61 else _UTF8_HEAD_PARSE2(6)
62 #endif
63*/
64
65#define _UTF8_HEAD_PARSE_MAX_3_BYTES \
66 UInt32 val = c; \
67 _UTF8_HEAD_PARSE2(1) \
68 else _UTF8_HEAD_PARSE2(2) \
69 else { numBytes = 3; val -= _UTF8_START(3); }
70
71
72#define _UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))
73
74
75#define START_POINT_FOR_SURROGATE 0x10000
76
77
78/* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes
79 Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000)
80 to simplify internal intermediate conversion in Linux:
81 RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8
82*/
83
84
85#if defined(_WCHART_IS_16BIT)
86
87#define UTF_ESCAPE_PLANE 0
88
89#else
90
91/*
92we can place 128 ESCAPE chars to
93 ef 80 - ee be 80 (3-bytes utf-8) : similar to WSL
94 ef ff - ee bf bf
95
961f ef 80 - f7 be be 80 (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode)
971f ef ff - f7 be bf bf (4-bytes utf-8) : last 4-bytes utf-8 plane (out of Unicode)
98*/
99
100// #define UTF_ESCAPE_PLANE_HIGH (0x1f << 16)
101// #define UTF_ESCAPE_PLANE UTF_ESCAPE_PLANE_HIGH
102#define UTF_ESCAPE_PLANE 0
103
104/*
105 if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is set)
106 {
107 if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH)
108 {
109 we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane.
110 But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive)
111 So we still need a way to extract 8-bit Escapes and BMP-Escapes-8
112 from same BMP-Escapes-16 stored in 7z.
113 And if we want to restore any 8-bit from 7z archive,
114 we still must use UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT for (utf-8 -> utf-16)
115 Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21
116 }
117 else (UTF_ESCAPE_PLANE == 0)
118 {
119 we must convert original 3-bytes utf-8 BMP-Escape point to sequence
120 of 3 BMP-Escape-16 points with UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT
121 so we can extract original RAW-UTF-8 from UTFD-16 later.
122 }
123 }
124*/
125
126#endif
127
128
129
130#define UTF_ESCAPE_BASE 0xef00
131
132
133#ifdef UTF_ESCAPE_BASE
134#define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80)
135#endif
136
137#define IS_SURROGATE_POINT(v) (((v) & (UInt32)0xfffff800) == 0xd800)
138#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffC00) == 0xdc00)
139
140
141#define _ERROR_UTF8_CHECK \
142 { NonUtf = true; continue; }
143
144void CUtf8Check::Check_Buf(const char *src, size_t size) throw()
145{
146 Clear();
147 // Byte maxByte = 0;
148
149 for (;;)
150 {
151 if (size == 0)
152 break;
153
154 const Byte c = (Byte)(*src++);
155 size--;
156
157 if (c == 0)
158 {
159 ZeroChar = true;
160 continue;
161 }
162
163 /*
164 if (c > maxByte)
165 maxByte = c;
166 */
167
168 if (c < 0x80)
169 continue;
170
171 if (c < 0xc0 + 2)// it's limit for 0x140000 unicode codes : win32 compatibility
172 _ERROR_UTF8_CHECK
173
174 unsigned numBytes;
175
176 UInt32 val = c;
177 _UTF8_HEAD_PARSE2(1)
178 else _UTF8_HEAD_PARSE2(2)
179 else _UTF8_HEAD_PARSE2(4)
180 else _UTF8_HEAD_PARSE2(5)
181 else
182 {
183 _ERROR_UTF8_CHECK
184 }
185
186 unsigned pos = 0;
187 do
188 {
189 if (pos == size)
190 break;
191 unsigned c2 = (Byte)src[pos];
192 c2 -= 0x80;
193 if (c2 >= 0x40)
194 break;
195 val <<= 6;
196 val |= c2;
197 if (pos == 0)
198 if (val < (((unsigned)1 << 7) >> numBytes))
199 break;
200 pos++;
201 }
202 while (--numBytes);
203
204 if (numBytes != 0)
205 {
206 if (pos == size)
207 Truncated = true;
208 else
209 _ERROR_UTF8_CHECK
210 }
211
212 #ifdef UTF_ESCAPE_BASE
213 if (IS_ESCAPE_POINT(val, 0))
214 Escape = true;
215 #endif
216
217 if (MaxHighPoint < val)
218 MaxHighPoint = val;
219
220 if (IS_SURROGATE_POINT(val))
221 SingleSurrogate = true;
222
223 src += pos;
224 size -= pos;
225 }
226
227 // MaxByte = maxByte;
228}
229
230bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw()
231{
232 CUtf8Check check;
233 check.Check_Buf(src, size);
234 return check.IsOK(allowReduced);
235}
236
237/*
238bool CheckUTF8_chars(const char *src, bool allowReduced) throw()
239{
240 CUtf8Check check;
241 check.CheckBuf(src, strlen(src));
242 return check.IsOK(allowReduced);
243}
244*/
245
246bool CheckUTF8_AString(const AString &s) throw()
247{
248 CUtf8Check check;
249 check.Check_AString(s);
250 return check.IsOK();
251}
252
253
254/*
255bool CheckUTF8(const char *src, bool allowReduced) throw()
256{
257 // return Check_UTF8_Buf(src, strlen(src), allowReduced);
258
259 for (;;)
260 {
261 const Byte c = (Byte)(*src++);
262 if (c == 0)
263 return true;
264
265 if (c < 0x80)
266 continue;
267 if (c < 0xC0 + 2 || c >= 0xf5)
268 return false;
269
270 unsigned numBytes;
271 _UTF8_HEAD_PARSE
272 else
273 return false;
274
275 unsigned pos = 0;
276
277 do
278 {
279 Byte c2 = (Byte)(*src++);
280 if (c2 < 0x80 || c2 >= 0xC0)
281 return allowReduced && c2 == 0;
282 val <<= 6;
283 val |= (c2 - 0x80);
284 pos++;
285 }
286 while (--numBytes);
287
288 if (val < _UTF8_RANGE(pos - 1))
289 return false;
290
291 if (val >= 0x110000)
292 return false;
293 }
294}
295*/
296
297// in case of UTF-8 error we have two ways:
298// 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version
299// 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols
300
301#define UTF_REPLACEMENT_CHAR 0xfffd
302
303
304
305#define UTF_ESCAPE(c) \
306 ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) ? \
307 UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR)
308
309/*
310#define _HARD_ERROR_UTF8
311 { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \
312 destPos++; ok = false; continue; }
313*/
314
315// we ignore utf errors, and don't change (ok) variable!
316
317#define _ERROR_UTF8 \
318 { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \
319 destPos++; continue; }
320
321// we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points:
322
323// for debug puposes only we can store UTF-32 in wchar_t:
324// #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1)
325
326
327/*
328 WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found.
329 Ant it can emit single 0xfffd from 2 src bytes.
330 It doesn't emit single 0xfffd from 3-4 src bytes.
331 We can
332 1) emit Escape point for each incorrect byte. So we can data recover later
333 2) emit 0xfffd for each incorrect byte.
334 That scheme is similar to Escape scheme, but we emit 0xfffd
335 instead of each Escape point.
336 3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme
337*/
338
339static bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw()
340{
341 size_t destPos = 0;
342 bool ok = true;
343
344 for (;;)
345 {
346 if (src == srcLim)
347 {
348 *destLen = destPos;
349 return ok;
350 }
351
352 const Byte c = (Byte)(*src++);
353
354 if (c < 0x80)
355 {
356 if (dest)
357 dest[destPos] = (wchar_t)c;
358 destPos++;
359 continue;
360 }
361
362 if (c < 0xc0 + 2
363 || c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility
364 {
365 _ERROR_UTF8
366 }
367
368 unsigned numBytes;
369
370 _UTF8_HEAD_PARSE_MAX_3_BYTES
371
372 unsigned pos = 0;
373 do
374 {
375 if (src + pos == srcLim)
376 break;
377 unsigned c2 = (Byte)src[pos];
378 c2 -= 0x80;
379 if (c2 >= 0x40)
380 break;
381 val <<= 6;
382 val |= c2;
383 pos++;
384 if (pos == 1)
385 {
386 if (val < (((unsigned)1 << 7) >> numBytes))
387 break;
388 if (numBytes == 2)
389 {
390 if (flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR)
391 if ((val & (0xF800 >> 6)) == (0xd800 >> 6))
392 break;
393 }
394 else if (numBytes == 3 && val >= (0x110000 >> 12))
395 break;
396 }
397 }
398 while (--numBytes);
399
400 if (numBytes != 0)
401 {
402 if ((flags & UTF_FLAG__FROM_UTF8__USE_ESCAPE) == 0)
403 {
404 // the following code to emit the 0xfffd chars as win32 Utf8 function.
405 // disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode
406 src += pos;
407 }
408 _ERROR_UTF8
409 }
410
411 /*
412 if (val < _UTF8_RANGE(pos - 1))
413 _ERROR_UTF8
414 */
415
416 #ifdef UTF_ESCAPE_BASE
417
418 if ((flags & UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT)
419 && IS_ESCAPE_POINT(val, 0))
420 {
421 // We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes)
422 _ERROR_UTF8
423 }
424
425 #endif
426
427 /*
428 We don't expect virtual Escape-21 points in UTF-8 stream.
429 And we don't check for Escape-21.
430 So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points.
431 Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases?
432 */
433
434 if (val < START_POINT_FOR_SURROGATE)
435 {
436 /*
437 if ((flags & UTF_FLAG__FROM_UTF8__SURROGATE_ERROR)
438 && IS_SURROGATE_POINT(val))
439 {
440 // We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes)
441 _ERROR_UTF8
442 }
443 */
444 if (dest)
445 dest[destPos] = (wchar_t)val;
446 destPos++;
447 }
448 else
449 {
450 /*
451 if (val >= 0x110000)
452 {
453 // We will emit utf16-Escape-16-21 point from each source byte
454 _ERROR_UTF8
455 }
456 */
457 if (dest)
458 {
459 dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10));
460 dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff));
461 }
462 destPos += 2;
463 }
464 src += pos;
465 }
466}
467
468
469
470#define _UTF8_HEAD(n, val) ((char)(_UTF8_START(n) + (val >> (6 * (n)))))
471#define _UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F)))
472
473static size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags)
474{
475 size_t size = (size_t)(srcLim - src);
476 for (;;)
477 {
478 if (src == srcLim)
479 return size;
480
481 UInt32 val = (UInt32)(*src++);
482
483 if (val < 0x80)
484 continue;
485
486 if (val < _UTF8_RANGE(1))
487 {
488 size++;
489 continue;
490 }
491
492 #ifdef UTF_ESCAPE_BASE
493
494 #if UTF_ESCAPE_PLANE != 0
495 if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE)
496 if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))
497 continue;
498 #endif
499
500 if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE)
501 if (IS_ESCAPE_POINT(val, 0))
502 continue;
503
504 #endif
505
506 if (IS_SURROGATE_POINT(val))
507 {
508 // it's hack to UTF-8 encoding
509
510 if (val < 0xdc00 && src != srcLim)
511 {
512 const UInt32 c2 = (UInt32)*src;
513 if (c2 >= 0xdc00 && c2 < 0xe000)
514 src++;
515 }
516 size += 2;
517 continue;
518 }
519
520 #ifdef _WCHART_IS_16BIT
521
522 size += 2;
523
524 #else
525
526 if (val < _UTF8_RANGE(2)) size += 2;
527 else if (val < _UTF8_RANGE(3)) size += 3;
528 else if (val < _UTF8_RANGE(4)) size += 4;
529 else if (val < _UTF8_RANGE(5)) size += 5;
530 else
531 #if _UTF8_NUM_TAIL_BYTES_MAX >= 6
532 size += 6;
533 #else
534 size += 3;
535 #endif
536
537 #endif
538 }
539}
540
541
542static char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags)
543{
544 for (;;)
545 {
546 if (src == srcLim)
547 return dest;
548
549 UInt32 val = (UInt32)*src++;
550
551 if (val < 0x80)
552 {
553 *dest++ = (char)val;
554 continue;
555 }
556
557 if (val < _UTF8_RANGE(1))
558 {
559 dest[0] = _UTF8_HEAD(1, val);
560 dest[1] = _UTF8_CHAR(0, val);
561 dest += 2;
562 continue;
563 }
564
565 #ifdef UTF_ESCAPE_BASE
566
567 #if UTF_ESCAPE_PLANE != 0
568 /*
569 if (wchar_t is 32-bit)
570 && (UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE is set)
571 && (point is virtual escape plane)
572 we extract 8-bit byte from virtual HIGH-ESCAPE PLANE.
573 */
574 if (flags & UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE)
575 if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))
576 {
577 *dest++ = (char)(val);
578 continue;
579 }
580 #endif // UTF_ESCAPE_PLANE != 0
581
582 /* if (UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE is defined)
583 we extract 8-bit byte from BMP-ESCAPE PLANE. */
584
585 if (flags & UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE)
586 if (IS_ESCAPE_POINT(val, 0))
587 {
588 *dest++ = (char)(val);
589 continue;
590 }
591
592 #endif // UTF_ESCAPE_BASE
593
594 if (IS_SURROGATE_POINT(val))
595 {
596 // it's hack to UTF-8 encoding
597 if (val < 0xdc00 && src != srcLim)
598 {
599 const UInt32 c2 = (UInt32)*src;
600 if (IS_LOW_SURROGATE_POINT(c2))
601 {
602 src++;
603 val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000;
604 dest[0] = _UTF8_HEAD(3, val);
605 dest[1] = _UTF8_CHAR(2, val);
606 dest[2] = _UTF8_CHAR(1, val);
607 dest[3] = _UTF8_CHAR(0, val);
608 dest += 4;
609 continue;
610 }
611 }
612 if (flags & UTF_FLAG__TO_UTF8__SURROGATE_ERROR)
613 val = UTF_REPLACEMENT_CHAR; // WIN32 function does it
614 }
615
616 #ifndef _WCHART_IS_16BIT
617 if (val < _UTF8_RANGE(2))
618 #endif
619 {
620 dest[0] = _UTF8_HEAD(2, val);
621 dest[1] = _UTF8_CHAR(1, val);
622 dest[2] = _UTF8_CHAR(0, val);
623 dest += 3;
624 continue;
625 }
626
627 #ifndef _WCHART_IS_16BIT
628
629 // we don't expect this case. so we can throw exception
630 // throw 20210407;
631
632 char b;
633 unsigned numBits;
634 if (val < _UTF8_RANGE(3)) { numBits = 6 * 3; b = _UTF8_HEAD(3, val); }
635 else if (val < _UTF8_RANGE(4)) { numBits = 6 * 4; b = _UTF8_HEAD(4, val); }
636 else if (val < _UTF8_RANGE(5)) { numBits = 6 * 5; b = _UTF8_HEAD(5, val); }
637 #if _UTF8_NUM_TAIL_BYTES_MAX >= 6
638 else { numBits = 6 * 6; b = (char)_UTF8_START(6); }
639 #else
640 else
641 {
642 val = UTF_REPLACEMENT_CHAR;
643 { numBits = 6 * 3; b = _UTF8_HEAD(3, val); }
644 }
645 #endif
646
647 *dest++ = b;
648
649 do
650 {
651 numBits -= 6;
652 *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F));
653 }
654 while (numBits != 0);
655
656 #endif
657 }
658}
659
660bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags)
661{
662 dest.Empty();
663 size_t destLen = 0;
664 Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags);
665 bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags);
666 dest.ReleaseBuf_SetEnd((unsigned)destLen);
667 return res;
668}
669
670bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags)
671{
672 return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest, flags);
673}
674
675
676static
677unsigned g_UTF8_To_Unicode_Flags =
678 UTF_FLAG__FROM_UTF8__USE_ESCAPE
679 #ifndef _WCHART_IS_16BIT
680 | UTF_FLAG__FROM_UTF8__SURROGATE_ERROR
681 #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED
682 | UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT
683 #endif
684 #endif
685 ;
686
687
688/*
689bool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest)
690{
691 return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);
692}
693*/
694
695bool ConvertUTF8ToUnicode(const AString &src, UString &dest)
696{
697 return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);
698}
699
700void Print_UString(const UString &a);
701
702void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags)
703{
704 /*
705 if (src.Len()== 24)
706 throw "202104";
707 */
708 dest.Empty();
709 const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);
710 char *destStart = dest.GetBuf((unsigned)destLen);
711 const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags);
712 dest.ReleaseBuf_SetEnd((unsigned)destLen);
713 // printf("\nlen = %d\n", src.Len());
714 if (destLen != (size_t)(destEnd - destStart))
715 {
716 /*
717 // dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart));
718 printf("\nlen = %d\n", (unsigned)destLen);
719 printf("\n(destEnd - destStart) = %d\n", (unsigned)(destEnd - destStart));
720 printf("\n");
721 // Print_UString(src);
722 printf("\n");
723 // printf("\nlen = %d\n", destLen);
724 */
725 throw 20210406;
726 }
727}
728
729
730
731unsigned g_Unicode_To_UTF8_Flags =
732 // UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE
733 0
734 #ifndef _WIN32
735 #ifdef _UTF8_RAW_NON_UTF8_SUPPORTED
736 | UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE
737 #else
738 | UTF_FLAG__TO_UTF8__SURROGATE_ERROR;
739 #endif
740 #endif
741 ;
742
743void ConvertUnicodeToUTF8(const UString &src, AString &dest)
744{
745 ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags);
746}
747
748void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest)
749{
750 const unsigned flags = g_Unicode_To_UTF8_Flags;
751 dest.Free();
752 const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);
753 dest.Alloc(destLen);
754 const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags);
755 if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest))
756 throw 202104;
757}
758
759/*
760
761#ifndef _WIN32
762void Convert_UTF16_To_UTF32(const UString &src, UString &dest)
763{
764 dest.Empty();
765 for (size_t i = 0; i < src.Len();)
766 {
767 wchar_t c = src[i++];
768 if (c >= 0xd800 && c < 0xdc00 && i < src.Len())
769 {
770 const wchar_t c2 = src[i];
771 if (c2 >= 0xdc00 && c2 < 0x10000)
772 {
773 // printf("\nSurragate [%d]: %4x %4x -> ", i, (int)c, (int)c2);
774 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
775 // printf("%4x\n", (int)c);
776 i++;
777 }
778 }
779 dest += c;
780 }
781}
782
783void Convert_UTF32_To_UTF16(const UString &src, UString &dest)
784{
785 dest.Empty();
786 for (size_t i = 0; i < src.Len();)
787 {
788 wchar_t w = src[i++];
789 if (w >= 0x10000 && w < 0x110000)
790 {
791 w -= 0x10000;
792 dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff));
793 w = 0xdc00 + (w & 0x3ff);
794 }
795 dest += w;
796 }
797}
798
799bool UTF32_IsThere_BigPoint(const UString &src)
800{
801 for (size_t i = 0; i < src.Len();)
802 {
803 const UInt32 c = (UInt32)src[i++];
804 if (c >= 0x110000)
805 return true;
806 }
807 return false;
808}
809
810bool Unicode_IsThere_BmpEscape(const UString &src)
811{
812 for (size_t i = 0; i < src.Len();)
813 {
814 const UInt32 c = (UInt32)src[i++];
815 if (IS_ESCAPE_POINT(c, 0))
816 return true;
817 }
818 return false;
819}
820
821
822#endif
823
824bool Unicode_IsThere_Utf16SurrogateError(const UString &src)
825{
826 for (size_t i = 0; i < src.Len();)
827 {
828 const UInt32 val = (UInt32)src[i++];
829 if (IS_SURROGATE_POINT(val))
830 {
831 // it's hack to UTF-8 encoding
832 if (val >= 0xdc00 || i == src.Len())
833 return true;
834 const UInt32 c2 = (UInt32)*src;
835 if (!IS_LOW_SURROGATE_POINT(c2))
836 return true;
837 }
838 }
839 return false;
840}
841*/
842
843#ifndef _WCHART_IS_16BIT
844
845void Convert_UnicodeEsc16_To_UnicodeEscHigh
846#if UTF_ESCAPE_PLANE == 0
847 (UString &) {}
848#else
849 (UString &s)
850{
851 const unsigned len = s.Len();
852 for (unsigned i = 0; i < len; i++)
853 {
854 wchar_t c = s[i];
855 if (IS_ESCAPE_POINT(c, 0))
856 {
857 c += UTF_ESCAPE_PLANE;
858 s.ReplaceOneCharAtPos(i, c);
859 }
860 }
861}
862#endif
863#endif
diff --git a/CPP/Common/UTFConvert.h b/CPP/Common/UTFConvert.h
new file mode 100644
index 0000000..37c4975
--- /dev/null
+++ b/CPP/Common/UTFConvert.h
@@ -0,0 +1,384 @@
1// Common/UTFConvert.h
2
3#ifndef __COMMON_UTF_CONVERT_H
4#define __COMMON_UTF_CONVERT_H
5
6#include "MyBuffer.h"
7#include "MyString.h"
8
9struct CUtf8Check
10{
11 // Byte MaxByte; // in original src stream
12 bool NonUtf;
13 bool ZeroChar;
14 bool SingleSurrogate;
15 bool Escape;
16 bool Truncated;
17 UInt32 MaxHighPoint; // only for points >= 0x80
18
19 CUtf8Check() { Clear(); }
20
21 void Clear()
22 {
23 // MaxByte = 0;
24 NonUtf = false;
25 ZeroChar = false;
26 SingleSurrogate = false;
27 Escape = false;
28 Truncated = false;
29 MaxHighPoint = 0;
30 }
31
32 void Update(const CUtf8Check &c)
33 {
34 if (c.NonUtf) NonUtf = true;
35 if (c.ZeroChar) ZeroChar = true;
36 if (c.SingleSurrogate) SingleSurrogate = true;
37 if (c.Escape) Escape = true;
38 if (c.Truncated) Truncated = true;
39 if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint;
40 }
41
42 void PrintStatus(AString &s) const
43 {
44 s.Empty();
45
46 // s.Add_OptSpaced("MaxByte=");
47 // s.Add_UInt32(MaxByte);
48
49 if (NonUtf) s.Add_OptSpaced("non-UTF8");
50 if (ZeroChar) s.Add_OptSpaced("ZeroChar");
51 if (SingleSurrogate) s.Add_OptSpaced("SingleSurrogate");
52 if (Escape) s.Add_OptSpaced("Escape");
53 if (Truncated) s.Add_OptSpaced("Truncated");
54
55 if (MaxHighPoint != 0)
56 {
57 s.Add_OptSpaced("MaxUnicode=");
58 s.Add_UInt32(MaxHighPoint);
59 }
60 }
61
62
63 bool IsOK(bool allowReduced = false) const
64 {
65 if (NonUtf || SingleSurrogate || ZeroChar)
66 return false;
67 if (MaxHighPoint >= 0x110000)
68 return false;
69 if (Truncated && !allowReduced)
70 return false;
71 return true;
72 }
73
74 // it checks full buffer as specified in (size) and it doesn't stop on zero char
75 void Check_Buf(const char *src, size_t size) throw();
76
77 void Check_AString(const AString &s) throw()
78 {
79 Check_Buf(s.Ptr(), s.Len());
80 }
81};
82
83/*
84if (allowReduced == false) - all UTF-8 character sequences must be finished.
85if (allowReduced == true) - it allows truncated last character-Utf8-sequence
86*/
87
88bool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw();
89bool CheckUTF8_AString(const AString &s) throw();
90
91#define UTF_FLAG__FROM_UTF8__SURROGATE_ERROR (1 << 0)
92#define UTF_FLAG__FROM_UTF8__USE_ESCAPE (1 << 1)
93#define UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT (1 << 2)
94
95/*
96UTF_FLAG__FROM_UTF8__SURROGATE_ERROR
97
98 if (flag is NOT set)
99 {
100 it processes SINGLE-SURROGATE-8 as valid Unicode point.
101 it converts SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16
102 Note: some sequencies of two SINGLE-SURROGATE-8 points
103 will generate correct SURROGATE-16-PAIR, and
104 that SURROGATE-16-PAIR later will be converted to correct
105 UTF8-SURROGATE-21 point. So we don't restore original
106 STR-8 sequence in that case.
107 }
108
109 if (flag is set)
110 {
111 if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is defined)
112 it generates ESCAPE for SINGLE-SURROGATE-8,
113 if (UTF_FLAG__FROM_UTF8__USE_ESCAPE is not defined)
114 it generates U+fffd for SINGLE-SURROGATE-8,
115 }
116
117
118UTF_FLAG__FROM_UTF8__USE_ESCAPE
119
120 if (flag is NOT set)
121 it generates (U+fffd) code for non-UTF-8 (invalid) characters
122
123 if (flag is set)
124 {
125 It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters.
126 And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes.
127 }
128
129UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT
130
131 if (flag is NOT set)
132 {
133 it process ESCAPE-8 points as another Unicode points.
134 In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences,
135 so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW
136 }
137
138 if (flag is set)
139 {
140 it generates ESCAPE-16-21 for ESCAPE-8 points
141 so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21.
142 }
143
144
145Main USE CASES with UTF-8 <-> UTF-16 conversions:
146
147 WIN32: UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW
148 {
149 set UTF_FLAG__FROM_UTF8__USE_ESCAPE
150 Do NOT set UTF_FLAG__FROM_UTF8__SURROGATE_ERROR
151 Do NOT set UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT
152
153 So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8.
154 }
155
156 Linux: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
157 {
158 we want restore original UTF-8-RAW sequence later from that ESCAPE-16.
159 Set the flags:
160 UTF_FLAG__FROM_UTF8__SURROGATE_ERROR
161 UTF_FLAG__FROM_UTF8__USE_ESCAPE
162 UTF_FLAG__FROM_UTF8__BMP_ESCAPE_CONVERT
163 }
164
165 MacOS: UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW
166 {
167 we want to restore correct UTF-8 without any BMP processing:
168 Set the flags:
169 UTF_FLAG__FROM_UTF8__SURROGATE_ERROR
170 UTF_FLAG__FROM_UTF8__USE_ESCAPE
171 }
172
173*/
174
175// zero char is not allowed in (src) buf
176bool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0);
177
178bool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0);
179bool ConvertUTF8ToUnicode(const AString &src, UString &dest);
180
181#define UTF_FLAG__TO_UTF8__SURROGATE_ERROR (1 << 8)
182#define UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE (1 << 9)
183// #define UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE (1 << 10)
184
185/*
186UTF_FLAG__TO_UTF8__SURROGATE_ERROR
187
188 if (flag is NOT set)
189 {
190 we extract SINGLE-SURROGATE as normal UTF-8
191
192 In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in .
193
194 In Linux :
195 use-case-1: UTF-8 -> UTF-16 -> UTF-8 doesn't generate UTF-16 SINGLE-SURROGATE,
196 if (UTF_FLAG__FROM_UTF8__SURROGATE_ERROR) is used.
197 use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux)
198 will generate SINGLE-SURROGATE-UTF-8 here.
199 }
200
201 if (flag is set)
202 {
203 we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE
204 it can be used for compatibility mode with WIN32 UTF function
205 or if we want UTF-8 stream without any errors
206 }
207
208
209UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE
210
211 if (flag is NOT set) it doesn't extract raw 8-bit symbol from Escape-Plane-16
212 if (flag is set) it extracts raw 8-bit symbol from Escape-Plane-16
213
214 in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive):
215 if (we use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane.
216 if (we don't use High-Escape-Plane), we must use UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE.
217
218
219UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE
220 // that flag affects the code only if (wchar_t is 32-bit)
221 // that mode with high-escape can be disabled now in UTFConvert.cpp
222 if (flag is NOT set)
223 it doesn't extract raw 8-bit symbol from High-Escape-Plane
224 if (flag is set)
225 it extracts raw 8-bit symbol from High-Escape-Plane
226
227Main use cases:
228
229WIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW
230 {
231 Do NOT set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE.
232 Do NOT set UTF_FLAG__TO_UTF8__SURROGATE_ERROR.
233 So we restore original UTF-16-RAW.
234 }
235
236Linix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes
237 set UTF_FLAG__TO_UTF8__EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive
238 set UTF_FLAG__TO_UTF8__PARSE_HIGH_ESCAPE for intermediate UTF-16.
239 Note: high esacape mode can be ignored now in UTFConvert.cpp
240
241macOS:
242 the system doesn't support incorrect UTF-8 in file names.
243 set UTF_FLAG__TO_UTF8__SURROGATE_ERROR
244*/
245
246extern unsigned g_Unicode_To_UTF8_Flags;
247
248void ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0);
249void ConvertUnicodeToUTF8(const UString &src, AString &dest);
250
251void Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest);
252
253/*
254#ifndef _WIN32
255void Convert_UTF16_To_UTF32(const UString &src, UString &dest);
256void Convert_UTF32_To_UTF16(const UString &src, UString &dest);
257bool UTF32_IsThere_BigPoint(const UString &src);
258bool Unicode_IsThere_BmpEscape(const UString &src);
259#endif
260
261bool Unicode_IsThere_Utf16SurrogateError(const UString &src);
262*/
263
264#ifdef _WCHART_IS_16BIT
265#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s)
266#else
267void Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s);
268#endif
269
270/*
271// #include "../../C/CpuArch.h"
272
273// ---------- Utf16 Little endian functions ----------
274
275// We store 16-bit surrogates even in 32-bit WCHARs in Linux.
276// So now we don't use the following code:
277
278#if WCHAR_MAX > 0xffff
279
280// void *p : pointer to src bytes stream
281// size_t len : num Utf16 characters : it can include or not include NULL character
282
283inline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len)
284{
285 #if WCHAR_MAX > 0xffff
286 size_t num_wchars = 0;
287 for (size_t i = 0; i < len; i++)
288 {
289 wchar_t c = GetUi16(p);
290 p = (const void *)((const Byte *)p + 2);
291 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
292 {
293 wchar_t c2 = GetUi16(p);
294 if (c2 >= 0xdc00 && c2 < 0xe000)
295 {
296 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
297 p = (const void *)((const Byte *)p + 2);
298 i++;
299 }
300 }
301 num_wchars++;
302 }
303 return num_wchars;
304 #else
305 UNUSED_VAR(p)
306 return len;
307 #endif
308}
309
310// #include <stdio.h>
311
312inline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest)
313{
314 for (size_t i = 0; i < len; i++)
315 {
316 wchar_t c = GetUi16(p);
317 p = (const void *)((const Byte *)p + 2);
318
319 #if WCHAR_PATH_SEPARATOR != L'/'
320 if (c == L'/')
321 c = WCHAR_PATH_SEPARATOR;
322 #endif
323
324 #if WCHAR_MAX > 0xffff
325
326 if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)
327 {
328 wchar_t c2 = GetUi16(p);
329 if (c2 >= 0xdc00 && c2 < 0xe000)
330 {
331 // printf("\nSurragate : %4x %4x -> ", (int)c, (int)c2);
332 c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);
333 p = (const void *)((const Byte *)p + 2);
334 i++;
335 // printf("%4x\n", (int)c);
336 }
337 }
338
339 #endif
340
341 *dest++ = c;
342 }
343 return dest;
344}
345
346
347inline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p)
348{
349 size_t num = 0;
350 for (;;)
351 {
352 wchar_t c = *p++;
353 if (c == 0)
354 return num;
355 num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1);
356 }
357 return num;
358}
359
360inline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest)
361{
362 for (;;)
363 {
364 wchar_t c = *p++;
365 if (c == 0)
366 return dest;
367 if (c >= 0x10000 && c < 0x110000)
368 {
369 SetUi16(dest , (UInt16)(0xd800 + ((c >> 10) & 0x3FF)));
370 SetUi16(dest + 2, (UInt16)(0xdc00 + ( c & 0x3FF)));
371 dest += 4;
372 }
373 else
374 {
375 SetUi16(dest, c);
376 dest += 2;
377 }
378 }
379}
380
381#endif
382*/
383
384#endif
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp
new file mode 100644
index 0000000..861f3f7
--- /dev/null
+++ b/CPP/Common/Wildcard.cpp
@@ -0,0 +1,790 @@
1// Common/Wildcard.cpp
2
3#include "StdAfx.h"
4
5#include "Wildcard.h"
6
7extern
8bool g_CaseSensitive;
9bool g_CaseSensitive =
10 #ifdef _WIN32
11 false;
12 #elif defined (__APPLE__)
13 #ifdef TARGET_OS_IPHONE
14 true;
15 #else
16 false;
17 #endif
18 #else
19 true;
20 #endif
21
22
23bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)
24{
25 if (g_CaseSensitive)
26 return IsString1PrefixedByString2(s1, s2);
27 return IsString1PrefixedByString2_NoCase(s1, s2);
28}
29
30// #include <stdio.h>
31
32/*
33static int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw()
34{
35 for (;;)
36 {
37 wchar_t c1 = *s1++;
38 wchar_t c2 = *s2++;
39 if (c1 != c2)
40 {
41 if (c1 == 0) return -1;
42 if (c2 == 0) return 1;
43 if (c1 == '/') c1 = 0;
44 if (c2 == '/') c2 = 0;
45 if (c1 < c2) return -1;
46 if (c1 > c2) return 1;
47 continue;
48 }
49 if (c1 == 0) return 0;
50 }
51}
52*/
53
54static int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw()
55{
56 for (;;)
57 {
58 wchar_t c1 = *s1++;
59 wchar_t c2 = *s2++;
60 if (c1 != c2)
61 {
62 if (c1 == 0) return -1;
63 if (c2 == 0) return 1;
64 if (IS_PATH_SEPAR(c1)) c1 = 0;
65 if (IS_PATH_SEPAR(c2)) c2 = 0;
66 if (c1 < c2) return -1;
67 if (c1 > c2) return 1;
68 continue;
69 }
70 if (c1 == 0) return 0;
71 }
72}
73
74static int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw()
75{
76 for (;;)
77 {
78 wchar_t c1 = *s1++;
79 wchar_t c2 = *s2++;
80 if (c1 != c2)
81 {
82 if (c1 == 0) return -1;
83 if (c2 == 0) return 1;
84 if (IS_PATH_SEPAR(c1)) c1 = 0;
85 if (IS_PATH_SEPAR(c2)) c2 = 0;
86 c1 = MyCharUpper(c1);
87 c2 = MyCharUpper(c2);
88 if (c1 < c2) return -1;
89 if (c1 > c2) return 1;
90 continue;
91 }
92 if (c1 == 0) return 0;
93 }
94}
95
96int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW
97{
98 /*
99 printf("\nCompareFileNames");
100 printf("\n S1: %ls", s1);
101 printf("\n S2: %ls", s2);
102 printf("\n");
103 */
104 // 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1
105 if (g_CaseSensitive)
106 return MyStringCompare_Path(s1, s2);
107 return MyStringCompareNoCase_Path(s1, s2);
108}
109
110#ifndef USE_UNICODE_FSTRING
111int CompareFileNames(const char *s1, const char *s2)
112{
113 const UString u1 = fs2us(s1);
114 const UString u2 = fs2us(s2);
115 return CompareFileNames(u1, u2);
116}
117#endif
118
119// -----------------------------------------
120// this function compares name with mask
121// ? - any char
122// * - any char or empty
123
124static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)
125{
126 for (;;)
127 {
128 wchar_t m = *mask;
129 wchar_t c = *name;
130 if (m == 0)
131 return (c == 0);
132 if (m == '*')
133 {
134 if (EnhancedMaskTest(mask + 1, name))
135 return true;
136 if (c == 0)
137 return false;
138 }
139 else
140 {
141 if (m == '?')
142 {
143 if (c == 0)
144 return false;
145 }
146 else if (m != c)
147 if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))
148 return false;
149 mask++;
150 }
151 name++;
152 }
153}
154
155// --------------------------------------------------
156// Splits path to strings
157
158void SplitPathToParts(const UString &path, UStringVector &pathParts)
159{
160 pathParts.Clear();
161 unsigned len = path.Len();
162 if (len == 0)
163 return;
164 UString name;
165 unsigned prev = 0;
166 for (unsigned i = 0; i < len; i++)
167 if (IsPathSepar(path[i]))
168 {
169 name.SetFrom(path.Ptr(prev), i - prev);
170 pathParts.Add(name);
171 prev = i + 1;
172 }
173 name.SetFrom(path.Ptr(prev), len - prev);
174 pathParts.Add(name);
175}
176
177void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)
178{
179 const wchar_t *start = path;
180 const wchar_t *p = start + path.Len();
181 for (; p != start; p--)
182 if (IsPathSepar(*(p - 1)))
183 break;
184 dirPrefix.SetFrom(path, (unsigned)(p - start));
185 name = p;
186}
187
188void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)
189{
190 const wchar_t *start = path;
191 const wchar_t *p = start + path.Len();
192 if (p != start)
193 {
194 if (IsPathSepar(*(p - 1)))
195 p--;
196 for (; p != start; p--)
197 if (IsPathSepar(*(p - 1)))
198 break;
199 }
200 dirPrefix.SetFrom(path, (unsigned)(p - start));
201 name = p;
202}
203
204/*
205UString ExtractDirPrefixFromPath(const UString &path)
206{
207 return path.Left(path.ReverseFind_PathSepar() + 1));
208}
209*/
210
211UString ExtractFileNameFromPath(const UString &path)
212{
213 return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1)));
214}
215
216
217bool DoesWildcardMatchName(const UString &mask, const UString &name)
218{
219 return EnhancedMaskTest(mask, name);
220}
221
222bool DoesNameContainWildcard(const UString &path)
223{
224 for (unsigned i = 0; i < path.Len(); i++)
225 {
226 wchar_t c = path[i];
227 if (c == '*' || c == '?')
228 return true;
229 }
230 return false;
231}
232
233
234// ----------------------------------------------------------'
235// NWildcard
236
237namespace NWildcard {
238
239/*
240
241M = MaskParts.Size();
242N = TestNameParts.Size();
243
244 File Dir
245ForFile rec M<=N [N-M, N) -
246!ForDir nonrec M=N [0, M) -
247
248ForDir rec M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File
249!ForFile nonrec [0, M) same as ForBoth-File
250
251ForFile rec m<=N [0, M) ... [N-M, N) same as ForBoth-File
252ForDir nonrec [0, M) same as ForBoth-File
253
254*/
255
256bool CItem::AreAllAllowed() const
257{
258 return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*";
259}
260
261bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const
262{
263 if (!isFile && !ForDir)
264 return false;
265
266 /*
267 if (PathParts.IsEmpty())
268 {
269 // PathParts.IsEmpty() means all items (universal wildcard)
270 if (!isFile)
271 return true;
272 if (pathParts.Size() <= 1)
273 return ForFile;
274 return (ForDir || Recursive && ForFile);
275 }
276 */
277
278 int delta = (int)pathParts.Size() - (int)PathParts.Size();
279 if (delta < 0)
280 return false;
281 int start = 0;
282 int finish = 0;
283
284 if (isFile)
285 {
286 if (!ForDir)
287 {
288 if (Recursive)
289 start = delta;
290 else if (delta !=0)
291 return false;
292 }
293 if (!ForFile && delta == 0)
294 return false;
295 }
296
297 if (Recursive)
298 {
299 finish = delta;
300 if (isFile && !ForFile)
301 finish = delta - 1;
302 }
303
304 for (int d = start; d <= finish; d++)
305 {
306 unsigned i;
307 for (i = 0; i < PathParts.Size(); i++)
308 {
309 if (WildcardMatching)
310 {
311 if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d]))
312 break;
313 }
314 else
315 {
316 if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0)
317 break;
318 }
319 }
320 if (i == PathParts.Size())
321 return true;
322 }
323 return false;
324}
325
326bool CCensorNode::AreAllAllowed() const
327{
328 if (!Name.IsEmpty() ||
329 !SubNodes.IsEmpty() ||
330 !ExcludeItems.IsEmpty() ||
331 IncludeItems.Size() != 1)
332 return false;
333 return IncludeItems.Front().AreAllAllowed();
334}
335
336int CCensorNode::FindSubNode(const UString &name) const
337{
338 FOR_VECTOR (i, SubNodes)
339 if (CompareFileNames(SubNodes[i].Name, name) == 0)
340 return (int)i;
341 return -1;
342}
343
344void CCensorNode::AddItemSimple(bool include, CItem &item)
345{
346 CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
347 items.Add(item);
348}
349
350void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)
351{
352 if (item.PathParts.Size() <= 1)
353 {
354 if (item.PathParts.Size() != 0 && item.WildcardMatching)
355 {
356 if (!DoesNameContainWildcard(item.PathParts.Front()))
357 item.WildcardMatching = false;
358 }
359 AddItemSimple(include, item);
360 return;
361 }
362
363 const UString &front = item.PathParts.Front();
364
365 // WIN32 doesn't support wildcards in file names
366 if (item.WildcardMatching
367 && ignoreWildcardIndex != 0
368 && DoesNameContainWildcard(front))
369 {
370 AddItemSimple(include, item);
371 return;
372 }
373 CCensorNode &subNode = Find_SubNode_Or_Add_New(front);
374 item.PathParts.Delete(0);
375 subNode.AddItem(include, item, ignoreWildcardIndex - 1);
376}
377
378/*
379void CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props)
380{
381 CItem item;
382 SplitPathToParts(path, item.PathParts);
383 item.Recursive = props.Recursive;
384 item.ForFile = props.ForFile;
385 item.ForDir = props.ForDir;
386 item.WildcardMatching = props.WildcardMatching;
387 AddItem(include, item);
388}
389*/
390
391bool CCensorNode::NeedCheckSubDirs() const
392{
393 FOR_VECTOR (i, IncludeItems)
394 {
395 const CItem &item = IncludeItems[i];
396 if (item.Recursive || item.PathParts.Size() > 1)
397 return true;
398 }
399 return false;
400}
401
402bool CCensorNode::AreThereIncludeItems() const
403{
404 if (IncludeItems.Size() > 0)
405 return true;
406 FOR_VECTOR (i, SubNodes)
407 if (SubNodes[i].AreThereIncludeItems())
408 return true;
409 return false;
410}
411
412bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const
413{
414 const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;
415 FOR_VECTOR (i, items)
416 if (items[i].CheckPath(pathParts, isFile))
417 return true;
418 return false;
419}
420
421bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const
422{
423 if (CheckPathCurrent(false, pathParts, isFile))
424 {
425 include = false;
426 return true;
427 }
428 if (pathParts.Size() > 1)
429 {
430 int index = FindSubNode(pathParts.Front());
431 if (index >= 0)
432 {
433 UStringVector pathParts2 = pathParts;
434 pathParts2.Delete(0);
435 if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include))
436 return true;
437 }
438 }
439 bool finded = CheckPathCurrent(true, pathParts, isFile);
440 include = finded; // if (!finded), then (true) is allowed also
441 return finded;
442}
443
444/*
445bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const
446{
447 UStringVector pathParts;
448 SplitPathToParts(path, pathParts);
449 if (CheckPathVect(pathParts, isFile, include))
450 {
451 if (!include || !isAltStream)
452 return true;
453 }
454 if (isAltStream && !pathParts.IsEmpty())
455 {
456 UString &back = pathParts.Back();
457 int pos = back.Find(L':');
458 if (pos > 0)
459 {
460 back.DeleteFrom(pos);
461 return CheckPathVect(pathParts, isFile, include);
462 }
463 }
464 return false;
465}
466
467bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const
468{
469 bool include;
470 if (CheckPath2(isAltStream, path, isFile, include))
471 return include;
472 return false;
473}
474*/
475
476bool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const
477{
478 if (CheckPathCurrent(include, pathParts, isFile))
479 return true;
480 if (!Parent)
481 return false;
482 pathParts.Insert(0, Name);
483 return Parent->CheckPathToRoot_Change(include, pathParts, isFile);
484}
485
486bool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const
487{
488 if (CheckPathCurrent(include, pathParts, isFile))
489 return true;
490 if (!Parent)
491 return false;
492 UStringVector pathParts2;
493 pathParts2.Add(Name);
494 pathParts2 += pathParts;
495 return Parent->CheckPathToRoot_Change(include, pathParts2, isFile);
496}
497
498/*
499bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const
500{
501 UStringVector pathParts;
502 SplitPathToParts(path, pathParts);
503 return CheckPathToRoot(include, pathParts, isFile);
504}
505*/
506
507void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)
508{
509 ExcludeItems += fromNodes.ExcludeItems;
510 FOR_VECTOR (i, fromNodes.SubNodes)
511 {
512 const CCensorNode &node = fromNodes.SubNodes[i];
513 Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node);
514 }
515}
516
517int CCensor::FindPairForPrefix(const UString &prefix) const
518{
519 FOR_VECTOR (i, Pairs)
520 if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)
521 return (int)i;
522 return -1;
523}
524
525#ifdef _WIN32
526
527bool IsDriveColonName(const wchar_t *s)
528{
529 wchar_t c = s[0];
530 return c != 0
531 && s[1] == ':'
532 && s[2] == 0
533 && ((c >= 'a' && c <= 'z')
534 || (c >= 'A' && c <= 'Z'));
535}
536
537unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)
538{
539 if (pathParts.IsEmpty())
540 return 0;
541
542 unsigned testIndex = 0;
543 if (pathParts[0].IsEmpty())
544 {
545 if (pathParts.Size() < 4
546 || !pathParts[1].IsEmpty()
547 || pathParts[2] != L"?")
548 return 0;
549 testIndex = 3;
550 }
551 if (NWildcard::IsDriveColonName(pathParts[testIndex]))
552 return testIndex + 1;
553 return 0;
554}
555
556#endif
557
558static unsigned GetNumPrefixParts(const UStringVector &pathParts)
559{
560 if (pathParts.IsEmpty())
561 return 0;
562
563 /* empty last part could be removed already from (pathParts),
564 if there was tail path separator (slash) in original full path string. */
565
566 #ifdef _WIN32
567
568 if (IsDriveColonName(pathParts[0]))
569 return 1;
570 if (!pathParts[0].IsEmpty())
571 return 0;
572
573 if (pathParts.Size() == 1)
574 return 1;
575 if (!pathParts[1].IsEmpty())
576 return 1;
577 if (pathParts.Size() == 2)
578 return 2;
579 if (pathParts[2] == L".")
580 return 3;
581
582 unsigned networkParts = 2;
583 if (pathParts[2] == L"?")
584 {
585 if (pathParts.Size() == 3)
586 return 3;
587 if (IsDriveColonName(pathParts[3]))
588 return 4;
589 if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC"))
590 return 3;
591 networkParts = 4;
592 }
593
594 networkParts +=
595 // 2; // server/share
596 1; // server
597 if (pathParts.Size() <= networkParts)
598 return pathParts.Size();
599 return networkParts;
600
601 #else
602
603 return pathParts[0].IsEmpty() ? 1 : 0;
604
605 #endif
606}
607
608void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path,
609 const CCensorPathProps &props)
610{
611 if (path.IsEmpty())
612 throw "Empty file path";
613
614 UStringVector pathParts;
615 SplitPathToParts(path, pathParts);
616
617 CCensorPathProps props2 = props;
618
619 bool forFile = true;
620 bool forDir = true;
621 const UString &back = pathParts.Back();
622 if (back.IsEmpty())
623 {
624 // we have tail path separator. So it's directory.
625 // we delete tail path separator here even for "\" and "c:\"
626 forFile = false;
627 pathParts.DeleteBack();
628 }
629 else
630 {
631 if (props.MarkMode == kMark_StrictFile
632 || (props.MarkMode == kMark_StrictFile_IfWildcard
633 && DoesNameContainWildcard(back)))
634 forDir = false;
635 }
636
637
638 UString prefix;
639
640 int ignoreWildcardIndex = -1;
641
642 // #ifdef _WIN32
643 // we ignore "?" wildcard in "\\?\" prefix.
644 if (pathParts.Size() >= 3
645 && pathParts[0].IsEmpty()
646 && pathParts[1].IsEmpty()
647 && pathParts[2] == L"?")
648 ignoreWildcardIndex = 2;
649 // #endif
650
651 if (pathMode != k_AbsPath)
652 {
653 // detection of the number of Skip Parts for prefix
654 ignoreWildcardIndex = -1;
655
656 const unsigned numPrefixParts = GetNumPrefixParts(pathParts);
657 unsigned numSkipParts = numPrefixParts;
658
659 if (pathMode != k_FullPath)
660 {
661 // if absolute path, then all parts before last part will be in prefix
662 if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)
663 numSkipParts = pathParts.Size() - 1;
664 }
665 {
666 int dotsIndex = -1;
667 for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)
668 {
669 const UString &part = pathParts[i];
670 if (part == L".." || part == L".")
671 dotsIndex = (int)i;
672 }
673
674 if (dotsIndex >= 0)
675 {
676 if (dotsIndex == (int)pathParts.Size() - 1)
677 numSkipParts = pathParts.Size();
678 else
679 numSkipParts = pathParts.Size() - 1;
680 }
681 }
682
683 // we split (pathParts) to (prefix) and (pathParts).
684 for (unsigned i = 0; i < numSkipParts; i++)
685 {
686 {
687 const UString &front = pathParts.Front();
688 // WIN32 doesn't support wildcards in file names
689 if (props.WildcardMatching)
690 if (i >= numPrefixParts && DoesNameContainWildcard(front))
691 break;
692 prefix += front;
693 prefix.Add_PathSepar();
694 }
695 pathParts.Delete(0);
696 }
697 }
698
699 int index = FindPairForPrefix(prefix);
700 if (index < 0)
701 {
702 index = (int)Pairs.Size();
703 Pairs.AddNew().Prefix = prefix;
704 }
705
706 if (pathMode != k_AbsPath)
707 {
708 if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty()))
709 {
710 // we create universal item, if we skip all parts as prefix (like \ or L:\ )
711 pathParts.Clear();
712 pathParts.Add(UString("*"));
713 forFile = true;
714 forDir = true;
715 props2.WildcardMatching = true;
716 props2.Recursive = false;
717 }
718 }
719
720 /*
721 // not possible now
722 if (!forDir && !forFile)
723 {
724 UString s ("file path was blocked for files and directories: ");
725 s += path;
726 throw s;
727 // return; // for debug : ignore item (don't create Item)
728 }
729 */
730
731 CItem item;
732 item.PathParts = pathParts;
733 item.ForDir = forDir;
734 item.ForFile = forFile;
735 item.Recursive = props2.Recursive;
736 item.WildcardMatching = props2.WildcardMatching;
737 Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex);
738}
739
740/*
741bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const
742{
743 bool finded = false;
744 FOR_VECTOR (i, Pairs)
745 {
746 bool include;
747 if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))
748 {
749 if (!include)
750 return false;
751 finded = true;
752 }
753 }
754 return finded;
755}
756*/
757
758void CCensor::ExtendExclude()
759{
760 unsigned i;
761 for (i = 0; i < Pairs.Size(); i++)
762 if (Pairs[i].Prefix.IsEmpty())
763 break;
764 if (i == Pairs.Size())
765 return;
766 unsigned index = i;
767 for (i = 0; i < Pairs.Size(); i++)
768 if (index != i)
769 Pairs[i].Head.ExtendExclude(Pairs[index].Head);
770}
771
772void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)
773{
774 FOR_VECTOR(i, CensorPaths)
775 {
776 const CCensorPath &cp = CensorPaths[i];
777 AddItem(censorPathMode, cp.Include, cp.Path, cp.Props);
778 }
779 CensorPaths.Clear();
780}
781
782void CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props)
783{
784 CCensorPath &cp = CensorPaths.AddNew();
785 cp.Path = path;
786 cp.Include = include;
787 cp.Props = props;
788}
789
790}
diff --git a/CPP/Common/Wildcard.h b/CPP/Common/Wildcard.h
new file mode 100644
index 0000000..0fa4887
--- /dev/null
+++ b/CPP/Common/Wildcard.h
@@ -0,0 +1,231 @@
1// Common/Wildcard.h
2
3#ifndef __COMMON_WILDCARD_H
4#define __COMMON_WILDCARD_H
5
6#include "MyString.h"
7
8int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;
9#ifndef USE_UNICODE_FSTRING
10 int CompareFileNames(const char *s1, const char *s2);
11#endif
12
13bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);
14
15void SplitPathToParts(const UString &path, UStringVector &pathParts);
16void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);
17void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)
18
19UString ExtractDirPrefixFromPath(const UString &path);
20UString ExtractFileNameFromPath(const UString &path);
21
22bool DoesNameContainWildcard(const UString &path);
23bool DoesWildcardMatchName(const UString &mask, const UString &name);
24
25namespace NWildcard {
26
27#ifdef _WIN32
28// returns true, if name is like "a:", "c:", ...
29bool IsDriveColonName(const wchar_t *s);
30unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);
31#endif
32
33struct CItem
34{
35 UStringVector PathParts;
36 bool Recursive;
37 bool ForFile;
38 bool ForDir;
39 bool WildcardMatching;
40
41 #ifdef _WIN32
42 bool IsDriveItem() const
43 {
44 return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]);
45 }
46 #endif
47
48 // CItem(): WildcardMatching(true) {}
49
50 bool AreAllAllowed() const;
51 bool CheckPath(const UStringVector &pathParts, bool isFile) const;
52};
53
54
55
56const Byte kMark_FileOrDir = 0;
57const Byte kMark_StrictFile = 1;
58const Byte kMark_StrictFile_IfWildcard = 2;
59
60struct CCensorPathProps
61{
62 bool Recursive;
63 bool WildcardMatching;
64 Byte MarkMode;
65
66 CCensorPathProps():
67 Recursive(false),
68 WildcardMatching(true),
69 MarkMode(kMark_FileOrDir)
70 {}
71};
72
73
74class CCensorNode MY_UNCOPYABLE
75{
76 CCensorNode *Parent;
77
78 bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;
79 void AddItemSimple(bool include, CItem &item);
80public:
81 // bool ExcludeDirItems;
82
83 CCensorNode():
84 Parent(NULL)
85 // , ExcludeDirItems(false)
86 {};
87
88 CCensorNode(const UString &name, CCensorNode *parent):
89 Parent(parent)
90 // , ExcludeDirItems(false)
91 , Name(name)
92 {}
93
94 UString Name; // WIN32 doesn't support wildcards in file names
95 CObjectVector<CCensorNode> SubNodes;
96 CObjectVector<CItem> IncludeItems;
97 CObjectVector<CItem> ExcludeItems;
98
99 CCensorNode &Find_SubNode_Or_Add_New(const UString &name)
100 {
101 int i = FindSubNode(name);
102 if (i >= 0)
103 return SubNodes[(unsigned)i];
104 // return SubNodes.Add(CCensorNode(name, this));
105 CCensorNode &node = SubNodes.AddNew();
106 node.Parent = this;
107 node.Name = name;
108 return node;
109 }
110
111 bool AreAllAllowed() const;
112
113 int FindSubNode(const UString &path) const;
114
115 void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);
116 // void AddItem(bool include, const UString &path, const CCensorPathProps &props);
117 void Add_Wildcard()
118 {
119 CItem item;
120 item.PathParts.Add(L"*");
121 item.Recursive = false;
122 item.ForFile = true;
123 item.ForDir = true;
124 item.WildcardMatching = true;
125 AddItem(
126 true // include
127 , item);
128 }
129
130 // NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs
131 bool NeedCheckSubDirs() const;
132 bool AreThereIncludeItems() const;
133
134 /*
135 CheckPathVect() doesn't check path in Parent CCensorNode
136 so use CheckPathVect() for root CCensorNode
137 OUT:
138 returns (true) && (include = false) - file in exlude list
139 returns (true) && (include = true) - file in include list and is not in exlude list
140 returns (false) - file is not in (include/exlude) list
141 */
142 bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;
143
144 // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;
145 // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
146
147 // CheckPathToRoot_Change() changes pathParts !!!
148 bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const;
149 bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const;
150
151 // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;
152 void ExtendExclude(const CCensorNode &fromNodes);
153};
154
155
156struct CPair MY_UNCOPYABLE
157{
158 UString Prefix;
159 CCensorNode Head;
160
161 // CPair(const UString &prefix): Prefix(prefix) { };
162};
163
164
165enum ECensorPathMode
166{
167 k_RelatPath, // absolute prefix as Prefix, remain path in Tree
168 k_FullPath, // drive prefix as Prefix, remain path in Tree
169 k_AbsPath // full path in Tree
170};
171
172
173struct CCensorPath
174{
175 UString Path;
176 bool Include;
177 CCensorPathProps Props;
178
179 CCensorPath():
180 Include(true)
181 {}
182};
183
184
185class CCensor MY_UNCOPYABLE
186{
187 int FindPairForPrefix(const UString &prefix) const;
188public:
189 CObjectVector<CPair> Pairs;
190
191 bool ExcludeDirItems;
192 bool ExcludeFileItems;
193
194 CCensor():
195 ExcludeDirItems(false),
196 ExcludeFileItems(false)
197 {}
198
199 CObjectVector<NWildcard::CCensorPath> CensorPaths;
200
201 bool AllAreRelative() const
202 { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }
203
204 void AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props);
205 // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;
206 void ExtendExclude();
207
208 void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);
209 void AddPreItem(bool include, const UString &path, const CCensorPathProps &props);
210
211 void AddPreItem_NoWildcard(const UString &path)
212 {
213 CCensorPathProps props;
214 props.WildcardMatching = false;
215 AddPreItem(
216 true, // include
217 path, props);
218 }
219 void AddPreItem_Wildcard()
220 {
221 CCensorPathProps props;
222 // props.WildcardMatching = true;
223 AddPreItem(
224 true, // include
225 UString("*"), props);
226 }
227};
228
229}
230
231#endif
diff --git a/CPP/Common/XzCrc64Init.cpp b/CPP/Common/XzCrc64Init.cpp
new file mode 100644
index 0000000..5cb8e67
--- /dev/null
+++ b/CPP/Common/XzCrc64Init.cpp
@@ -0,0 +1,7 @@
1// XzCrc64Init.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/XzCrc64.h"
6
7static struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;
diff --git a/CPP/Common/XzCrc64Reg.cpp b/CPP/Common/XzCrc64Reg.cpp
new file mode 100644
index 0000000..33b5249
--- /dev/null
+++ b/CPP/Common/XzCrc64Reg.cpp
@@ -0,0 +1,42 @@
1// XzCrc64Reg.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6#include "../../C/XzCrc64.h"
7
8#include "../Common/MyCom.h"
9
10#include "../7zip/Common/RegisterCodec.h"
11
12class CXzCrc64Hasher:
13 public IHasher,
14 public CMyUnknownImp
15{
16 UInt64 _crc;
17 Byte mtDummy[1 << 7];
18
19public:
20 CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}
21
22 MY_UNKNOWN_IMP1(IHasher)
23 INTERFACE_IHasher(;)
24};
25
26STDMETHODIMP_(void) CXzCrc64Hasher::Init() throw()
27{
28 _crc = CRC64_INIT_VAL;
29}
30
31STDMETHODIMP_(void) CXzCrc64Hasher::Update(const void *data, UInt32 size) throw()
32{
33 _crc = Crc64Update(_crc, data, size);
34}
35
36STDMETHODIMP_(void) CXzCrc64Hasher::Final(Byte *digest) throw()
37{
38 UInt64 val = CRC64_GET_DIGEST(_crc);
39 SetUi64(digest, val);
40}
41
42REGISTER_HASHER(CXzCrc64Hasher, 0x4, "CRC64", 8)