From 4a0bb67358423d766ad9627ba2c8aa461c680487 Mon Sep 17 00:00:00 2001 From: fishca Date: Wed, 8 Nov 2017 23:30:50 +0300 Subject: [PATCH 1/5] =?UTF-8?q?=D0=A1=D0=B1=D0=BE=D1=80=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=20VS2017?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++ src/main.cpp | 2 ++ v8unpack.sln | 31 +++++++++++++++++ v8unpack.vcxproj | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 v8unpack.sln create mode 100644 v8unpack.vcxproj diff --git a/.gitignore b/.gitignore index 765e1d0..fc6b351 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,13 @@ *~ *.tmp Debug +Release *.o *.d tmp .codelite +.VS +*.json v8unpack.txt *.workspace Makefile diff --git a/src/main.cpp b/src/main.cpp index a59cee3..5393af1 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,8 @@ at http://mozilla.org/MPL/2.0/. #include #include +#pragma comment (lib, "zlibstatic.lib") + using namespace std; typedef int (*handler_t)(vector &argv); diff --git a/v8unpack.sln b/v8unpack.sln new file mode 100644 index 0000000..4433dae --- /dev/null +++ b/v8unpack.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2008 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8unpack", "v8unpack.vcxproj", "{C1AA1412-5A3E-4E7A-89DD-D62C6020F779}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Debug|x64.ActiveCfg = Debug|x64 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Debug|x64.Build.0 = Debug|x64 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Debug|x86.ActiveCfg = Debug|Win32 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Debug|x86.Build.0 = Debug|Win32 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x64.ActiveCfg = Release|x64 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x64.Build.0 = Release|x64 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x86.ActiveCfg = Release|Win32 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2A873274-AEA2-4C6A-8DD2-22EEB512F108} + EndGlobalSection +EndGlobal diff --git a/v8unpack.vcxproj b/v8unpack.vcxproj new file mode 100644 index 0000000..157b229 --- /dev/null +++ b/v8unpack.vcxproj @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {C1AA1412-5A3E-4E7A-89DD-D62C6020F779} + 8.1 + + + + Application + true + v140 + + + Application + false + v140 + + + Application + true + v141 + + + Application + false + v141 + + + + + + + + + + + + + + + + + + + + + D:\zlib;C:\local\boost_1_63_0;$(IncludePath) + D:\zlib\bin_msvs\Debug;C:\local\boost_1_63_0\lib32-msvc-14.0;$(LibraryPath) + + + D:\zlib;C:\local\boost_1_63_0;$(IncludePath) + D:\zlib\bin_msvs\Debug;C:\local\boost_1_63_0\lib32-msvc-14.0;$(LibraryPath) + + + + + + + + + + + + + + + + + \ No newline at end of file From b5ffa86e1e58365a067c4dd8c82ac7777aad2fa6 Mon Sep 17 00:00:00 2001 From: fishca Date: Wed, 8 Nov 2017 23:36:37 +0300 Subject: [PATCH 2/5] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V8File.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/V8File.cpp b/src/V8File.cpp index 9302a2a..2ec8c38 100644 --- a/src/V8File.cpp +++ b/src/V8File.cpp @@ -36,8 +36,6 @@ at http://mozilla.org/MPL/2.0/. using namespace std; - - template void full_copy(basic_istream &in_file, basic_ostream &out_file) { From f0c57dbea6f43c1676926535c83f30eac61774b1 Mon Sep 17 00:00:00 2001 From: fishca Date: Thu, 9 Nov 2017 09:00:45 +0300 Subject: [PATCH 3/5] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BC=D0=B0=D0=BA=D1=80=D0=BE=D1=81=D0=B0=20MAX=20=D0=BD=D0=B0?= =?UTF-8?q?=20std::max?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/V8File.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/V8File.cpp b/src/V8File.cpp index 2ec8c38..ad84dd2 100644 --- a/src/V8File.cpp +++ b/src/V8File.cpp @@ -957,8 +957,9 @@ int CV8File::ReadBlockData(char *pFileData, stBlockHeader *pBlockHeader, char *& page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - - bytes_to_read = MIN(page_size, data_size - read_in_bytes); + + //bytes_to_read = MIN(page_size, data_size - read_in_bytes); + bytes_to_read = std::min(page_size, data_size - read_in_bytes); memcpy(&pBlockData[read_in_bytes], (char*)(&pBlockHeader[1]), bytes_to_read); @@ -1000,7 +1001,8 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - bytes_to_read = MIN(page_size, data_size - read_in_bytes); + //bytes_to_read = MIN(page_size, data_size - read_in_bytes); + bytes_to_read = std::min(page_size, data_size - read_in_bytes); file.read(&pBlockData[read_in_bytes], bytes_to_read); @@ -1039,7 +1041,8 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - bytes_to_read = MIN(page_size, data_size - read_in_bytes); + //bytes_to_read = MIN(page_size, data_size - read_in_bytes); + bytes_to_read = std::min(page_size, data_size - read_in_bytes); const int buf_size = 1024; // TODO: Настраиваемый размер буфера char *pBlockData = new char [buf_size]; @@ -1047,6 +1050,7 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock while (read_done < bytes_to_read) { file.read(pBlockData, MIN(buf_size, bytes_to_read - read_done)); + //file.read(pBlockData, std::min(buf_size, bytes_to_read - read_done)); int rd = file.gcount(); out.write(pBlockData, rd); read_done += rd; @@ -1168,7 +1172,8 @@ int CV8File::PackFromFolder(const std::string &dirname, const std::string &filen // [0] + [1] DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); - size_t addr_block_size = MAX(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); + //size_t addr_block_size = MAX(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); + size_t addr_block_size = std::max(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); cur_block_addr += addr_block_size; // +[2] for (auto elem : Elems) { @@ -1179,7 +1184,8 @@ int CV8File::PackFromFolder(const std::string &dirname, const std::string &filen addr.elem_data_addr = cur_block_addr; cur_block_addr += sizeof(stBlockHeader); // +[5] - cur_block_addr += MAX(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] + //cur_block_addr += MAX(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] + cur_block_addr += std::max(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] addr.fffffff = V8_FF_SIGNATURE; @@ -1466,7 +1472,8 @@ int CV8File::BuildCfFile(const std::string &in_dirname, const std::string &out_f DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); stElemAddr *pTOC; pTOC = new stElemAddr[ElemsNum]; - cur_block_addr += MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + //cur_block_addr += MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + cur_block_addr += std::max(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); boost::filesystem::ofstream file_out(out_filename, std::ios_base::binary); //Открываем выходной файл контейнер на запись @@ -1749,7 +1756,8 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) NeedDataBufferSize += stFileHeader::Size(); // заголовок блока и данные блока - адреса элементов с учетом минимальной страницы 512 байт - NeedDataBufferSize += stBlockHeader::Size() + MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + //NeedDataBufferSize += stBlockHeader::Size() + MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + NeedDataBufferSize += stBlockHeader::Size() + std::max(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); for (auto elem : Elems) { @@ -1762,7 +1770,8 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) elem.IsV8File = false; } - NeedDataBufferSize += stBlockHeader::Size() + MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + //NeedDataBufferSize += stBlockHeader::Size() + MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + NeedDataBufferSize += stBlockHeader::Size() + std::max(elem.DataSize, V8_DEFAULT_PAGE_SIZE); } @@ -1771,7 +1780,8 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) pCurrentTempElem = pTempElemsAddrs; DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); - cur_block_addr += MAX(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); + //cur_block_addr += MAX(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); + cur_block_addr += std::max(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); for (auto elem : Elems) { @@ -1781,7 +1791,8 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) pCurrentTempElem->elem_data_addr = cur_block_addr; cur_block_addr += sizeof(stBlockHeader); - cur_block_addr += MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + //cur_block_addr += MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + cur_block_addr += std::max(elem.DataSize, V8_DEFAULT_PAGE_SIZE); pCurrentTempElem->fffffff = V8_FF_SIGNATURE; ++pCurrentTempElem; From c361d498d36a56552715ce553c4948a269bde52c Mon Sep 17 00:00:00 2001 From: fishca Date: Thu, 9 Nov 2017 10:47:14 +0300 Subject: [PATCH 4/5] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B9?= =?UTF-8?q?=D0=BA=D0=B8=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8=20appveyor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 63ec3ed..a6eb052 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,7 +38,7 @@ build_script: after_build: - cmd: >- - SET PATH=%PATH%;"C:/Program Files (x86)/WiX Toolset v3.10/bin" + SET PATH=%PATH%;"C:/Program Files (x86)/WiX Toolset v3.11/bin" candle v8unpack.wxs From d56afc263a1d232f65da2d14c237cfe1ad070abc Mon Sep 17 00:00:00 2001 From: fishca Date: Sun, 22 Sep 2019 23:31:20 +0300 Subject: [PATCH 5/5] =?UTF-8?q?=D0=A1=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SystemClasses/.gitignore | 14 + src/SystemClasses/CMakeLists.txt | 33 ++ src/SystemClasses/Classes.hpp | 8 + src/SystemClasses/DynamicArray.hpp | 38 ++ src/SystemClasses/Exception.hpp | 64 +++ src/SystemClasses/GetTickCount.cpp | 30 ++ src/SystemClasses/GetTickCount.hpp | 15 + src/SystemClasses/String.cpp | 510 ++++++++++++++++++ src/SystemClasses/String.hpp | 130 +++++ src/SystemClasses/SysInit.hpp | 4 + src/SystemClasses/System.Classes.cpp | 22 + src/SystemClasses/System.Classes.hpp | 38 ++ src/SystemClasses/System.IOUtils.cpp | 78 +++ src/SystemClasses/System.IOUtils.hpp | 39 ++ src/SystemClasses/System.SysUtils.cpp | 170 ++++++ src/SystemClasses/System.SysUtils.hpp | 85 +++ src/SystemClasses/System.cpp | 130 +++++ src/SystemClasses/System.hpp | 106 ++++ .../SystemClasses.vcxproj.filters | 105 ++++ src/SystemClasses/SystemClasses.vcxproj.user | 4 + src/SystemClasses/TFileStream.cpp | 78 +++ src/SystemClasses/TFileStream.hpp | 48 ++ src/SystemClasses/TMemoryStream.cpp | 82 +++ src/SystemClasses/TMemoryStream.hpp | 51 ++ src/SystemClasses/TStream.cpp | 219 ++++++++ src/SystemClasses/TStream.hpp | 105 ++++ src/SystemClasses/TStreamReader.cpp | 32 ++ src/SystemClasses/TStreamReader.hpp | 29 + src/SystemClasses/TStreamWriter.cpp | 27 + src/SystemClasses/TStreamWriter.hpp | 29 + src/SystemClasses/main.cpp | 37 ++ src/SystemClasses/utf8.h | 34 ++ src/SystemClasses/utf8/checked.h | 327 +++++++++++ src/SystemClasses/utf8/core.h | 332 ++++++++++++ src/SystemClasses/utf8/unchecked.h | 228 ++++++++ src/SystemClasses/vcl.h | 0 src/V8File.cpp | 31 +- src/metaread/Base64.cpp | 152 ++++++ src/metaread/Base64.h | 14 + v8unpack.sln | 10 + v8unpack.vcxproj | 11 +- v8unpack.vcxproj.filters | 24 + v8unpack.vcxproj.user | 4 + 43 files changed, 3503 insertions(+), 24 deletions(-) create mode 100644 src/SystemClasses/.gitignore create mode 100644 src/SystemClasses/CMakeLists.txt create mode 100644 src/SystemClasses/Classes.hpp create mode 100644 src/SystemClasses/DynamicArray.hpp create mode 100644 src/SystemClasses/Exception.hpp create mode 100644 src/SystemClasses/GetTickCount.cpp create mode 100644 src/SystemClasses/GetTickCount.hpp create mode 100644 src/SystemClasses/String.cpp create mode 100644 src/SystemClasses/String.hpp create mode 100644 src/SystemClasses/SysInit.hpp create mode 100644 src/SystemClasses/System.Classes.cpp create mode 100644 src/SystemClasses/System.Classes.hpp create mode 100644 src/SystemClasses/System.IOUtils.cpp create mode 100644 src/SystemClasses/System.IOUtils.hpp create mode 100644 src/SystemClasses/System.SysUtils.cpp create mode 100644 src/SystemClasses/System.SysUtils.hpp create mode 100644 src/SystemClasses/System.cpp create mode 100644 src/SystemClasses/System.hpp create mode 100644 src/SystemClasses/SystemClasses.vcxproj.filters create mode 100644 src/SystemClasses/SystemClasses.vcxproj.user create mode 100644 src/SystemClasses/TFileStream.cpp create mode 100644 src/SystemClasses/TFileStream.hpp create mode 100644 src/SystemClasses/TMemoryStream.cpp create mode 100644 src/SystemClasses/TMemoryStream.hpp create mode 100644 src/SystemClasses/TStream.cpp create mode 100644 src/SystemClasses/TStream.hpp create mode 100644 src/SystemClasses/TStreamReader.cpp create mode 100644 src/SystemClasses/TStreamReader.hpp create mode 100644 src/SystemClasses/TStreamWriter.cpp create mode 100644 src/SystemClasses/TStreamWriter.hpp create mode 100644 src/SystemClasses/main.cpp create mode 100644 src/SystemClasses/utf8.h create mode 100644 src/SystemClasses/utf8/checked.h create mode 100644 src/SystemClasses/utf8/core.h create mode 100644 src/SystemClasses/utf8/unchecked.h create mode 100644 src/SystemClasses/vcl.h create mode 100644 src/metaread/Base64.cpp create mode 100644 src/metaread/Base64.h create mode 100644 v8unpack.vcxproj.filters create mode 100644 v8unpack.vcxproj.user diff --git a/src/SystemClasses/.gitignore b/src/SystemClasses/.gitignore new file mode 100644 index 0000000..998aa2e --- /dev/null +++ b/src/SystemClasses/.gitignore @@ -0,0 +1,14 @@ + +*.o +bin/* +obj/* +build/* +Debug/* +x64/* + +*.layout +*.depend + +*.a +*.out + diff --git a/src/SystemClasses/CMakeLists.txt b/src/SystemClasses/CMakeLists.txt new file mode 100644 index 0000000..bae9388 --- /dev/null +++ b/src/SystemClasses/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required (VERSION 2.8) +project (SystemClasses) + +set (SYSTEM_SOURCES String.cpp System.Classes.cpp System.cpp + System.IOUtils.cpp TFileStream.cpp TMemoryStream.cpp TStream.cpp + TStreamReader.cpp TStreamWriter.cpp System.SysUtils.cpp + GetTickCount.cpp) +set (SYSTEM_HEADERS String.hpp System.Classes.hpp System.hpp + System.IOUtils.hpp TFileStream.hpp TMemoryStream.hpp TStream.hpp + TStreamReader.hpp TStreamWriter.hpp System.SysUtils.hpp + GetTickCount.hpp) + +if (CMAKE_VERSION VERSION_LESS "3.1") + if(CMAKE_COMPILER_IS_GNUCXX) + set (CMAKE_CXX_FLAGS "--std=gnu++11 ${CMAKE_CXX_FLAGS}") + endif() +else() + set (CMAKE_CXX_STANDARD 11) + set (CMAKE_CXX_STANDARD_REQUIRED YES) + set (CMAKE_CXX_EXTENSIONS OFF) +endif() + +add_library (SystemClasses STATIC ${SYSTEM_SOURCES} ${SYSTEM_HEADERS}) + +add_definitions (-DBOOST_ALL_NO_LIB) +set (Boost_USE_STATIC_LIBS ON) +set (Boost_USE_MULTITHREADED OFF) +set (Boost_USE_STATIC_RUNTIME ON) + +find_package (Boost 1.53 REQUIRED COMPONENTS filesystem regex system) + +include_directories (${Boost_INCLUDE_DIRS}) +target_link_libraries (SystemClasses ${Boost_LIBRARIES}) diff --git a/src/SystemClasses/Classes.hpp b/src/SystemClasses/Classes.hpp new file mode 100644 index 0000000..3184d76 --- /dev/null +++ b/src/SystemClasses/Classes.hpp @@ -0,0 +1,8 @@ +#ifndef CLASSES_HPP +#define CLASSES_HPP + +#include "System.Classes.hpp" + +#endif + + diff --git a/src/SystemClasses/DynamicArray.hpp b/src/SystemClasses/DynamicArray.hpp new file mode 100644 index 0000000..4ae508b --- /dev/null +++ b/src/SystemClasses/DynamicArray.hpp @@ -0,0 +1,38 @@ +#ifndef SYSTEM_DYNAMICARRAY_HPP +#define SYSTEM_DYNAMICARRAY_HPP + +#include + +namespace System { + +template +class DynamicArray : public std::vector { + +public: + + int get_length() const + { + return this->size(); + } + + void set_length(int new_length) + { + this->resize(new_length); + } + + int GetLength() const + { + return this->size(); + } + + void SetLength(int NewSize) + { + this->resize(NewSize); + } + +}; + +} + +#endif + diff --git a/src/SystemClasses/Exception.hpp b/src/SystemClasses/Exception.hpp new file mode 100644 index 0000000..53677e3 --- /dev/null +++ b/src/SystemClasses/Exception.hpp @@ -0,0 +1,64 @@ +#ifndef SYSTEM__EXCEPTION_HPP +#define SYSTEM__EXCEPTION_HPP + +#include +#include "String.hpp" + +namespace System { + +// http://stackoverflow.com/a/8152888 +class Exception: public std::exception +{ +public: + /** Constructor (C strings). + * @param message C-style string error message. + * The string contents are copied upon construction. + * Hence, responsibility for deleting the char* lies + * with the caller. + */ + explicit Exception(const char* message): + msg_(message) + { + } + + explicit Exception(const wchar_t* message): + msg_("") + { + } + + /** Constructor (C++ STL strings). + * @param message The error message. + */ + explicit Exception(const std::string& message): + msg_(message) + {} + + /** Destructor. + * Virtual to allow for subclassing. + */ + virtual ~Exception() throw (){} + + /** Returns a pointer to the (constant) error description. + * @return A pointer to a const char*. The underlying memory + * is in posession of the Exception object. Callers must + * not attempt to free the memory. + */ + virtual const char* what() const throw (){ + return msg_.c_str(); + } + + String Message() const + { + return msg_; + } + +protected: + /** Error message. + */ + std::string msg_; +}; + +} // System + +#endif + diff --git a/src/SystemClasses/GetTickCount.cpp b/src/SystemClasses/GetTickCount.cpp new file mode 100644 index 0000000..93016ea --- /dev/null +++ b/src/SystemClasses/GetTickCount.cpp @@ -0,0 +1,30 @@ +#include "GetTickCount.hpp" + +#ifdef _WIN32 +#include +#else +#include +#endif // _WIN32 + +namespace System { + +namespace Classes { + +// (c) http://www.doctort.org/adam/nerd-notes/linux-equivalent-of-the-windows-gettickcount-function.html +unsigned long GetTickCount() +{ + #ifdef _WIN32 + return (unsigned long)(::GetTickCount()); + #else + struct timeval tv; + if(gettimeofday(&tv, nullptr) != 0) { + return 0; + } + + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + #endif // _WIN32 +} + +} // Classe + +} // System diff --git a/src/SystemClasses/GetTickCount.hpp b/src/SystemClasses/GetTickCount.hpp new file mode 100644 index 0000000..630bbc6 --- /dev/null +++ b/src/SystemClasses/GetTickCount.hpp @@ -0,0 +1,15 @@ +#ifndef GETTICKCOUNT_HPP_INCLUDED +#define GETTICKCOUNT_HPP_INCLUDED + +namespace System { + +namespace Classes { + +unsigned long GetTickCount(); + +} + +} + + +#endif // GETTICKCOUNT_HPP_INCLUDED diff --git a/src/SystemClasses/String.cpp b/src/SystemClasses/String.cpp new file mode 100644 index 0000000..66500a5 --- /dev/null +++ b/src/SystemClasses/String.cpp @@ -0,0 +1,510 @@ +#include "String.hpp" +#include +#include +#include +#include +#include +#include +#include +#include "System.SysUtils.hpp" + +using namespace std; + +namespace System { + +/** Конструктор (C strings). + * @param - без параметров + * + * + * + */ +String::String() +{ +} + +/** Конструктор (C strings). + * @src - входная строка + */ +String::String(const string &src) : string(src) +{ +} + +/** Конструктор (C strings). + * @src - входная строка + */ +String::String(const char *src) : string(src) +{ +} + +/** Конструктор (C strings). + * @src - входная строка + * @limit_size - лимит в размере + */ +String::String(const char *src, int limit_size) : string(src, limit_size) +{ +} + +/** Конструктор (C strings). + * @src - входная строка + * @limit_size - лимит в размере + */ +String::String(const DynamicArray &bytes) : string(reinterpret_cast(bytes.data()), bytes.size()) +{ +} + +/** Конструктор (C strings). + * @w_src - входная строка + * @limit_size - лимит в размере + */ +String::String(const WCHART *w_src, int limit_size) +{ + // Костыль + DynamicArray tmpdata; + const WCHART *p = w_src; + bool limit_exceeded = false; + + if( limit_size > 0 && p != nullptr ) { + + while ( !limit_exceeded && *p != '\0' ) { + + tmpdata.push_back((uint16_t)(*p) & 0xFF); + tmpdata.push_back((uint16_t)(*p) >> 8); + + ++p; + + if (limit_size) { + limit_exceeded = --limit_size == 0; + } + } + } + string tmp(SysUtils::TEncoding::Unicode->toUtf8(tmpdata)); + append(tmp); +} + +/** Конструктор (C strings). + * @w_src - входная строка + */ +String::String(const WCHART *w_src) +{ + // Костыль + DynamicArray tmpdata; + const WCHART *p = w_src; + + if( p != nullptr ) { + + while ( *p != u'\0' ) { + + tmpdata.push_back((uint16_t)(*p) & 0xFF); + tmpdata.push_back((uint16_t)(*p) >> 8); + + ++p; + + } + } + string tmp(SysUtils::TEncoding::Unicode->toUtf8(tmpdata)); + append(tmp); +} + + +String::String(int value) : string(ToString(value)) {} +String::String(unsigned int value) : string(ToString(value)) {} +String::String(long value) : string(ToString(value)) {} +String::String(unsigned long value) : string(ToString(value)) {} +String::String(long long value) : string(ToString(value)) {} +String::String(unsigned long long value) : string(ToString(value)) {} + +/** Функция перевода каждого символа в строчные (C strings). + * @param - нет + * Переводит символы в строчные + */ +String String::UpperCase() const +{ + string copy (*this); + transform(copy.begin(), copy.end(), copy.begin(), ::toupper); + return String(copy); +} + +/** Функция перевода каждого символа в нижний регистр (C strings). + * @param - нет + * Переводит символы в нижний регистр + */ +String String::LowerCase() const +{ + string copy (*this); + transform(copy.begin(), copy.end(), copy.begin(), ::tolower); + return String(copy); +} + +/** Функция определяет пустая строка или нет. + * @param - нет + * + */ +bool String::IsEmpty() const +{ + return empty(); +} + +/** Функция возвращает длину строки. + * @param - нет + * + */ +int String::Length() const +{ + return size(); +} + +/** Функция сравнивает строки. + * @const String &b - строка для сравнения + * + */ +int String::CompareIC(const String &b) const +{ + return LowerCase().compare(b.LowerCase()); +} + +/** Функция сравнивает строки. + * @const String &b - строка для сравнения + * + */ +int String::Compare(const String &b) const +{ + return compare(b); +} + +/** Функция заменяет подстроки в строке. + * @const String &b - строка для сравнения + * + */ +String String::Replace(const String &sub, const String &replace) const +{ + string _copy(*this); + + auto pos = _copy.find(sub); + + while (pos != string::npos) { + + _copy.replace(pos, sub.size(), replace); + pos += replace.size(); + pos = _copy.find(sub, pos); + + } + + return _copy; +} + +/** Функция выделяет подстроку в строке. + * @int StartIndex - начальный индекс + * @int Count - количество символов + * + */ +String String::SubString(int StartIndex, int Count) const +{ + if (StartIndex > Length() || StartIndex <= 0) { + + return String(""); + + } + + return String(substr(StartIndex - 1, Count)); +} + +/** Функция позволяет обращаться со строкой как с массивом, доступ по индексу. + * @int index - индекс символа + * + */ +char &String::operator[] (int index) +{ + return at(index - 1); +} + +/** Функция позволяет обращаться со строкой как с массивом, доступ по индексу. + * @int index - индекс символа + * + */ +const char &String::operator[] (int index) const +{ + return at(index - 1); +} + +/** Функция позволяет преобразовать строку в число int. + * @param - нет + * + */ +int String::ToInt() const +{ + return stoi(*this); +} + +/** Функция позволяет преобразовать строку в число int. + * @int default_value - значение по умолчанию + * + */ +int String::ToIntDef(int default_value) const +{ + try { + return ToInt(); + } catch (const invalid_argument &) { + return default_value; + } +} + +/** Функция ищет подстроку в строке. + * @const String &substr - подстрока поиска + * + */ +int String::Pos(const String &substr) +{ + auto index = find(substr); + if (index == npos) { + return 0; + } + return index + 1; +} + +/** Функция возвращает длину строки. + * @params - нет + * + */ +int String::GetLength() const +{ + return this->size(); +} + +/** Функция устанавливает длину строки. + * @int NewLength - новая длина строки + * + */ +void String::SetLength(int NewLength) +{ + resize(NewLength); +} + +/** Функция ищет вхождение последнего разделителя в строке. + * @const String &delimiters - разделитель который ищем + * + */ +int String::LastDelimiter(const String &delimiters) const +{ + return 0; // TODO: реализовать функцию поиска последнего разделителя +} + +/** Функция ищет вхождение последнего символа в строке. + * @params - нет + * + */ +const char *String::LastChar() const +{ + if (size() == 0) { + return nullptr; + } + return c_str() + (size() - 1); +} + +/** Функция возвращает размер широких символов юникод. + * @params - нет + * + */ +int String::WideCharBufSize() const +{ + return sizeof(wchar_t) * (size() + 1); +} + +/** Функция возвращает широкую строку символов юникод. + * @WCHART *wbuf - буфер + * @int destsize - размер + * + */ +WCHART *String::WideChar(WCHART *wbuf, int destSize) const +{ + bool limit_exceeded = false; + for (size_t i = 0; i < size() && !limit_exceeded; i++) { + wbuf[i] = c_str()[i]; + if (destSize) { + limit_exceeded = --destSize == 0; + } + } + return wbuf; +} + +/** Метод добавляющий в списко строк данные. + * @const String &item - строка для добавления + * + */ +void TStringList::Add(const String &item) +{ + push_back(item); +} + +/** Метод устанавливает значение в списке строк. + * @const String &text - строка для добавления + * + */ +void TStringList::SetText(const String &text) +{ + clear(); + stringstream iss(text); + string line; + while (getline(iss, line)) { + push_back(line); + } +} + +/** Метод возвращает размер списка строк. + * @params - нет + * + */ +int TStringList::Count() const +{ + return size(); +} + +/** Метод удаляет элемент списка по индексу. + * @int index - индекс удаляемого элемента + * + */ +void TStringList::Delete(int index) +{ + erase(begin() + index); +} + +/** Метод загружает данные из файла в список строк. + * @const String &filename - имя файла для загрузки строк + * + */ +void TStringList::LoadFromFile(const String &filename) +{ + clear(); + boost::filesystem::ifstream ifs(boost::filesystem::path(filename.c_str())); + string line; + while (getline(ifs, line)) { + push_back(line); + } +} + +/** Метод возвращает строку преобразования из числа. + * @int n - число для преобразования + * + */ +String String::IntToStr(int n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @unsigned int n - число для преобразования + * + */ +String String::UIntToStr(unsigned int n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @unsigned long n - число для преобразования + * + */ +String String::ULongToStr(unsigned long n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @long n - число для преобразования + * + */ +String String::LongToStr(long n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @unsigned long long n - число для преобразования + * + */ +String String::ULongLongToStr(unsigned long long n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @long long n - число для преобразования + * + */ +String String::LongLongToStr(long long n) +{ + return to_string(n); +} + +/** Метод возвращает строку преобразования из числа. + * @int n - число для преобразования + * + */ +String String::ToString(int n) +{ + return IntToStr(n); +} +/** Метод возвращает строку преобразования из числа. + * @unsigned int n - число для преобразования + * + */ +String String::ToString(unsigned int n) +{ + return UIntToStr(n); +} + +/** Метод возвращает строку преобразования из числа. + * unsigned long n - число для преобразования + * + */ +String String::ToString(unsigned long n) +{ + return ULongToStr(n); +} + +/** Метод возвращает строку преобразования из числа. + * @long n - число для преобразования + * + */ +String String::ToString(long n) +{ + return LongToStr(n); +} + +/** Метод возвращает строку преобразования из числа. + * @unsigned long long n - число для преобразования + * + */ +String String::ToString(unsigned long long n) +{ + return ULongLongToStr(n); +} + +/** Метод возвращает строку преобразования из числа. + * @long long n - число для преобразования + * + */ +String String::ToString(long long n) +{ + return LongLongToStr(n); +} + +/** Метод возвращает строку преобразования из числа + * десятичного в число шестнадцатеричное + * @int n - число для преобразования + * @int digits - число цифр + */ +String String::IntToHex(int n, int digits) +{ + stringstream ss; + ss << hex; + if (digits != 0) { + ss << setfill('0') << setw(digits); + } + ss << n; + + return String(ss.str()); +} + + +} // System + diff --git a/src/SystemClasses/String.hpp b/src/SystemClasses/String.hpp new file mode 100644 index 0000000..c9f3f30 --- /dev/null +++ b/src/SystemClasses/String.hpp @@ -0,0 +1,130 @@ +#ifndef SYSTEM_STRING_HPP +#define SYSTEM_STRING_HPP + +#include +#include +#include "System.hpp" +#include "DynamicArray.hpp" + +namespace System { + +// Важно: в String индексация символов идёт с 1, а не с 0! + +class String : public std::string +{ +public: + + String(); + + String(const std::string &src); + + String(const char *src); + + String(const char *src, int limit_size); + + explicit String(const DynamicArray &bytes); + + String(const WCHART *w_src, int limit_size); + + String(const WCHART *w_src); + + + String(int value); + String(unsigned int value); + String(long value); + String(unsigned long value); + String(long long value); + String(unsigned long long value); + + String UpperCase() const; + + String LowerCase() const; + + bool IsEmpty() const; + + int Length() const; + + int CompareIC(const String &b) const; + + int Compare(const String &b) const; + + String Replace(const String &sub, const String &replace) const; + + String SubString(int StartIndex, int Count) const; + + char &operator[] (int index); + const char &operator[] (int index) const; + + template + String& operator += (AnyStringable b) + { + append(String(b)); + return *this; + } + + template + String operator + (AnyStringable value) const + { + String result(*this); + result.append(String(value)); + return result; + } + + int ToInt() const; + + int ToIntDef(int default_value) const; + + int Pos(const String &substr); + + int GetLength() const; + void SetLength(int NewLength); + + int LastDelimiter(const String &delimiters) const; + + const char *LastChar() const; + + int WideCharBufSize() const; + WCHART *WideChar(WCHART *wbuf, int destSize) const; + + static String IntToHex(int n, int digits); + static String IntToStr(int n); + static String UIntToStr(unsigned int n); + static String LongToStr(long int n); + static String ULongToStr(unsigned long n); + static String LongLongToStr(long long n); + static String ULongLongToStr(unsigned long long n); + + static String ToString(int n); + static String ToString(unsigned int n); + static String ToString(long n); + static String ToString(unsigned long n); + static String ToString(long long n); + static String ToString(unsigned long long n); +}; + +template +String operator + (const std::basic_string &text, const int value) +{ + String a(text); + a += value; + return a; +} + +class TStringList : public std::vector +{ +public: + + void Add(const String &item); + void SetText(const String &text); + int Count() const; + void Delete(int index); + + void LoadFromFile(const String &filename); +}; + + +} // System + +using namespace System; + +#endif diff --git a/src/SystemClasses/SysInit.hpp b/src/SystemClasses/SysInit.hpp new file mode 100644 index 0000000..901f6d4 --- /dev/null +++ b/src/SystemClasses/SysInit.hpp @@ -0,0 +1,4 @@ +#ifndef SYSINIT_HPP +#define SYSINIT_HPP +#endif + diff --git a/src/SystemClasses/System.Classes.cpp b/src/SystemClasses/System.Classes.cpp new file mode 100644 index 0000000..b9fad40 --- /dev/null +++ b/src/SystemClasses/System.Classes.cpp @@ -0,0 +1,22 @@ +#include "System.Classes.hpp" + +namespace System { + +namespace Classes { + +TCriticalSection::TCriticalSection() +{ +} + +void TCriticalSection::Acquire() +{ +} + +void TCriticalSection::Release() +{ +} + +} // Classes + + +} // System diff --git a/src/SystemClasses/System.Classes.hpp b/src/SystemClasses/System.Classes.hpp new file mode 100644 index 0000000..280513a --- /dev/null +++ b/src/SystemClasses/System.Classes.hpp @@ -0,0 +1,38 @@ +#ifndef SYSTEM_CLASSES_HPP +#define SYSTEM_CLASSES_HPP + +#include +#include +#include +#include +#include "System.hpp" +#include "DynamicArray.hpp" +#include "String.hpp" +#include "TStream.hpp" +#include "TMemoryStream.hpp" +#include "TFileStream.hpp" +#include "System.SysUtils.hpp" +#include "Exception.hpp" +#include "TStreamWriter.hpp" +#include "TStreamReader.hpp" +#include "GetTickCount.hpp" + +namespace System { + +namespace Classes { + + +class TCriticalSection +{ +public: + TCriticalSection(); + + virtual void Acquire(); + virtual void Release(); +}; + +} // Classes + +} // System + +#endif diff --git a/src/SystemClasses/System.IOUtils.cpp b/src/SystemClasses/System.IOUtils.cpp new file mode 100644 index 0000000..99b4bec --- /dev/null +++ b/src/SystemClasses/System.IOUtils.cpp @@ -0,0 +1,78 @@ +#include "System.IOUtils.hpp" +#include + +namespace System { + +namespace Ioutils { + + +void CreateDir(const String &dirname) +{ + boost::filesystem::create_directory(boost::filesystem::path(dirname.c_str())); +} + +bool FileExists(const String &filename) +{ + return boost::filesystem::exists(boost::filesystem::path(filename.c_str())); +} + +bool DirectoryExists(const String &filename) +{ + return boost::filesystem::exists(boost::filesystem::path(filename.c_str())) + && boost::filesystem::is_directory(boost::filesystem::path(filename.c_str())); +} + +void DeleteFile(const String &filename) +{ + boost::filesystem::remove_all(filename.c_str()); +} + +void RemoveDir(const String &dirname) +{ + // boost::filesystem::remove_all(dirname.c_str()); +} + +namespace TDirectory { + +void CreateDirectory(const String &dirname) +{ + CreateDir(dirname); +} + +} // TDirectory + + +namespace TPath { + +String GetFullPath(const String &filename) +{ + auto absolute_path = boost::filesystem::absolute(boost::filesystem::path(filename.c_str())); + return String(absolute_path.string()); +} + +String GetTempPath() +{ + return boost::filesystem::temp_directory_path().string(); +} + +#if defined(_MSC_EXTENSIONS) +void GetTempPath(int bufSize, char *buf) +{ + strncpy_s(buf, bufSize, GetTempPath().c_str(), bufSize); +} + +#else +void GetTempPath(int bufSize, char *buf) +{ + strncpy(buf, GetTempPath().c_str(), bufSize); +} + +#endif + + +} // TPath + +} // Ioutils + + +} // System diff --git a/src/SystemClasses/System.IOUtils.hpp b/src/SystemClasses/System.IOUtils.hpp new file mode 100644 index 0000000..a617b7c --- /dev/null +++ b/src/SystemClasses/System.IOUtils.hpp @@ -0,0 +1,39 @@ +#ifndef SYSTEM_IOUTILS_HPP +#define SYSTEM_IOUTILS_HPP + +#include "String.hpp" + +namespace System { +namespace Ioutils { + +void CreateDir(const String &dirname); + +bool FileExists(const String &filename); + +bool DirectoryExists(const String &filename); + +void DeleteFile(const String &filename); + +void RemoveDir(const String &dirname); + +namespace TDirectory { + +void CreateDirectory(const String &dirname); + +} // TDirectory + +namespace TPath { + +String GetFullPath(const String &filename); +String GetTempPath(); +void GetTempPath(int bufSize, char *buf); + +} // TPath + +} // Ioutils + +} // System + +using namespace System::Ioutils; + +#endif diff --git a/src/SystemClasses/System.SysUtils.cpp b/src/SystemClasses/System.SysUtils.cpp new file mode 100644 index 0000000..51317b1 --- /dev/null +++ b/src/SystemClasses/System.SysUtils.cpp @@ -0,0 +1,170 @@ +#include "System.SysUtils.hpp" +#include +#include +#include "utf8.h" + +using namespace std; + +namespace System { + +namespace SysUtils { + +class TUtf8Encoding : public TEncoding +{ + +virtual DynamicArray GetPreamble() +{ + DynamicArray result; + result.push_back(0xEF); + result.push_back(0xBB); + result.push_back(0xBF); + return result; +} + +virtual String toUtf8(const System::DynamicArray &Buffer) const +{ + return String(Buffer); +} + +virtual DynamicArray fromUtf8(const String &str) +{ + DynamicArray result; + for (char c : str) { + result.push_back((t::Byte)c); + } + result.push_back(0); + return result; +} + +}; + +class TUcs2Encoding : public TEncoding +{ + +virtual DynamicArray GetPreamble() +{ + DynamicArray result; + result.push_back(0xFF); + result.push_back(0xFE); + return result; +} + +virtual String toUtf8(const System::DynamicArray &Buffer) const +{ + auto data_first = (const uint16_t *)Buffer.data(); + auto data_last = data_first + Buffer.size() / sizeof(uint16_t); + DynamicArray result_vector; + utf8::utf16to8(data_first, data_last, back_inserter(result_vector)); + return String(result_vector); +} + +virtual DynamicArray fromUtf8(const String &data) +{ + auto data_first = data.c_str(); + auto data_last = data_first + data.size(); + DynamicArray result_vector; + utf8::utf8to16(data_first, data_last, back_inserter(result_vector)); + return result_vector; +} + + +}; + +TStringBuilder::TStringBuilder() +{ +} + +TStringBuilder::TStringBuilder(const String &initial) + : value(initial) +{ +} + +TStringBuilder *TStringBuilder::Replace(const String &substring, const String &replace) +{ + value = value.Replace(substring, replace); + return this; +} + +String TStringBuilder::ToString() const +{ + return value; +} + +void TStringBuilder::Clear() +{ + value = ""; +} + +void TStringBuilder::Append(const String &s) +{ + value += s; +} + +void TStringBuilder::Append(char c) +{ + value.append(1, c); +} + + + +void TMultiReadExclusiveWriteSynchronizer::BeginWrite() +{ +} + +void TMultiReadExclusiveWriteSynchronizer::EndWrite() +{ +} + +void TMultiReadExclusiveWriteSynchronizer::BeginRead() +{ +} + +void TMultiReadExclusiveWriteSynchronizer::EndRead() +{ +} + + +TEncoding *TEncoding::UTF8 = new TUtf8Encoding(); +TEncoding *TEncoding::Unicode = new TUcs2Encoding(); + + +int TEncoding::GetBufferEncoding(const System::DynamicArray &Buffer, TEncoding* &AEncoding) +{ + // TODO: реализовать GetBufferEncoding + return 0; +} + +DynamicArray TEncoding::Convert(TEncoding * const Source, TEncoding * const Destination, const DynamicArray &Bytes, int StartIndex, int Count) +{ + // TODO: Исправить работу TEncoding::Convert + auto data = Source->toUtf8(Bytes); // TODO: StartIndex, Count + DynamicArray Result = Destination->fromUtf8(data); + return Result; +} + +DynamicArray TEncoding::GetPreamble() +{ + return DynamicArray(); +} + +int StrToInt(const String &s) +{ + return stoi(s.c_str()); +} + +String ExtractFileExt(const String &filename) +{ + boost::filesystem::path _p(filename.c_str()); + return _p.extension().string(); +} + +String StringReplace(const String &S, const String &OldPattern, const String &NewPattern, TReplaceFlags Flags) +{ + // TODO: реализовать StringReplace + return S.Replace(OldPattern, NewPattern); +} + + + +} // SysUtils +} // System diff --git a/src/SystemClasses/System.SysUtils.hpp b/src/SystemClasses/System.SysUtils.hpp new file mode 100644 index 0000000..647e6a7 --- /dev/null +++ b/src/SystemClasses/System.SysUtils.hpp @@ -0,0 +1,85 @@ +#ifndef SYSTEM_SYSUTILS_HPP +#define SYSTEM_SYSUTILS_HPP + +#include "System.IOUtils.hpp" +#include "String.hpp" + +namespace System { + +namespace SysUtils { + +String StringReplace(const String &S, const String &OldPattern, const String &NewPattern, TReplaceFlags Flags); + +class TStringBuilder +{ +public: + explicit TStringBuilder(); + + explicit TStringBuilder(const String &initial); + + TStringBuilder *Replace(const String &substring, const String &replace); + + String ToString() const; + + void Clear(); + + void Append(const String &s); + + void Append(char c); + + String value; +}; + +class TMultiReadExclusiveWriteSynchronizer +{ +public: + void BeginWrite(); + void EndWrite(); + + void BeginRead(); + void EndRead(); +}; + +class TEncoding +{ + +public: + +virtual System::DynamicArray GetPreamble() = 0; +virtual String toUtf8(const System::DynamicArray &Buffer) const = 0; +virtual DynamicArray fromUtf8(const String &str) = 0; + +static int GetBufferEncoding(const System::DynamicArray &Buffer, TEncoding* &AEncoding); +static DynamicArray Convert(TEncoding * const Source, TEncoding * const Destination, const DynamicArray &Bytes, int StartIndex, int Count); + +//! двухбайтная кодировка WCHART +static TEncoding *Unicode; + +static TEncoding *UTF8; + +}; + +typedef System::DynamicArray TBytes; + +int StrToInt(const String &s); + + +struct TSearchRec { + int Time; + int64_t Size; + int Attr; + String Name; + int ExcludeAttr; +}; + +String ExtractFileExt(const String &filename); + +} // SysUtils + +namespace Sysutils = SysUtils; + +} // System + +using namespace System::SysUtils; + +#endif diff --git a/src/SystemClasses/System.cpp b/src/SystemClasses/System.cpp new file mode 100644 index 0000000..97edb38 --- /dev/null +++ b/src/SystemClasses/System.cpp @@ -0,0 +1,130 @@ +#include "System.hpp" + + + +namespace System { + +bool operator == (const TGUID &a, const TGUID &b) +{ + return a.D1 == b.D1 + && a.D2 == b.D2 + && a.D3 == b.D3 + && a.D4[0] == b.D4[0] + && a.D4[1] == b.D4[1] + && a.D4[2] == b.D4[2] + && a.D4[3] == b.D4[3] + && a.D4[4] == b.D4[4] + && a.D4[5] == b.D4[5] + && a.D4[6] == b.D4[6] + && a.D4[7] == b.D4[7] + ; +} + +//--------------------------------------------------------------------------- +// Замена макросов Microsoft +int64_t Int32x32To64(int64_t a, int64_t b) +{ + return ((int64_t)(((int64_t)((long)(a))) * ((long)(b)))); +} + +//--------------------------------------------------------------------------- +// Замена макросов Microsoft +uint64_t UInt32x32To64(int64_t a, int64_t b) +{ + return ((uint64_t)(((uint64_t)((unsigned int)(a))) * ((unsigned int)(b)))); +} + + +//--------------------------------------------------------------------------- +// Преобразование времени FILETIME to POSIX +uint64_t FileTime_to_POSIX(LPFILETIME pft) +{ + // takes the last modified date + LARGE_INTEGER date, adjust; + date.HighPart = pft -> dwHighDateTime; + date.LowPart = pft -> dwLowDateTime; + + // 100-nanoseconds = milliseconds * 10000 + adjust.QuadPart = SEC_TO_UNIX_EPOCH * 10000; + + // removes the diff between 1970 and 1601 + date.QuadPart -= adjust.QuadPart; + + // converts back from 100-nanoseconds to seconds + return date.QuadPart / 10000000; +} + +//--------------------------------------------------------------------------- +// Преобразование времени POSIX to FILETIME +void UnixTimeToFileTime(time_t t, LPFILETIME pft) +{ + + uint64_t ll = UInt32x32To64(t, 10000000) + SEC_TO_UNIX_EPOCH; + + pft->dwLowDateTime = (uint32_t)ll; + pft->dwHighDateTime = ll >> 32; +} + + +bool SystemTimeToFileTime(const SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime) +{ + struct tm ttm; + time_t UnixTime; + + ttm.tm_year = lpSystemTime->wYear - 1900; + ttm.tm_mon = lpSystemTime->wMonth - 1; + ttm.tm_mday = lpSystemTime->wDay; + ttm.tm_hour = lpSystemTime->wHour; + ttm.tm_min = lpSystemTime->wMinute; + ttm.tm_sec = lpSystemTime->wSecond; + ttm.tm_isdst = 0; + ttm.tm_wday = 0; // возможно здесь что-то не то, надо проверять; days since Sunday - [0, 6] + ttm.tm_yday = 0; // возможно здесь что-то не то, надо проверять; days since January 1 - [0, 365] + + UnixTime = mktime(&ttm); + UnixTimeToFileTime(UnixTime, lpFileTime); + + return true; +} + +bool LocalFileTimeToFileTime(const FILETIME *lpLocalFileTime, LPFILETIME lpFileTime) +{ + + // TODO: реализовать кроссплатформенное преобразование локального системного файлового времени в универсальное (UTC) файловое время + time_t rawtime = FileTime_to_POSIX((LPFILETIME)lpLocalFileTime); + struct tm *ptm = gmtime(&rawtime); + time_t UnixTime = mktime(ptm); + UnixTimeToFileTime(UnixTime, lpFileTime); + + return true; + +} + +bool FileTimeToLocalFileTime(const FILETIME *lpLocalFileTime, LPFILETIME lpFileTime) +{ + + time_t rawtime = FileTime_to_POSIX((LPFILETIME)lpLocalFileTime); + struct tm * ptm = localtime(&rawtime); + time_t UnixTime = mktime(ptm); + UnixTimeToFileTime(UnixTime, lpFileTime); + + return true; + +} + +void GetSystemTime(LPSYSTEMTIME lpSystemTime) +{ + + time_t CurrTime = time(NULL); + tm *ttm = localtime(&CurrTime); + + lpSystemTime->wYear = ttm->tm_year + 1900; + lpSystemTime->wMonth = ttm->tm_mon + 1; + lpSystemTime->wDay = ttm->tm_mday; + lpSystemTime->wHour = ttm->tm_hour; + lpSystemTime->wMinute = ttm->tm_min; + lpSystemTime->wSecond = ttm->tm_sec; + +} + +} // System diff --git a/src/SystemClasses/System.hpp b/src/SystemClasses/System.hpp new file mode 100644 index 0000000..c4a8aed --- /dev/null +++ b/src/SystemClasses/System.hpp @@ -0,0 +1,106 @@ +#ifndef SYSTEM_HPP +#define SYSTEM_HPP + +#ifndef DELPHI_PACKAGE +#define DELPHI_PACKAGE +#endif // DELPHI_PACKAGE + +#include +#include +#include +#include + +#define WINDOWS_TICK 10000000 +#define SEC_TO_UNIX_EPOCH 11644473600LL + +namespace System { + +typedef uint32_t LongWord; +typedef uint16_t Word; +typedef uint16_t WORD; +typedef unsigned long DWORD; +typedef char16_t WCHART; +typedef char *LPSTR; +typedef int64_t LONGLONG; +typedef uint64_t ULONGLONG; +typedef long LONG; + + + +namespace t { // в msvc конфликтует с zlib +typedef uint8_t Byte; +} + +const int MAX_PATH = 260; + +typedef struct _FILETIME { + + DWORD dwLowDateTime; + DWORD dwHighDateTime; + +} FILETIME, *LPFILETIME; + +typedef struct _SYSTEMTIME { + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + + +typedef union _LARGE_INTEGER { + struct { + DWORD LowPart; + LONG HighPart; + }; + struct { + DWORD LowPart; + LONG HighPart; + } u; + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + + +int64_t Int32x32To64(int64_t a, int64_t b); +uint64_t UInt32x32To64(int64_t a, int64_t b); + +uint64_t FileTime_to_POSIX(LPFILETIME pft); +void UnixTimeToFileTime(time_t t, LPFILETIME pft); + +bool SystemTimeToFileTime(const SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime); +bool LocalFileTimeToFileTime(const FILETIME *lpLocalFileTime, LPFILETIME lpFileTime); +bool FileTimeToLocalFileTime(const FILETIME *lpLocalFileTime, LPFILETIME lpFileTime); + +void GetSystemTime(LPSYSTEMTIME lpSystemTime); + + +struct TGUID { + LongWord D1; + Word D2; + Word D3; + t::Byte D4[8]; +}; + +bool operator == (const TGUID &a, const TGUID &b); + +typedef TGUID GUID; + +enum TReplaceFlags { + rfReplaceAll = 1, + rfIgnoreCase = 2 +}; + +template +void LocalFree(T *anyvalue) +{ + // Do nothing +} + +} // System + +#endif + diff --git a/src/SystemClasses/SystemClasses.vcxproj.filters b/src/SystemClasses/SystemClasses.vcxproj.filters new file mode 100644 index 0000000..9c4349e --- /dev/null +++ b/src/SystemClasses/SystemClasses.vcxproj.filters @@ -0,0 +1,105 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + Заголовочные файлы + + + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + Файлы исходного кода + + + \ No newline at end of file diff --git a/src/SystemClasses/SystemClasses.vcxproj.user b/src/SystemClasses/SystemClasses.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/src/SystemClasses/SystemClasses.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/SystemClasses/TFileStream.cpp b/src/SystemClasses/TFileStream.cpp new file mode 100644 index 0000000..3cf48fb --- /dev/null +++ b/src/SystemClasses/TFileStream.cpp @@ -0,0 +1,78 @@ +#include "TFileStream.hpp" +#include +#include + +namespace System { + +namespace Classes { + +TFileStream::TFileStream(const String &FileName, const uint16_t fileMode) + : TWrapperStream(), filename(FileName) +{ + std::ios_base::openmode mode = std::ios::binary | std::ios::in | std::ios::out; + if (fileMode == fmCreate) { + mode |= std::ios::trunc; + } + _stream = std::make_shared(boost::filesystem::path(filename), mode); + reopen(_stream); + m_position = 0; +} + +TFileStream::TFileStream(const boost::filesystem::path &path, const uint16_t fileMode) + : TWrapperStream(), filename(path.string()) +{ + std::ios_base::openmode mode = std::ios::binary | std::ios::in | std::ios::out; + if (fileMode == fmCreate) { + mode |= std::ios::trunc; + } + _stream = std::make_shared(path, mode); + reopen(_stream); + m_position = 0; +} + + +TFileStream::~TFileStream() +{ + Close(); +} + +int16_t TFileStream::GetHandle() const +{ + return 0; +} + +void TFileStream::Reopen() +{ + if (_stream) { + if (_stream->is_open()) { + return; + } + } + std::ios_base::openmode mode = std::ios::binary | std::ios::in | std::ios::out; + _stream = std::make_shared(boost::filesystem::path(filename), mode); + reopen(_stream); +} + + +void TFileStream::Close() +{ + _stream->close(); + _stream.reset(); +} + +int64_t TFileStream::Read(void *Buffer, int64_t Count) +{ + Reopen(); + return TWrapperStream::Read(Buffer, Count); +} + +int64_t TFileStream::Write(const void *Buffer, int64_t Count) +{ + Reopen(); + return TWrapperStream::Write(Buffer, Count); +} + + +} // Classes + +} // System diff --git a/src/SystemClasses/TFileStream.hpp b/src/SystemClasses/TFileStream.hpp new file mode 100644 index 0000000..941eac1 --- /dev/null +++ b/src/SystemClasses/TFileStream.hpp @@ -0,0 +1,48 @@ +#ifndef SYSTEM_CLASSES_TFSTREAM +#define SYSTEM_CLASSES_TFSTREAM + +#include "TStream.hpp" +#include "String.hpp" +#include +#include +#include +#include + +namespace System { + +namespace Classes { + +const uint16_t fmOpenRead = 0x0000; +const uint16_t fmOpenReadWrite = 0x0002; +const uint16_t fmShareDenyNone = 0x0040; +const uint16_t fmShareDenyWrite = 0x0020; +const uint16_t fmShareDenyRead = 0x0030; +const uint16_t fmCreate = 0xFFFF; + +typedef uint16_t HANDLE; + +class TFileStream : public TWrapperStream +{ +public: + + TFileStream(const String &FileName, const uint16_t fileMode); + TFileStream(const boost::filesystem::path &path, const uint16_t fileMode); + + virtual ~TFileStream(); + + int16_t GetHandle() const; + + virtual void Close(); + virtual void Reopen(); + virtual int64_t Read(void *Buffer, int64_t Count); + virtual int64_t Write(const void *Buffer, int64_t Count); + +protected: + std::string filename; + std::shared_ptr _stream; +}; + +} // Classes +} // System + +#endif diff --git a/src/SystemClasses/TMemoryStream.cpp b/src/SystemClasses/TMemoryStream.cpp new file mode 100644 index 0000000..1dbe359 --- /dev/null +++ b/src/SystemClasses/TMemoryStream.cpp @@ -0,0 +1,82 @@ +#include "TMemoryStream.hpp" + +#include "System.hpp" +#include "DynamicArray.hpp" +#include "TStream.hpp" +#include + +namespace System { + +namespace Classes { + +TMemoryStream::TMemoryStream() {} +TMemoryStream::~TMemoryStream() {} + +int64_t TMemoryStream::GetSize() const +{ + return _data.size(); +} + +void TMemoryStream::SetSize(int64_t NewSize) +{ + _data.resize(NewSize); + m_size = NewSize; + if (m_position > m_size) { + m_position = m_size; + } +} + +int64_t TMemoryStream::Read(void *Buffer, int64_t Count) +{ + int64_t toRead = Count; + if (_data.size() <= m_position + toRead) { + toRead = _data.size() - m_position; + } + if (toRead > 0) { + memcpy(Buffer, _data.data() + m_position, toRead); + m_position += toRead; + return toRead; + } + return 0; +} + +int64_t TMemoryStream::Write(const void *Buffer, int64_t Count) +{ + auto buf = reinterpret_cast(Buffer); + EnsureSize(m_position + Count); + for (auto i = Count; i; i--) { + _data[m_position++] = *buf++; + } + return Count; +} + +const DynamicArray &TMemoryStream::GetBytes() const +{ + return _data; +} + +void *TMemoryStream::GetMemory() +{ + return _data.data(); +} + + +void TMemoryStream::EnsureSize(size_t size) +{ + if (_data.size() < size) { + _data.resize(size); + m_size = _data.size(); + } +} + +TBytesStream::TBytesStream(const DynamicArray &initial) +{ + Write(initial.data(), initial.size()); + m_position = 0; +} + +TBytesStream::~TBytesStream() {} + +} // Classes + +} // System diff --git a/src/SystemClasses/TMemoryStream.hpp b/src/SystemClasses/TMemoryStream.hpp new file mode 100644 index 0000000..0208580 --- /dev/null +++ b/src/SystemClasses/TMemoryStream.hpp @@ -0,0 +1,51 @@ +#ifndef SYSTEM_CLASSES_TMEMORYSTREAM +#define SYSTEM_CLASSES_TMEMORYSTREAM + +#include "System.hpp" +#include "DynamicArray.hpp" +#include "TStream.hpp" +#include + +namespace System { + +namespace Classes { + +class TMemoryStream : public TStream +{ +public: + + TMemoryStream(); + virtual ~TMemoryStream(); + + virtual int64_t GetSize() const; + + virtual void SetSize(int64_t NewSize); + + virtual int64_t Read(void *Buffer, int64_t Count); + + virtual int64_t Write(const void *Buffer, int64_t Count); + + const DynamicArray &GetBytes() const; + + void *GetMemory(); + +private: + + void EnsureSize(size_t size); + + DynamicArray _data; +}; + +class TBytesStream : public TMemoryStream +{ +public: + TBytesStream(const DynamicArray &initial); + + virtual ~TBytesStream(); +}; + +} // Classes + +} // System + +#endif diff --git a/src/SystemClasses/TStream.cpp b/src/SystemClasses/TStream.cpp new file mode 100644 index 0000000..30700a2 --- /dev/null +++ b/src/SystemClasses/TStream.cpp @@ -0,0 +1,219 @@ +#include "TStream.hpp" +#include "Exception.hpp" +#include + +namespace System { + +namespace Classes { + +TStream::TStream() + : m_position(0), m_size(0) +{ +} + + +int64_t TStream::GetSize() const +{ + return m_size; +} + +void TStream::SetSize(int64_t NewSize) +{ + // TODO: реализовать TStream::SetSize + m_size = NewSize; +} + +int64_t TStream::GetPosition() const +{ + return m_position; +} + +void TStream::SetPosition(int64_t NewPosition) +{ + m_position = NewPosition; +} + + +int64_t TStream::Read(void *Buffer, int64_t Count) +{ + return 0; +} + +int64_t TStream::Seek(const int64_t offset, const TSeekOrigin Origin) +{ + if (Origin == soFromBeginning) { + + if (offset > GetSize()) { + throw Exception("Wrong offset"); + } + m_position = offset; + + } else if (Origin == soFromEnd) { + + m_position = GetSize() - offset; + + if (GetSize() < offset) { + throw Exception("Wrong offset"); + } + + } else { + + if (m_position + offset < 0 || m_position + offset > GetSize()) { + throw Exception("Wrong offset"); + } + m_position += offset; + } + return m_position; +} + +int64_t TStream::Write(const void *Buffer, int64_t Count) +{ + return 0; +} + +int64_t TStream::ReadBuffer(void *Buffer, int64_t Count) +{ + auto data_read = Read(Buffer, Count); + return data_read; +} + +int64_t TStream::Read(System::DynamicArray &Buffer, int64_t Count) +{ + auto CountToRead = (Count <= 0) ? GetSize() : Count; + if (Buffer.size() < CountToRead) { + Buffer.resize(CountToRead); + } + return Read(Buffer.data(), CountToRead); +} + +int64_t TStream::CopyFrom(TStream *Source, const int64_t Count) +{ + if (Count == 0) { + Source->Seek(0, soFromBeginning); + auto data_size = Source->GetSize(); + if (data_size != 0) { + return CopyFrom(Source, data_size); + } + return 0; + } + System::DynamicArray _data; + auto resultCount = Source->Read(_data, Count); + return Write(_data, resultCount); +} + +int64_t TStream::WriteBuffer(const void *Buffer, const int64_t Count) +{ + auto result = Write(Buffer, Count); + if (result != Count) { + // Throw EWriteError + } + return result; +} + +int64_t TStream::Write(const System::DynamicArray &Buffer, const int64_t Count) +{ + if (Count == 0) { + auto data_size = Buffer.size(); + if (data_size != 0) { + return Write(Buffer.data(), data_size); + } + return 0; + } + return Write(Buffer.data(), Count); +} + +void TStream::Close() +{ +} + +TStream::~TStream() +{ +} + + +THandleStream::~THandleStream() +{ +} + +TWrapperStream::TWrapperStream() +{ +} + +TWrapperStream::TWrapperStream(const std::shared_ptr &stream) + : _stream(stream) +{ + init_size(); +} + +TWrapperStream::TWrapperStream(std::shared_ptr &&stream) + : _stream(stream) +{ + init_size(); +} + +void TWrapperStream::reset(std::iostream *stream) +{ + _stream.reset(stream); + init_size(); + m_position = 0; +} + +void TWrapperStream::reopen(const std::shared_ptr &stream) +{ + _stream = stream; + init_size(); +} + +void TWrapperStream::init_size() +{ + _stream->seekg(0, std::ios_base::end); + m_size = _stream->tellg(); + _stream->seekg(0, std::ios_base::beg); + if (m_size < 0) { + m_size = 0; + } +} + + +int64_t TWrapperStream::Read(void *Buffer, int64_t Count) +{ + _stream->seekg(GetPosition(), std::ios_base::beg); + _stream->read((char*)Buffer, Count); + if (_stream->bad()) { + String err(std::strerror(errno)); + std::cerr << err << std::endl; + throw Exception(err); + } + auto data_read = _stream->gcount(); + m_position += data_read; + return data_read; +} + +int64_t TWrapperStream::Write(const void *Buffer, int64_t Count) +{ + _stream->seekp(GetPosition(), std::ios_base::beg); + _stream->write((char*)Buffer, Count); + _stream->flush(); + if (_stream->bad()) { + String err(std::strerror(errno)); + std::cerr << err << std::endl; + throw Exception(err); + } + + m_position += Count; + if (m_position > m_size) { + m_size = m_position; + } + + return Count; +} + +TWrapperStream::~TWrapperStream() +{ + _stream.reset(); +} + +} // Classes + +} // System + diff --git a/src/SystemClasses/TStream.hpp b/src/SystemClasses/TStream.hpp new file mode 100644 index 0000000..5d7e416 --- /dev/null +++ b/src/SystemClasses/TStream.hpp @@ -0,0 +1,105 @@ +#ifndef SYSTEM_CLASSES_TSTREAM_HPP +#define SYSTEM_CLASSES_TSTREAM_HPP + +#include +#include +#include +#include +#include +#include +#include "System.hpp" +#include "DynamicArray.hpp" + +namespace System { + +namespace Classes { + +typedef std::ios_base::seekdir TSeekOrigin; + +const TSeekOrigin soBeginning = std::ios_base::beg; +const TSeekOrigin soCurrent = std::ios_base::cur; +const TSeekOrigin soEnd = std::ios_base::end; +const TSeekOrigin soFromBeginning = soBeginning; +const TSeekOrigin soFromCurrent = std::ios_base::cur; +const TSeekOrigin soFromEnd = std::ios_base::end; + +class TStream +{ +protected: + int64_t m_position; + int64_t m_size; + +public: + + TStream(); + + virtual int64_t GetSize() const; + + virtual void SetSize(int64_t NewSize); + + virtual int64_t GetPosition() const; + + virtual void SetPosition(int64_t NewPosition); + +public: + + virtual int64_t Read(void *Buffer, int64_t Count); + + virtual int64_t Seek(const int64_t offset, const TSeekOrigin Origin); + + virtual int64_t Write(const void *Buffer, int64_t Count); + + virtual int64_t ReadBuffer(void *Buffer, int64_t Count); + + virtual int64_t Read(System::DynamicArray &Buffer, int64_t Count); + + virtual int64_t CopyFrom(TStream *Source, const int64_t Count); + + virtual int64_t WriteBuffer(const void *Buffer, const int64_t Count); + + virtual int64_t Write(const System::DynamicArray &Buffer, const int64_t Count); + + virtual void Close(); + + virtual ~TStream(); +}; + +class THandleStream : public TStream +{ + virtual ~THandleStream(); +}; + +class TWrapperStream : public TStream +{ +protected: + + TWrapperStream(); + + TWrapperStream(const std::shared_ptr &stream); + + TWrapperStream(std::shared_ptr &&stream); + + void reset(std::iostream *stream); + void reopen(const std::shared_ptr &stream); + + void init_size(); + +public: + + virtual int64_t Read(void *Buffer, int64_t Count); + + virtual int64_t Write(const void *Buffer, int64_t Count); + + virtual ~TWrapperStream(); + +private: + std::shared_ptr _stream; +}; + +} // Classes + +} // System + +using namespace System::Classes; + +#endif diff --git a/src/SystemClasses/TStreamReader.cpp b/src/SystemClasses/TStreamReader.cpp new file mode 100644 index 0000000..a5cd6af --- /dev/null +++ b/src/SystemClasses/TStreamReader.cpp @@ -0,0 +1,32 @@ +#include "TStreamReader.hpp" + +namespace System { + +namespace Classes { + + +TStreamReader::TStreamReader(TStream *stream, bool DetectBOM) + : stream(stream) +{ +} + +int TStreamReader::Read() +{ + t::Byte data; + auto data_read = stream->Read(&data, 1); + if (data_read != 1) { + return -1; + } + return data; +} + +String TStreamReader::ReadLine() +{ + // TODO: реализовать TStreamReader::ReadLine() + return String(); +} + + +} // Classes + +} // System diff --git a/src/SystemClasses/TStreamReader.hpp b/src/SystemClasses/TStreamReader.hpp new file mode 100644 index 0000000..9386306 --- /dev/null +++ b/src/SystemClasses/TStreamReader.hpp @@ -0,0 +1,29 @@ +#ifndef SYSTEM_TSTREAMREADER_HPP +#define SYSTEM_TSTREAMREADAER_HPP + +#include "TStream.hpp" +#include "System.SysUtils.hpp" +#include "String.hpp" + +namespace System { + +namespace Classes { + +class TStreamReader +{ +public: + TStreamReader(TStream *stream, bool DetectBOM); + + int Read(); + + String ReadLine(); + +private: + TStream *stream; +}; + +} // Classes + +} // System + +#endif diff --git a/src/SystemClasses/TStreamWriter.cpp b/src/SystemClasses/TStreamWriter.cpp new file mode 100644 index 0000000..dfdacab --- /dev/null +++ b/src/SystemClasses/TStreamWriter.cpp @@ -0,0 +1,27 @@ +#include "TStreamWriter.hpp" +#include "TFileStream.hpp" + +namespace System { + +namespace Classes { + + +TStreamWriter::TStreamWriter(const String &Filename, TEncoding* Encoding, int BufferSize) + : stream(new TFileStream(Filename, fmOpenReadWrite)) +{ +} + +TStreamWriter::TStreamWriter(TStream *stream, TEncoding* Encoding, int BufferSize) + : stream(stream) +{ +} + +void TStreamWriter::Write(const String &s) +{ + // TODO: кодировка TEncoding::Convert() + stream->Write(s.c_str(), s.size()); +} + +} // Classes + +} // System diff --git a/src/SystemClasses/TStreamWriter.hpp b/src/SystemClasses/TStreamWriter.hpp new file mode 100644 index 0000000..d22b4f9 --- /dev/null +++ b/src/SystemClasses/TStreamWriter.hpp @@ -0,0 +1,29 @@ +#ifndef SYSTEM_TSTREAMWRITER_HPP +#define SYSTEM_TSTREAMWRITER_HPP + +#include "TStream.hpp" +#include "System.SysUtils.hpp" +#include "String.hpp" + +namespace System { + +namespace Classes { + +class TStreamWriter +{ +public: + + TStreamWriter(const String &Filename, TEncoding* Encoding, int BufferSize); + TStreamWriter( TStream *stream, TEncoding* Encoding, int BufferSize); + + void Write (const String &s); + +private: + TStream *stream; +}; + +} // Classes + +} // System + +#endif diff --git a/src/SystemClasses/main.cpp b/src/SystemClasses/main.cpp new file mode 100644 index 0000000..49b56ed --- /dev/null +++ b/src/SystemClasses/main.cpp @@ -0,0 +1,37 @@ +#include "System.Classes.hpp" + +using namespace System; +using namespace System::Classes; + +String doit(char d1, char d2) +{ + String s = (int)d1; + s += "."; + s += (int)d2; + + return s; +} + +int main() +{ + + DynamicArray buf; + buf.push_back((Byte)'a'); + buf.push_back((Byte)'b'); + buf.push_back((Byte)'c'); + buf.push_back((Byte)'\n'); + + TStream *data = new TMemoryStream(); + data->Write(buf, 0); + data->Seek(0, soBeginning); + + TStream *stream = new TFileStream("somefile", fmCreate); + stream->CopyFrom(data, 0); + + if (doit('\x00', '\x02') == "0.2") { + std::cout << "Ok!" << std::endl; + } else { + std::cout << "Bug :(" << std::endl; + } + return 0; +} \ No newline at end of file diff --git a/src/SystemClasses/utf8.h b/src/SystemClasses/utf8.h new file mode 100644 index 0000000..82b13f5 --- /dev/null +++ b/src/SystemClasses/utf8.h @@ -0,0 +1,34 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "utf8/checked.h" +#include "utf8/unchecked.h" + +#endif // header guard diff --git a/src/SystemClasses/utf8/checked.h b/src/SystemClasses/utf8/checked.h new file mode 100644 index 0000000..2aef583 --- /dev/null +++ b/src/SystemClasses/utf8/checked.h @@ -0,0 +1,327 @@ +// Copyright 2006-2016 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include + +namespace utf8 +{ + // Base for the exceptions that may be thrown from the library + class exception : public ::std::exception { + }; + + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public exception { + uint32_t cp; + public: + invalid_code_point(uint32_t codepoint) : cp(codepoint) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!utf8::internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + out = utf8::append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + out = utf8::append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) + ++start; + break; + } + } + return out; + } + + template + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); + return utf8::replace_invalid(start, end, out, replacement_marker); + } + + template + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return utf8::next(it, end); + } + + template + uint32_t prior(octet_iterator& it, octet_iterator start) + { + // can't do much if it == start + if (it == start) + throw not_enough_room(); + + octet_iterator end = it; + // Go back until we hit either a lead octet or start + while (utf8::internal::is_trail(*(--it))) + if (it == start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + return utf8::peek_next(it, end); + } + + /// Deprecated in versions that include "prior" + template + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (utf8::internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return utf8::next(temp, end); + } + + template + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + utf8::next(it, end); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::next(first, last); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast(trail_surrogate)); + } + else + throw invalid_utf16(static_cast(cp)); + + } + // Lone trail surrogate + else if (utf8::internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast(cp)); + + result = utf8::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::next(start, end); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& rangestart, + const octet_iterator& rangeend) : + it(octet_it), range_start(rangestart), range_end(rangeend) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + utf8::next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator& operator -- () + { + utf8::prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/src/SystemClasses/utf8/core.h b/src/SystemClasses/utf8/core.h new file mode 100644 index 0000000..ae0f367 --- /dev/null +++ b/src/SystemClasses/utf8/core.h @@ -0,0 +1,332 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template + inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template + inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template + inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } + + template + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); + } + + template + inline typename std::iterator_traits::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + template + inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// Helper for get_sequence_x + template + utf_error increase_safely(octet_iterator& it, octet_iterator end) + { + if (++it == end) + return NOT_ENOUGH_ROOM; + + if (!utf8::internal::is_trail(*it)) + return INCOMPLETE_SEQUENCE; + + return UTF8_OK; + } + + #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + + /// get_sequence_x functions decode utf-8 sequences of the length x + template + utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + return UTF8_OK; + } + + template + utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + + return UTF8_OK; + } + + template + utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + template + utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 0: + return INVALID_LEAD; + case 1: + err = utf8::internal::get_sequence_1(it, end, cp); + break; + case 2: + err = utf8::internal::get_sequence_2(it, end, cp); + break; + case 3: + err = utf8::internal::get_sequence_3(it, end, cp); + break; + case 4: + err = utf8::internal::get_sequence_4(it, end, cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. Now, security checks... + if (utf8::internal::is_code_point_valid(cp)) { + if (!utf8::internal::is_overlong_sequence(cp, length)){ + // Passed! Return here. + code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; + } + else + err = INVALID_CODE_POINT; + } + + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } + + template + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (utf8::find_invalid(start, end) == end); + } + + template + inline bool starts_with_bom (octet_iterator it, octet_iterator end) + { + return ( + ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) + ); + } + + //Deprecated in release 2.3 + template + inline bool is_bom (octet_iterator it) + { + return ( + (utf8::internal::mask8(*it++)) == bom[0] && + (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/src/SystemClasses/utf8/unchecked.h b/src/SystemClasses/utf8/unchecked.h new file mode 100644 index 0000000..cb24271 --- /dev/null +++ b/src/SystemClasses/utf8/unchecked.h @@ -0,0 +1,228 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + uint32_t next(octet_iterator& it) + { + uint32_t cp = utf8::internal::mask8(*it); + typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (utf8::internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template + uint32_t peek_next(octet_iterator it) + { + return utf8::unchecked::next(it); + } + + template + uint32_t prior(octet_iterator& it) + { + while (utf8::internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template + inline uint32_t previous(octet_iterator& it) + { + return utf8::unchecked::prior(it); + } + + template + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + utf8::unchecked::next(it); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::unchecked::next(first); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = utf8::unchecked::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::unchecked::next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::unchecked::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::unchecked::next(start); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + ::std::advance(it, utf8::internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + ::std::advance(it, utf8::internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + utf8::unchecked::prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::unchecked::prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + diff --git a/src/SystemClasses/vcl.h b/src/SystemClasses/vcl.h new file mode 100644 index 0000000..e69de29 diff --git a/src/V8File.cpp b/src/V8File.cpp index ad84dd2..3fd3164 100644 --- a/src/V8File.cpp +++ b/src/V8File.cpp @@ -958,8 +958,7 @@ int CV8File::ReadBlockData(char *pFileData, stBlockHeader *pBlockHeader, char *& page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - //bytes_to_read = MIN(page_size, data_size - read_in_bytes); - bytes_to_read = std::min(page_size, data_size - read_in_bytes); + bytes_to_read = MIN(page_size, data_size - read_in_bytes); memcpy(&pBlockData[read_in_bytes], (char*)(&pBlockHeader[1]), bytes_to_read); @@ -1001,8 +1000,7 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - //bytes_to_read = MIN(page_size, data_size - read_in_bytes); - bytes_to_read = std::min(page_size, data_size - read_in_bytes); + bytes_to_read = MIN(page_size, data_size - read_in_bytes); file.read(&pBlockData[read_in_bytes], bytes_to_read); @@ -1041,8 +1039,7 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock page_size = _httoi(pBlockHeader->page_size_hex); next_page_addr = _httoi(pBlockHeader->next_page_addr_hex); - //bytes_to_read = MIN(page_size, data_size - read_in_bytes); - bytes_to_read = std::min(page_size, data_size - read_in_bytes); + bytes_to_read = MIN(page_size, data_size - read_in_bytes); const int buf_size = 1024; // TODO: Настраиваемый размер буфера char *pBlockData = new char [buf_size]; @@ -1050,7 +1047,6 @@ int CV8File::ReadBlockData(std::basic_istream &file, stBlockHeader *pBlock while (read_done < bytes_to_read) { file.read(pBlockData, MIN(buf_size, bytes_to_read - read_done)); - //file.read(pBlockData, std::min(buf_size, bytes_to_read - read_done)); int rd = file.gcount(); out.write(pBlockData, rd); read_done += rd; @@ -1172,8 +1168,7 @@ int CV8File::PackFromFolder(const std::string &dirname, const std::string &filen // [0] + [1] DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); - //size_t addr_block_size = MAX(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); - size_t addr_block_size = std::max(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); + size_t addr_block_size = MAX(sizeof(stElemAddr) * ElemsNum, V8_DEFAULT_PAGE_SIZE); cur_block_addr += addr_block_size; // +[2] for (auto elem : Elems) { @@ -1184,8 +1179,7 @@ int CV8File::PackFromFolder(const std::string &dirname, const std::string &filen addr.elem_data_addr = cur_block_addr; cur_block_addr += sizeof(stBlockHeader); // +[5] - //cur_block_addr += MAX(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] - cur_block_addr += std::max(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] + cur_block_addr += MAX(elem.data_size, V8_DEFAULT_PAGE_SIZE); // +[6] addr.fffffff = V8_FF_SIGNATURE; @@ -1472,8 +1466,7 @@ int CV8File::BuildCfFile(const std::string &in_dirname, const std::string &out_f DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); stElemAddr *pTOC; pTOC = new stElemAddr[ElemsNum]; - //cur_block_addr += MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); - cur_block_addr += std::max(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + cur_block_addr += MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); boost::filesystem::ofstream file_out(out_filename, std::ios_base::binary); //Открываем выходной файл контейнер на запись @@ -1756,8 +1749,7 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) NeedDataBufferSize += stFileHeader::Size(); // заголовок блока и данные блока - адреса элементов с учетом минимальной страницы 512 байт - //NeedDataBufferSize += stBlockHeader::Size() + MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); - NeedDataBufferSize += stBlockHeader::Size() + std::max(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); + NeedDataBufferSize += stBlockHeader::Size() + MAX(stElemAddr::Size() * ElemsNum, V8_DEFAULT_PAGE_SIZE); for (auto elem : Elems) { @@ -1770,8 +1762,7 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) elem.IsV8File = false; } - //NeedDataBufferSize += stBlockHeader::Size() + MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); - NeedDataBufferSize += stBlockHeader::Size() + std::max(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + NeedDataBufferSize += stBlockHeader::Size() + MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); } @@ -1780,8 +1771,7 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) pCurrentTempElem = pTempElemsAddrs; DWORD cur_block_addr = stFileHeader::Size() + stBlockHeader::Size(); - //cur_block_addr += MAX(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); - cur_block_addr += std::max(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); + cur_block_addr += MAX(V8_DEFAULT_PAGE_SIZE, stElemAddr::Size() * ElemsNum); for (auto elem : Elems) { @@ -1791,8 +1781,7 @@ int CV8File::GetData(char **DataBuffer, ULONG *DataBufferSize) pCurrentTempElem->elem_data_addr = cur_block_addr; cur_block_addr += sizeof(stBlockHeader); - //cur_block_addr += MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); - cur_block_addr += std::max(elem.DataSize, V8_DEFAULT_PAGE_SIZE); + cur_block_addr += MAX(elem.DataSize, V8_DEFAULT_PAGE_SIZE); pCurrentTempElem->fffffff = V8_FF_SIGNATURE; ++pCurrentTempElem; diff --git a/src/metaread/Base64.cpp b/src/metaread/Base64.cpp new file mode 100644 index 0000000..15d2cb5 --- /dev/null +++ b/src/metaread/Base64.cpp @@ -0,0 +1,152 @@ +//--------------------------------------------------------------------------- + + +#include +#include "Base64.h" + +//--------------------------------------------------------------------------- + + +// http://base64.sourceforge.net/ + +// Translation Table as described in RFC1113 +static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +//// Translation Table to decode (created by author) +static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; + +// encode +// base64 encode a stream adding padding and line breaks as per spec. +// linesize - . linesize = 0, , +void base64_encode(TStream* infile, TStream* outfile, int linesize) +{ + unsigned char in[3]; + wchar_t out[4]; + __int64 i; + int len, blocksout = 0; + //__int64 inlenblock = infile->m_Size / 3; + __int64 inlenblock = infile->GetSize() / 3; + + infile->Seek(0i64, soBeginning); + for(i = 0; i < inlenblock; i++) + { + if(blocksout >= linesize/4 && linesize) + { + outfile->Write(L"\r\n", 4); + blocksout = 0; + } + blocksout++; + infile->Read(in, 3); + out[0] = cb64[in[0] >> 2]; + out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; + out[2] = cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)]; + out[3] = cb64[in[2] & 0x3f]; + outfile->Write(out, 8); + } + + //len = infile->Size - infile->Position; + len = infile->GetSize() - infile->GetPosition(); + if(len > 0) + { + if(blocksout >= linesize / 4 && linesize) outfile->Write(L"\r\n", 4); + in[1] = 0; + in[2] = 0; + infile->Read(in, len); + out[0] = cb64[in[0] >> 2]; + out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; + out[2] = len > 1 ? cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)] : L'='; + out[3] = len > 2 ? cb64[in[2] & 0x3f] : L'='; + outfile->Write(out, 8); + } + +} + + +// decode +// decode a base64 encoded stream discarding padding, line breaks and noise +void base64_decode(TStream* infile, TStream* outfile) +{ + unsigned char in[4], out[3], v; + wchar_t s; + int i, len; + +// infile->Seek(0i64, soBeginning); + //while(infile->Position < infile->Size) + while (infile->GetPosition() < infile->GetSize()) + { + //for(len = 0, i = 0; i < 4 && infile->Position < infile->Size; i++ ) + for (len = 0, i = 0; i < 4 && infile->GetPosition() < infile->GetSize(); i++) + { + v = 0; + while(infile->GetPosition() < infile->GetSize() && v == 0) + { + infile->Read(&s, 2); + v = (unsigned char)((s < 43 || s > 122) ? 0 : cd64[s - 43]); + if(v) v = (unsigned char)((v == '$') ? 0 : v - 61); + } + if(v) + { + in[i] = (unsigned char)(v - 1); + len++; + } + else + in[i] = 0; + } + if(len) + { + out[0] = (unsigned char) (in[0] << 2 | in[1] >> 4); + out[1] = (unsigned char) (in[1] << 4 | in[2] >> 2); + out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]); + outfile->Write(out, len - 1); + } + + } + +} + +// decode +// decode a base64 encoded stream discarding padding, line breaks and noise +void base64_decode(const String& instr, TStream* outfile, int start) +{ + unsigned char in[4], out[3], v; + wchar_t s; + //wchar_t* str; + const char* str; + int i, len, is, slen; + + slen = instr.Length(); + //slen = instr.length(); + //slen = (int)instr.Length(); + str = instr.c_str(); + is = start; + + while(is < slen) + { + for(len = 0, i = 0; i < 4 && is < slen; i++ ) + { + v = 0; + while(is < slen && v == 0) + { + s = str[is++]; + v = (unsigned char)((s < 43 || s > 122) ? 0 : cd64[s - 43]); + if(v) v = (unsigned char)((v == '$') ? 0 : v - 61); + } + if(v) + { + in[i] = (unsigned char)(v - 1); + len++; + } + else in[i] = 0; + } + if(len) + { + out[0] = (unsigned char) (in[0] << 2 | in[1] >> 4); + out[1] = (unsigned char) (in[1] << 4 | in[2] >> 2); + out[2] = (unsigned char) (((in[2] << 6) & 0xc0) | in[3]); + outfile->Write(out, len - 1); + } + + } + +} + diff --git a/src/metaread/Base64.h b/src/metaread/Base64.h new file mode 100644 index 0000000..122a158 --- /dev/null +++ b/src/metaread/Base64.h @@ -0,0 +1,14 @@ +//--------------------------------------------------------------------------- + +#ifndef Base64H +#define Base64H + + +//--------------------------------------------------------------------------- + +void base64_encode(TStream* infile, TStream* outfile, int linesize); +void base64_decode(TStream* infile, TStream* outfile); +void base64_decode(const String& instr, TStream* outfile, int start = 0); + +#endif + diff --git a/v8unpack.sln b/v8unpack.sln index 4433dae..e6ad0bf 100644 --- a/v8unpack.sln +++ b/v8unpack.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.27004.2008 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8unpack", "v8unpack.vcxproj", "{C1AA1412-5A3E-4E7A-89DD-D62C6020F779}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SystemClasses", "src\SystemClasses\SystemClasses.vcxproj", "{7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +23,14 @@ Global {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x64.Build.0 = Release|x64 {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x86.ActiveCfg = Release|Win32 {C1AA1412-5A3E-4E7A-89DD-D62C6020F779}.Release|x86.Build.0 = Release|Win32 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Debug|x64.ActiveCfg = Debug|x64 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Debug|x64.Build.0 = Debug|x64 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Debug|x86.ActiveCfg = Debug|Win32 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Debug|x86.Build.0 = Debug|Win32 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Release|x64.ActiveCfg = Release|x64 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Release|x64.Build.0 = Release|x64 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Release|x86.ActiveCfg = Release|Win32 + {7A634FA8-B3A8-4EAD-A23A-AC5B2AB88457}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/v8unpack.vcxproj b/v8unpack.vcxproj index 157b229..7ac8bfa 100644 --- a/v8unpack.vcxproj +++ b/v8unpack.vcxproj @@ -67,16 +67,21 @@ D:\zlib\bin_msvs\Debug;C:\local\boost_1_63_0\lib32-msvc-14.0;$(LibraryPath) - D:\zlib;C:\local\boost_1_63_0;$(IncludePath) - D:\zlib\bin_msvs\Debug;C:\local\boost_1_63_0\lib32-msvc-14.0;$(LibraryPath) + D:\work\repo_git\fishca_v8unpack\src\SystemClasses;D:\zlib;C:\local\boost_1_63_0;$(IncludePath) + D:\work\repo_git\fishca_v8unpack\Debug;D:\zlib\bin_msvs\Debug;C:\local\boost_1_63_0\lib32-msvc-14.0;$(LibraryPath) - + + + D:\work\repo_git\fishca_v8unpack\src\SystemClasses;%(AdditionalIncludeDirectories) + + + diff --git a/v8unpack.vcxproj.filters b/v8unpack.vcxproj.filters new file mode 100644 index 0000000..8e150ba --- /dev/null +++ b/v8unpack.vcxproj.filters @@ -0,0 +1,24 @@ + + + + + + + metaread + + + + + + + + + metaread + + + + + {67811e5c-fe00-4ca7-adff-5a7907466d33} + + + \ No newline at end of file diff --git a/v8unpack.vcxproj.user b/v8unpack.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/v8unpack.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file