├── .gitattributes ├── .gitignore ├── README.md ├── StructuredStorage.sln ├── StructuredStorage ├── CompoundFile.cpp ├── CompoundFile.h ├── CompoundFileReaderWriter.cpp ├── CompoundFileReaderWriter.h ├── ReadMe.txt ├── StructuredStorage.vcxproj ├── StructuredStorage.vcxproj.filters ├── stdafx.cpp ├── stdafx.h └── targetver.h └── StructuredStorageTests ├── StructuredStorageTests.vcxproj ├── StructuredStorageTests.vcxproj.filters ├── TestCreateAndOpen.cpp ├── stdafx.cpp ├── stdafx.h └── targetver.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StructuredStorage 2 | 3 | C++ wrapper for the Windows structured storage implementation known as Compound Files. 4 | -------------------------------------------------------------------------------- /StructuredStorage.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StructuredStorage", "StructuredStorage\StructuredStorage.vcxproj", "{A17358A2-B11B-4E9F-938F-3AB344333BAC}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StructuredStorageTests", "StructuredStorageTests\StructuredStorageTests.vcxproj", "{3A8B4A4C-2F62-4290-A478-3F05EE51EA83}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {A17358A2-B11B-4E9F-938F-3AB344333BAC} = {A17358A2-B11B-4E9F-938F-3AB344333BAC} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|x64 = Release|x64 18 | Release|x86 = Release|x86 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Debug|x64.ActiveCfg = Debug|x64 22 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Debug|x64.Build.0 = Debug|x64 23 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Debug|x86.ActiveCfg = Debug|Win32 24 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Debug|x86.Build.0 = Debug|Win32 25 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Release|x64.ActiveCfg = Release|x64 26 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Release|x64.Build.0 = Release|x64 27 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Release|x86.ActiveCfg = Release|Win32 28 | {A17358A2-B11B-4E9F-938F-3AB344333BAC}.Release|x86.Build.0 = Release|Win32 29 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Debug|x64.ActiveCfg = Debug|x64 30 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Debug|x64.Build.0 = Debug|x64 31 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Debug|x86.ActiveCfg = Debug|Win32 32 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Debug|x86.Build.0 = Debug|Win32 33 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Release|x64.ActiveCfg = Release|x64 34 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Release|x64.Build.0 = Release|x64 35 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Release|x86.ActiveCfg = Release|Win32 36 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83}.Release|x86.Build.0 = Release|Win32 37 | EndGlobalSection 38 | GlobalSection(SolutionProperties) = preSolution 39 | HideSolutionNode = FALSE 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /StructuredStorage/CompoundFile.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CompoundFile.h" 3 | 4 | using namespace std; 5 | using namespace StructuredStorage; 6 | 7 | unique_ptr CompoundFile::Create(const std::wstring & path, PSECURITY_DESCRIPTOR securityDescriptor) { 8 | CComPtr spStg; 9 | auto hr = ::StgCreateStorageEx(path.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 10 | STGFMT_STORAGE, 0, nullptr, securityDescriptor, __uuidof(IStorage), reinterpret_cast(&spStg)); 11 | if (FAILED(hr)) 12 | return nullptr; 13 | 14 | return unique_ptr(new CompoundFile(spStg)); 15 | } 16 | 17 | unique_ptr CompoundFile::Open(const std::wstring & path, CompoundFileMode mode) { 18 | CComPtr spStg; 19 | auto hr = ::StgOpenStorageEx(path.c_str(), (mode == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 20 | STGFMT_STORAGE, 0, nullptr, nullptr, __uuidof(IStorage), reinterpret_cast(&spStg)); 21 | if (FAILED(hr)) 22 | return nullptr; 23 | 24 | return unique_ptr(new CompoundFile(spStg, mode)); 25 | } 26 | 27 | unique_ptr StructuredDirectory::CreateStructuredDirectory(const std::wstring & name) { 28 | CheckNameLength(name); 29 | 30 | CComPtr spStg; 31 | auto hr = GetStorage()->CreateStorage(name.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStg); 32 | if (FAILED(hr)) 33 | return nullptr; 34 | 35 | return unique_ptr(new StructuredDirectory(spStg)); 36 | } 37 | 38 | unique_ptr StructuredDirectory::CreateStructuredFile(const std::wstring & name) { 39 | CheckNameLength(name); 40 | 41 | CComPtr spStm; 42 | auto hr = GetStorage()->CreateStream(name.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStm); 43 | if (FAILED(hr)) 44 | return nullptr; 45 | 46 | return unique_ptr(new StructuredFile(spStm)); 47 | } 48 | 49 | unique_ptr StructuredDirectory::OpenStructuredFile(const std::wstring & name) { 50 | CheckNameLength(name); 51 | 52 | CComPtr spStm; 53 | auto hr = GetStorage()->OpenStream(name.c_str(), nullptr, 54 | (GetMode() == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 0, &spStm); 55 | if (FAILED(hr)) 56 | return nullptr; 57 | 58 | return unique_ptr(new StructuredFile(spStm)); 59 | } 60 | 61 | unique_ptr StructuredDirectory::OpenStructuredDirectory(const std::wstring & name) { 62 | CheckNameLength(name); 63 | 64 | CComPtr spStg; 65 | auto hr = GetStorage()->OpenStorage(name.c_str(), nullptr, 66 | (GetMode() == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 0, 0, &spStg); 67 | if (FAILED(hr)) 68 | return nullptr; 69 | 70 | return unique_ptr(new StructuredDirectory(spStg, GetMode())); 71 | } 72 | 73 | void StructuredDirectory::Close() { 74 | m_spStorage = nullptr; 75 | } 76 | 77 | void StructuredDirectory::CheckNameLength(const std::wstring & name) const { 78 | if (name.size() > 31) 79 | throw exception("structured directory and file names must be less than 32 characters"); 80 | } 81 | 82 | void StructuredFile::Write(const void * buffer, uint32_t count) { 83 | auto hr = m_spStream->Write(buffer, count, nullptr); 84 | if (FAILED(hr)) 85 | throw ComException(hr); 86 | } 87 | 88 | void StructuredFile::Read(void * buffer, uint32_t count) { 89 | auto hr = m_spStream->Read(buffer, count, nullptr); 90 | if (FAILED(hr)) 91 | throw ComException(hr); 92 | } 93 | 94 | uint32_t StructuredFile::Seek(uint32_t offset, SeekMode mode) { 95 | LARGE_INTEGER li; 96 | li.QuadPart = offset; 97 | ULARGE_INTEGER newOffset; 98 | auto hr = m_spStream->Seek(li, static_cast(mode), &newOffset); 99 | if (FAILED(hr)) 100 | throw ComException(hr); 101 | 102 | return newOffset.LowPart; 103 | } 104 | 105 | uint32_t StructuredFile::GetSize() const { 106 | STATSTG stat = { 0 }; 107 | m_spStream->Stat(&stat, STATFLAG_NONAME); 108 | return stat.cbSize.LowPart; 109 | } 110 | 111 | void StructuredFile::Close() { 112 | m_spStream = nullptr; 113 | } 114 | -------------------------------------------------------------------------------- /StructuredStorage/CompoundFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace StructuredStorage { 9 | enum class CompoundFileMode { 10 | Read, 11 | ReadWrite 12 | }; 13 | 14 | enum class SeekMode { 15 | Set, 16 | Current, 17 | End 18 | }; 19 | 20 | struct ComException : std::exception { 21 | ComException(HRESULT hr) : HResult(hr) { 22 | } 23 | 24 | HRESULT HResult; 25 | }; 26 | 27 | class StructuredFile { 28 | friend class StructuredDirectory; 29 | 30 | public: 31 | void Write(const void* buffer, uint32_t count); 32 | void Read(void* buffer, uint32_t count); 33 | 34 | uint32_t Seek(uint32_t offset, SeekMode mode = SeekMode::Set); 35 | 36 | uint32_t GetSize() const; 37 | 38 | void Close(); 39 | 40 | private: 41 | StructuredFile(IStream* pStm) : m_spStream(pStm) {} 42 | 43 | CComPtr m_spStream; 44 | }; 45 | 46 | class StructuredDirectory { 47 | public: 48 | std::unique_ptr CreateStructuredDirectory(const std::wstring& name); 49 | std::unique_ptr CreateStructuredFile(const std::wstring& name); 50 | std::unique_ptr OpenStructuredDirectory(const std::wstring& name); 51 | std::unique_ptr OpenStructuredFile(const std::wstring& name); 52 | 53 | void Close(); 54 | 55 | ~StructuredDirectory() { 56 | Close(); 57 | } 58 | 59 | CompoundFileMode GetMode() const { 60 | return m_FileMode; 61 | } 62 | 63 | protected: 64 | IStorage* GetStorage() const { 65 | return m_spStorage.p; 66 | } 67 | 68 | StructuredDirectory(IStorage* pStg, CompoundFileMode mode = CompoundFileMode::ReadWrite) : m_spStorage(pStg), m_FileMode(mode) { 69 | } 70 | 71 | void CheckNameLength(const std::wstring& name) const; 72 | 73 | private: 74 | CComPtr m_spStorage; 75 | CompoundFileMode m_FileMode; 76 | }; 77 | 78 | class CompoundFile : public StructuredDirectory { 79 | public: 80 | // factory methods 81 | 82 | static std::unique_ptr Create(const std::wstring& path, PSECURITY_DESCRIPTOR securityDescriptor = nullptr); 83 | static std::unique_ptr Open(const std::wstring& path, CompoundFileMode mode = CompoundFileMode::Read); 84 | 85 | // ctors 86 | 87 | CompoundFile(const CompoundFile&) = delete; 88 | CompoundFile& operator=(const CompoundFile&) = delete; 89 | 90 | private: 91 | CompoundFile(IStorage* pStg, CompoundFileMode mode = CompoundFileMode::ReadWrite) : StructuredDirectory(pStg, mode) {} 92 | 93 | }; 94 | } -------------------------------------------------------------------------------- /StructuredStorage/CompoundFileReaderWriter.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CompoundFileReaderWriter.h" 3 | 4 | using namespace std; 5 | using namespace StructuredStorage; 6 | 7 | CompoundFileReaderWriter::CompoundFileReaderWriter(StructuredFile& file) : m_File(file) { 8 | } 9 | 10 | void CompoundFileReaderWriter::Write(const std::wstring & value) { 11 | auto len = static_cast(value.size()); 12 | m_File.Write(&len, sizeof(len)); 13 | m_File.Write(value.c_str(), len * sizeof(wchar_t)); 14 | } 15 | 16 | void CompoundFileReaderWriter::Read(std::wstring & value) { 17 | uint32_t len; 18 | m_File.Read(&len, sizeof(len)); 19 | auto buffer = make_unique(len); 20 | m_File.Read(buffer.get(), len * 2); 21 | value.assign(buffer.get(), len); 22 | } 23 | 24 | void CompoundFileReaderWriter::Write(const std::string & value) { 25 | auto len = static_cast(value.size()); 26 | m_File.Write(&len, sizeof(len)); 27 | m_File.Write(value.c_str(), len * sizeof(char)); 28 | } 29 | 30 | void CompoundFileReaderWriter::Read(std::string & value) { 31 | uint32_t len; 32 | m_File.Read(&len, sizeof(len)); 33 | auto buffer = make_unique(len); 34 | m_File.Read(buffer.get(), len); 35 | value.assign(buffer.get(), len); 36 | } 37 | -------------------------------------------------------------------------------- /StructuredStorage/CompoundFileReaderWriter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "CompoundFile.h" 7 | 8 | namespace StructuredStorage { 9 | class CompoundFileReaderWriter { 10 | public: 11 | CompoundFileReaderWriter(StructuredFile& file); 12 | 13 | template 14 | void Write(const T& value) { 15 | static_assert(std::is_pod(), "T must be POD"); 16 | 17 | m_File.Write(&value, sizeof(value)); 18 | } 19 | 20 | template 21 | void Read(T& value) { 22 | static_assert(std::is_pod() , "T must be POD"); 23 | 24 | m_File.Read(&value, sizeof(value)); 25 | } 26 | 27 | void Write(const std::wstring& value); 28 | void Read(std::wstring& value); 29 | void Write(const std::string& value); 30 | void Read(std::string& value); 31 | 32 | template 33 | void Write(const std::vector& vec) { 34 | auto count = static_cast(vec.size()); 35 | Write(count); 36 | if (std::is_pod::value) { 37 | m_File.Write(vec.data(), count * sizeof(T)); 38 | } 39 | else { 40 | for (const auto& item : vec) 41 | Write(item); 42 | } 43 | } 44 | 45 | template 46 | void Read(std::vector& vec) { 47 | uint32_t count; 48 | Read(count); 49 | if (count == 0) { 50 | vec.clear(); 51 | return; 52 | } 53 | 54 | vec.resize(count); 55 | if (std::is_pod::value) { 56 | m_File.Read(vec.data(), count * sizeof(T)); 57 | } 58 | else { 59 | for (uint32_t i = 0; i < count; ++i) { 60 | T value; 61 | Read(value); 62 | vec[i] = value; 63 | } 64 | } 65 | } 66 | 67 | template 68 | void Write(const std::pair& pair) { 69 | Write(pair.first); 70 | Write(pair.second); 71 | } 72 | 73 | template 74 | void Read(std::pair& pair) { 75 | Read(pair.first); 76 | Read(pair.second); 77 | } 78 | 79 | template 80 | void Write(const std::map& map) { 81 | Write(static_cast(map.size())); 82 | for (const auto& pair : map) 83 | Write(pair); 84 | } 85 | 86 | template 87 | void Read(std::map& map) { 88 | uint32_t count; 89 | Read(count); 90 | for (uint32_t i = 0; i < count; i++) { 91 | std::pair pair; 92 | Read(pair); 93 | map.insert(pair); 94 | } 95 | } 96 | 97 | private: 98 | StructuredFile& m_File; 99 | }; 100 | 101 | } 102 | -------------------------------------------------------------------------------- /StructuredStorage/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | STATIC LIBRARY : StructuredStorage Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this StructuredStorage library project for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your StructuredStorage application. 9 | 10 | 11 | StructuredStorage.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | StructuredStorage.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | 25 | ///////////////////////////////////////////////////////////////////////////// 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named StructuredStorage.pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /StructuredStorage/StructuredStorage.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {A17358A2-B11B-4E9F-938F-3AB344333BAC} 23 | Win32Proj 24 | StructuredStorage 25 | 10.0 26 | 27 | 28 | 29 | StaticLibrary 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | StaticLibrary 36 | false 37 | v142 38 | true 39 | Unicode 40 | 41 | 42 | StaticLibrary 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | StaticLibrary 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Use 76 | Level3 77 | Disabled 78 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 79 | true 80 | 81 | 82 | Windows 83 | 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | _DEBUG;_LIB;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Windows 95 | 96 | 97 | 98 | 99 | Level3 100 | Use 101 | MaxSpeed 102 | true 103 | true 104 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Windows 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | 116 | Level3 117 | Use 118 | MaxSpeed 119 | true 120 | true 121 | NDEBUG;_LIB;%(PreprocessorDefinitions) 122 | true 123 | 124 | 125 | Windows 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | Create 144 | Create 145 | Create 146 | Create 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /StructuredStorage/StructuredStorage.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /StructuredStorage/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // StructuredStorage.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /StructuredStorage/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | 12 | #include 13 | -------------------------------------------------------------------------------- /StructuredStorage/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /StructuredStorageTests/StructuredStorageTests.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3A8B4A4C-2F62-4290-A478-3F05EE51EA83} 23 | Win32Proj 24 | StructuredStorageTests 25 | 10.0 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v142 32 | Unicode 33 | false 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | false 42 | 43 | 44 | DynamicLibrary 45 | true 46 | v142 47 | Unicode 48 | false 49 | 50 | 51 | DynamicLibrary 52 | false 53 | v142 54 | true 55 | Unicode 56 | false 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | true 78 | 79 | 80 | true 81 | 82 | 83 | true 84 | 85 | 86 | true 87 | 88 | 89 | 90 | Use 91 | Level3 92 | Disabled 93 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 94 | WIN32;_DEBUG;%(PreprocessorDefinitions) 95 | true 96 | 97 | 98 | Windows 99 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 100 | 101 | 102 | 103 | 104 | Use 105 | Level3 106 | Disabled 107 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 108 | _DEBUG;%(PreprocessorDefinitions) 109 | true 110 | 111 | 112 | Windows 113 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 114 | 115 | 116 | 117 | 118 | Level3 119 | Use 120 | MaxSpeed 121 | true 122 | true 123 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 124 | WIN32;NDEBUG;%(PreprocessorDefinitions) 125 | true 126 | 127 | 128 | Windows 129 | true 130 | true 131 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 132 | 133 | 134 | 135 | 136 | Level3 137 | Use 138 | MaxSpeed 139 | true 140 | true 141 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 142 | NDEBUG;%(PreprocessorDefinitions) 143 | true 144 | 145 | 146 | Windows 147 | true 148 | true 149 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | Create 159 | Create 160 | Create 161 | Create 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /StructuredStorageTests/StructuredStorageTests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /StructuredStorageTests/TestCreateAndOpen.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "CppUnitTest.h" 3 | #include "..\StructuredStorage\CompoundFile.h" 4 | #include "..\StructuredStorage\CompoundFileReaderWriter.h" 5 | 6 | #ifdef _DEBUG 7 | #ifdef _WIN64 8 | #pragma comment(lib, "..\\x64\\Debug\\StructuredStorage.lib") 9 | #else 10 | #pragma comment(lib, "..\\Debug\\StructuredStorage.lib") 11 | #endif 12 | #else 13 | #ifdef _WIN64 14 | #pragma comment(lib, "..\\x64\\Release\\StructuredStorage.lib") 15 | #else 16 | #pragma comment(lib, "..\\Release\\StructuredStorage.lib") 17 | #endif 18 | #endif 19 | 20 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 21 | using namespace StructuredStorage; 22 | 23 | namespace StructuredStorageTests { 24 | TEST_CLASS(TestCreateAndOpen) { 25 | public: 26 | 27 | TEST_METHOD(CreateAndOpen) { 28 | auto path = L"g:\\temp\\file1.bin"; 29 | auto file = CompoundFile::Create(path); 30 | Assert::IsNotNull(file.get()); 31 | 32 | auto dir = file->CreateStructuredDirectory(L"Cactus"); 33 | Assert::IsNotNull(dir.get()); 34 | 35 | dir->Close(); 36 | file->Close(); 37 | 38 | file = CompoundFile::Open(path); 39 | Assert::IsNotNull(file.get()); 40 | 41 | dir = file->OpenStructuredDirectory(L"Cactus"); 42 | Assert::IsNotNull(dir.get()); 43 | } 44 | 45 | TEST_METHOD(WriteAndRead) { 46 | auto path = L"g:\\temp\\file1.bin"; 47 | auto file = CompoundFile::Create(path); 48 | auto ssfile = file->CreateStructuredFile(L"IntValue"); 49 | CompoundFileReaderWriter writer(*ssfile.get()); 50 | writer.Write(0x1234abcd); 51 | 52 | auto vfile = file->CreateStructuredFile(L"Vector"); 53 | std::vector vec; 54 | for (int i = 0; i < 10; i++) 55 | vec.push_back(i * i); 56 | 57 | CompoundFileReaderWriter writer2(*vfile.get()); 58 | writer2.Write(vec); 59 | 60 | { 61 | auto mfile = file->CreateStructuredFile(L"Map"); 62 | std::map m; 63 | m.insert(std::make_pair(L"one", 1)); 64 | m.insert(std::make_pair(L"five", 5)); 65 | m.insert(std::make_pair(L"ten", 10)); 66 | m.insert(std::make_pair(L"twelve", 12)); 67 | m.insert(std::make_pair(L"zero", 0)); 68 | 69 | CompoundFileReaderWriter writer3(*mfile.get()); 70 | writer3.Write(m); 71 | } 72 | 73 | vfile->Close(); 74 | ssfile->Close(); 75 | file->Close(); 76 | 77 | file = CompoundFile::Open(path); 78 | ssfile = file->OpenStructuredFile(L"IntValue"); 79 | CompoundFileReaderWriter reader(*ssfile.get()); 80 | int value; 81 | reader.Read(value); 82 | Assert::IsTrue(value == 0x1234abcd); 83 | 84 | vfile = file->OpenStructuredFile(L"Vector"); 85 | vec.clear(); 86 | CompoundFileReaderWriter reader2(*vfile.get()); 87 | reader2.Read(vec); 88 | Assert::IsTrue(10 == vec.size()); 89 | 90 | auto mfile = file->OpenStructuredFile(L"Map"); 91 | std::map m; 92 | CompoundFileReaderWriter reader3(*mfile.get()); 93 | reader3.Read(m); 94 | 95 | Assert::IsTrue(m.size() == 5); 96 | Assert::IsTrue(m[L"zero"] == 0); 97 | Assert::IsTrue(m[L"ten"] == 10); 98 | Assert::IsTrue(m[L"five"] == 5); 99 | Assert::IsTrue(m[L"twelve"] == 12); 100 | 101 | } 102 | }; 103 | } -------------------------------------------------------------------------------- /StructuredStorageTests/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // StructuredStorageTests.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /StructuredStorageTests/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | // Headers for CppUnitTest 11 | #include "CppUnitTest.h" 12 | 13 | // TODO: reference additional headers your program requires here 14 | -------------------------------------------------------------------------------- /StructuredStorageTests/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | --------------------------------------------------------------------------------