(outputLayout.size()) * sizeof (Vst2::VstSpeakerArrangement)), 1);
*pluginInput = cachedInArrangement. getData();
*pluginOutput = cachedOutArrangement.getData();
@@ -2116,7 +2133,7 @@ private:
{
if (processor != nullptr)
{
- processor->setProcessingPrecision ((args.value == vstProcessingSampleTypeDouble
+ processor->setProcessingPrecision ((args.value == Vst2::kVstProcessPrecision64
&& processor->supportsDoublePrecisionProcessing())
? AudioProcessor::doublePrecision
: AudioProcessor::singlePrecision);
@@ -2196,7 +2213,7 @@ private:
//==============================================================================
namespace
{
- VstEffectInterface* pluginEntryPoint (VstHostCallback audioMaster)
+ Vst2::AEffect* pluginEntryPoint (Vst2::audioMasterCallback audioMaster)
{
JUCE_AUTORELEASEPOOL
{
@@ -2204,7 +2221,7 @@ namespace
try
{
- if (audioMaster (0, hostOpcodeVstVersion, 0, 0, 0, 0) != 0)
+ if (audioMaster (0, Vst2::audioMasterVersion, 0, 0, 0, 0) != 0)
{
#if JUCE_LINUX
MessageManagerLock mmLock;
@@ -2212,7 +2229,7 @@ namespace
auto* processor = createPluginFilterOfType (AudioProcessor::wrapperType_VST);
auto* wrapper = new JuceVSTWrapper (audioMaster, processor);
- return wrapper->getVstEffectInterface();
+ return wrapper->getAEffect();
}
}
catch (...)
@@ -2231,8 +2248,8 @@ namespace
// Mac startup code..
#if JUCE_MAC
- JUCE_EXPORTED_FUNCTION VstEffectInterface* VSTPluginMain (VstHostCallback audioMaster);
- JUCE_EXPORTED_FUNCTION VstEffectInterface* VSTPluginMain (VstHostCallback audioMaster)
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster);
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
@@ -2240,8 +2257,8 @@ namespace
return pluginEntryPoint (audioMaster);
}
- JUCE_EXPORTED_FUNCTION VstEffectInterface* main_macho (VstHostCallback audioMaster);
- JUCE_EXPORTED_FUNCTION VstEffectInterface* main_macho (VstHostCallback audioMaster)
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_macho (Vst2::audioMasterCallback audioMaster);
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_macho (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
@@ -2253,8 +2270,8 @@ namespace
// Linux startup code..
#elif JUCE_LINUX
- JUCE_EXPORTED_FUNCTION VstEffectInterface* VSTPluginMain (VstHostCallback audioMaster);
- JUCE_EXPORTED_FUNCTION VstEffectInterface* VSTPluginMain (VstHostCallback audioMaster)
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster);
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
@@ -2262,8 +2279,8 @@ namespace
return pluginEntryPoint (audioMaster);
}
- JUCE_EXPORTED_FUNCTION VstEffectInterface* main_plugin (VstHostCallback audioMaster) asm ("main");
- JUCE_EXPORTED_FUNCTION VstEffectInterface* main_plugin (VstHostCallback audioMaster)
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_plugin (Vst2::audioMasterCallback audioMaster) asm ("main");
+ JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_plugin (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
@@ -2278,7 +2295,7 @@ namespace
// Win32 startup code..
#else
- extern "C" __declspec (dllexport) VstEffectInterface* VSTPluginMain (VstHostCallback audioMaster)
+ extern "C" __declspec (dllexport) Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
@@ -2286,7 +2303,7 @@ namespace
}
#ifndef JUCE_64BIT // (can't compile this on win64, but it's not needed anyway with VST2.4)
- extern "C" __declspec (dllexport) int main (VstHostCallback audioMaster)
+ extern "C" __declspec (dllexport) int main (Vst2::audioMasterCallback audioMaster)
{
PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;
diff --git a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
index 89b2f21ea0..5c2c5ba2c6 100644
--- a/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
+++ b/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
@@ -50,7 +50,10 @@
#endif
#if JUCE_VST3_CAN_REPLACE_VST2
-#include "../../juce_audio_processors/format_types/juce_VSTInterface.h"
+namespace Vst2
+{
+#include "../../juce_audio_processors/format_types/VST3_SDK/pluginterfaces/vst2.x/vstfxstore.h"
+}
#endif
#ifndef JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS
@@ -1440,16 +1443,16 @@ public:
bool loadVST2CcnKBlock (const char* data, int size)
{
- auto bank = (const vst2FxBank*) data;
+ auto bank = (const Vst2::fxBank*) data;
- jassert ('CcnK' == htonl (bank->magic1));
- jassert ('FBCh' == htonl (bank->magic2));
- jassert (htonl (bank->version1) == 1 || htonl (bank->version1) == 2);
+ jassert ('CcnK' == htonl (bank->chunkMagic));
+ jassert ('FBCh' == htonl (bank->fxMagic));
+ jassert (htonl (bank->version) == 1 || htonl (bank->version) == 2);
jassert (JucePlugin_VSTUniqueID == htonl (bank->fxID));
- setStateInformation (bank->chunk,
- jmin ((int) (size - (bank->chunk - data)),
- (int) htonl (bank->chunkSize)));
+ setStateInformation (bank->content.data.chunk,
+ jmin ((int) (size - (bank->content.data.chunk - data)),
+ (int) htonl (bank->content.data.size)));
return true;
}
@@ -1642,16 +1645,16 @@ public:
return status;
const int bankBlockSize = 160;
- vst2FxBank bank;
+ Vst2::fxBank bank;
zerostruct (bank);
- bank.magic1 = (int32) htonl ('CcnK');
- bank.size = (int32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
- bank.magic2 = (int32) htonl ('FBCh');
- bank.version1 = (int32) htonl (2);
- bank.fxID = (int32) htonl (JucePlugin_VSTUniqueID);
- bank.version2 = (int32) htonl (JucePlugin_VersionCode);
- bank.chunkSize = (int32) htonl ((unsigned int) mem.getSize());
+ bank.chunkMagic = (int32) htonl ('CcnK');
+ bank.byteSize = (int32) htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
+ bank.fxMagic = (int32) htonl ('FBCh');
+ bank.version = (int32) htonl (2);
+ bank.fxID = (int32) htonl (JucePlugin_VSTUniqueID);
+ bank.fxVersion = (int32) htonl (JucePlugin_VersionCode);
+ bank.content.data.size = (int32) htonl ((unsigned int) mem.getSize());
status = state->write (&bank, bankBlockSize);
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/LICENSE.txt b/modules/juce_audio_processors/format_types/VST3_SDK/LICENSE.txt
new file mode 100644
index 0000000000..c653a2ef70
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/LICENSE.txt
@@ -0,0 +1,41 @@
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+This license applies only to files referencing this license,
+for other files of the Software Development Kit the respective embedded license text
+is applicable. The license can be found at: www.steinberg.net/sdklicenses_vst3
+
+This Software Development Kit is licensed under the terms of the Steinberg VST3 License,
+or alternatively under the terms of the General Public License (GPL) Version 3.
+You may use the Software Development Kit according to either of these licenses as it is
+most appropriate for your project on a case-by-case basis (commercial or not).
+
+a) Proprietary Steinberg VST3 License
+The Software Development Kit may not be distributed in parts or its entirety
+without prior written agreement by Steinberg Media Technologies GmbH.
+The SDK must not be used to re-engineer or manipulate any technology used
+in any Steinberg or Third-party application or software module,
+unless permitted by law.
+Neither the name of the Steinberg Media Technologies GmbH nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+Before publishing a software under the proprietary license, you need to obtain a copy
+of the License Agreement signed by Steinberg Media Technologies GmbH.
+The Steinberg VST SDK License Agreement can be found at:
+www.steinberg.net/en/company/developers.html
+
+THE SDK IS PROVIDED BY STEINBERG MEDIA TECHNOLOGIES GMBH "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL STEINBERG MEDIA TECHNOLOGIES GMBH BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+b) General Public License (GPL) Version 3
+Details of these licenses can be found at: www.gnu.org/licenses/gpl-3.0.html
+//----------------------------------------------------------------------------------
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/README.md b/modules/juce_audio_processors/format_types/VST3_SDK/README.md
new file mode 100644
index 0000000000..f208d870ca
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/README.md
@@ -0,0 +1,153 @@
+# Welcome to VST SDK 3.6.9
+
+## Table Of Contents
+1. [The VST SDK package](#100)
+1. [System requirements](#200)
+1. [About VST Plug-ins in general](#300)
+1. [About VST 3](#400)
+1. [How to build VST 3](#How_to_build_VST_3)
+1. [License & Usage guidelines](#license_&_usage_guidelines)
+
+
+
+## The VST SDK package contains:
+- The VST 3 API
+- VST 3 Implementation Helper Classes
+- AAX, AU and VST 2 wrappers
+- VST 3 Plug-ins Examples
+
+The full VST 3 SDK is available [here!](https://www.steinberg.net/en/company/developers.html). It contains a VST 3 Plug-in Test Host Application/Validator.
+
+
+
+## System requirements
+
+Supported OS:
+
+- Microsoft Windows 7-10
+- Apple OSX 10.7-10.13
+- Apple iOS 8-9
+- Linux (Beta version)
+
+Supported IDE:
+- Visual Studio 2015/2017
+- minimum Xcode 7
+- Qt Creator
+
+---
+
+
+## About VST Plug-ins in general
+A VST Plug-in is an audio processing component that is utilized within a host application. This host application provides the audio or/and event streams that are processed by the Plug-in's code. Generally speaking, a VST Plug-in can take a stream of audio data, apply a process to the audio, and return the result to the host application. A VST Plug-in performs its process normally using the processor of the computer. The audio stream is broken down into a series of blocks. The host supplies the blocks in sequence. The host and its current environment control the block-size. The VST Plug-in maintains the status of all its own parameters relating to the running process: The host does not maintain any information about what the Plug-in did with the last block of data it processed.
+
+From the host application's point of view, a VST Plug-in is a black box with an arbitrary number of inputs, outputs (Event (MIDI) or Audio), and associated parameters. The host needs no implicit knowledge of the Plug-in's process to be able to use it. The Plug-in process can use whatever parameters it wishes, internally to the process, but depending on the capabilities of the host, it can allow the changes to user parameters to be automated by the host.
+
+The source code of a VST Plug-in is platform independent, but the delivery system depends on the platform architecture:
+- On **Windows**, a VST Plug-in is a multi-threaded DLL (Dynamic Link Library).
+- On **Mac OS X**, a VST Plug-in is a Mach-O Bundle
+- On **Linux**, a VST Plug-in is a package
+
+To learn more about VST you can subscribe to the [VST Developer Forum](https://sdk.steinberg.net) - check the 3rd Party Developer Support section at [www.steinberg.net](http://www.steinberg.net).
+
+ ---
+
+
+## About VST 3
+VST 3 is a general rework of the long-serving VST Plug-in interface. It is not compatible with the older VST versions, but it includes some new features and possibilities. We have redesigned the API to make it not only far easier and more reliable for developers to work with, but have also provided completely new possibilities for Plug-ins. These include:
+
+### 1. Improved Performance with the Silence Flag
+Processing can optionally be applied to Plug-ins only when audio signals are present on their respective inputs, so VST 3 Plug-ins can apply their processing economically and only when it is needed.
+
+### 2. Multiple Dynamic I/Os
+VST 3 Plug-ins are no longer limited to a fixed number of inputs and outputs, and their I/O configuration can dynamically adapt to the channel configuration. Side-chains are also very easily realizable. This includes the possibility to deactivate unused buses after loading and even reactivate those when needed. This cleans up the mixer and further helps to reduce CPU load.
+
+### 3. Sample-accurate Automation
+VST 3 also features vastly improved parameter automation with sample accuracy and support for ramped automation data, allowing completely accurate and rapid parameter automation changes.
+
+### 4. Logical Parameter Organization
+The VST 3 Plug-in parameters are displayed in a tree structure. Parameters are grouped into sections which represent the structure of the Plug-in. Plug-ins can communicate their internal structure for the purpose of overview, but also for some associated functionality (eg. program-lists).
+
+### 5. Resizeable UI Editor
+VST 3 defines a way to allow resizing of the Plug-in editor by a user.
+
+### 6. Mouse Over Support
+The Host could ask the Plug-in which parameter is under the mouse.
+
+### 7. Context Menu Support
+VST 3 defines a way to allow the host to add its own entries in the Plug-in context menu of a specific parameter.
+
+### 8. Channel Context Information
+A VST 3 Plug-in could access some channel information where it is instantiated: name, color,...
+
+### 9. Note Expression
+VST 3 defines with Note Expression a new way of event controller editing. The Plug-in is able to break free from the limitations of MIDI controller events by providing access to new VST 3 controller events that circumvent the laws of MIDI and provide articulation information for each individual note (event) in a polyphonic arrangement according to its noteId.
+
+### 10. 3D Support
+VST 3 supports new speaker configurations like Ambisonic, Atmos, Auro 3D or 22.2.
+
+### 11. Factory Concept
+VST 3 Plug-in library could export multiple Plug-ins and in this way replaces the shell concept of VST 2 (kPlugCategShell).
+
+### 12. Support Remote control Representation
+VST 3 Plug-in can deliver a specific parameter mapping for remote controls like Nuage.
+
+### 13. Others
+While designing VST 3, we performed a careful analysis of the existing functionality of VST and rewrote the interfaces from scratch. In doing so, we focused a lot on providing clear interfaces and their documentation in order to avoid usage errors from the deepest possible layer.
+Some more features implemented specifically for developers include:
+- More stable technical Host/Plug-in environment
+- Advanced technical definition of the standard
+- Modular approach
+- Separation of UI and processing
+- Advanced Preset System
+- Multiple Plug-ins per Library
+- Test Host included
+- Automated Testing Environment
+- Validator (small command line Test Host) and Plug-in examples code included
+
+---
+
+
+## How to build
+
+### Get the source code from GitHub
+git clone --recursive https://github.com/steinbergmedia/vst3sdk.git
+
+
+### Build the examples on Linux
+
+mkdir build
+cd build
+cmake ../vst3sdk
+make (or alternatively cmake --build .)
+
+
+### Build the examples on macOS
+
+mkdir build
+cd build
+cmake -GXcode ../vst3sdk
+xcodebuild (or alternatively cmake --build .)
+
+
+### Build the examples on Windows
+
+mkdir build
+cd build
+cmake.exe -G"Visual Studio 15 2017 Win64" ../vst3sdk
+msbuild.exe vstsdk.sln (or alternatively cmake --build .)
+
+
+### Build using cmake-gui
+
+* start the cmake-gui Application
+* "Browse Source...": select the folder VST3_SDK
+* "Browse Build...": select a folder where the outputs (projects/...) will be created. Typically a folder named "build"
+* you can check the SMTG Options
+* Press "Configure"
+* Press "Generate" and the project will be created
+
+
+---
+
+## License & Usage guidelines
+More details are found at [www.steinberg.net/sdklicenses_vst3](http://www.steinberg.net/sdklicenses_vst3)
\ No newline at end of file
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/LICENSE.txt b/modules/juce_audio_processors/format_types/VST3_SDK/base/LICENSE.txt
new file mode 100644
index 0000000000..1f195a9088
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/LICENSE.txt
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/baseiids.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/baseiids.cpp
new file mode 100644
index 0000000000..09dcfb0cae
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/baseiids.cpp
@@ -0,0 +1,52 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/baseidds.cpp
+// Created by : Steinberg, 01/2008
+// Description : Basic Interface
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "pluginterfaces/base/funknown.h"
+#include "pluginterfaces/base/istringresult.h"
+#include "pluginterfaces/base/ipersistent.h"
+
+
+namespace Steinberg {
+
+DEF_CLASS_IID (IString)
+DEF_CLASS_IID (IStringResult)
+
+DEF_CLASS_IID (IPersistent)
+DEF_CLASS_IID (IAttributes)
+DEF_CLASS_IID (IAttributes2)
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/classfactoryhelpers.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/classfactoryhelpers.h
new file mode 100644
index 0000000000..f331dedbb4
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/classfactoryhelpers.h
@@ -0,0 +1,87 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/classfactoryhelpers.h
+// Created by : Steinberg, 03/2017
+// Description : Class factory
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+//------------------------------------------------------------------------------
+// Helper Macros. Not intended for direct use.
+// Use:
+// META_CLASS(className),
+// META_CLASS_IFACE(className,Interface),
+// META_CLASS_SINGLE(className,Interface)
+// instead.
+//------------------------------------------------------------------------------
+#define META_CREATE_FUNC(funcName) static FUnknown* funcName ()
+
+#define CLASS_CREATE_FUNC(className) \
+ namespace Meta { \
+ META_CREATE_FUNC (make##className) { return (NEW className)->unknownCast (); } \
+ }
+
+#define SINGLE_CREATE_FUNC(className) \
+ namespace Meta { \
+ META_CREATE_FUNC (make##className) { return className::instance ()->unknownCast (); } \
+ }
+
+#define _META_CLASS(className) \
+ namespace Meta { \
+ static Steinberg::MetaClass meta##className ((#className), Meta::make##className); \
+ }
+
+#define _META_CLASS_IFACE(className, Interface) \
+ namespace Meta { \
+ static Steinberg::MetaClass meta##Interface##className ((#className), Meta::make##className, \
+ Interface##_iid); \
+ }
+
+/** TODO
+ */
+#define META_CLASS(className) \
+ CLASS_CREATE_FUNC (className) \
+ _META_CLASS (className)
+
+/** TODO
+ */
+#define META_CLASS_IFACE(className, Interface) \
+ CLASS_CREATE_FUNC (className) \
+ _META_CLASS_IFACE (className, Interface)
+
+/** TODO
+ */
+#define META_CLASS_SINGLE(className, Interface) \
+ SINGLE_CREATE_FUNC (className) \
+ _META_CLASS_IFACE (className, Interface)
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.cpp
new file mode 100644
index 0000000000..8de06dac98
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.cpp
@@ -0,0 +1,644 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fbuffer.cpp
+// Created by : Steinberg, 2008
+// Description :
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "base/source/fbuffer.h"
+#include "base/source/fstring.h"
+#include
+
+namespace Steinberg {
+
+//-------------------------------------------------------------------------------------
+Buffer::Buffer ()
+: buffer (0)
+, memSize (0)
+, fillSize (0)
+, delta (defaultDelta)
+{}
+
+//-------------------------------------------------------------------------------------
+Buffer::Buffer (uint32 s, uint8 initVal)
+: buffer (0)
+, memSize (s)
+, fillSize (0)
+, delta (defaultDelta)
+{
+ if (memSize == 0)
+ return;
+ buffer = (int8*)::malloc (memSize);
+ if (buffer)
+ memset (buffer, initVal, memSize);
+ else
+ memSize = 0;
+}
+
+//-------------------------------------------------------------------------------------
+Buffer::Buffer (uint32 s)
+: buffer (0)
+, memSize (s)
+, fillSize (0)
+, delta (defaultDelta)
+{
+ if (memSize == 0)
+ return;
+ buffer = (int8*)::malloc (memSize);
+ if (!buffer)
+ memSize = 0;
+}
+
+//-------------------------------------------------------------------------------------
+Buffer::Buffer (const void* b , uint32 s)
+: buffer (0)
+, memSize (s)
+, fillSize (s)
+, delta (defaultDelta)
+{
+ if (memSize == 0)
+ return;
+ buffer = (int8*)::malloc (memSize);
+ if (buffer)
+ memcpy (buffer, b, memSize);
+ else
+ {
+ memSize = 0;
+ fillSize = 0;
+ }
+}
+
+//-------------------------------------------------------------------------------------
+Buffer::Buffer (const Buffer& bufferR)
+: buffer (0)
+, memSize (bufferR.memSize)
+, fillSize (bufferR.fillSize)
+, delta (bufferR.delta)
+{
+ if (memSize == 0)
+ return;
+
+ buffer = (int8*)::malloc (memSize);
+ if (buffer)
+ memcpy (buffer, bufferR.buffer, memSize);
+ else
+ memSize = 0;
+}
+
+//-------------------------------------------------------------------------------------
+Buffer::~Buffer ()
+{
+ if (buffer)
+ ::free (buffer);
+ buffer = 0;
+}
+
+//-------------------------------------------------------------------------------------
+void Buffer::operator = (const Buffer& b2)
+{
+ if (&b2 != this)
+ {
+ setSize (b2.memSize);
+ if (b2.memSize > 0 && buffer)
+ memcpy (buffer, b2.buffer, b2.memSize);
+ fillSize = b2.fillSize;
+ delta = b2.delta;
+ }
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::operator == (const Buffer& b2)const
+{
+ if (&b2 == this)
+ return true;
+ if (b2.getSize () != getSize ())
+ return false;
+ return memcmp (this->int8Ptr (), b2.int8Ptr (), getSize ()) == 0 ? true : false;
+}
+
+//-------------------------------------------------------------------------------------
+uint32 Buffer::get (void* b, uint32 size)
+{
+ uint32 maxGet = memSize - fillSize;
+ if (size > maxGet)
+ size = maxGet;
+ if (size > 0)
+ memcpy (b, buffer + fillSize, size);
+ fillSize += size;
+ return size;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::put (char16 c)
+{
+ return put ((const void*)&c, sizeof (c));
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::put (uint8 byte)
+{
+ if (grow (fillSize + 1) == false)
+ return false;
+
+ buffer [fillSize++] = byte;
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::put (char c)
+{
+ if (grow (fillSize + 1) == false)
+ return false;
+
+ buffer [fillSize++] = c;
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::put (const void* toPut, uint32 s)
+{
+ if (!toPut)
+ return false;
+
+ if (grow (fillSize + s) == false)
+ return false;
+
+ memcpy (buffer + fillSize, toPut, s);
+ fillSize += s;
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::put (const String& str)
+{
+ return put ((const void*)str.text () , (str.length () + 1) * sizeof (tchar));
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::appendString8 (const char8* s)
+{
+ if (!s)
+ return false;
+
+ uint32 len = (uint32) strlen (s);
+ return put (s, len);
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::appendString16 (const char16* s)
+{
+ if (!s)
+ return false;
+ ConstString str (s);
+ uint32 len = (uint32) str.length () * sizeof (char16);
+ return put (s, len);
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::prependString8 (const char8* s)
+{
+ if (!s)
+ return false;
+
+ uint32 len = (uint32) strlen (s);
+
+ if (len > 0)
+ {
+ shiftStart (len);
+ memcpy (buffer, s, len);
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::prependString16 (const char16* s)
+{
+ if (!s)
+ return false;
+
+ ConstString str (s);
+ uint32 len = (uint32) str.length () * sizeof (char16);
+
+ if (len > 0)
+ {
+ shiftStart (len);
+ memcpy (buffer, s, len);
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::prependString8 (char8 c)
+{
+ shiftStart (sizeof (char));
+ char* b = (char*)buffer;
+ b [0] = c;
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::prependString16 (char16 c)
+{
+ shiftStart (sizeof (char16));
+ char16* b = (char16*)buffer;
+ b [0] = c;
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::copy (uint32 from, uint32 to, uint32 bytes)
+{
+ if (from + bytes > memSize || bytes == 0)
+ return false;
+
+ if (to + bytes > memSize)
+ setSize (to + bytes);
+
+ if (from + bytes > to && from < to)
+ { // overlap
+ Buffer tmp (buffer + from, bytes);
+ memcpy (buffer + to, tmp, bytes);
+ }
+ else
+ memcpy (buffer + to, buffer + from, bytes);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::makeHexString (String& result)
+{
+ unsigned char* data = uint8Ptr ();
+ uint32 bytes = getSize ();
+
+ if (data == 0 || bytes == 0)
+ return false;
+
+ char8* stringBuffer = (char8*)malloc ((bytes * 2) + 1);
+ if (!stringBuffer)
+ return false;
+
+ int32 count = 0;
+ while (bytes > 0)
+ {
+ unsigned char t1 = ((*data) >> 4) & 0x0F;
+ unsigned char t2 = (*data) & 0x0F;
+ if (t1 < 10)
+ t1 += '0';
+ else
+ t1 = t1 - 10 + 'A';
+ if (t2 < 10)
+ t2 += '0';
+ else
+ t2 = t2 - 10 + 'A';
+
+ stringBuffer [count++] = t1;
+ stringBuffer [count++] = t2;
+ data++;
+ bytes--;
+ }
+ stringBuffer [count] = 0;
+
+ result.take ((void*)stringBuffer, false);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::fromHexString (const char8* string)
+{
+ flush ();
+ if (string == 0)
+ return false;
+
+ int32 len = strlen8 (string);
+ if (len == 0 || ((len & 1) == 1)/*odd number*/ )
+ return false;
+
+ setSize (len / 2);
+ unsigned char* data = uint8Ptr ();
+
+ bool upper = true;
+ int32 count = 0;
+ while (count < len)
+ {
+ char c = string [count];
+
+ unsigned char d = 0;
+ if (c >= '0' && c <= '9') d += c - '0';
+ else if (c >= 'A' && c <= 'F') d += c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f') d += c - 'a' + 10;
+ else return false; // no hex string
+
+ if (upper)
+ data [count >> 1] = d << 4;
+ else
+ data [count >> 1] += d;
+
+ upper = !upper;
+ count++;
+ }
+ setFillSize (len / 2);
+ return true;
+}
+
+//------------------------------------------------------------------------
+void Buffer::set (uint8 value)
+{
+ if (buffer)
+ memset (buffer, value, memSize);
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::setFillSize (uint32 c)
+{
+ if (c <= memSize)
+ {
+ fillSize = c;
+ return true;
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::truncateToFillSize ()
+{
+ if (fillSize < memSize)
+ setSize (fillSize);
+
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::grow (uint32 newSize)
+{
+ if (newSize > memSize)
+ {
+ if (delta == 0)
+ delta = defaultDelta;
+ uint32 s = ((newSize + delta - 1) / delta) * delta;
+ return setSize (s);
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+void Buffer::shiftAt (uint32 position, int32 amount)
+{
+ if (amount > 0)
+ {
+ if (grow (fillSize + amount))
+ {
+ if (position < fillSize)
+ memmove (buffer + amount + position, buffer + position, fillSize - position);
+
+ fillSize += amount;
+ }
+ }
+ else if (amount < 0 && fillSize > 0)
+ {
+ uint32 toRemove = -amount;
+
+ if (toRemove < fillSize)
+ {
+ if (position < fillSize)
+ memmove (buffer + position, buffer + toRemove + position, fillSize - position - toRemove);
+ fillSize -= toRemove;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------
+void Buffer::move (int32 amount, uint8 initVal)
+{
+ if (memSize == 0)
+ return;
+
+ if (amount > 0)
+ {
+ if ((uint32)amount < memSize)
+ {
+ memmove (buffer + amount, buffer, memSize - amount);
+ memset (buffer, initVal, amount);
+ }
+ else
+ memset (buffer, initVal, memSize);
+ }
+ else
+ {
+ uint32 toRemove = -amount;
+ if (toRemove < memSize)
+ {
+ memmove (buffer, buffer + toRemove, memSize - toRemove);
+ memset (buffer + memSize - toRemove, initVal, toRemove);
+ }
+ else
+ memset (buffer, initVal, memSize);
+ }
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::setSize (uint32 newSize)
+{
+ if (memSize != newSize)
+ {
+ if (buffer)
+ {
+ if (newSize > 0)
+ {
+ int8* newBuffer = (int8*) ::realloc (buffer, newSize);
+ if (newBuffer == 0)
+ {
+ newBuffer = (int8*)::malloc (newSize);
+ if (newBuffer)
+ {
+ uint32 tmp = newSize;
+ if (tmp > memSize)
+ tmp = memSize;
+ memcpy (newBuffer, buffer, tmp);
+ ::free (buffer);
+ buffer = newBuffer;
+ }
+ else
+ {
+ ::free (buffer);
+ buffer = 0;
+ }
+ }
+ else
+ buffer = newBuffer;
+ }
+ else
+ {
+ ::free (buffer);
+ buffer = 0;
+ }
+ }
+ else
+ buffer = (int8*)::malloc (newSize);
+
+ if (newSize > 0 && !buffer)
+ memSize = 0;
+ else
+ memSize = newSize;
+ if (fillSize > memSize)
+ fillSize = memSize;
+ }
+
+ return (newSize > 0) == (buffer != 0);
+}
+
+//-------------------------------------------------------------------------------------
+void Buffer::fillup (uint8 value)
+{
+ if (getFree () > 0)
+ memset (buffer + fillSize, value, getFree ());
+}
+
+//-------------------------------------------------------------------------------------
+int8* Buffer::operator + (uint32 i)
+{
+ if (i < memSize)
+ return buffer + i;
+ else
+ {
+ static int8 eof;
+ eof = 0;
+ return &eof;
+ }
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::swap (int16 swapSize)
+{
+ return swap (buffer, memSize, swapSize);
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::swap (void* buffer, uint32 bufferSize, int16 swapSize)
+{
+ if (swapSize != kSwap16 && swapSize != kSwap32 && swapSize != kSwap64)
+ return false;
+
+ if (swapSize == kSwap16)
+ {
+ for (uint32 count = 0 ; count < bufferSize ; count += 2)
+ {
+ SWAP_16 ( * (((int16*)buffer) + count) );
+ }
+ }
+ else if (swapSize == kSwap32)
+ {
+ for (uint32 count = 0 ; count < bufferSize ; count += 4)
+ {
+ SWAP_32 ( * (((int32*)buffer) + count) );
+ }
+ }
+ else if (swapSize == kSwap64)
+ {
+ for (uint32 count = 0 ; count < bufferSize ; count += 8)
+ {
+ SWAP_64 ( * (((int64*)buffer) + count) );
+ }
+ }
+
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+void Buffer::take (Buffer& from)
+{
+ setSize (0);
+ memSize = from.memSize;
+ fillSize = from.fillSize;
+ buffer = from.buffer;
+ from.buffer = 0;
+ from.memSize = 0;
+ from.fillSize = 0;
+}
+
+//-------------------------------------------------------------------------------------
+int8* Buffer::pass ()
+{
+ int8* res = buffer;
+ buffer = 0;
+ memSize = 0;
+ fillSize = 0;
+ return res;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::toWideString (int32 sourceCodePage)
+{
+ if (getFillSize () > 0)
+ {
+ if (str8 () [getFillSize () - 1] != 0) // multiByteToWideString only works with 0-terminated strings
+ endString8 ();
+
+ Buffer dest (getFillSize () * sizeof (char16));
+ int32 result = String::multiByteToWideString (dest.str16 (), buffer, dest.getFree () / sizeof (char16), sourceCodePage);
+ if (result > 0)
+ {
+ dest.setFillSize ((result - 1) * sizeof (char16));
+ take (dest);
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+//-------------------------------------------------------------------------------------
+bool Buffer::toMultibyteString (int32 destCodePage)
+{
+ if (getFillSize () > 0)
+ {
+ int32 textLength = getFillSize () / sizeof (char16); // wideStringToMultiByte only works with 0-terminated strings
+ if (str16 () [textLength - 1] != 0)
+ endString16 ();
+
+ Buffer dest (getFillSize ());
+ int32 result = String::wideStringToMultiByte (dest.str8 (), str16 (), dest.getFree (), destCodePage);
+ if (result > 0)
+ {
+ dest.setFillSize (result - 1);
+ take (dest);
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.h
new file mode 100644
index 0000000000..e8dd936a84
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fbuffer.h
@@ -0,0 +1,306 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fbuffer.h
+// Created by : Steinberg, 2008
+// Description :
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include "pluginterfaces/base/ftypes.h"
+#include
+
+namespace Steinberg {
+class String;
+
+//------------------------------------------------------------------------
+/** Buffer.
+@ingroup adt
+
+A Buffer is an object-oriented wrapper for a piece of memory.
+It adds several utility functions, e.g. for managing the size of the Buffer,
+appending or prepending values or strings to it.
+Internally it uses the standard memory functions malloc(), free(), etc. */
+//------------------------------------------------------------------------
+class Buffer
+{
+public:
+//---------------------------------------------------------------------
+
+ /** Default constructor, allocates no memory at all.
+ */
+ Buffer ();
+
+ /** Constructor - creates a new Buffer with a given size and copies contents from optional memory pointer.
+ \param[in] b : optional memory pointer with the size of at least the given size
+ \param[in] size : the size of the new Buffer to be allocated, in bytes.
+ */
+ Buffer (const void* b, uint32 size);
+
+ /** Constructor - creates a new Buffer with a given size and fills it all with a given value.
+ \param[in] size : the size of the new Buffer to be allocated, in bytes.
+ \param[in] initVal : the initial value the Buffer will be completely filled with
+ */
+ Buffer (uint32 size, uint8 initVal);
+
+ /** Constructor - creates a new Buffer with a given size.
+ \param[in] size : the size of the new Buffer to be allocated, in bytes.
+ */
+ Buffer (uint32 size);
+
+ /** Copy constructor - creates a new Buffer from a given Buffer.
+ \param[in] buff : the Buffer from which all memory will be copied to the new one
+ */
+ Buffer (const Buffer& buff);
+
+ /** Destructor - deallocates the internal memory.
+ */
+ ~Buffer ();
+
+ /** Assignment operator - copies contents from a given Buffer and increases the size if necessary.
+ \param[in] buff : the Buffer from which all memory will be copied
+ */
+ void operator = (const Buffer& buff);
+
+ /** Comparison operator - copies contents from a given Buffer and increases the size if necessary.
+ \param[in] buff : the Buffer to be compared to
+ \return true, if the given Buffer's content is equal to this one, else false
+ */
+ bool operator == (const Buffer& buff)const;
+
+ uint32 getSize () const {return memSize;} ///< \return the actual size of the Buffer's memory, in bytes.
+
+ /** Sets a new size for this Buffer, keeping as much content as possible.
+ \param[in] newSize : the new size for the Buffer, in bytes, newSize maybe zero
+ \return true, if the new size could be adapted, else false
+ */
+ bool setSize (uint32 newSize);
+
+ /** Increases the Buffer to the next block, block size given by delta.
+ \param[in] memSize : the new minimum size of the Buffer, newSize maybe zero
+ \return true, if the Buffer could be grown successfully, else false
+ */
+ bool grow (uint32 memSize);
+ bool setMaxSize (uint32 size) {return grow (size);} ///< see \ref grow()
+
+ void fillup (uint8 initVal = 0); ///< set from fillSize to end
+ uint32 getFillSize ()const {return fillSize;} ///< \return the actual fill size
+ bool setFillSize (uint32 c); ///< sets a new fill size, does not change any memory
+ inline void flush () {setFillSize (0);} ///< sets fill size to zero
+ bool truncateToFillSize (); ///< \return always true, truncates the size of the Buffer to the actual fill size
+
+ bool isFull () const { return (fillSize == memSize); } ///< \return true, if all memory is filled up, else false
+ uint32 getFree () const { return (memSize - fillSize); }///< \return remaining memory
+
+ inline void shiftStart (int32 amount) {return shiftAt (0, amount);} ///< moves all memory by given amount, grows the Buffer if necessary
+ void shiftAt (uint32 position, int32 amount); ///< moves memory starting at the given position
+ void move (int32 amount, uint8 initVal = 0); ///< shifts memory at start without growing the buffer, so data is lost and initialized with init val
+
+ bool copy (uint32 from, uint32 to, uint32 bytes); ///< copies a number of bytes from one position to another, the size may be adapted
+ uint32 get (void* b, uint32 size); ///< copy to buffer from fillSize, and shift fillSize
+
+ void setDelta (uint32 d) {delta = d;} ///< define the block size by which the Buffer grows, see \ref grow()
+
+ bool put (uint8); ///< append value at end, grows Buffer if necessary
+ bool put (char16 c); ///< append value at end, grows Buffer if necessary
+ bool put (char c); ///< append value at end, grows Buffer if necessary
+ bool put (const void* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (void* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (uint8* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (char8* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (const uint8* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (const char8* , uint32 size); ///< append bytes from a given buffer, grows Buffer if necessary
+ bool put (const String&); ///< append String at end, grows Buffer if necessary
+
+ void set (uint8 value); ///< fills complete Buffer with given value
+
+ // strings ----------------
+ bool appendString (const tchar* s);
+ bool appendString (tchar* s);
+ bool appendString (tchar c) { return put (c); }
+
+ bool appendString8 (const char8* s);
+ bool appendString16 (const char16* s);
+
+ bool appendString8 (char8* s) { return appendString8 ((const char8*)s); }
+ bool appendString8 (unsigned char* s) { return appendString8 ((const char8*)s); }
+ bool appendString8 (const unsigned char* s) { return appendString8 ((const char8*)s); }
+
+ bool appendString8 (char8 c) { return put ((uint8)c); }
+ bool appendString8 (unsigned char c) { return put (c); }
+ bool appendString16 (char16 c) { return put (c); }
+ bool appendString16 (char16* s) { return appendString16 ((const char16*)s); }
+
+ bool prependString (const tchar* s);
+ bool prependString (tchar* s);
+ bool prependString (tchar c);
+
+ bool prependString8 (const char8* s);
+ bool prependString16 (const char16* s);
+
+ bool prependString8 (char8 c);
+ bool prependString8 (unsigned char c) { return prependString8 ((char8)c); }
+ bool prependString8 (char8* s) { return prependString8 ((const char8*)s); }
+ bool prependString8 (unsigned char* s) { return prependString8((const char8*)s); }
+ bool prependString8 (const unsigned char* s) { return prependString8 ((const char8*)s); }
+ bool prependString16 (char16 c);
+ bool prependString16 (char16* s) { return prependString16 ((const char16*)s); }
+
+ bool operator+= (const char* s) { return appendString8 (s); }
+ bool operator+= (char c) { return appendString8 (c); }
+ bool operator+= (const char16* s) { return appendString16 (s); }
+ bool operator+= (char16 c) { return appendString16 (c); }
+
+ bool operator= (const char* s) { flush (); return appendString8 (s); }
+ bool operator= (const char16* s) { flush (); return appendString16 (s); }
+ bool operator= (char8 c) { flush (); return appendString8 (c); }
+ bool operator= (char16 c) { flush (); return appendString16 (c); }
+
+ void endString () {put (tchar (0));}
+ void endString8 () {put (char8 (0));}
+ void endString16 () {put (char16 (0));}
+
+ bool makeHexString (String& result);
+ bool fromHexString (const char8* string);
+
+ // conversion
+ operator void* () const { return (void*)buffer; } ///< conversion
+ inline tchar* str () const {return (tchar*)buffer;} ///< conversion
+ inline char8* str8 () const {return (char8*)buffer;} ///< conversion
+ inline char16* str16 () const {return (char16*)buffer;} ///< conversion
+ inline int8* int8Ptr () const {return (int8*)buffer;} ///< conversion
+ inline uint8* uint8Ptr () const {return (uint8*)buffer; } ///< conversion
+ inline int16* int16Ptr () const {return (int16*)buffer; } ///< conversion
+ inline uint16* uint16Ptr () const {return (uint16*)buffer; } ///< conversion
+ inline int32* int32Ptr () const {return (int32*)buffer; } ///< conversion
+ inline uint32* uint32Ptr () const {return (uint32*)buffer; } ///< conversion
+ inline float* floatPtr () const {return (float*)buffer; } ///< conversion
+ inline double* doublePtr () const {return (double*)buffer; } ///< conversion
+ inline char16* wcharPtr () const {return (char16*)buffer;} ///< conversion
+
+ int8* operator + (uint32 i); ///< \return the internal Buffer's address plus the given offset i, zero if offset is out of range
+
+ int32 operator ! () { return buffer == 0; }
+
+ enum swapSize
+ {
+ kSwap16 = 2,
+ kSwap32 = 4,
+ kSwap64 = 8
+ };
+ bool swap (int16 swapSize); ///< swap all bytes of this Buffer by the given swapSize
+ static bool swap (void* buffer, uint32 bufferSize, int16 swapSize); ///< utility, swap given number of bytes in given buffer by the given swapSize
+
+ void take (Buffer& from); ///< takes another Buffer's memory, frees the current Buffer's memory
+ int8* pass (); ///< pass the current Buffer's memory
+
+ /** Converts a Buffer's content to UTF-16 from a given multi-byte code page, Buffer must contain char8 of given encoding.
+ \param[in] sourceCodePage : the actual code page of the Buffer's content
+ \return true, if the conversion was successful, else false
+ */
+ virtual bool toWideString (int32 sourceCodePage); // Buffer contains char8 of given encoding -> utf16
+
+ /** Converts a Buffer's content from UTF-16 to a given multi-byte code page, Buffer must contain UTF-16 encoded characters.
+ \param[in] destCodePage : the desired code page to convert the Buffer's content to
+ \return true, if the conversion was successful, else false
+ */
+ virtual bool toMultibyteString (int32 destCodePage); // Buffer contains utf16 -> char8 of given encoding
+
+//------------------------------------------------------------------------
+protected:
+ static const uint32 defaultDelta = 0x1000; // 0x1000
+
+ int8* buffer;
+ uint32 memSize;
+ uint32 fillSize;
+ uint32 delta;
+};
+
+inline bool Buffer::put (void* p, uint32 count) { return put ((const void*)p , count ); }
+inline bool Buffer::put (uint8 * p, uint32 count) { return put ((const void*)p , count ); }
+inline bool Buffer::put (char8* p, uint32 count) { return put ((const void*)p , count ); }
+inline bool Buffer::put (const uint8* p, uint32 count) { return put ((const void*)p , count ); }
+inline bool Buffer::put (const char8* p, uint32 count) { return put ((const void*)p , count ); }
+
+//------------------------------------------------------------------------
+inline bool Buffer::appendString (const tchar* s)
+{
+#ifdef UNICODE
+ return appendString16 (s);
+#else
+ return appendString8 (s);
+#endif
+}
+
+//------------------------------------------------------------------------
+inline bool Buffer::appendString (tchar* s)
+{
+#ifdef UNICODE
+ return appendString16 (s);
+#else
+ return appendString8 (s);
+#endif
+}
+
+//------------------------------------------------------------------------
+inline bool Buffer::prependString (const tchar* s)
+{
+#ifdef UNICODE
+ return prependString16 (s);
+#else
+ return prependString8 (s);
+#endif
+}
+
+//------------------------------------------------------------------------
+inline bool Buffer::prependString (tchar* s)
+{
+#ifdef UNICODE
+ return prependString16 (s);
+#else
+ return prependString8 (s);
+#endif
+}
+
+//------------------------------------------------------------------------
+inline bool Buffer::prependString (tchar c)
+{
+#ifdef UNICODE
+ return prependString16 (c);
+#else
+ return prependString8 (c);
+#endif
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.cpp
new file mode 100644
index 0000000000..7828add9fa
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.cpp
@@ -0,0 +1,314 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fdebug.cpp
+// Created by : Steinberg, 1995
+// Description : There are 2 levels of debugging messages:
+// DEVELOPMENT During development
+// RELEASE Program is shipping.
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "base/source/fdebug.h"
+
+#if DEVELOPMENT
+
+#include
+#include
+#include
+
+#if SMTG_OS_WINDOWS
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+#include
+#include
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+
+#elif SMTG_OS_MACOS
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static bool AmIBeingDebugged (void);
+
+#define THREAD_ALLOC_WATCH 0 // check allocations on specific threads
+
+#if THREAD_ALLOC_WATCH
+mach_port_t watchThreadID = 0;
+#endif
+
+#endif
+
+AssertionHandler gAssertionHandler = nullptr;
+AssertionHandler gPreAssertionHook = nullptr;
+DebugPrintLogger gDebugPrintLogger = nullptr;
+
+namespace boost {
+// Define the boost assertion handler to redirect to our assertion handler,
+// otherwise it just calls abort(). Note that we don't need to include any boost
+// headers for this, it just provides the handler.
+void assertion_failed (char const* expr, char const* function, char const* file, long line)
+{
+#if DEVELOPMENT
+ char message[512];
+ snprintf (message, 512, "%s at %s, %s:%ld", expr, function, file, line);
+ if (gAssertionHandler)
+ {
+ FDebugBreak (message);
+ }
+ else
+ {
+ assert (!(const char *)message);
+ }
+#endif
+}
+}
+
+//--------------------------------------------------------------------------
+static const int kDebugPrintfBufferSize = 10000;
+static bool neverDebugger = false; // so I can switch it off in the debugger...
+
+//--------------------------------------------------------------------------
+static void printDebugString (const char* string)
+{
+ if (!string)
+ return;
+
+ if (gDebugPrintLogger)
+ {
+ gDebugPrintLogger (string);
+ }
+ else
+ {
+#if SMTG_OS_MACOS
+ fprintf (stderr, "%s", string);
+#elif SMTG_OS_WINDOWS
+ OutputDebugStringA (string);
+#endif
+ }
+}
+
+//--------------------------------------------------------------------------
+// printf style debugging output
+//--------------------------------------------------------------------------
+void FDebugPrint (const char* format, ...)
+{
+ char string[kDebugPrintfBufferSize];
+ va_list marker;
+ va_start (marker, format);
+ vsnprintf (string, kDebugPrintfBufferSize, format, marker);
+
+ printDebugString (string);
+}
+
+#if SMTG_OS_WINDOWS
+#define AmIBeingDebugged IsDebuggerPresent
+#endif
+
+#if SMTG_OS_LINUX
+#include
+#include
+#include
+//--------------------------------------------------------------------------
+static inline bool AmIBeingDebugged ()
+{
+ // TODO: check if GDB or LLDB is attached
+ return true;
+}
+#endif
+
+//--------------------------------------------------------------------------
+// printf style debugging output
+//--------------------------------------------------------------------------
+void FDebugBreak (const char* format, ...)
+{
+ char string[kDebugPrintfBufferSize];
+ va_list marker;
+ va_start (marker, format);
+ vsnprintf (string, kDebugPrintfBufferSize, format, marker);
+
+ printDebugString (string);
+
+ // The Pre-assertion hook is always called, even if we're not running in the debugger,
+ // so that we can log asserts without displaying them
+ if (gPreAssertionHook)
+ {
+ gPreAssertionHook (string);
+ }
+
+ if (neverDebugger)
+ return;
+ if (AmIBeingDebugged ())
+ {
+ // do not crash if no debugger present
+ // If there is an assertion handler defined then let this override the UI
+ // and tell us whether we want to break into the debugger
+ bool breakIntoDebugger = true;
+ if (gAssertionHandler && gAssertionHandler (string) == false)
+ {
+ breakIntoDebugger = false;
+ }
+
+ if (breakIntoDebugger)
+ {
+#if SMTG_OS_WINDOWS
+ __debugbreak (); // intrinsic version of DebugBreak()
+#elif __ppc64__ || __ppc__ || __arm__
+ kill (getpid (), SIGINT);
+#elif __i386__ || __x86_64__
+ {
+ __asm__ volatile ("int3");
+ }
+#endif
+ }
+ }
+}
+
+//--------------------------------------------------------------------------
+void FPrintLastError (const char* file, int line)
+{
+#if SMTG_OS_WINDOWS
+ LPVOID lpMessageBuffer;
+ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+ GetLastError (), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&lpMessageBuffer, 0, NULL);
+ FDebugPrint ("%s(%d) : %s\n", file, line, lpMessageBuffer);
+ LocalFree (lpMessageBuffer);
+#endif
+
+#if SMTG_OS_MACOS
+#if !__MACH__
+ extern int errno;
+#endif
+ FDebugPrint ("%s(%d) : Errno %d\n", file, line, errno);
+#endif
+}
+
+#if SMTG_OS_MACOS
+
+//------------------------------------------------------------------------
+void* operator new (size_t size, int, const char* file, int line)
+{
+#if THREAD_ALLOC_WATCH
+ mach_port_t threadID = mach_thread_self ();
+ if (watchThreadID == threadID)
+ {
+ FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
+ }
+#endif
+ try
+ {
+ return ::operator new (size);
+ }
+ catch (std::bad_alloc exception)
+ {
+ FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line);
+ }
+ return (void*)-1;
+}
+
+//------------------------------------------------------------------------
+void* operator new[] (size_t size, int, const char* file, int line)
+{
+#if THREAD_ALLOC_WATCH
+ mach_port_t threadID = mach_thread_self ();
+ if (watchThreadID == threadID)
+ {
+ FDebugPrint ("Watched Thread Allocation : %s (Line:%d)\n", file ? file : "Unknown", line);
+ }
+#endif
+ try
+ {
+ return ::operator new[] (size);
+ }
+ catch (std::bad_alloc exception)
+ {
+ FDebugPrint ("bad_alloc exception : %s (Line:%d)", file ? file : "Unknown", line);
+ }
+ return (void*)-1;
+}
+
+//------------------------------------------------------------------------
+void operator delete (void* p, int, const char* file, int line)
+{
+ ::operator delete (p);
+}
+
+//------------------------------------------------------------------------
+void operator delete[] (void* p, int, const char* file, int line)
+{
+ ::operator delete[] (p);
+}
+
+//------------------------------------------------------------------------
+// from Technical Q&A QA1361 (http://developer.apple.com/qa/qa2004/qa1361.html)
+//------------------------------------------------------------------------
+bool AmIBeingDebugged (void)
+// Returns true if the current process is being debugged (either
+// running under the debugger or has a debugger attached post facto).
+{
+ int mib[4];
+ struct kinfo_proc info;
+ size_t size;
+
+ // Initialize the flags so that, if sysctl fails for some bizarre
+ // reason, we get a predictable result.
+
+ info.kp_proc.p_flag = 0;
+
+ // Initialize mib, which tells sysctl the info we want, in this case
+ // we're looking for information about a specific process ID.
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = getpid ();
+
+ // Call sysctl.
+
+ size = sizeof (info);
+ sysctl (mib, sizeof (mib) / sizeof (*mib), &info, &size, NULL, 0);
+
+ // We're being debugged if the P_TRACED flag is set.
+ return ((info.kp_proc.p_flag & P_TRACED) != 0);
+}
+
+#endif // SMTG_OS_MACOS
+
+#endif // DEVELOPMENT
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.h
new file mode 100644
index 0000000000..e61f0aacc9
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fdebug.h
@@ -0,0 +1,233 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fdebug.h
+// Created by : Steinberg, 1995
+// Description : There are 2 levels of debugging messages:
+// DEVELOPMENT During development
+// RELEASE Program is shipping.
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+/** @file base/source/fdebug.h
+ Debugging tools.
+
+ There are 2 levels of debugging messages:
+ - DEVELOPMENT
+ - During development
+ - RELEASE
+ - Program is shipping.
+*/
+//-----------------------------------------------------------------------------
+#pragma once
+
+#include "pluginterfaces/base/ftypes.h"
+#include
+
+#if SMTG_OS_MACOS
+#include
+#endif
+
+//-----------------------------------------------------------------------------
+// development / release
+//-----------------------------------------------------------------------------
+#if !defined (DEVELOPMENT) && !defined (RELEASE)
+ #ifdef _DEBUG
+ #define DEVELOPMENT 1
+ #elif defined (NDEBUG)
+ #define RELEASE 1
+ #else
+ #error DEVELOPMENT, RELEASE, _DEBUG, or NDEBUG must be defined!
+ #endif
+#endif
+
+//-----------------------------------------------------------------------------
+#if SMTG_OS_WINDOWS
+
+/** Disable compiler warning:
+ * C4291: "No matching operator delete found; memory will not be freed if initialization throws an
+ * exception. A placement new is used for which there is no placement delete." */
+#if DEVELOPMENT && defined(_MSC_VER)
+#pragma warning(disable : 4291)
+#pragma warning(disable : 4985)
+#endif
+
+#endif // SMTG_OS_WINDOWS
+
+#if DEVELOPMENT
+//-----------------------------------------------------------------------------
+/** If "f" is not true and a debugger is present, send an error string to the debugger for display
+ and cause a breakpoint exception to occur in the current process. SMTG_ASSERT is removed
+ completely in RELEASE configuration. So do not pass methods calls to this macro that are expected
+ to exist in the RELEASE build (for method calls that need to be present in a RELEASE build, use
+ the VERIFY macros instead)*/
+#define SMTG_ASSERT(f) \
+ if (!(f)) \
+ FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f);
+
+/** Send "comment" string to the debugger for display. */
+#define SMTG_WARNING(comment) FDebugPrint ("%s(%d) : %s\n", __FILE__, __LINE__, comment);
+
+/** Send the last error string to the debugger for display. */
+#define SMTG_PRINTSYSERROR FPrintLastError (__FILE__, __LINE__);
+
+/** If a debugger is present, send string "s" to the debugger for display and
+ cause a breakpoint exception to occur in the current process. */
+#define SMTG_DEBUGSTR(s) FDebugBreak (s);
+
+/** Use VERIFY for calling methods "f" having a bool result (expecting them to return 'true')
+ The call of "f" is not removed in RELEASE builds, only the result verification. eg: SMTG_VERIFY
+ (isValid ()) */
+#define SMTG_VERIFY(f) SMTG_ASSERT (f)
+
+/** Use VERIFY_IS for calling methods "f" and expect a certain result "r".
+ The call of "f" is not removed in RELEASE builds, only the result verification. eg:
+ SMTG_VERIFY_IS (callMethod (), kResultOK) */
+#define SMTG_VERIFY_IS(f, r) \
+ if ((f) != (r)) \
+ FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f);
+
+/** Use VERIFY_NOT for calling methods "f" and expect the result to be anything else but "r".
+ The call of "f" is not removed in RELEASE builds, only the result verification. eg:
+ SMTG_VERIFY_NOT (callMethod (), kResultError) */
+#define SMTG_VERIFY_NOT(f, r) \
+ if ((f) == (r)) \
+ FDebugBreak ("%s(%d) : Assert failed: %s\n", __FILE__, __LINE__, #f);
+
+/** @name Shortcut macros for sending strings to the debugger for display.
+ First parameter is always the format string (printf like).
+*/
+
+///@{
+#define DBPRT0(a) FDebugPrint (a);
+#define DBPRT1(a, b) FDebugPrint (a, b);
+#define DBPRT2(a, b, c) FDebugPrint (a, b, c);
+#define DBPRT3(a, b, c, d) FDebugPrint (a, b, c, d);
+#define DBPRT4(a, b, c, d, e) FDebugPrint (a, b, c, d, e);
+#define DBPRT5(a, b, c, d, e, f) FDebugPrint (a, b, c, d, e, f);
+///@}
+
+/** @name Helper functions for the above defined macros.
+
+ You shouldn't use them directly (if you do so, don't forget "#if DEVELOPMENT")!
+ It is recommended to use the macros instead.
+*/
+///@{
+void FDebugPrint (const char* format, ...);
+void FDebugBreak (const char* format, ...);
+void FPrintLastError (const char* file, int line);
+///@}
+
+/** @name Provide a custom assertion handler and debug print handler, eg
+ so that we can provide an assert with a custom dialog, or redirect
+ the debug output to a file or stream.
+*/
+///@{
+typedef bool (*AssertionHandler) (const char* message);
+extern AssertionHandler gAssertionHandler;
+extern AssertionHandler gPreAssertionHook;
+typedef void (*DebugPrintLogger) (const char* message);
+extern DebugPrintLogger gDebugPrintLogger;
+///@}
+
+/** Definition of memory allocation macros:
+ Use "NEW" to allocate storage for individual objects.
+ Use "NEWVEC" to allocate storage for an array of objects. */
+#if SMTG_OS_MACOS
+void* operator new (size_t, int, const char*, int);
+void* operator new[] (size_t, int, const char*, int);
+void operator delete (void* p, int, const char* file, int line);
+void operator delete[] (void* p, int, const char* file, int line);
+#ifndef NEW
+#define NEW new (1, __FILE__, __LINE__)
+#define NEWVEC new (1, __FILE__, __LINE__)
+#endif
+
+#define DEBUG_NEW DEBUG_NEW_LEAKS
+
+#elif SMTG_OS_WINDOWS && defined(_MSC_VER)
+#ifndef NEW
+void* operator new (size_t, int, const char*, int);
+#define NEW new (1, __FILE__, __LINE__)
+#define NEWVEC new (1, __FILE__, __LINE__)
+#endif
+
+#else
+#ifndef NEW
+#define NEW new
+#define NEWVEC new
+#endif
+#endif
+
+#else
+/** if DEVELOPMENT is not set, these macros will do nothing. */
+#define SMTG_ASSERT(f)
+#define SMTG_WARNING(s)
+#define SMTG_PRINTSYSERROR
+#define SMTG_DEBUGSTR(s)
+#define SMTG_VERIFY(f) f;
+#define SMTG_VERIFY_IS(f, r) f;
+#define SMTG_VERIFY_NOT(f, r) f;
+
+#define DBPRT0(a)
+#define DBPRT1(a, b)
+#define DBPRT2(a, b, c)
+#define DBPRT3(a, b, c, d)
+#define DBPRT4(a, b, c, d, e)
+#define DBPRT5(a, b, c, d, e, f)
+
+#ifndef NEW
+#define NEW new
+#define NEWVEC new
+
+#endif
+#endif
+
+#if SMTG_CPPUNIT_TESTING
+#define SMTG_IS_TEST true
+#else
+#define SMTG_IS_TEST false
+#endif
+
+#if !SMTG_RENAME_ASSERT
+#if SMTG_OS_WINDOWS
+#undef ASSERT
+#endif
+
+#define ASSERT SMTG_ASSERT
+#define WARNING SMTG_WARNING
+#define DEBUGSTR SMTG_DEBUGSTR
+#define VERIFY SMTG_VERIFY
+#define VERIFY_IS SMTG_VERIFY_IS
+#define VERIFY_NOT SMTG_VERIFY_NOT
+#define PRINTSYSERROR SMTG_PRINTSYSERROR
+#endif
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.cpp
new file mode 100644
index 0000000000..7e83d3f9a7
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.cpp
@@ -0,0 +1,184 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fobject.cpp
+// Created by : Steinberg, 2008
+// Description : Basic Object implementing FUnknown
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "base/source/fobject.h"
+#include "base/thread/include/flock.h"
+
+#include
+
+namespace Steinberg {
+
+IUpdateHandler* FObject::gUpdateHandler = 0;
+
+//------------------------------------------------------------------------
+const FUID FObject::iid;
+
+//------------------------------------------------------------------------
+struct FObjectIIDInitializer
+{
+ // the object iid is always generated so that different components
+ // only can cast to their own objects
+ // this initializer must be after the definition of FObject::iid, otherwise
+ // the default constructor of FUID will clear the generated iid
+ FObjectIIDInitializer ()
+ {
+ const_cast (FObject::iid).generate ();
+ }
+} gFObjectIidInitializer;
+
+//------------------------------------------------------------------------
+uint32 PLUGIN_API FObject::addRef ()
+{
+ return FUnknownPrivate::atomicAdd (refCount, 1);
+}
+
+//------------------------------------------------------------------------
+uint32 PLUGIN_API FObject::release ()
+{
+ if (FUnknownPrivate::atomicAdd (refCount, -1) == 0)
+ {
+ refCount = -1000;
+ delete this;
+ return 0;
+ }
+ return refCount;
+}
+
+//------------------------------------------------------------------------
+tresult PLUGIN_API FObject::queryInterface (const TUID _iid, void** obj)
+{
+ QUERY_INTERFACE (_iid, obj, FUnknown::iid, FUnknown)
+ QUERY_INTERFACE (_iid, obj, IDependent::iid, IDependent)
+ QUERY_INTERFACE (_iid, obj, FObject::iid, FObject)
+ *obj = 0;
+ return kNoInterface;
+}
+
+//------------------------------------------------------------------------
+void FObject::addDependent (IDependent* dep)
+{
+ if (gUpdateHandler)
+ gUpdateHandler->addDependent (unknownCast (), dep);
+}
+
+//------------------------------------------------------------------------
+void FObject::removeDependent (IDependent* dep)
+{
+ if (gUpdateHandler)
+ gUpdateHandler->removeDependent (unknownCast (), dep);
+}
+
+//------------------------------------------------------------------------
+void FObject::changed (int32 msg)
+{
+ if (gUpdateHandler)
+ gUpdateHandler->triggerUpdates (unknownCast (), msg);
+ else
+ updateDone (msg);
+}
+
+//------------------------------------------------------------------------
+void FObject::deferUpdate (int32 msg)
+{
+ if (gUpdateHandler)
+ gUpdateHandler->deferUpdates (unknownCast (), msg);
+ else
+ updateDone (msg);
+}
+
+//------------------------------------------------------------------------
+/** Automatic creation and destruction of singleton instances. */
+//------------------------------------------------------------------------
+namespace Singleton
+{
+ typedef std::vector ObjectVector;
+ ObjectVector* singletonInstances = 0;
+ bool singletonsTerminated = false;
+ Steinberg::Base::Thread::FLock* singletonsLock;
+
+ bool isTerminated () {return singletonsTerminated;}
+
+ void lockRegister ()
+ {
+ if (!singletonsLock) // assume first call not from multiple threads
+ singletonsLock = NEW Steinberg::Base::Thread::FLock;
+ singletonsLock->lock ();
+ }
+ void unlockRegister ()
+ {
+ singletonsLock->unlock ();
+ }
+
+ void registerInstance (FObject** o)
+ {
+ SMTG_ASSERT (singletonsTerminated == false)
+ if (singletonsTerminated == false)
+ {
+ if (singletonInstances == 0)
+ singletonInstances = NEW std::vector;
+ singletonInstances->push_back (o);
+ }
+ }
+
+ struct Deleter
+ {
+ ~Deleter ()
+ {
+ singletonsTerminated = true;
+ if (singletonInstances)
+ {
+ for (ObjectVector::iterator it = singletonInstances->begin (),
+ end = singletonInstances->end ();
+ it != end; ++it)
+ {
+ FObject** obj = (*it);
+ (*obj)->release ();
+ *obj = 0;
+ obj = 0;
+ }
+
+ delete singletonInstances;
+ singletonInstances = 0;
+ }
+ delete singletonsLock;
+ singletonsLock = 0;
+ }
+ } deleter;
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.h
new file mode 100644
index 0000000000..67b0af12fe
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fobject.h
@@ -0,0 +1,518 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fobject.h
+// Created by : Steinberg, 2008
+// Description : Basic Object implementing FUnknown
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------
+/** @file base/source/fobject.h
+ Basic Object implementing FUnknown. */
+//------------------------------------------------------------------------
+#pragma once
+
+#include "pluginterfaces/base/funknown.h"
+#include "pluginterfaces/base/iupdatehandler.h"
+//#include "base/source/basefwd.h"
+#include "base/source/fdebug.h" // NEW
+
+
+namespace Steinberg {
+
+//----------------------------------
+
+typedef FIDString FClassID;
+
+//------------------------------------------------------------------------
+// Basic FObject - implements FUnknown + IDependent
+//------------------------------------------------------------------------
+/** Implements FUnknown and IDependent.
+
+FObject is a polymorphic class that implements IDependent (of SKI module)
+and therefore derived from FUnknown, which is the most abstract base class of all.
+
+All COM-like virtual methods of FUnknown such as queryInterface(), addRef(), release()
+are implemented here. On top of that, dependency-related methods are implemented too.
+
+Pointer casting is done via the template methods FCast, either FObject to FObject or
+FUnknown to FObject.
+
+FObject supports a new singleton concept, therefore these objects are deleted automatically upon program termination.
+
+- Runtime type information: An object can be queried at runtime, of what class
+it is. To do this correctly, every class must override some methods. This
+is simplified by using the OBJ_METHODS macros
+
+
+@see
+ - FUnknown
+ - IDependent
+ - IUpdateHandler
+*/
+//------------------------------------------------------------------------
+class FObject : public IDependent
+{
+public:
+ //------------------------------------------------------------------------
+ FObject () : refCount (1) {} ///< default constructor...
+ FObject (const FObject&) : refCount (1) {} ///< overloaded constructor...
+ virtual ~FObject () {} ///< destructor...
+ FObject& operator = (const FObject&) { return *this; } ///< overloads operator "=" as the reference assignment
+
+ // OBJECT_METHODS
+ static inline FClassID getFClassID () {return "FObject";} ///< return Class ID as an ASCII string (statically)
+ virtual FClassID isA () const {return FObject::getFClassID ();} ///< a local alternative to getFClassID ()
+ virtual bool isA (FClassID s) const {return isTypeOf (s, false);} ///< evaluates if the passed ID is of the FObject type
+ virtual bool isTypeOf (FClassID s, bool /*askBaseClass*/ = true) const {return classIDsEqual (s, FObject::getFClassID ());}
+ ///< evaluates if the passed ID is of the FObject type
+ int32 getRefCount () {return refCount;} ///< returns the current interface reference count
+ FUnknown* unknownCast () {return this;} ///< get FUnknown interface from object
+
+ // FUnknown
+ virtual tresult PLUGIN_API queryInterface (const TUID _iid, void** obj) SMTG_OVERRIDE; ///< please refer to FUnknown::queryInterface ()
+ virtual uint32 PLUGIN_API addRef () SMTG_OVERRIDE; ///< please refer to FUnknown::addref ()
+ virtual uint32 PLUGIN_API release () SMTG_OVERRIDE; ///< please refer to FUnknown::release ()
+
+ // IDependent
+ virtual void PLUGIN_API update (FUnknown* /*changedUnknown*/, int32 /*message*/) SMTG_OVERRIDE {}
+ ///< empty virtual method that should be overridden by derived classes for data updates upon changes
+ // IDependency
+ virtual void addDependent (IDependent* dep); ///< adds dependency to the object
+ virtual void removeDependent (IDependent* dep); ///< removes dependency from the object
+ virtual void changed (int32 msg = kChanged); ///< Inform all dependents, that the object has changed.
+ virtual void deferUpdate (int32 msg = kChanged); ///< Similar to triggerUpdates, except only delivered in idle (usefull in collecting updates).
+ virtual void updateDone (int32 /* msg */) {} ///< empty virtual method that should be overridden by derived classes
+ virtual bool isEqualInstance (FUnknown* d) {return this == d;}
+
+ static void setUpdateHandler (IUpdateHandler* handler) {gUpdateHandler = handler;} ///< set method for the local attribute
+ static IUpdateHandler* getUpdateHandler () {return gUpdateHandler;} ///< get method for the local attribute
+
+ // static helper functions
+ static inline bool classIDsEqual (FClassID ci1, FClassID ci2); ///< compares (evaluates) 2 class IDs
+ static inline FObject* unknownToObject (FUnknown* unknown); ///< pointer conversion from FUnknown to FObject
+
+ /** Special UID that is used to cast an FUnknown pointer to a FObject */
+ static const FUID iid;
+
+//------------------------------------------------------------------------
+protected:
+ int32 refCount; ///< COM-model local reference count
+
+ static IUpdateHandler* gUpdateHandler;
+};
+
+
+//------------------------------------------------------------------------
+// conversion from FUnknown to FObject
+//------------------------------------------------------------------------
+inline FObject* FObject::unknownToObject (FUnknown* unknown)
+{
+ FObject* object = 0;
+ if (unknown)
+ {
+ unknown->queryInterface (FObject::iid, (void**)&object);
+ if (object)
+ object->release (); // queryInterface has added ref
+ }
+ return object;
+}
+
+//------------------------------------------------------------------------
+inline bool FObject::classIDsEqual (FClassID ci1, FClassID ci2)
+{
+ return (ci1 && ci2) ? (strcmp (ci1, ci2) == 0) : false;
+}
+
+//-----------------------------------------------------------------------
+/** FCast overload 1 - FObject to FObject */
+//-----------------------------------------------------------------------
+template
+inline C* FCast (const FObject* object)
+{
+ if (object && object->isTypeOf (C::getFClassID (), true))
+ return (C*) object;
+ return 0;
+}
+
+//-----------------------------------------------------------------------
+/** FCast overload 2 - FUnknown to FObject */
+//-----------------------------------------------------------------------
+template
+inline C* FCast (FUnknown* unknown)
+{
+ FObject* object = FObject::unknownToObject (unknown);
+ return FCast (object);
+}
+
+//-----------------------------------------------------------------------
+/** FUCast - casting from FUnknown to Interface */
+//-----------------------------------------------------------------------
+template
+inline C* FUCast (FObject* object)
+{
+ return FUnknownPtr (object ? object->unknownCast () : 0);
+}
+
+template
+inline C* FUCast (FUnknown* object)
+{
+ return FUnknownPtr (object);
+}
+
+//------------------------------------------------------------------------
+/** @name Convenience methods that call release or delete respectively
+ on a pointer if it is non-zero, and then set the pointer to zero.
+ Note: you should prefer using IPtr or OPtr instead of these methods
+ whenever possible.
+ Examples:
+ @code
+ ~Foo ()
+ {
+ // instead of ...
+ if (somePointer)
+ {
+ somePointer->release ();
+ somePointer = 0;
+ }
+ // ... just being lazy I write
+ SafeRelease (somePointer)
+ }
+ @endcode
+*/
+///@{
+//-----------------------------------------------------------------------
+template
+inline void SafeRelease (I *& ptr)
+{
+ if (ptr)
+ {
+ ptr->release ();
+ ptr = 0;
+ }
+}
+
+//-----------------------------------------------------------------------
+template
+inline void SafeRelease (IPtr & ptr)
+{
+ ptr = 0;
+}
+
+
+//-----------------------------------------------------------------------
+template
+inline void SafeDelete (T *& ptr)
+{
+ if (ptr)
+ {
+ delete ptr;
+ ptr = 0;
+ }
+}
+///@}
+
+//-----------------------------------------------------------------------
+template
+inline void AssignShared (T*& dest, T* newPtr)
+{
+ if (dest == newPtr)
+ return;
+
+ if (dest)
+ dest->release ();
+ dest = newPtr;
+ if (dest)
+ dest->addRef ();
+}
+
+//-----------------------------------------------------------------------
+template
+inline void AssignSharedDependent (IDependent* _this, T*& dest, T* newPtr)
+{
+ if (dest == newPtr)
+ return;
+
+ if (dest)
+ dest->removeDependent (_this);
+ AssignShared (dest, newPtr);
+ if (dest)
+ dest->addDependent (_this);
+}
+
+//-----------------------------------------------------------------------
+template
+inline void AssignSharedDependent (IDependent* _this, IPtr& dest, T* newPtr)
+{
+ if (dest == newPtr)
+ return;
+
+ if (dest)
+ dest->removeDependent (_this);
+ dest = newPtr;
+ if (dest)
+ dest->addDependent (_this);
+}
+
+//-----------------------------------------------------------------------
+template
+inline void SafeReleaseDependent (IDependent* _this, T*& dest)
+{
+ if (dest)
+ dest->removeDependent (_this);
+ SafeRelease (dest);
+}
+
+//-----------------------------------------------------------------------
+template
+inline void SafeReleaseDependent (IDependent* _this, IPtr& dest)
+{
+ if (dest)
+ dest->removeDependent (_this);
+ SafeRelease (dest);
+}
+
+
+//------------------------------------------------------------------------
+/** Automatic creation and destruction of singleton instances. */
+namespace Singleton {
+ /** registers an instance (type FObject) */
+ void registerInstance (FObject** o);
+
+ /** Returns true when singleton instances were already released. */
+ bool isTerminated ();
+
+ /** lock and unlock the singleton registration for multi-threading safety */
+ void lockRegister ();
+ void unlockRegister ();
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
+
+//-----------------------------------------------------------------------
+#define SINGLETON(ClassName) \
+ static ClassName* instance (bool create = true) \
+ { \
+ static Steinberg::FObject* inst = nullptr; \
+ if (inst == nullptr && create && Steinberg::Singleton::isTerminated () == false) \
+ { \
+ Steinberg::Singleton::lockRegister (); \
+ if (inst == nullptr) \
+ { \
+ inst = NEW ClassName; \
+ Steinberg::Singleton::registerInstance (&inst); \
+ } \
+ Steinberg::Singleton::unlockRegister (); \
+ } \
+ return (ClassName*)inst; \
+ }
+
+//-----------------------------------------------------------------------
+#define OBJ_METHODS(className, baseClass) \
+ static inline Steinberg::FClassID getFClassID () {return (#className);} \
+ virtual Steinberg::FClassID isA () const SMTG_OVERRIDE {return className::getFClassID ();} \
+ virtual bool isA (Steinberg::FClassID s) const SMTG_OVERRIDE {return isTypeOf (s, false);} \
+ virtual bool isTypeOf (Steinberg::FClassID s, bool askBaseClass = true) const SMTG_OVERRIDE \
+ { return (classIDsEqual (s, #className) ? true : (askBaseClass ? baseClass::isTypeOf (s, true) : false)); }
+
+//------------------------------------------------------------------------
+/** Delegate refcount functions to BaseClass.
+ BaseClase must implement ref counting.
+*/
+//------------------------------------------------------------------------
+#define REFCOUNT_METHODS(BaseClass) \
+virtual Steinberg::uint32 PLUGIN_API addRef ()SMTG_OVERRIDE{ return BaseClass::addRef (); } \
+virtual Steinberg::uint32 PLUGIN_API release ()SMTG_OVERRIDE{ return BaseClass::release (); }
+
+//------------------------------------------------------------------------
+/** @name Macros to implement FUnknown::queryInterface ().
+
+ Examples:
+ @code
+ class Foo : public FObject, public IFoo2, public IFoo3
+ {
+ ...
+ DEFINE_INTERFACES
+ DEF_INTERFACE (IFoo2)
+ DEF_INTERFACE (IFoo3)
+ END_DEFINE_INTERFACES (FObject)
+ REFCOUNT_METHODS(FObject)
+ // Implement IFoo2 interface ...
+ // Implement IFoo3 interface ...
+ ...
+ };
+ @endcode
+*/
+///@{
+//------------------------------------------------------------------------
+/** Start defining interfaces. */
+//------------------------------------------------------------------------
+#define DEFINE_INTERFACES \
+Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID iid, void** obj) SMTG_OVERRIDE \
+{
+
+//------------------------------------------------------------------------
+/** Add a interfaces. */
+//------------------------------------------------------------------------
+#define DEF_INTERFACE(InterfaceName) \
+ QUERY_INTERFACE (iid, obj, InterfaceName::iid, InterfaceName)
+
+//------------------------------------------------------------------------
+/** End defining interfaces. */
+//------------------------------------------------------------------------
+#define END_DEFINE_INTERFACES(BaseClass) \
+ return BaseClass::queryInterface (iid, obj); \
+}
+///@}
+
+//------------------------------------------------------------------------
+/** @name Convenient macros to implement Steinberg::FUnknown::queryInterface ().
+ Examples:
+ @code
+ class Foo : public FObject, public IFoo2, public IFoo3
+ {
+ ...
+ DEF_INTERFACES_2(IFoo2,IFoo3,FObject)
+ REFCOUNT_METHODS(FObject)
+ ...
+ };
+ @endcode
+*/
+///@{
+//------------------------------------------------------------------------
+#define DEF_INTERFACES_1(InterfaceName,BaseClass) \
+DEFINE_INTERFACES \
+DEF_INTERFACE (InterfaceName) \
+END_DEFINE_INTERFACES (BaseClass)
+
+//------------------------------------------------------------------------
+#define DEF_INTERFACES_2(InterfaceName1,InterfaceName2,BaseClass) \
+DEFINE_INTERFACES \
+DEF_INTERFACE (InterfaceName1) \
+DEF_INTERFACE (InterfaceName2) \
+END_DEFINE_INTERFACES (BaseClass)
+
+//------------------------------------------------------------------------
+#define DEF_INTERFACES_3(InterfaceName1,InterfaceName2,InterfaceName3,BaseClass) \
+DEFINE_INTERFACES \
+DEF_INTERFACE (InterfaceName1) \
+DEF_INTERFACE (InterfaceName2) \
+DEF_INTERFACE (InterfaceName3) \
+END_DEFINE_INTERFACES (BaseClass)
+
+//------------------------------------------------------------------------
+#define DEF_INTERFACES_4(InterfaceName1,InterfaceName2,InterfaceName3,InterfaceName4,BaseClass) \
+ DEFINE_INTERFACES \
+ DEF_INTERFACE (InterfaceName1) \
+ DEF_INTERFACE (InterfaceName2) \
+ DEF_INTERFACE (InterfaceName3) \
+ DEF_INTERFACE (InterfaceName4) \
+ END_DEFINE_INTERFACES (BaseClass)
+///@}
+
+//------------------------------------------------------------------------
+/** @name Convenient macros to implement Steinberg::FUnknown methods.
+ Examples:
+ @code
+ class Foo : public FObject, public IFoo2, public IFoo3
+ {
+ ...
+ FUNKNOWN_METHODS2(IFoo2,IFoo3,FObject)
+ ...
+ };
+ @endcode
+*/
+///@{
+#define FUNKNOWN_METHODS(InterfaceName,BaseClass) \
+DEF_INTERFACES_1(InterfaceName,BaseClass) \
+REFCOUNT_METHODS(BaseClass)
+
+#define FUNKNOWN_METHODS2(InterfaceName1,InterfaceName2,BaseClass) \
+DEF_INTERFACES_2(InterfaceName1,InterfaceName2,BaseClass) \
+REFCOUNT_METHODS(BaseClass)
+
+#define FUNKNOWN_METHODS3(InterfaceName1,InterfaceName2,InterfaceName3,BaseClass) \
+DEF_INTERFACES_3(InterfaceName1,InterfaceName2,InterfaceName3,BaseClass) \
+REFCOUNT_METHODS(BaseClass)
+
+#define FUNKNOWN_METHODS4(InterfaceName1,InterfaceName2,InterfaceName3,InterfaceName4,BaseClass) \
+DEF_INTERFACES_4(InterfaceName1,InterfaceName2,InterfaceName3,InterfaceName4,BaseClass) \
+REFCOUNT_METHODS(BaseClass)
+///@}
+
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+#if COM_COMPATIBLE
+//------------------------------------------------------------------------
+/** @name Macros to implement IUnknown interfaces with FObject.
+ Examples:
+ @code
+ class MyEnumFormat : public FObject, IEnumFORMATETC
+ {
+ ...
+ COM_UNKNOWN_METHODS (IEnumFORMATETC, IUnknown)
+ ...
+ };
+ @endcode
+*/
+///@{
+//------------------------------------------------------------------------
+#define IUNKNOWN_REFCOUNT_METHODS(BaseClass) \
+STDMETHOD_ (ULONG, AddRef) (void) {return BaseClass::addRef ();} \
+STDMETHOD_ (ULONG, Release) (void) {return BaseClass::release ();}
+
+//------------------------------------------------------------------------
+#define COM_QUERY_INTERFACE(iid, obj, InterfaceName) \
+if (riid == __uuidof(InterfaceName)) \
+{ \
+ addRef (); \
+ *obj = (InterfaceName*)this; \
+ return kResultOk; \
+}
+
+//------------------------------------------------------------------------
+#define COM_OBJECT_QUERY_INTERFACE(InterfaceName,BaseClass) \
+STDMETHOD (QueryInterface) (REFIID riid, void** object) \
+{ \
+ COM_QUERY_INTERFACE (riid, object, InterfaceName) \
+ return BaseClass::queryInterface ((FIDString)&riid, object); \
+}
+
+//------------------------------------------------------------------------
+#define COM_UNKNOWN_METHODS(InterfaceName,BaseClass) \
+COM_OBJECT_QUERY_INTERFACE(InterfaceName,BaseClass) \
+IUNKNOWN_REFCOUNT_METHODS(BaseClass)
+///@}
+
+#endif // COM_COMPATIBLE
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.cpp
new file mode 100644
index 0000000000..bb87dc66b4
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.cpp
@@ -0,0 +1,726 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fstreamer.cpp
+// Created by : Steinberg, 15.12.2005
+// Description : Extract of typed stream i/o methods from FStream
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "fstreamer.h"
+
+#include "base/source/fstring.h"
+#include "base/source/fbuffer.h"
+#include "pluginterfaces/base/ibstream.h"
+
+#ifndef UNICODE
+#include "pluginterfaces/base/futils.h"
+#endif
+
+namespace Steinberg {
+
+//------------------------------------------------------------------------
+// IBStreamer
+//------------------------------------------------------------------------
+IBStreamer::IBStreamer (IBStream* stream, int16 _byteOrder)
+: FStreamer (_byteOrder)
+, stream (stream)
+{}
+
+//------------------------------------------------------------------------
+TSize IBStreamer::readRaw (void* buffer, TSize size)
+{
+ int32 numBytesRead = 0;
+ stream->read (buffer, (int32)size, &numBytesRead);
+ return numBytesRead;
+}
+
+//------------------------------------------------------------------------
+TSize IBStreamer::writeRaw (const void* buffer, TSize size)
+{
+ int32 numBytesWritten = 0;
+ stream->write ((void*)buffer, (int32)size, &numBytesWritten);
+ return numBytesWritten;
+}
+
+//------------------------------------------------------------------------
+int64 IBStreamer::seek (int64 pos, FSeekMode mode)
+{
+ int64 result = -1;
+ stream->seek (pos, mode, &result);
+ return result;
+}
+
+//------------------------------------------------------------------------
+int64 IBStreamer::tell ()
+{
+ int64 pos = 0;
+ stream->tell (&pos);
+ return pos;
+}
+
+//------------------------------------------------------------------------
+// FStreamSizeHolder Implementation
+//------------------------------------------------------------------------
+FStreamSizeHolder::FStreamSizeHolder (FStreamer &s)
+: stream (s), sizePos (-1)
+{}
+
+//------------------------------------------------------------------------
+void FStreamSizeHolder::beginWrite ()
+{
+ sizePos = stream.tell ();
+ stream.writeInt32 (0L);
+}
+
+//------------------------------------------------------------------------
+int32 FStreamSizeHolder::endWrite ()
+{
+ if (sizePos < 0)
+ return 0;
+
+ int64 currentPos = stream.tell ();
+
+ stream.seek (sizePos, kSeekSet);
+ int32 size = int32 (currentPos - sizePos - sizeof (int32));
+ stream.writeInt32 (size);
+
+ stream.seek (currentPos, kSeekSet);
+ return size;
+}
+
+//------------------------------------------------------------------------
+int32 FStreamSizeHolder::beginRead ()
+{
+ sizePos = stream.tell ();
+ int32 size = 0;
+ stream.readInt32 (size);
+ sizePos += size + sizeof (int32);
+ return size;
+}
+
+//------------------------------------------------------------------------
+void FStreamSizeHolder::endRead ()
+{
+ if (sizePos >= 0)
+ stream.seek (sizePos, kSeekSet);
+}
+
+//------------------------------------------------------------------------
+// FStreamer
+//------------------------------------------------------------------------
+FStreamer::FStreamer (int16 _byteOrder)
+: byteOrder (_byteOrder)
+{}
+
+// int8 / char -----------------------------------------------------------
+//------------------------------------------------------------------------
+bool FStreamer::writeChar8 (char8 c)
+{
+ return writeRaw ((void*)&c, sizeof (char8)) == sizeof (char8);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readChar8 (char8& c)
+{
+ return readRaw ((void*)&c, sizeof (char8)) == sizeof (char8);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeUChar8 (unsigned char c)
+{
+ return writeRaw ((void*)&c, sizeof (unsigned char)) == sizeof (unsigned char);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readUChar8 (unsigned char& c)
+{
+ return readRaw ((void*)&c, sizeof (unsigned char)) == sizeof (unsigned char);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeChar16 (char16 c)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (c);
+ return writeRaw ((void*)&c, sizeof (char16)) == sizeof (char16);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readChar16 (char16& c)
+{
+ if (readRaw ((void*)&c, sizeof (char16)) == sizeof (char16))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (c);
+ return true;
+ }
+ c = 0;
+ return false;
+}
+
+// int16 -----------------------------------------------------------------
+//------------------------------------------------------------------------
+bool FStreamer::writeInt16 (int16 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (i);
+ return writeRaw ((void*)&i, sizeof (int16)) == sizeof (int16);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt16 (int16& i)
+{
+ if (readRaw ((void*)&i, sizeof (int16)) == sizeof (int16))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt16Array (const int16* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt16 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt16Array (int16* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt16 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt16u (uint16 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (i);
+ return writeRaw ((void*)&i, sizeof (uint16)) == sizeof (uint16);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt16u (uint16& i)
+{
+ if (readRaw ((void*)&i, sizeof (uint16)) == sizeof (uint16))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_16 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt16uArray (const uint16* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt16u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt16uArray (uint16* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt16u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+// int32 -----------------------------------------------------------------
+//------------------------------------------------------------------------
+bool FStreamer::writeInt32 (int32 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (i);
+ return writeRaw ((void*)&i, sizeof (int32)) == sizeof (int32);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt32 (int32& i)
+{
+ if (readRaw ((void*)&i, sizeof (int32)) == sizeof (int32))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt32Array (const int32* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt32 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt32Array (int32* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt32 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt32u (uint32 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (i);
+ return writeRaw ((void*)&i, sizeof (uint32)) == sizeof (uint32);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt32u (uint32& i)
+{
+ if (readRaw ((void*)&i, sizeof (uint32)) == sizeof (uint32))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt32uArray (const uint32* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt32u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt32uArray (uint32* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt32u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+// int64 -----------------------------------------------------------------
+//------------------------------------------------------------------------
+bool FStreamer::writeInt64 (int64 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (i);
+ return writeRaw ((void*)&i, sizeof (int64)) == sizeof (int64);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt64 (int64& i)
+{
+ if (readRaw ((void*)&i, sizeof (int64)) == sizeof (int64))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt64Array (const int64* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt64 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt64Array (int64* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt64 (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt64u (uint64 i)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (i);
+ return writeRaw ((void*)&i, sizeof (uint64)) == sizeof (uint64);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt64u (uint64& i)
+{
+ if (readRaw ((void*)&i, sizeof (uint64)) == sizeof (uint64))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (i);
+ return true;
+ }
+ i = 0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeInt64uArray (const uint64* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeInt64u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readInt64uArray (uint64* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readInt64u (array[i]))
+ return false;
+ }
+ return true;
+}
+
+// float / double --------------------------------------------------------
+//------------------------------------------------------------------------
+bool FStreamer::writeFloat (float f)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (f);
+ return writeRaw ((void*)&f, sizeof (float)) == sizeof (float);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readFloat (float& f)
+{
+ if (readRaw ((void*)&f, sizeof (float)) == sizeof (float))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_32 (f);
+ return true;
+ }
+ f = 0.f;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeFloatArray (const float* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeFloat (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readFloatArray (float* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readFloat (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeDouble (double d)
+{
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (d);
+ return writeRaw ((void*)&d, sizeof (double)) == sizeof (double);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readDouble (double& d)
+{
+ if (readRaw ((void*)&d, sizeof (double)) == sizeof (double))
+ {
+ if (BYTEORDER != byteOrder)
+ SWAP_64 (d);
+ return true;
+ }
+ d = 0.0;
+ return false;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeDoubleArray (const double* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!writeDouble (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readDoubleArray (double* array, int32 count)
+{
+ for (int32 i = 0; i < count; i++)
+ {
+ if (!readDouble (array[i]))
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::readBool (bool& b)
+{
+ int16 v = 0;
+ bool res = readInt16 (v);
+ b = (v != 0);
+ return res;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeBool (bool b)
+{
+ return writeInt16 ((int16)b);
+}
+
+//------------------------------------------------------------------------
+TSize FStreamer::writeString8 (const char8* ptr, bool terminate)
+{
+ TSize size = strlen (ptr);
+ if (terminate) // write \0
+ size++;
+
+ return writeRaw ((void*)ptr, size);
+}
+
+//------------------------------------------------------------------------
+TSize FStreamer::readString8 (char8* ptr, TSize size)
+{
+ TSize i = 0;
+ char8 c = 0;
+ while (i < size)
+ {
+ if (readRaw ((void*)&c, sizeof (char)) != sizeof (char))
+ break;
+ ptr[i] = c;
+ i++;
+ if (c == '\n' || c == '\0')
+ break;
+ }
+ if (c == '\n' && ptr[i - 2] == '\r')
+ ptr[i - 2] = 0;
+ if (i < size)
+ ptr[i] = 0;
+ else
+ ptr[size - 1] = 0;
+
+ return strlen (ptr);
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeStringUtf8 (const tchar* ptr)
+{
+ bool isUtf8 = false;
+
+ String str (ptr);
+ if (str.isAsciiString () == false)
+ {
+ str.toMultiByte (kCP_Utf8);
+ isUtf8 = true;
+ }
+ else
+ {
+ str.toMultiByte ();
+ }
+
+ if (isUtf8)
+ if (writeRaw (kBomUtf8, kBomUtf8Length) != kBomUtf8Length)
+ return false;
+
+ TSize size = str.length () + 1;
+ if (writeRaw (str.text8 (), size) != size)
+ return false;
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+int32 FStreamer::readStringUtf8 (tchar* ptr, int32 nChars)
+{
+ char8 c = 0;
+
+ ptr [0] = 0;
+
+ Buffer tmp;
+ tmp.setDelta (1024);
+
+ while (true)
+ {
+ if (readRaw ((void*)&c, sizeof (char)) != sizeof (char))
+ break;
+ tmp.put (c);
+ if (c == '\0')
+ break;
+ }
+
+ char8* source = tmp.int8Ptr ();
+ uint32 codePage = kCP_Default; // for legacy take default page if no utf8 bom is present...
+ if (tmp.getFillSize () > 2)
+ {
+ if (memcmp (source, kBomUtf8, kBomUtf8Length) == 0)
+ {
+ codePage = kCP_Utf8;
+ source += 3;
+ }
+ }
+
+ if (tmp.getFillSize () > 1)
+ {
+#ifdef UNICODE
+ ConstString::multiByteToWideString (ptr, source, nChars, codePage);
+#else
+ if (codePage == kCP_Utf8)
+ {
+ Buffer wideBuffer (tmp.getFillSize () * 3);
+ ConstString::multiByteToWideString (wideBuffer.wcharPtr (), source, wideBuffer.getSize () / 2, kCP_Utf8);
+ ConstString::wideStringToMultiByte (ptr, wideBuffer.wcharPtr (), nChars);
+ }
+ else
+ {
+ memcpy (ptr, source, Min (nChars, tmp.getFillSize ()));
+ }
+#endif
+ }
+
+ ptr[nChars - 1] = 0;
+ return ConstString (ptr).length ();
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::writeStr8 (const char8* s)
+{
+ int32 length = (s) ? (int32) strlen (s) + 1 : 0;
+ if (!writeInt32 (length))
+ return false;
+
+ if (length > 0)
+ return writeRaw (s, sizeof (char8) * length) == static_cast(sizeof (char8) * length);
+
+ return true;
+}
+
+//------------------------------------------------------------------------
+int32 FStreamer::getStr8Size (const char8* s)
+{
+ return sizeof (int32) + (int32)strlen (s) + 1;
+}
+
+//------------------------------------------------------------------------
+char8* FStreamer::readStr8 ()
+{
+ int32 length;
+ if (!readInt32 (length))
+ return 0;
+
+ // check corruption
+ if (length > 262144)
+ return 0;
+
+ char8* s = (length > 0) ? NEWVEC char8[length] : 0;
+ if (s)
+ readRaw (s, length * sizeof (char8));
+ return s;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::skip (uint32 bytes)
+{
+ int8 tmp;
+ while (bytes-- > 0)
+ {
+ if (readInt8 (tmp) == false)
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+bool FStreamer::pad (uint32 bytes)
+{
+ while (bytes-- > 0)
+ {
+ if (writeInt8 (0) == false)
+ return false;
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.h
new file mode 100644
index 0000000000..1c4d1033b4
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstreamer.h
@@ -0,0 +1,242 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fstreamer.h
+// Created by : Steinberg, 12/2005
+// Description : Extract of typed stream i/o methods from FStream
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include "pluginterfaces/base/funknown.h"
+
+namespace Steinberg {
+
+//------------------------------------------------------------------------
+enum FSeekMode
+{
+ kSeekSet,
+ kSeekCurrent,
+ kSeekEnd
+};
+
+//------------------------------------------------------------------------
+// FStreamer
+//------------------------------------------------------------------------
+/** Byteorder-aware base class for typed stream i/o. */
+//------------------------------------------------------------------------
+class FStreamer
+{
+public:
+//------------------------------------------------------------------------
+ FStreamer (int16 byteOrder = BYTEORDER);
+ virtual ~FStreamer () {}
+
+ /** @name Implementing class must override. */
+ ///@{
+ virtual TSize readRaw (void*, TSize) = 0; ///< Read one buffer of size.
+ virtual TSize writeRaw (const void*, TSize) = 0; ///< Write one buffer of size.
+ virtual int64 seek (int64, FSeekMode) = 0; ///< Set file position for stream.
+ virtual int64 tell () = 0; ///< Return current file position.
+ ///@}
+
+ /** @name Streams are byteOrder aware. */
+ ///@{
+ inline void setByteOrder (int32 e) { byteOrder = (int16)e; }
+ inline int32 getByteOrder () { return byteOrder; }
+ ///@}
+
+ /** @name read and write int8 and char. */
+ ///@{
+ bool writeChar8 (char8);
+ bool readChar8 (char8&);
+ bool writeUChar8 (unsigned char);
+ bool readUChar8 (unsigned char&);
+ bool writeChar16 (char16 c);
+ bool readChar16 (char16& c);
+
+ bool writeInt8 (int8 c){return writeChar8 (c);}
+ bool readInt8 (int8& c){return readChar8 (c);}
+ bool writeInt8u (uint8 c){return writeUChar8 (c);}
+ bool readInt8u (uint8& c){return readUChar8 (c);}
+ ///@}
+
+ /** @name read and write int16. */
+ ///@{
+ bool writeInt16 (int16);
+ bool readInt16 (int16&);
+ bool writeInt16Array (const int16* array, int32 count);
+ bool readInt16Array (int16* array, int32 count);
+ bool writeInt16u (uint16);
+ bool readInt16u (uint16&);
+ bool writeInt16uArray (const uint16* array, int32 count);
+ bool readInt16uArray (uint16* array, int32 count);
+ ///@}
+
+ /** @name read and write int32. */
+ ///@{
+ bool writeInt32 (int32);
+ bool readInt32 (int32&);
+ bool writeInt32Array (const int32* array, int32 count);
+ bool readInt32Array (int32* array, int32 count);
+ bool writeInt32u (uint32);
+ bool readInt32u (uint32&);
+ bool writeInt32uArray (const uint32* array, int32 count);
+ bool readInt32uArray (uint32* array, int32 count);
+ ///@}
+
+ /** @name read and write int64. */
+ ///@{
+ bool writeInt64 (int64);
+ bool readInt64 (int64&);
+ bool writeInt64Array (const int64* array, int32 count);
+ bool readInt64Array (int64* array, int32 count);
+ bool writeInt64u (uint64);
+ bool readInt64u (uint64&);
+ bool writeInt64uArray (const uint64* array, int32 count);
+ bool readInt64uArray (uint64* array, int32 count);
+ ///@}
+
+ /** @name read and write float and float array. */
+ ///@{
+ bool writeFloat (float);
+ bool readFloat (float&);
+ bool writeFloatArray (const float* array, int32 count);
+ bool readFloatArray (float* array, int32 count);
+ ///@}
+
+ /** @name read and write double and double array. */
+ ///@{
+ bool writeDouble (double);
+ bool readDouble (double&);
+ bool writeDoubleArray (const double* array, int32 count);
+ bool readDoubleArray (double* array, int32 count);
+ ///@}
+
+ /** @name read and write Boolean. */
+ ///@{
+ bool writeBool (bool); ///< Write one boolean
+ bool readBool (bool&); ///< Read one bool.
+ ///@}
+
+ /** @name read and write Strings. */
+ ///@{
+ TSize writeString8 (const char8* ptr, bool terminate = false); ///< a direct output function writing only one string (ascii 8bit)
+ TSize readString8 (char8* ptr, TSize size); ///< a direct input function reading only one string (ascii) (ended by a \n or \0 or eof)
+
+ bool writeStr8 (const char8* ptr); ///< write a string length (strlen) and string itself
+ char8* readStr8 (); ///< read a string length and string text (The return string must be deleted when use is finished)
+
+ static int32 getStr8Size (const char8* ptr); ///< returns the size of a saved string
+
+ bool writeStringUtf8 (const tchar* ptr); ///< always terminated, converts to utf8 if non ascii characters are in string
+ int32 readStringUtf8 (tchar* ptr, int32 maxSize); ///< read a UTF8 string
+ ///@}
+
+ bool skip (uint32 bytes);
+ bool pad (uint32 bytes);
+
+
+//------------------------------------------------------------------------
+protected:
+ int16 byteOrder;
+};
+
+
+//------------------------------------------------------------------------
+/** FStreamSizeHolder Declaration
+ remembers size of stream chunk for backward compatibility.
+
+ Example:
+ @code
+ externalize (a)
+ {
+ FStreamSizeHolder sizeHolder;
+ sizeHolder.beginWrite (); // sets start mark, writes dummy size
+ a << ....
+ sizeHolder.endWrite (); // jumps to start mark, updates size, jumps back here
+ }
+
+ internalize (a)
+ {
+ FStreamSizeHolder sizeHolder;
+ sizeHolder.beginRead (); // reads size, mark
+ a >> ....
+ sizeHolder.endRead (); // jumps forward if new version has larger size
+ }
+ @endcode
+*/
+//------------------------------------------------------------------------
+class FStreamSizeHolder
+{
+public:
+ FStreamSizeHolder (FStreamer &s);
+
+ void beginWrite (); ///< remembers position and writes 0
+ int32 endWrite (); ///< writes and returns size (since the start marker)
+ int32 beginRead (); ///< returns size
+ void endRead (); ///< jump to end of chunk
+
+protected:
+ FStreamer &stream;
+ int64 sizePos;
+};
+
+class IBStream;
+
+//------------------------------------------------------------------------
+// IBStreamer
+//------------------------------------------------------------------------
+/** Wrapper class for typed reading/writing from or to IBStream.
+ Can be used framework-independent in Plug-ins. */
+//------------------------------------------------------------------------
+class IBStreamer: public FStreamer
+{
+public:
+//------------------------------------------------------------------------
+ /** Constructor for a given IBSTream and a byteOrder. */
+ IBStreamer (IBStream* stream, int16 byteOrder = BYTEORDER);
+
+ IBStream* getStream () { return stream; } ///< Returns the associated IBStream.
+
+ // FStreamer overrides:
+ TSize readRaw (void*, TSize) SMTG_OVERRIDE; ///< Read one buffer of size.
+ TSize writeRaw (const void*, TSize) SMTG_OVERRIDE; ///< Write one buffer of size.
+ int64 seek (int64, FSeekMode) SMTG_OVERRIDE; ///< Set file position for stream.
+ int64 tell () SMTG_OVERRIDE; ///< Return current file position.
+//------------------------------------------------------------------------
+protected:
+ IBStream* stream;
+};
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.cpp
new file mode 100644
index 0000000000..bd3a360b6f
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.cpp
@@ -0,0 +1,3996 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fstring.cpp
+// Created by : Steinberg, 2008
+// Description : String class
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "base/source/fstring.h"
+#include "base/source/fdebug.h"
+#include "pluginterfaces/base/futils.h"
+#include "pluginterfaces/base/fvariant.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#if SMTG_OS_WINDOWS
+#include
+#pragma warning (disable : 4244)
+#pragma warning (disable : 4267)
+#pragma warning (disable : 4996)
+
+#if DEVELOPMENT
+#include
+
+#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
+#define realloc(p,s) _realloc_dbg(p,s, _NORMAL_BLOCK, __FILE__, __LINE__)
+#define free(p) _free_dbg(p, _NORMAL_BLOCK)
+
+#endif
+
+#endif
+
+#ifndef kPrintfBufferSize
+#define kPrintfBufferSize 4096
+#endif
+
+#if SMTG_OS_MACOS
+#include
+#include
+#include
+#include
+
+#if defined (__GNUC__) && (__GNUC__ >= 4) && !__LP64__
+// on 32 bit Mac OS X we can safely ignore the format warnings as sizeof(int) == sizeof(long)
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+
+#define SMTG_ENABLE_DEBUG_CFALLOCATOR 0
+#define SMTG_DEBUG_CFALLOCATOR (DEVELOPMENT && SMTG_ENABLE_DEBUG_CFALLOCATOR)
+
+#if SMTG_DEBUG_CFALLOCATOR
+#include
+#include
+#endif
+
+namespace Steinberg {
+#if SMTG_DEBUG_CFALLOCATOR
+static CFAllocatorRef kCFAllocator = NULL;
+
+struct CFStringDebugAllocator : CFAllocatorContext
+{
+ CFStringDebugAllocator ()
+ {
+ version = 0;
+ info = this;
+ retain = nullptr;
+ release = nullptr;
+ copyDescription = nullptr;
+ allocate = allocateCallBack;
+ reallocate = reallocateCallBack;
+ deallocate = deallocateCallBack;
+ preferredSize = preferredSizeCallBack;
+
+ numAllocations = allocationSize = numDeallocations = 0;
+ cfAllocator = CFAllocatorCreate (kCFAllocatorUseContext, this);
+
+ Dl_info info;
+ if (dladdr ((const void*)CFStringDebugAllocator::allocateCallBack, &info))
+ {
+ moduleName = info.dli_fname;
+ }
+ kCFAllocator = cfAllocator;
+ }
+
+ ~CFStringDebugAllocator ()
+ {
+ kCFAllocator = kCFAllocatorDefault;
+ CFRelease (cfAllocator);
+ FDebugPrint ("CFStringDebugAllocator (%s):\n", moduleName.text8 ());
+ FDebugPrint ("\tNumber of allocations : %u\n", numAllocations);
+ FDebugPrint ("\tNumber of deallocations: %u\n", numDeallocations);
+ FDebugPrint ("\tAllocated Bytes : %u\n", allocationSize);
+ }
+
+ String moduleName;
+ CFAllocatorRef cfAllocator;
+ volatile int64_t numAllocations;
+ volatile int64_t numDeallocations;
+ volatile int64_t allocationSize;
+
+ void* doAllocate (CFIndex allocSize, CFOptionFlags hint)
+ {
+ void* ptr = CFAllocatorAllocate (kCFAllocatorDefault, allocSize, hint);
+ OSAtomicIncrement64 (&numAllocations);
+ OSAtomicAdd64 (allocSize, &allocationSize);
+ return ptr;
+ }
+ void* doReallocate (void* ptr, CFIndex newsize, CFOptionFlags hint)
+ {
+ void* newPtr = CFAllocatorReallocate (kCFAllocatorDefault, ptr, newsize, hint);
+ return newPtr;
+ }
+ void doDeallocate (void* ptr)
+ {
+ CFAllocatorDeallocate (kCFAllocatorDefault, ptr);
+ OSAtomicIncrement64 (&numDeallocations);
+ }
+ CFIndex getPreferredSize (CFIndex size, CFOptionFlags hint)
+ {
+ return CFAllocatorGetPreferredSizeForSize (kCFAllocatorDefault, size, hint);
+ }
+
+ static void* allocateCallBack (CFIndex allocSize, CFOptionFlags hint, void* info)
+ {
+ return static_cast (info)->doAllocate (allocSize, hint);
+ }
+ static void* reallocateCallBack (void* ptr, CFIndex newsize, CFOptionFlags hint, void* info)
+ {
+ return static_cast (info)->doReallocate (ptr, newsize, hint);
+ }
+
+ static void deallocateCallBack (void* ptr, void* info)
+ {
+ static_cast (info)->doDeallocate (ptr);
+ }
+ static CFIndex preferredSizeCallBack (CFIndex size, CFOptionFlags hint, void* info)
+ {
+ return static_cast (info)->getPreferredSize (size, hint);
+ }
+};
+static CFStringDebugAllocator gDebugAllocator;
+#else
+
+static const CFAllocatorRef kCFAllocator = ::kCFAllocatorDefault;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+static void* toCFStringRef (const Steinberg::char8* source, Steinberg::uint32 encoding)
+{
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingASCII;
+ if (source)
+ return (void*)CFStringCreateWithCString (Steinberg::kCFAllocator, source, encoding);
+ else
+ return (void*)CFStringCreateWithCString (Steinberg::kCFAllocator, "", encoding);
+}
+
+//-----------------------------------------------------------------------------
+static bool fromCFStringRef (Steinberg::char8* dest, Steinberg::int32 destSize, const void* cfStr, Steinberg::uint32 encoding)
+{
+ CFIndex usedBytes;
+ CFRange range = {0, CFStringGetLength ((CFStringRef)cfStr)};
+ bool result = CFStringGetBytes ((CFStringRef)cfStr, range, encoding, '?', false, (UInt8*)dest, destSize, &usedBytes);
+ dest[usedBytes] = 0;
+ return result;
+}
+#endif // SMTG_OS_MACOS
+
+#if SMTG_OS_WINDOWS
+#define stricmp16 wcsicmp
+#define strnicmp16 wcsnicmp
+#define strrchr16 wcsrchr
+#define sprintf16 swprintf
+#define snprintf16 snwprintf
+#define vsnprintf16 vsnwprintf
+#define vsprintf16 wvsprintf
+#define vfprintf16 vfwprintf
+#define sscanf16 swscanf
+#define toupper16 towupper
+#define tolower16 towlower
+#define isupper16 iswupper
+#define islower16 iswlower
+#define isspace16 iswspace
+#define isalpha16 iswalpha
+#define isdigit16 iswdigit
+#define isalnum16 iswalnum
+
+#define stricmp _stricmp
+#define strnicmp _strnicmp
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define snwprintf _snwprintf
+#define vsnwprintf _vsnwprintf
+
+#define wtoi _wtoi
+#define wtol _wtol
+#define wtof _wtof
+
+#elif SMTG_OS_LINUX
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using ConverterFacet = std::codecvt_utf8_utf16;
+using Converter = std::wstring_convert;
+
+//------------------------------------------------------------------------
+static ConverterFacet& converterFacet ()
+{
+ static ConverterFacet gFacet;
+ return gFacet;
+}
+
+//------------------------------------------------------------------------
+static Converter& converter ()
+{
+ static Converter gConverter;
+ return gConverter;
+}
+
+//-----------------------------------------------------------------------------
+static inline int stricasecmp (const Steinberg::char8* s1, const Steinberg::char8* s2)
+{
+ return ::strcasecmp (s1, s2);
+}
+
+//-----------------------------------------------------------------------------
+static inline int strnicasecmp (const Steinberg::char8* s1, const Steinberg::char8* s2, size_t n)
+{
+ return ::strncasecmp (s1, s2, n);
+}
+
+//-----------------------------------------------------------------------------
+static inline int stricmp16 (const Steinberg::char16* s1, const Steinberg::char16* s2)
+{
+ auto str1 = converter ().to_bytes (s1);
+ auto str2 = converter ().to_bytes (s2);
+ return stricasecmp (str1.data (), str2.data ());
+}
+
+//-----------------------------------------------------------------------------
+static inline int strnicmp16 (const Steinberg::char16* s1, const Steinberg::char16* s2, int n)
+{
+ auto str1 = converter ().to_bytes (s1);
+ auto str2 = converter ().to_bytes (s2);
+ return strnicasecmp (str1.data (), str2.data (), n);
+}
+
+//-----------------------------------------------------------------------------
+static inline int sprintf16 (Steinberg::char16* wcs, const Steinberg::char16* format, ...)
+{
+#warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+static inline int vsnwprintf (Steinberg::char16* wcs, size_t maxlen,
+ const Steinberg::char16* format, va_list args)
+{
+ Steinberg::char8 str8[kPrintfBufferSize];
+ auto format_utf8 = converter ().to_bytes(format);
+ auto len = vsnprintf (str8, kPrintfBufferSize, format_utf8.data (), args);
+
+ auto tmp_str = converter ().from_bytes (str8, str8 + len);
+ auto target_len = std::min (tmp_str.size (), maxlen - 1);
+ tmp_str.copy (wcs, target_len);
+ wcs[target_len] = '\0';
+
+ return tmp_str.size ();
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::char16* strrchr16 (const Steinberg::char16* str, Steinberg::char16 c)
+{
+#warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ return nullptr;
+}
+
+#elif SMTG_OS_MACOS
+#define tstrtoi64 strtoll
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 strnicmp16 (const Steinberg::char16* str1, const Steinberg::char16* str2, size_t size)
+{
+ if (size == 0)
+ return 0;
+
+ CFIndex str1Len = Steinberg::strlen16 (str1);
+ CFIndex str2Len = Steinberg::strlen16 (str2);
+ if (size < str2Len) // range is not applied to second string
+ str2Len = size;
+ CFStringRef cfStr1 = CFStringCreateWithCharactersNoCopy (Steinberg::kCFAllocator, (UniChar*)str1, str1Len, kCFAllocatorNull);
+ CFStringRef cfStr2 = CFStringCreateWithCharactersNoCopy (Steinberg::kCFAllocator, (UniChar*)str2, str2Len, kCFAllocatorNull);
+ CFComparisonResult result = CFStringCompareWithOptions (cfStr1, cfStr2, CFRangeMake (0, size), kCFCompareCaseInsensitive);
+ CFRelease (cfStr1);
+ CFRelease (cfStr2);
+ switch (result)
+ {
+ case kCFCompareEqualTo: return 0;
+ case kCFCompareLessThan: return -1;
+ case kCFCompareGreaterThan:
+ default: return 1;
+ };
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 stricmp16 (const Steinberg::char16* str1, CFIndex str1Len, const Steinberg::char16* str2, CFIndex str2Len)
+{
+ CFStringRef cfStr1 = CFStringCreateWithCharactersNoCopy (Steinberg::kCFAllocator, (UniChar*)str1, str1Len, kCFAllocatorNull);
+ CFStringRef cfStr2 = CFStringCreateWithCharactersNoCopy (Steinberg::kCFAllocator, (UniChar*)str2, str2Len, kCFAllocatorNull);
+ CFComparisonResult result = CFStringCompare (cfStr1, cfStr2, kCFCompareCaseInsensitive);
+ CFRelease (cfStr1);
+ CFRelease (cfStr2);
+ switch (result)
+ {
+ case kCFCompareEqualTo: return 0;
+ case kCFCompareLessThan: return -1;
+ case kCFCompareGreaterThan:
+ default: return 1;
+ };
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 stricmp16 (const Steinberg::ConstString& str1, const Steinberg::ConstString& str2)
+{
+ return stricmp16 (str1.text16 (), str1.length (), str2.text16 (), str2.length ());
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 stricmp16 (const Steinberg::char16* str1, const Steinberg::char16* str2)
+{
+ CFIndex str1Len = Steinberg::strlen16 (str1);
+ CFIndex str2Len = Steinberg::strlen16 (str2);
+ return stricmp16 (str1, str1Len, str2, str2Len);
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::char16* strrchr16 (const Steinberg::char16* str, Steinberg::char16 c)
+{
+ Steinberg::int32 len = Steinberg::ConstString (str).length ();
+ while (len > 0)
+ {
+ if (str[len] == c)
+ return const_cast(str + len);
+ len--;
+ }
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 vsnwprintf (Steinberg::char16* str, Steinberg::int32 size, const Steinberg::char16* format, va_list ap)
+{
+ // wrapped using CoreFoundation's CFString
+ CFMutableStringRef formatString = (CFMutableStringRef)Steinberg::ConstString (format).toCFStringRef (0xFFFF, true);
+ CFStringFindAndReplace (formatString, CFSTR("%s"), CFSTR("%S"), CFRangeMake (0, CFStringGetLength (formatString)), 0);
+ CFStringRef resultString = CFStringCreateWithFormatAndArguments (Steinberg::kCFAllocator, 0, formatString, ap);
+ CFRelease (formatString);
+ if (resultString)
+ {
+ Steinberg::String res;
+ res.fromCFStringRef (resultString);
+ res.copyTo16 (str, 0, size);
+ CFRelease (resultString);
+ return 0;
+ }
+ return 1;
+}
+
+//-----------------------------------------------------------------------------
+static inline Steinberg::int32 sprintf16 (Steinberg::char16* str, const Steinberg::char16* format, ...)
+{
+ va_list marker;
+ va_start (marker, format);
+ return vsnwprintf (str, -1, format, marker);
+}
+
+#endif
+
+/*
+UTF-8 EF BB BF
+UTF-16 Big Endian FE FF
+UTF-16 Little Endian FF FE
+UTF-32 Big Endian 00 00 FE FF
+UTF-32 Little Endian FF FE 00 00
+*/
+
+namespace Steinberg {
+
+//-----------------------------------------------------------------------------
+static inline bool isCaseSensitive (ConstString::CompareMode mode)
+{
+ return mode == ConstString::kCaseSensitive;
+}
+
+//-----------------------------------------------------------------------------
+// ConstString
+//-----------------------------------------------------------------------------
+ConstString::ConstString (const char8* str, int32 length)
+: buffer8 ((char8*)str)
+, len (length < 0 ? (str ? static_cast (strlen (str)) : 0) : length)
+, isWide (0)
+{
+}
+
+//-----------------------------------------------------------------------------
+ConstString::ConstString (const char16* str, int32 length)
+: buffer16 ((char16*)str)
+, len (length < 0 ? (str ? strlen16 (str) : 0) : length)
+, isWide (1)
+{
+}
+
+//-----------------------------------------------------------------------------
+ConstString::ConstString (const ConstString& str, int32 offset, int32 length)
+: buffer (str.buffer)
+, len (length < 0 ? (str.len - (offset > 0 ? offset : 0)) : length)
+, isWide (str.isWide)
+{
+ if (offset > 0)
+ {
+ if (isWide)
+ buffer16 += offset;
+ else
+ buffer8 += offset;
+ }
+}
+
+//-----------------------------------------------------------------------------
+ConstString::ConstString (const FVariant& var)
+: buffer (0)
+, len (0)
+, isWide (0)
+{
+ switch (var.getType ())
+ {
+ case FVariant::kString8:
+ buffer8 = (char8*)var.getString8 ();
+ len = buffer8 ? strlen8 (buffer8) : 0;
+ isWide = false;
+ break;
+
+ case FVariant::kString16:
+ buffer16 = (char16*)var.getString16 ();
+ len = buffer16 ? strlen16 (buffer16) : 0;
+ isWide = true;
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+ConstString::ConstString ()
+: buffer (0)
+, len (0)
+, isWide (0)
+{
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::testChar8 (uint32 index, char8 c) const
+{
+ if (index >= len)
+ return c == 0;
+ if (isWide)
+ {
+ // make c wide
+ char8 src[] = {c, 0};
+ char16 dest[2] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ return buffer16[index] == dest[0];
+ return false;
+ }
+ return buffer8[index] == c;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::testChar16 (uint32 index, char16 c) const
+{
+ if (index >= len)
+ return c == 0;
+ if (!isWide)
+ {
+ // make c ansi
+ char16 src[] = {c, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ return buffer8[index] == dest[0];
+ return false;
+ }
+ return buffer16[index] == c;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::extract (String& result, uint32 idx, int32 n) const
+{
+ if (len == 0|| idx >= len)
+ return false;
+
+ if ((idx + n > len) || n < 0)
+ n = len - idx;
+
+ if (isWide)
+ result.assign (buffer16 + idx, n);
+ else
+ result.assign (buffer8 + idx, n);
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::copyTo8 (char8* str, uint32 idx, int32 n) const
+{
+ if (!str)
+ return 0;
+
+ if (isWide)
+ {
+ String tmp (text16 ());
+ if (tmp.toMultiByte () == false)
+ return 0;
+ return tmp.copyTo8 (str, idx, n);
+ }
+
+ if (isEmpty () || idx >= len || !buffer8)
+ {
+ str[0] = 0;
+ return 0;
+ }
+
+ if ((idx + n > len) || n < 0)
+ n = len - idx;
+
+ memcpy (str, &(buffer8[idx]), n * sizeof (char8));
+ str[n] = 0;
+ return n;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::copyTo16 (char16* str, uint32 idx, int32 n) const
+{
+ if (!str)
+ return 0;
+
+ if (!isWide)
+ {
+ String tmp (text8 ());
+ if (tmp.toWideString () == false)
+ return 0;
+ return tmp.copyTo16 (str, idx, n);
+ }
+
+ if (isEmpty () || idx >= len || !buffer16)
+ {
+ str[0] = 0;
+ return 0;
+ }
+
+ if ((idx + n > len) || n < 0)
+ n = len - idx;
+
+ memcpy (str, &(buffer16[idx]), n * sizeof (char16));
+ str[n] = 0;
+ return n;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::copyTo (tchar* str, uint32 idx, int32 n) const
+{
+#ifdef UNICODE
+ return copyTo16 (str, idx, n);
+#else
+ return copyTo8 (str, idx, n);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+void ConstString::copyTo (IStringResult* result) const
+{
+ if (isWideString () == false)
+ {
+ result->setText (text8 ());
+ }
+ else
+ {
+ FUnknownPtr iStr (result);
+ if (iStr)
+ {
+ iStr->setText16 (text16 ());
+ }
+ else
+ {
+ String tmp (*this);
+ tmp.toMultiByte ();
+ result->setText (tmp.text8 ());
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+void ConstString::copyTo (IString& string) const
+{
+ if (isWideString ())
+ string.setText16 (text16 ());
+ else
+ string.setText8 (text8 ());
+}
+
+
+
+//-----------------------------------------------------------------------------
+int32 ConstString::compare (const ConstString& str, int32 n, CompareMode mode) const
+{
+ if (n == 0)
+ return 0;
+
+ if (str.isEmpty ())
+ {
+ if (isEmpty ())
+ return 0;
+ return 1;
+ }
+ else if (isEmpty ())
+ return -1;
+
+ if (!isWide && !str.isWide)
+ {
+ if (n < 0)
+ {
+ if (isCaseSensitive (mode))
+ return strcmp (*this, str);
+ else
+ return stricmp (*this, str);
+ }
+ else
+ {
+ if (isCaseSensitive (mode))
+ return strncmp (*this, str, n);
+ else
+ return strnicmp (*this, str, n);
+ }
+ }
+ else if (isWide && str.isWide)
+ {
+ if (n < 0)
+ {
+ if (isCaseSensitive (mode))
+ return strcmp16 (*this, str);
+ else
+ return stricmp16 (*this, str);
+ }
+ else
+ {
+ if (isCaseSensitive (mode))
+ return strncmp16 (*this, str, n);
+ else
+ return strnicmp16 (*this, str, n);
+ }
+ }
+ return compareAt (0, str, n, mode);
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::compare (const ConstString& str, CompareMode mode) const
+{
+ return compare (str, -1, mode);
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::compareAt (uint32 index, const ConstString& str, int32 n, CompareMode mode) const
+{
+ if (n == 0)
+ return 0;
+
+ if (str.isEmpty ())
+ {
+ if (isEmpty ())
+ return 0;
+ return 1;
+ }
+ else if (isEmpty ())
+ return -1;
+
+ if (!isWide && !str.isWide)
+ {
+ char8* toCompare = buffer8;
+ if (index > 0)
+ {
+ if (index >= len)
+ {
+ if (str.isEmpty ())
+ return 0;
+ return -1;
+ }
+ toCompare += index;
+ }
+
+ if (n < 0)
+ {
+ if (isCaseSensitive (mode))
+ return strcmp (toCompare, str);
+ else
+ return stricmp (toCompare, str);
+ }
+ else
+ {
+ if (isCaseSensitive (mode))
+ return strncmp (toCompare, str, n);
+ else
+ return strnicmp (toCompare, str, n);
+ }
+ }
+ else if (isWide && str.isWide)
+ {
+ char16* toCompare = buffer16;
+ if (index > 0)
+ {
+ if (index >= len)
+ {
+ if (str.isEmpty ())
+ return 0;
+ return -1;
+ }
+ toCompare += index;
+ }
+
+ if (n < 0)
+ {
+ if (isCaseSensitive (mode))
+ return strcmp16 (toCompare, str.text16 ());
+ else
+ return stricmp16 (toCompare, str.text16 ());
+ }
+ else
+ {
+ if (isCaseSensitive (mode))
+ return strncmp16 (toCompare, str.text16 (), n);
+ else
+ return strnicmp16 (toCompare, str.text16 (), n);
+ }
+ }
+ else
+ {
+ if (isWide)
+ {
+ String tmp (str.text8 ());
+ if (tmp.toWideString () == false)
+ return -1;
+ return compareAt (index, tmp, n, mode);
+ }
+ else
+ {
+ String tmp (text8 ());
+ if (tmp.toWideString () == false)
+ return 1;
+ return tmp.compareAt (index, str, n, mode);
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+Steinberg::int32 ConstString::naturalCompare (const ConstString& str, CompareMode mode /*= kCaseSensitive*/) const
+{
+ if (str.isEmpty ())
+ {
+ if (isEmpty ())
+ return 0;
+ return 1;
+ }
+ else if (isEmpty ())
+ return -1;
+
+ if (!isWide && !str.isWide)
+ return strnatcmp8 (buffer8, str.text8 (), isCaseSensitive (mode));
+ else if (isWide && str.isWide)
+ return strnatcmp16 (buffer16, str.text16 (), isCaseSensitive (mode));
+ else
+ {
+ if (isWide)
+ {
+ String tmp (str.text8 ());
+ tmp.toWideString ();
+ return strnatcmp16 (buffer16, tmp.text16 (), isCaseSensitive (mode));
+ }
+ else
+ {
+ String tmp (text8 ());
+ tmp.toWideString ();
+ return strnatcmp16 (tmp.text16 (), str.text16 (), isCaseSensitive (mode));
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::startsWith (const ConstString& str, CompareMode mode /*= kCaseSensitive*/) const
+{
+ if (str.isEmpty ())
+ {
+ return isEmpty ();
+ }
+ else if (isEmpty ())
+ {
+ return false;
+ }
+ if (length () < str.length ())
+ {
+ return false;
+ }
+ if (!isWide && !str.isWide)
+ {
+ if (isCaseSensitive (mode))
+ return strncmp (buffer8, str.buffer8, str.length ()) == 0;
+ return strnicmp (buffer8, str.buffer8, str.length ()) == 0;
+ }
+ else if (isWide && str.isWide)
+ {
+ if (isCaseSensitive (mode))
+ return strncmp16 (buffer16, str.buffer16, str.length ()) == 0;
+ return strnicmp16 (buffer16, str.buffer16, str.length ()) == 0;
+ }
+ else if (isWide)
+ {
+ String tmp (str.text8 ());
+ tmp.toWideString ();
+ if (tmp.length () > length ())
+ return false;
+ if (isCaseSensitive (mode))
+ return strncmp16 (buffer16, tmp.buffer16, tmp.length ()) == 0;
+ return strnicmp16 (buffer16, tmp.buffer16, tmp.length ()) == 0;
+ }
+ else
+ {
+ String tmp (text8 ());
+ tmp.toWideString ();
+ if (str.length () > tmp.length ())
+ return false;
+ if (isCaseSensitive (mode))
+ return strncmp16 (tmp.buffer16, str.buffer16, str.length ()) == 0;
+ return strnicmp16 (tmp.buffer16, str.buffer16, str.length ()) == 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::endsWith (const ConstString& str, CompareMode mode /*= kCaseSensitive*/) const
+{
+ if (str.isEmpty ())
+ {
+ return isEmpty ();
+ }
+ else if (isEmpty ())
+ {
+ return false;
+ }
+ if (length () < str.length ())
+ {
+ return false;
+ }
+ if (!isWide && !str.isWide)
+ {
+ if (isCaseSensitive (mode))
+ return strncmp (buffer8 + (length () - str.length ()), str.buffer8, str.length ()) == 0;
+ return strnicmp (buffer8 + (length () - str.length ()), str.buffer8, str.length ()) == 0;
+ }
+ else if (isWide && str.isWide)
+ {
+ if (isCaseSensitive (mode))
+ return strncmp16 (buffer16 + (length () - str.length ()), str.buffer16, str.length ()) == 0;
+ return strnicmp16 (buffer16 + (length () - str.length ()), str.buffer16, str.length ()) == 0;
+ }
+ else if (isWide)
+ {
+ String tmp (str.text8 ());
+ tmp.toWideString ();
+ if (tmp.length () > length ())
+ return false;
+ if (isCaseSensitive (mode))
+ return strncmp16 (buffer16 + (length () - tmp.length ()), tmp.buffer16, tmp.length ()) == 0;
+ return strnicmp16 (buffer16 + (length () - tmp.length ()), tmp.buffer16, tmp.length ()) == 0;
+ }
+ else
+ {
+ String tmp (text8 ());
+ tmp.toWideString ();
+ if (str.length () > tmp.length ())
+ return false;
+ if (isCaseSensitive (mode))
+ return strncmp16 (tmp.buffer16 + (tmp.length () - str.length ()), str.buffer16, str.length ()) == 0;
+ return strnicmp16 (tmp.buffer16 + (tmp.length () - str.length ()), str.buffer16, str.length ()) == 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::contains (const ConstString& str, CompareMode m) const
+{
+ return findFirst (str, -1, m) != -1;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::findNext (int32 startIndex, const ConstString& str, int32 n, CompareMode mode, int32 endIndex) const
+{
+ uint32 endLength = len;
+ if (endIndex > -1 && (uint32)endIndex < len)
+ endLength = endIndex + 1;
+
+ if (isWide && str.isWide)
+ {
+ if (startIndex < 0)
+ startIndex = 0;
+
+ uint32 stringLength = str.length ();
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (n > 0)
+ {
+ uint32 i = 0;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i < endLength; i++)
+ if (strncmp16 (buffer16 + i, str, n) == 0)
+ return i;
+ }
+ else
+ {
+ for (i = startIndex; i < endLength; i++)
+ if (strnicmp16 (buffer16 + i, str, n) == 0)
+ return i;
+ }
+ }
+ return -1;
+ }
+ else if (!isWide && !str.isWide)
+ {
+ uint32 stringLength = str.length ();
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (startIndex < 0)
+ startIndex = 0;
+
+ if (n > 0)
+ {
+ uint32 i = 0;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i < endLength; i++)
+ if (strncmp (buffer8 + i, str, n) == 0)
+ return i;
+ }
+ else
+ {
+ for (i = startIndex; i < endLength; i++)
+ if (strnicmp (buffer8 + i, str, n) == 0)
+ return i;
+ }
+ }
+ return -1;
+ }
+ String tmp;
+ if (isWide)
+ {
+ tmp = str.text8 ();
+ tmp.toWideString ();
+ return findNext (startIndex, tmp, n , mode, endIndex);
+ }
+ tmp = text8 ();
+ tmp.toWideString ();
+ return tmp.findNext (startIndex, str, n, mode, endIndex);
+}
+
+//------------------------------------------------------------------------------------------------
+int32 ConstString::findNext (int32 startIndex, char8 c, CompareMode mode, int32 endIndex) const
+{
+ uint32 endLength = len;
+ if (endIndex > -1 && (uint32)endIndex < len)
+ endLength = endIndex + 1;
+
+ if (isWide)
+ {
+ char8 src[] = {c, 0};
+ char16 dest[8] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ return findNext (startIndex, dest[0], mode, endIndex);
+ return -1;
+ }
+
+ if (startIndex < 0)
+ startIndex = 0;
+ uint32 i;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i < endLength; i++)
+ {
+ if (buffer8[i] == c)
+ return i;
+ }
+ }
+ else
+ {
+ c = toLower (c);
+ for (i = startIndex; i < endLength; i++)
+ {
+ if (toLower (buffer8[i]) == c)
+ return i;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::findNext (int32 startIndex, char16 c, CompareMode mode, int32 endIndex) const
+{
+ uint32 endLength = len;
+ if (endIndex > -1 && (uint32)endIndex < len)
+ endLength = endIndex + 1;
+
+ if (!isWide)
+ {
+ char16 src[] = {c, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ return findNext (startIndex, dest[0], mode, endIndex);
+
+ return -1;
+ }
+
+ uint32 i;
+ if (startIndex < 0)
+ startIndex = 0;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i < endLength; i++)
+ {
+ if (buffer16[i] == c)
+ return i;
+ }
+ }
+ else
+ {
+ c = toLower (c);
+ for (i = startIndex; i < endLength; i++)
+ {
+ if (toLower (buffer16[i]) == c)
+ return i;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::findPrev (int32 startIndex, char8 c, CompareMode mode) const
+{
+ if (len == 0)
+ return -1;
+
+ if (isWide)
+ {
+ char8 src[] = {c, 0};
+ char16 dest[8] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ return findPrev (startIndex, dest[0], mode);
+ return -1;
+ }
+
+ if (startIndex < 0 || startIndex > (int32)len)
+ startIndex = len;
+
+ int32 i;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i >= 0; i--)
+ {
+ if (buffer8[i] == c)
+ return i;
+ }
+ }
+ else
+ {
+ c = toLower (c);
+ for (i = startIndex; i >= 0; i--)
+ {
+ if (toLower (buffer8[i]) == c)
+ return i;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::findPrev (int32 startIndex, char16 c, CompareMode mode) const
+{
+ if (len == 0)
+ return -1;
+
+ if (!isWide)
+ {
+ char16 src[] = {c, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ return findPrev (startIndex, dest[0], mode);
+
+ return -1;
+ }
+
+ if (startIndex < 0 || startIndex > (int32)len)
+ startIndex = len;
+
+ int32 i;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i >= 0; i--)
+ {
+ if (buffer16[i] == c)
+ return i;
+ }
+ }
+ else
+ {
+ c = toLower (c);
+ for (i = startIndex; i >= 0; i--)
+ {
+ if (toLower (buffer16[i]) == c)
+ return i;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::findPrev (int32 startIndex, const ConstString& str, int32 n, CompareMode mode) const
+{
+ if (isWide && str.isWide)
+ {
+ uint32 stringLength = str.length ();
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (startIndex < 0 || startIndex >= (int32)len)
+ startIndex = len - 1;
+
+ if (n > 0)
+ {
+ int32 i = 0;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i >= 0; i--)
+ if (strncmp16 (buffer16 + i, str, n) == 0)
+ return i;
+ }
+ else
+ {
+ for (i = startIndex; i >= 0; i--)
+ if (strnicmp16 (buffer16 + i, str, n) == 0)
+ return i;
+ }
+ }
+ return -1;
+ }
+ else if (!isWide && !str.isWide)
+ {
+ uint32 stringLength = str.length ();
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (startIndex < 0 || startIndex >= (int32)len)
+ startIndex = len - 1;
+
+ if (n > 0)
+ {
+ int32 i = 0;
+
+ if (isCaseSensitive (mode))
+ {
+ for (i = startIndex; i >= 0; i--)
+ if (strncmp (buffer8 + i, str, n) == 0)
+ return i;
+ }
+ else
+ {
+ for (i = startIndex; i >= 0; i--)
+ if (strnicmp (buffer8 + i, str, n) == 0)
+ return i;
+ }
+ }
+ return -1;
+ }
+ if (isWide)
+ {
+ String tmp (str.text8 ());
+ tmp.toWideString ();
+ return findPrev (startIndex, tmp, n, mode);
+ }
+ String tmp (text8 ());
+ tmp.toWideString ();
+ return tmp.findPrev (startIndex, str, n, mode);
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::countOccurences (char8 c, uint32 startIndex, CompareMode mode) const
+{
+ if (isWide)
+ {
+ char8 src[] = {c, 0};
+ char16 dest[8] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ return countOccurences (dest[0], startIndex, mode);
+ return -1;
+ }
+
+ int32 result = 0;
+ int32 next = startIndex;
+ while (true)
+ {
+ next = findNext (next, c, mode);
+ if (next >= 0)
+ {
+ next++;
+ result++;
+ }
+ else
+ break;
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::countOccurences (char16 c, uint32 startIndex, CompareMode mode) const
+{
+ if (!isWide)
+ {
+ char16 src[] = {c, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ return countOccurences (dest[0], startIndex, mode);
+
+ return -1;
+ }
+ int32 result = 0;
+ int32 next = startIndex;
+ while (true)
+ {
+ next = findNext (next, c, mode);
+ if (next >= 0)
+ {
+ next++;
+ result++;
+ }
+ else
+ break;
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::getFirstDifferent (const ConstString& str, CompareMode mode) const
+{
+ if (str.isWide != isWide)
+ {
+ if (isWide)
+ {
+ String tmp (str.text8 ());
+ if (tmp.toWideString () == false)
+ return -1;
+ return getFirstDifferent (tmp, mode);
+ }
+ else
+ {
+ String tmp (text8 ());
+ if (tmp.toWideString () == false)
+ return -1;
+ return tmp.getFirstDifferent (str, mode);
+ }
+ }
+
+ uint32 len1 = len;
+ uint32 len2 = str.len;
+ uint32 i;
+
+ if (isWide)
+ {
+ if (isCaseSensitive (mode))
+ {
+ for (i = 0; i <= len1 && i <= len2; i++)
+ {
+ if (buffer16[i] != str.buffer16[i])
+ return i;
+ }
+ }
+ else
+ {
+ for (i = 0; i <= len1 && i <= len2; i++)
+ {
+ if (toLower (buffer16[i]) != toLower (str.buffer16[i]))
+ return i;
+ }
+ }
+ }
+ else
+ {
+ if (isCaseSensitive (mode))
+ {
+ for (i = 0; i <= len1 && i <= len2; i++)
+ {
+ if (buffer8[i] != str.buffer8[i])
+ return i;
+ }
+ }
+ else
+ {
+ for (i = 0; i <= len1 && i <= len2; i++)
+ {
+ if (toLower (buffer8[i]) != toLower (str.buffer8[i]))
+ return i;
+ }
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanInt64 (int64& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ if (isWide)
+ return scanInt64_16 (buffer16 + offset, value, scanToEnd);
+ else
+ return scanInt64_8 (buffer8 + offset, value, scanToEnd);
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanUInt64 (uint64& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ if (isWide)
+ return scanUInt64_16 (buffer16 + offset, value, scanToEnd);
+ else
+ return scanUInt64_8 (buffer8 + offset, value, scanToEnd);
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanHex (uint8& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ if (isWide)
+ return scanHex_16 (buffer16 + offset, value, scanToEnd);
+ else
+ return scanHex_8 (buffer8 + offset, value, scanToEnd);
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanInt32 (int32& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ if (isWide)
+ return scanInt32_16 (buffer16 + offset, value, scanToEnd);
+ else
+ return scanInt32_8 (buffer8 + offset, value, scanToEnd);
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanUInt32 (uint32& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ if (isWide)
+ return scanUInt32_16 (buffer16 + offset, value, scanToEnd);
+ else
+ return scanUInt32_8 (buffer8 + offset, value, scanToEnd);
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanInt64_8 (const char8* text, int64& value, bool scanToEnd)
+{
+ while (text && text[0])
+ {
+ if (sscanf (text, "%" FORMAT_INT64A, &value) == 1)
+ return true;
+ else if (scanToEnd == false)
+ return false;
+ text++;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanInt64_16 (const char16* text, int64& value, bool scanToEnd)
+{
+ if (text && text[0])
+ {
+ String str (text);
+ str.toMultiByte (kCP_Default);
+ return scanInt64_8 (str, value, scanToEnd);
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanUInt64_8 (const char8* text, uint64& value, bool scanToEnd)
+{
+ while (text && text[0])
+ {
+ if (sscanf (text, "%" FORMAT_UINT64A, &value) == 1)
+ return true;
+ else if (scanToEnd == false)
+ return false;
+ text++;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanUInt64_16 (const char16* text, uint64& value, bool scanToEnd)
+{
+ if (text && text[0])
+ {
+ String str (text);
+ str.toMultiByte (kCP_Default);
+ return scanUInt64_8 (str, value, scanToEnd);
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanInt64 (const tchar* text, int64& value, bool scanToEnd)
+{
+#ifdef UNICODE
+ return scanInt64_16 (text, value,scanToEnd);
+#else
+ return scanInt64_8 (text, value, scanToEnd);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanUInt64 (const tchar* text, uint64& value, bool scanToEnd)
+{
+#ifdef UNICODE
+ return scanUInt64_16 (text, value, scanToEnd);
+#else
+ return scanUInt64_8 (text, value, scanToEnd);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanHex_8 (const char8* text, uint8& value, bool scanToEnd)
+{
+ while (text && text[0])
+ {
+ unsigned int v; // scanf expects an unsigned int for %x
+ if (sscanf (text, "%x", &v) == 1)
+ {
+ value = (uint8)v;
+ return true;
+ }
+ else if (scanToEnd == false)
+ return false;
+ text++;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanHex_16 (const char16* text, uint8& value, bool scanToEnd)
+{
+ if (text && text[0])
+ {
+ String str (text);
+ str.toMultiByte (kCP_Default); // scanf uses default codepage
+ return scanHex_8 (str, value, scanToEnd);
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanHex (const tchar* text, uint8& value, bool scanToEnd)
+{
+#ifdef UNICODE
+ return scanHex_16 (text, value, scanToEnd);
+#else
+ return scanHex_8 (text, value, scanToEnd);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::scanFloat (double& value, uint32 offset, bool scanToEnd) const
+{
+ if (isEmpty () || offset >= len)
+ return false;
+
+ String str (*this);
+ int32 pos = -1;
+ if (isWide)
+ {
+ if ((pos = str.findNext (offset, STR(','))) >= 0 && ((uint32)pos) >= offset)
+ str.setChar (pos, STR('.'));
+
+ str.toMultiByte (kCP_Default); // scanf uses default codepage
+ }
+ else
+ {
+ if ((pos = str.findNext (offset, ',')) >= 0 && ((uint32)pos) >= offset)
+ str.setChar (pos, '.');
+ }
+
+ const char8* txt = str.text8 () + offset;
+ while (txt && txt[0])
+ {
+ if (sscanf (txt, "%lf", &value) == 1)
+ return true;
+ else if (scanToEnd == false)
+ return false;
+ txt++;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+char16 ConstString::toLower (char16 c)
+{
+ #if SMTG_OS_WINDOWS
+ WCHAR temp[2] = {c, 0};
+ ::CharLowerW (temp);
+ return temp[0];
+ #elif SMTG_OS_MACOS
+ // only convert characters which in lowercase are also single characters
+ UniChar characters [2] = {0};
+ characters[0] = c;
+ CFMutableStringRef str = CFStringCreateMutableWithExternalCharactersNoCopy (kCFAllocator, characters, 1, 2, kCFAllocatorNull);
+ if (str)
+ {
+ CFStringLowercase (str, NULL);
+ CFRelease (str);
+ if (characters[1] == 0)
+ return characters[0];
+ }
+ return c;
+ #elif SMTG_OS_LINUX
+ #warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ return c;
+ #else
+ return towlower (c);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+char16 ConstString::toUpper (char16 c)
+{
+ #if SMTG_OS_WINDOWS
+ WCHAR temp[2] = {c, 0};
+ ::CharUpperW (temp);
+ return temp[0];
+ #elif SMTG_OS_MACOS
+ // only convert characters which in uppercase are also single characters (don't translate a sharp-s which would result in SS)
+ UniChar characters [2] = {0};
+ characters[0] = c;
+ CFMutableStringRef str = CFStringCreateMutableWithExternalCharactersNoCopy (kCFAllocator, characters, 1, 2, kCFAllocatorNull);
+ if (str)
+ {
+ CFStringUppercase (str, NULL);
+ CFRelease (str);
+ if (characters[1] == 0)
+ return characters[0];
+ }
+ return c;
+ #elif SMTG_OS_LINUX
+ #warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ return c;
+ #else
+ return towupper (c);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+char8 ConstString::toLower (char8 c)
+{
+ if ((c >= 'A') && (c <= 'Z'))
+ return c + ('a' - 'A');
+ #if SMTG_OS_WINDOWS
+ CHAR temp[2] = {c, 0};
+ ::CharLowerA (temp);
+ return temp[0];
+ #else
+ return tolower (c);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+char8 ConstString::toUpper (char8 c)
+{
+ if ((c >= 'a') && (c <= 'z'))
+ return c - ('a' - 'A');
+ #if SMTG_OS_WINDOWS
+ CHAR temp[2] = {c, 0};
+ ::CharUpperA (temp);
+ return temp[0];
+ #else
+ return toupper (c);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharSpace (const char8 character)
+{
+ return isspace (character) != 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharSpace (const char16 character)
+{
+ switch (character)
+ {
+ case 0x0020:
+ case 0x00A0:
+ case 0x2002:
+ case 0x2003:
+ case 0x2004:
+ case 0x2005:
+ case 0x2006:
+ case 0x2007:
+ case 0x2008:
+ case 0x2009:
+ case 0x200A:
+ case 0x200B:
+ case 0x202F:
+ case 0x205F:
+ case 0x3000:
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAlpha (const char8 character)
+{
+ return isalpha (character) != 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAlpha (const char16 character)
+{
+ return iswalpha (character) != 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAlphaNum (const char8 character)
+{
+ return isalnum (character) != 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAlphaNum (const char16 character)
+{
+ return iswalnum (character) != 0; // this may not work on macOSX when another locale is set inside the c-lib
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharDigit (const char8 character)
+{
+ return isdigit (character) != 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharDigit (const char16 character)
+{
+ return iswdigit (character) != 0; // this may not work on macOSX when another locale is set inside the c-lib
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAscii (char8 character)
+{
+ return character >= 0;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharAscii (char16 character)
+{
+ return character < 128;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharUpper (char8 character)
+{
+ return toUpper (character) == character;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharUpper (char16 character)
+{
+ return toUpper (character) == character;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharLower (char8 character)
+{
+ return toLower (character) == character;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isCharLower (char16 character)
+{
+ return toLower (character) == character;
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isDigit (uint32 index) const
+{
+ if (isEmpty () || index >= len)
+ return false;
+
+ if (isWide)
+ return ConstString::isCharDigit (buffer16[index]);
+ else
+ return ConstString::isCharDigit (buffer8[index]);
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::getTrailingNumberIndex (uint32 width) const
+{
+ if (isEmpty ())
+ return -1;
+
+ int32 endIndex = len - 1;
+ int32 i = endIndex;
+ while (isDigit ((uint32) i) && i >= 0)
+ i--;
+
+ // now either all are digits or i is on the first non digit
+ if (i < endIndex)
+ {
+ if (width > 0 && (endIndex - i != static_cast (width)))
+ return -1;
+
+ return i + 1;
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+int64 ConstString::getTrailingNumber (int64 fallback) const
+{
+ int32 index = getTrailingNumberIndex ();
+
+ int64 number = 0;
+
+ if (index >= 0)
+ if (scanInt64 (number, index))
+ return number;
+
+ return fallback;
+}
+
+
+
+//-----------------------------------------------------------------------------
+void ConstString::toVariant (FVariant& var) const
+{
+ if (isWide)
+ {
+ var.setString16 (buffer16);
+ }
+ else
+ {
+ var.setString8 (buffer8);
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isAsciiString () const
+{
+ uint32 i;
+ if (isWide)
+ {
+ for (i = 0; i < len; i++)
+ if (ConstString::isCharAscii (buffer16 [i]) == false)
+ return false;
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ if (ConstString::isCharAscii (buffer8 [i]) == false)
+ return false;
+ }
+ return true;
+}
+
+
+#if SMTG_OS_MACOS
+uint32 kDefaultSystemEncoding = kCFStringEncodingMacRoman;
+//-----------------------------------------------------------------------------
+static CFStringEncoding MBCodePageToCFStringEncoding (uint32 codePage)
+{
+ switch (codePage)
+ {
+ case kCP_ANSI: return kDefaultSystemEncoding; // MacRoman or JIS
+ case kCP_MAC_ROMAN: return kCFStringEncodingMacRoman;
+ case kCP_ANSI_WEL: return kCFStringEncodingWindowsLatin1;
+ case kCP_MAC_CEE: return kCFStringEncodingMacCentralEurRoman;
+ case kCP_Utf8: return kCFStringEncodingUTF8;
+ case kCP_ShiftJIS: return kCFStringEncodingShiftJIS_X0213_00;
+ case kCP_US_ASCII: return kCFStringEncodingASCII;
+ }
+ return kCFStringEncodingASCII;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+int32 ConstString::multiByteToWideString (char16* dest, const char8* source, int32 charCount, uint32 sourceCodePage)
+{
+ if (source == 0 || source[0] == 0)
+ {
+ if (dest && charCount > 0)
+ {
+ dest[0] = 0;
+ }
+ return 0;
+ }
+ int32 result = 0;
+#if SMTG_OS_WINDOWS
+ result = MultiByteToWideChar (sourceCodePage, MB_ERR_INVALID_CHARS, source, -1, dest, charCount);
+#endif
+
+#if SMTG_OS_MACOS
+ CFStringRef cfStr =
+ (CFStringRef)::toCFStringRef (source, MBCodePageToCFStringEncoding (sourceCodePage));
+ if (cfStr)
+ {
+ CFRange range = {0, CFStringGetLength (cfStr)};
+ CFIndex usedBytes;
+ if (CFStringGetBytes (cfStr, range, kCFStringEncodingUnicode, ' ', false, (UInt8*)dest,
+ charCount * 2, &usedBytes) > 0)
+ {
+ result = static_cast (usedBytes / 2 + 1);
+ if (dest)
+ dest[usedBytes / 2] = 0;
+ }
+
+ CFRelease (cfStr);
+ }
+#endif
+
+#if SMTG_OS_LINUX
+ if (sourceCodePage == kCP_ANSI || sourceCodePage == kCP_Utf8)
+ {
+ if (dest == nullptr)
+ {
+ auto state = std::mbstate_t ();
+ auto maxChars = charCount ? charCount : std::numeric_limits::max () - 1;
+ result = converterFacet ().length (state, source, source + strlen (source), maxChars);
+ }
+ else
+ {
+ auto utf16Str = converter ().from_bytes (source);
+ if (!utf16Str.empty ())
+ {
+ result = std::min (charCount, utf16Str.size ());
+ memcpy (dest, utf16Str.data (), result * sizeof (char16));
+ dest[result] = 0;
+ }
+ }
+ }
+ else
+ {
+#warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ }
+
+#endif
+
+ SMTG_ASSERT (result > 0)
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+int32 ConstString::wideStringToMultiByte (char8* dest, const char16* wideString, int32 charCount, uint32 destCodePage)
+{
+#if SMTG_OS_WINDOWS
+ return WideCharToMultiByte (destCodePage, 0, wideString, -1, dest, charCount, 0, 0);
+
+#elif SMTG_OS_MACOS
+ int32 result = 0;
+ if (wideString != 0)
+ {
+ if (dest)
+ {
+ CFStringRef cfStr = CFStringCreateWithCharactersNoCopy (kCFAllocator, (const UniChar*)wideString, strlen16 (wideString), kCFAllocatorNull);
+ if (cfStr)
+ {
+ if (fromCFStringRef (dest, charCount, cfStr, MBCodePageToCFStringEncoding (destCodePage)))
+ result = static_cast (strlen (dest) + 1);
+ CFRelease (cfStr);
+ }
+ }
+ else
+ {
+ return static_cast (CFStringGetMaximumSizeForEncoding (strlen16 (wideString), MBCodePageToCFStringEncoding (destCodePage)));
+ }
+ }
+ return result;
+
+#elif SMTG_OS_LINUX
+ int32 result = 0;
+ if (destCodePage == kCP_Utf8)
+ {
+ if (dest == nullptr)
+ {
+ auto maxChars = charCount ? charCount : tstrlen (wideString);
+ result = converterFacet ().max_length () * maxChars;
+ }
+ else
+ {
+ auto utf8Str = converter ().to_bytes (wideString);
+ if (!utf8Str.empty ())
+ {
+ result = std::min (charCount, utf8Str.size ());
+ memcpy (dest, utf8Str.data (), result * sizeof (char8));
+ dest[result] = 0;
+ }
+ }
+ }
+ else if (destCodePage == kCP_ANSI)
+ {
+ if (dest == nullptr)
+ {
+ result = strlen16 (wideString) + 1;
+ }
+ else
+ {
+ int32 i = 0;
+ for (; i < charCount; ++i)
+ {
+ if (wideString[i] == 0)
+ break;
+ if (wideString[i] <= 0x007F)
+ dest[i] = wideString[i];
+ else
+ dest[i] = '_';
+ }
+ dest[i] = 0;
+ result = i;
+ }
+ }
+ else
+ {
+#warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ }
+ return result;
+
+#else
+#warning DEPRECATED No Linux implementation
+ assert(false && "DEPRECATED No Linux implementation");
+ return 0;
+#endif
+
+}
+
+//-----------------------------------------------------------------------------
+bool ConstString::isNormalized (UnicodeNormalization n)
+{
+ if (isWide == false)
+ return false;
+
+#if SMTG_OS_WINDOWS
+#ifdef UNICODE
+ if (n != kUnicodeNormC)
+ return false;
+ uint32 normCharCount = static_cast (FoldString (MAP_PRECOMPOSED, buffer16, len, 0, 0));
+ return (normCharCount == len);
+#else
+ return false;
+#endif
+
+#elif SMTG_OS_MACOS
+ if (n != kUnicodeNormC)
+ return false;
+
+ CFStringRef cfStr = (CFStringRef)toCFStringRef ();
+ CFIndex charCount = CFStringGetLength (cfStr);
+ CFRelease (cfStr);
+ return (charCount == len);
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// String
+//-----------------------------------------------------------------------------
+String::String ()
+{
+ isWide = kWideStringDefault ? 1 : 0;
+}
+
+//-----------------------------------------------------------------------------
+String::String (const char8* str, MBCodePage codePage, int32 n, bool isTerminated)
+{
+ isWide = 0;
+ if (str)
+ {
+ assign (str, n, isTerminated);
+ toWideString (codePage);
+ }
+}
+
+//-----------------------------------------------------------------------------
+String::String (const char8* str, int32 n, bool isTerminated)
+{
+ if (str)
+ assign (str, n, isTerminated);
+}
+
+//-----------------------------------------------------------------------------
+String::String (const char16* str, int32 n, bool isTerminated)
+{
+ isWide = 1;
+ if (str)
+ assign (str, n, isTerminated);
+}
+
+//-----------------------------------------------------------------------------
+String::String (const String& str, int32 n)
+{
+ isWide = str.isWideString ();
+ if (!str.isEmpty ())
+ assign (str, n);
+}
+
+//-----------------------------------------------------------------------------
+String::String (const ConstString& str, int32 n)
+{
+ isWide = str.isWideString ();
+ if (!str.isEmpty ())
+ assign (str, n);
+}
+
+//-----------------------------------------------------------------------------
+String::String (const FVariant& var)
+{
+ isWide = kWideStringDefault ? 1 : 0;
+ fromVariant (var);
+}
+
+//-----------------------------------------------------------------------------
+String::String (IString* str)
+{
+ isWide = str->isWideString ();
+ if (isWide)
+ assign (str->getText16 ());
+ else
+ assign (str->getText8 ());
+}
+
+//-----------------------------------------------------------------------------
+String::~String ()
+{
+ if (buffer)
+ resize (0, false);
+}
+
+#if SMTG_CPP11_STDLIBSUPPORT
+//-----------------------------------------------------------------------------
+String::String (String&& str)
+{
+ *this = std::move (str);
+}
+
+//-----------------------------------------------------------------------------
+String& String::operator= (String&& str)
+{
+ SMTG_ASSERT (buffer == 0 || buffer != str.buffer);
+ tryFreeBuffer ();
+
+ isWide = str.isWide;
+ buffer = str.buffer;
+ len = str.len;
+ str.buffer = nullptr;
+ str.len = 0;
+ return *this;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+void String::updateLength ()
+{
+ if (isWide)
+ len = strlen16 (text16 ());
+ else
+ len = strlen8 (text8 ());
+}
+
+//-----------------------------------------------------------------------------
+bool String::toWideString (uint32 sourceCodePage)
+{
+ if (!isWide)
+ {
+ if (buffer8 && len > 0)
+ {
+ int32 bytesNeeded = multiByteToWideString (0, buffer8, 0, sourceCodePage) * sizeof (char16);
+ if (bytesNeeded)
+ {
+ bytesNeeded += sizeof (char16);
+ char16* newStr = (char16*) malloc (bytesNeeded);
+ if (multiByteToWideString (newStr, buffer8, len + 1, sourceCodePage) <= 0)
+ {
+ free (newStr);
+ return false;
+ }
+ free (buffer8);
+ buffer16 = newStr;
+ isWide = true;
+ updateLength ();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ isWide = true;
+ }
+ return true;
+}
+
+#define SMTG_STRING_CHECK_CONVERSION 1
+#define SMTG_STRING_CHECK_CONVERSION_NO_BREAK 1
+
+#if SMTG_STRING_CHECK_CONVERSION_NO_BREAK
+ #define SMTG_STRING_CHECK_MSG FDebugPrint
+#else
+ #define SMTG_STRING_CHECK_MSG FDebugBreak
+#endif
+//-----------------------------------------------------------------------------
+bool String::checkToMultiByte (uint32 destCodePage) const
+{
+ if (!isWide || isEmpty ())
+ return true;
+
+#if DEVELOPMENT && SMTG_STRING_CHECK_CONVERSION
+ int debugLen = length ();
+ int debugNonASCII = 0;
+ for (int32 i = 0; i < length (); i++)
+ {
+ if (buffer16[i] > 127)
+ ++debugNonASCII;
+ }
+
+ String* backUp = nullptr;
+ if (debugNonASCII > 0)
+ backUp = NEW String (*this);
+#endif
+
+ // this should be avoided, since it can lead to information loss
+ bool result = const_cast (*this).toMultiByte (destCodePage);
+
+#if DEVELOPMENT && SMTG_STRING_CHECK_CONVERSION
+ if (backUp)
+ {
+ String temp (*this);
+ temp.toWideString (destCodePage);
+
+ if (temp != *backUp)
+ {
+ backUp->toMultiByte (kCP_Utf8);
+ SMTG_STRING_CHECK_MSG ("Indirect string conversion information loss ! %d/%d non ASCII chars: \"%s\" -> \"%s\"\n", debugNonASCII, debugLen, backUp->buffer8, buffer8);
+ }
+ else
+ SMTG_STRING_CHECK_MSG ("Indirect string potential conversion information loss ! %d/%d non ASCII chars result: \"%s\"\n", debugNonASCII, debugLen, buffer8);
+
+ delete backUp;
+ }
+#endif
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+bool String::toMultiByte (uint32 destCodePage)
+{
+ if (isWide)
+ {
+ if (buffer16 && len > 0)
+ {
+ int32 numChars = wideStringToMultiByte (0, buffer16, 0, destCodePage) + sizeof (char8);
+ char8* newStr = (char8*) malloc (numChars * sizeof (char8));
+ if (wideStringToMultiByte (newStr, buffer16, numChars, destCodePage) <= 0)
+ {
+ free (newStr);
+ return false;
+ }
+ free (buffer16);
+ buffer8 = newStr;
+ isWide = false;
+ updateLength ();
+ }
+ isWide = false;
+ }
+ else if (destCodePage != kCP_Default)
+ {
+ if (toWideString () == false)
+ return false;
+ return toMultiByte (destCodePage);
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void String::fromUTF8 (const char8* utf8String)
+{
+ assign (utf8String);
+ toWideString (kCP_Utf8);
+}
+
+//-----------------------------------------------------------------------------
+bool String::normalize (UnicodeNormalization n)
+{
+ if (isWide == false)
+ return false;
+
+ if (buffer16 == 0)
+ return true;
+
+#if SMTG_OS_WINDOWS
+#ifdef UNICODE
+ if (n != kUnicodeNormC)
+ return false;
+
+ uint32 normCharCount = static_cast (FoldString (MAP_PRECOMPOSED, buffer16, len, 0, 0));
+ if (normCharCount == len)
+ return true;
+
+ char16* newString = (char16*)malloc ((normCharCount + 1) * sizeof (char16));
+ uint32 converterCount = static_cast (FoldString (MAP_PRECOMPOSED, buffer16, len, newString, normCharCount + 1));
+ if (converterCount != normCharCount)
+ {
+ free (newString);
+ return false;
+ }
+ newString [converterCount] = 0;
+ free (buffer16);
+ buffer16 = newString;
+ updateLength ();
+ return true;
+#else
+ return false;
+#endif
+
+#elif SMTG_OS_MACOS
+ CFMutableStringRef origStr = (CFMutableStringRef)toCFStringRef (0xFFFF, true);
+ if (origStr)
+ {
+ CFStringNormalizationForm normForm = kCFStringNormalizationFormD;
+ switch (n)
+ {
+ case kUnicodeNormC: normForm = kCFStringNormalizationFormC; break;
+ case kUnicodeNormD: normForm = kCFStringNormalizationFormD; break;
+ case kUnicodeNormKC: normForm = kCFStringNormalizationFormKC; break;
+ case kUnicodeNormKD: normForm = kCFStringNormalizationFormKD; break;
+ }
+ CFStringNormalize (origStr, normForm);
+ bool result = fromCFStringRef (origStr);
+ CFRelease (origStr);
+ return result;
+ }
+ return false;
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+void String::tryFreeBuffer ()
+{
+ if (buffer)
+ {
+ free (buffer);
+ buffer = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool String::resize (uint32 newLength, bool wide, bool fill)
+{
+ if (newLength == 0)
+ {
+ tryFreeBuffer ();
+ len = 0;
+ isWide = wide ? 1 : 0;
+ }
+ else
+ {
+ size_t newCharSize = wide ? sizeof (char16) : sizeof (char8);
+ size_t oldCharSize = (isWide != 0) ? sizeof (char16) : sizeof (char8);
+
+ size_t newBufferSize = (newLength + 1) * newCharSize;
+ size_t oldBufferSize = (len + 1) * oldCharSize;
+
+ isWide = wide ? 1 : 0;
+
+ if (buffer)
+ {
+ if (newBufferSize != oldBufferSize)
+ {
+ void* newstr = realloc (buffer, newBufferSize);
+ if (newstr == 0)
+ return false;
+ buffer = newstr;
+ if (isWide)
+ buffer16[newLength] = 0;
+ else
+ buffer8[newLength] = 0;
+ }
+ else if (wide && newCharSize != oldCharSize)
+ buffer16[newLength] = 0;
+ }
+ else
+ {
+ void* newstr = malloc (newBufferSize);
+ if (newstr == 0)
+ return false;
+ buffer = newstr;
+ if (isWide)
+ {
+ buffer16[0] = 0;
+ buffer16[newLength] = 0;
+ }
+ else
+ {
+ buffer8[0] = 0;
+ buffer8[newLength] = 0;
+ }
+ }
+
+ if (fill && len < newLength && buffer)
+ {
+ if (isWide)
+ {
+ char16 c = ' ';
+ for (uint32 i = len; i < newLength; i++)
+ buffer16 [i] = c;
+ }
+ else
+ {
+ memset (buffer8 + len, ' ', newLength - len);
+ }
+ }
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool String::setChar8 (uint32 index, char8 c)
+{
+ if (index == len && c == 0)
+ return true;
+
+ if (index >= len)
+ {
+ if (c == 0)
+ {
+ if (resize (index, isWide, true) == false)
+ return false;
+ len = index;
+ return true;
+ }
+ else
+ {
+ if (resize (index + 1, isWide, true) == false)
+ return false;
+ len = index + 1;
+ }
+ }
+
+ if (index < len && buffer)
+ {
+ if (isWide)
+ {
+ if (c == 0)
+ buffer16[index] = 0;
+ else
+ {
+ char8 src[] = {c, 0};
+ char16 dest[8] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ buffer16[index] = dest[0];
+ }
+ SMTG_ASSERT (buffer16[len] == 0)
+ }
+ else
+ {
+ buffer8[index] = c;
+ SMTG_ASSERT (buffer8[len] == 0)
+ }
+
+ if (c == 0)
+ updateLength ();
+
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool String::setChar16 (uint32 index, char16 c)
+{
+ if (index == len && c == 0)
+ return true;
+
+ if (index >= len)
+ {
+ if (c == 0)
+ {
+ if (resize (index, isWide, true) == false)
+ return false;
+ len = index;
+ return true;
+ }
+ else
+ {
+ if (resize (index + 1, isWide, true) == false)
+ return false;
+ len = index + 1;
+ }
+ }
+
+ if (index < len && buffer)
+ {
+ if (isWide)
+ {
+ buffer16[index] = c;
+ SMTG_ASSERT (buffer16[len] == 0)
+ }
+ else
+ {
+ SMTG_ASSERT (buffer8[len] == 0)
+ char16 src[] = {c, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ buffer8[index] = dest[0];
+ else
+ return false;
+ }
+
+ if (c == 0)
+ updateLength ();
+
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+String& String::assign (const ConstString& str, int32 n)
+{
+ if (str.isWideString ())
+ return assign (str.text16 (), n < 0 ? str.length () : n);
+ else
+ return assign (str.text8 (), n < 0 ? str.length () : n);
+}
+
+//-----------------------------------------------------------------------------
+String& String::assign (const char8* str, int32 n, bool isTerminated)
+{
+ if (str == buffer8)
+ return *this;
+
+ if (isTerminated)
+ {
+ uint32 stringLength = (uint32)((str) ? strlen (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+ }
+ else if (n < 0)
+ return *this;
+
+ if (resize (n, false))
+ {
+ if (buffer8 && n > 0)
+ {
+ memcpy (buffer8, str, n * sizeof (char8));
+ SMTG_ASSERT (buffer8[n] == 0)
+ }
+ isWide = 0;
+ len = n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::assign (const char16* str, int32 n, bool isTerminated)
+{
+ if (str == buffer16)
+ return *this;
+
+ if (isTerminated)
+ {
+ uint32 stringLength = (uint32)((str) ? strlen16 (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+ }
+ else if (n < 0)
+ return *this;
+
+ if (resize (n, true))
+ {
+ if (buffer16 && n > 0)
+ {
+ memcpy (buffer16, str, n * sizeof (char16));
+ SMTG_ASSERT (buffer16[n] == 0)
+ }
+ isWide = 1;
+ len = n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::assign (char8 c, int32 n)
+{
+ if (resize (n, false))
+ {
+ if (buffer8 && n > 0)
+ {
+ memset (buffer8, c, n * sizeof (char8));
+ SMTG_ASSERT (buffer8[n] == 0)
+ }
+ isWide = 0;
+ len = n;
+ }
+ return *this;
+
+}
+
+//-----------------------------------------------------------------------------
+String& String::assign (char16 c, int32 n)
+{
+ if (resize (n, true))
+ {
+ if (buffer && n > 0)
+ {
+ for (int32 i = 0; i < n; i++)
+ buffer16[i] = c;
+ SMTG_ASSERT (buffer16[n] == 0)
+ }
+ isWide = 1;
+ len = n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::append (const ConstString& str, int32 n)
+{
+ if (str.isWideString ())
+ return append (str.text16 (), n);
+ else
+ return append (str.text8 (), n);
+}
+
+//-----------------------------------------------------------------------------
+String& String::append (const char8* str, int32 n)
+{
+ if (str == buffer8)
+ return *this;
+
+ if (len == 0)
+ return assign (str, n);
+
+ if (isWide)
+ {
+ String tmp (str);
+ if (tmp.toWideString () == false)
+ return *this;
+
+ return append (tmp.buffer16, n);
+ }
+
+ uint32 stringLength = (uint32)((str) ? strlen (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (n > 0)
+ {
+ int32 newlen = n + len;
+ if (!resize (newlen, false))
+ return *this;
+
+ if (buffer)
+ {
+ memcpy (buffer8 + len, str, n * sizeof (char8));
+ SMTG_ASSERT (buffer8[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::append (const char16* str, int32 n)
+{
+ if (str == buffer16)
+ return *this;
+
+ if (len == 0)
+ return assign (str, n);
+
+ if (!isWide)
+ {
+ if (toWideString () == false)
+ return *this;
+ }
+
+ uint32 stringLength = (uint32)((str) ? strlen16 (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (n > 0)
+ {
+ int32 newlen = n + len;
+ if (!resize (newlen, true))
+ return *this;
+
+ if (buffer16)
+ {
+ memcpy (buffer16 + len, str, n * sizeof (char16));
+ SMTG_ASSERT (buffer16[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::append (const char8 c, int32 n)
+{
+ char8 str[] = {c, 0};
+ if (n == 1)
+ {
+ return append (str, 1);
+ }
+ else if (n > 1)
+ {
+ if (isWide)
+ {
+ String tmp (str);
+ if (tmp.toWideString () == false)
+ return *this;
+
+ return append (tmp.buffer16[0], n);
+ }
+
+ int32 newlen = n + len;
+ if (!resize (newlen, false))
+ return *this;
+
+ if (buffer)
+ {
+ memset (buffer8 + len, c, n * sizeof (char8));
+ SMTG_ASSERT (buffer8[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::append (const char16 c, int32 n)
+{
+ if (n == 1)
+ {
+ char16 str[] = {c, 0};
+ return append (str, 1);
+ }
+ else if (n > 1)
+ {
+ if (!isWide)
+ {
+ if (toWideString () == false)
+ return *this;
+ }
+
+ int32 newlen = n + len;
+ if (!resize (newlen, true))
+ return *this;
+
+ if (buffer16)
+ {
+ for (int32 i = len; i < newlen; i++)
+ buffer16[i] = c;
+ SMTG_ASSERT (buffer16[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::insertAt (uint32 idx, const ConstString& str, int32 n)
+{
+ if (str.isWideString ())
+ return insertAt (idx, str.text16 (), n);
+ else
+ return insertAt (idx, str.text8 (), n);
+}
+
+//-----------------------------------------------------------------------------
+String& String::insertAt (uint32 idx, const char8* str, int32 n)
+{
+ if (idx > len)
+ return *this;
+
+ if (isWide)
+ {
+ String tmp (str);
+ if (tmp.toWideString () == false)
+ return *this;
+ return insertAt (idx, tmp.buffer16, n);
+ }
+
+ uint32 stringLength = (uint32)((str) ? strlen (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (n > 0)
+ {
+ int32 newlen = len + n;
+ if (!resize (newlen, false))
+ return *this;
+
+ if (buffer)
+ {
+ if (idx < len)
+ memmove (buffer8 + idx + n, buffer8 + idx, (len - idx) * sizeof (char8));
+ memcpy (buffer8 + idx, str, n * sizeof (char8));
+ SMTG_ASSERT (buffer8[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::insertAt (uint32 idx, const char16* str, int32 n)
+{
+ if (idx > len)
+ return *this;
+
+ if (!isWide)
+ {
+ if (toWideString () == false)
+ return *this;
+ }
+
+ uint32 stringLength = (uint32)((str) ? strlen16 (str) : 0);
+ n = n < 0 ? stringLength : Min (n, stringLength);
+
+ if (n > 0)
+ {
+ int32 newlen = len + n;
+ if (!resize (newlen, true))
+ return *this;
+
+ if (buffer)
+ {
+ if (idx < len)
+ memmove (buffer16 + idx + n, buffer16 + idx, (len - idx) * sizeof (char16));
+ memcpy (buffer16 + idx, str, n * sizeof (char16));
+ SMTG_ASSERT (buffer16[newlen] == 0)
+ }
+
+ len += n;
+ }
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::replace (uint32 idx, int32 n1, const ConstString& str, int32 n2)
+{
+ if (str.isWideString ())
+ return replace (idx, n1, str.text16 (), n2);
+ else
+ return replace (idx, n1, str.text8 (), n2);
+}
+
+// "replace" replaces n1 number of characters at the specified index with
+// n2 characters from the specified string.
+//-----------------------------------------------------------------------------
+String& String::replace (uint32 idx, int32 n1, const char8* str, int32 n2)
+{
+ if (idx > len || str == 0)
+ return *this;
+
+ if (isWide)
+ {
+ String tmp (str);
+ if (tmp.toWideString () == false)
+ return *this;
+ if (tmp.length () == 0 || n2 == 0)
+ return remove (idx, n1);
+ return replace (idx, n1, tmp.buffer16, n2);
+ }
+
+ if (n1 < 0 || idx + n1 > len)
+ n1 = len - idx;
+ if (n1 == 0)
+ return *this;
+
+ uint32 stringLength = (uint32)((str) ? strlen (str) : 0);
+ n2 = n2 < 0 ? stringLength : Min (n2, stringLength);
+
+ uint32 newlen = len - n1 + n2;
+ if (newlen > len)
+ if (!resize (newlen, false))
+ return *this;
+
+ if (buffer)
+ {
+ memmove (buffer8 + idx + n2, buffer8 + idx + n1, (len - (idx + n1)) * sizeof (char8));
+ memcpy (buffer8 + idx, str, n2 * sizeof (char8));
+ buffer8[newlen] = 0; // cannot be removed because resize is not called called in all cases (newlen > len)
+ }
+
+ len = newlen;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+String& String::replace (uint32 idx, int32 n1, const char16* str, int32 n2)
+{
+ if (idx > len || str == 0)
+ return *this;
+
+ if (!isWide)
+ {
+ if (toWideString () == false)
+ return *this;
+ }
+
+ if (n1 < 0 || idx + n1 > len)
+ n1 = len - idx;
+ if (n1 == 0)
+ return *this;
+
+ uint32 stringLength = (uint32)((str) ? strlen16 (str) : 0);
+ n2 = n2 < 0 ? stringLength : Min (n2, stringLength);
+
+ uint32 newlen = len - n1 + n2;
+ if (newlen > len)
+ if (!resize (newlen, true))
+ return *this;
+
+ if (buffer)
+ {
+ memmove (buffer16 + idx + n2, buffer16 + idx + n1, (len - (idx + n1)) * sizeof (char16));
+ memcpy (buffer16 + idx, str, n2 * sizeof (char16));
+ buffer16[newlen] = 0; // cannot be removed because resize is not called called in all cases (newlen > len)
+ }
+
+ len = newlen;
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+int32 String::replace (const char8* toReplace, const char8* toReplaceWith, bool all, CompareMode m)
+{
+ if (toReplace == 0 || toReplaceWith == 0)
+ return 0;
+
+ int32 result = 0;
+
+ int32 idx = findFirst (toReplace, -1, m);
+ if (idx > -1)
+ {
+ int32 toReplaceLen = static_cast (strlen (toReplace));
+ int32 toReplaceWithLen = static_cast (strlen (toReplaceWith));
+ while (idx > -1)
+ {
+ replace (idx, toReplaceLen, toReplaceWith, toReplaceWithLen);
+ result++;
+
+ if (all)
+ idx = findNext (idx + toReplaceWithLen , toReplace, -1, m);
+ else
+ break;
+ }
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+int32 String::replace (const char16* toReplace, const char16* toReplaceWith, bool all, CompareMode m)
+{
+ if (toReplace == 0 || toReplaceWith == 0)
+ return 0;
+
+ int32 result = 0;
+
+ int32 idx = findFirst (toReplace, -1, m);
+ if (idx > -1)
+ {
+ int32 toReplaceLen = strlen16 (toReplace);
+ int32 toReplaceWithLen = strlen16 (toReplaceWith);
+ while (idx > -1)
+ {
+ replace (idx, toReplaceLen, toReplaceWith, toReplaceWithLen);
+ result++;
+
+ if (all)
+ idx = findNext (idx + toReplaceWithLen, toReplace, -1, m);
+ else
+ break;
+ }
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+template
+static bool performReplace (T* str, const T* toReplace, T toReplaceBy)
+{
+ bool anyReplace = false;
+ T* p = str;
+ while (*p)
+ {
+ const T* rep = toReplace;
+ while (*rep)
+ {
+ if (*p == *rep)
+ {
+ *p = toReplaceBy;
+ anyReplace = true;
+ break;
+ }
+ rep++;
+ }
+ p++;
+ }
+ return anyReplace;
+}
+
+//-----------------------------------------------------------------------------
+bool String::replaceChars8 (const char8* toReplace, char8 toReplaceBy)
+{
+ if (isEmpty ())
+ return false;
+
+ if (isWide)
+ {
+ String toReplaceW (toReplace);
+ if (toReplaceW.toWideString () == false)
+ return false;
+
+ char8 src[] = {toReplaceBy, 0};
+ char16 dest[2] = {0};
+ if (multiByteToWideString (dest, src, 2) > 0)
+ {
+ return replaceChars16 (toReplaceW.text16 (), dest[0]);
+ }
+ return false;
+ }
+
+ if (toReplaceBy == 0)
+ toReplaceBy = ' ';
+
+ return performReplace (buffer8, toReplace, toReplaceBy);
+}
+
+//-----------------------------------------------------------------------------
+bool String::replaceChars16 (const char16* toReplace, char16 toReplaceBy)
+{
+ if (isEmpty ())
+ return false;
+
+ if (!isWide)
+ {
+ String toReplaceA (toReplace);
+ if (toReplaceA.toMultiByte () == false)
+ return false;
+
+ if (toReplaceA.length () > 1)
+ {
+ SMTG_WARNING("cannot replace non ASCII chars on non Wide String")
+ return false;
+ }
+
+ char16 src[] = {toReplaceBy, 0};
+ char8 dest[8] = {0};
+ if (wideStringToMultiByte (dest, src, 2) > 0 && dest[1] == 0)
+ return replaceChars8 (toReplaceA.text8 (), dest[0]);
+
+ return false;
+ }
+
+ if (toReplaceBy == 0)
+ toReplaceBy = STR16 (' ');
+
+ return performReplace (buffer16, toReplace, toReplaceBy);
+}
+
+// "remove" removes the specified number of characters from the string
+// starting at the specified index.
+//-----------------------------------------------------------------------------
+String& String::remove (uint32 idx, int32 n)
+{
+ if (isEmpty () || idx >= len || n == 0)
+ return *this;
+
+ if ((idx + n > len) || n < 0)
+ n = len - idx;
+ else
+ {
+ int32 toMove = len - idx - n;
+ if (buffer)
+ {
+ if (isWide)
+ memmove (buffer16 + idx, buffer16 + idx + n, toMove * sizeof (char16));
+ else
+ memmove (buffer8 + idx, buffer8 + idx + n, toMove * sizeof (char8));
+ }
+ }
+
+ resize (len - n, isWide);
+ updateLength ();
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+bool String::removeSubString (const ConstString& subString, bool allOccurences)
+{
+ bool removed = false;
+ while (!removed || allOccurences)
+ {
+ int32 idx = findFirst (subString);
+ if (idx < 0)
+ break;
+ remove (idx, subString.length ());
+ removed = true;
+ }
+ return removed;
+}
+
+//-----------------------------------------------------------------------------
+template
+static uint32 performTrim (T* str, uint32 length, F func, bool funcResult)
+{
+ uint32 toRemoveAtHead = 0;
+ uint32 toRemoveAtTail = 0;
+
+ T* p = str;
+
+ while ((*p) && ((func (*p) != 0) == funcResult))
+ p++;
+
+ toRemoveAtHead = static_cast (p - str);
+
+ if (toRemoveAtHead < length)
+ {
+ p = str + length - 1;
+
+ while (((func (*p) != 0) == funcResult) && (p > str))
+ {
+ p--;
+ toRemoveAtTail++;
+ }
+ }
+
+ uint32 newLength = length - (toRemoveAtHead + toRemoveAtTail);
+ if (newLength != length)
+ {
+ if (toRemoveAtHead)
+ memmove (str, str + toRemoveAtHead, newLength * sizeof (T));
+ }
+ return newLength;
+}
+
+// "trim" trims the leading and trailing unwanted characters from the string.
+//-----------------------------------------------------------------------------
+bool String::trim (String::CharGroup group)
+{
+ if (isEmpty ())
+ return false;
+
+ uint32 newLength;
+
+ switch (group)
+ {
+ case kSpace:
+ if (isWide)
+ newLength = performTrim (buffer16, len, iswspace, true);
+ else
+ newLength = performTrim (buffer8, len, isspace, true);
+ break;
+
+ case kNotAlphaNum:
+ if (isWide)
+ newLength = performTrim (buffer16, len, iswalnum, false);
+ else
+ newLength = performTrim (buffer8, len, isalnum, false);
+ break;
+
+ case kNotAlpha:
+ if (isWide)
+ newLength = performTrim (buffer16, len, iswalpha, false);
+ else
+ newLength = performTrim (buffer8, len, isalpha, false);
+ break;
+
+ default: // Undefined enum value
+ return false;
+ }
+
+ if (newLength != len)
+ {
+ resize (newLength, isWide);
+ len = newLength;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+template
+static uint32 performRemove (T* str, uint32 length, F func, bool funcResult)
+{
+ T* p = str;
+
+ while (*p)
+ {
+ if ((func (*p) != 0) == funcResult)
+ {
+ size_t toMove = length - (p - str);
+ memmove (p, p + 1, toMove * sizeof (T));
+ length--;
+ }
+ else
+ p++;
+ }
+ return length;
+}
+//-----------------------------------------------------------------------------
+void String::removeChars (CharGroup group)
+{
+ if (isEmpty ())
+ return;
+
+ uint32 newLength;
+
+ switch (group)
+ {
+ case kSpace:
+ if (isWide)
+ newLength = performRemove (buffer16, len, iswspace, true);
+ else
+ newLength = performRemove (buffer8, len, isspace, true);
+ break;
+
+ case kNotAlphaNum:
+ if (isWide)
+ newLength = performRemove (buffer16, len, iswalnum, false);
+ else
+ newLength = performRemove (buffer8, len, isalnum, false);
+ break;
+
+ case kNotAlpha:
+ if (isWide)
+ newLength = performRemove (buffer16, len, iswalpha, false);
+ else
+ newLength = performRemove (buffer8, len, isalpha, false);
+ break;
+
+ default: // Undefined enum value
+ return;
+ }
+
+ if (newLength != len)
+ {
+ resize (newLength, isWide);
+ len = newLength;
+ }
+}
+
+//-----------------------------------------------------------------------------
+template
+static uint32 performRemoveChars (T* str, uint32 length, const T* toRemove)
+{
+ T* p = str;
+
+ while (*p)
+ {
+ bool found = false;
+ const T* rem = toRemove;
+ while (*rem)
+ {
+ if (*p == *rem)
+ {
+ found = true;
+ break;
+ }
+ rem++;
+ }
+
+ if (found)
+ {
+ size_t toMove = length - (p - str);
+ memmove (p, p + 1, toMove * sizeof (T));
+ length--;
+ }
+ else
+ p++;
+ }
+ return length;
+}
+
+//-----------------------------------------------------------------------------
+bool String::removeChars8 (const char8* toRemove)
+{
+ if (isEmpty () || toRemove == 0)
+ return true;
+
+ if (isWide)
+ {
+ String wStr (toRemove);
+ if (wStr.toWideString () == false)
+ return false;
+ return removeChars16 (wStr.text16 ());
+ }
+
+ uint32 newLength = performRemoveChars (buffer8, len, toRemove);
+
+ if (newLength != len)
+ {
+ resize (newLength, false);
+ len = newLength;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool String::removeChars16 (const char16* toRemove)
+{
+ if (isEmpty () || toRemove == 0)
+ return true;
+
+ if (!isWide)
+ {
+ String str8 (toRemove);
+ if (str8.toMultiByte () == false)
+ return false;
+ return removeChars8 (str8.text8 ());
+ }
+
+ uint32 newLength = performRemoveChars (buffer16, len, toRemove);
+
+ if (newLength != len)
+ {
+ resize (newLength, true);
+ len = newLength;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+String& String::printf (const char8* format, ...)
+{
+ char8 string[kPrintfBufferSize];
+
+ va_list marker;
+ va_start (marker, format);
+
+ vsnprintf (string, kPrintfBufferSize-1, format, marker);
+ return assign (string);
+}
+
+
+//-----------------------------------------------------------------------------
+String& String::printf (const char16* format, ...)
+{
+ char16 string[kPrintfBufferSize];
+
+ va_list marker;
+ va_start (marker, format);
+
+ vsnwprintf (string, kPrintfBufferSize-1, format, marker);
+ return assign (string);
+}
+
+//-----------------------------------------------------------------------------
+String& String::vprintf (const char8* format, va_list args)
+{
+ char8 string[kPrintfBufferSize];
+
+ vsnprintf (string, kPrintfBufferSize-1, format, args);
+ return assign (string);
+}
+
+//-----------------------------------------------------------------------------
+String& String::vprintf (const char16* format, va_list args)
+{
+ char16 string[kPrintfBufferSize];
+
+ vsnwprintf (string, kPrintfBufferSize-1, format, args);
+ return assign (string);
+}
+
+//-----------------------------------------------------------------------------
+String& String::printInt64 (int64 value)
+{
+ if (isWide)
+ {
+ #if SMTG_CPP11
+ return String::printf (STR("%") STR(FORMAT_INT64A), value);
+ #else
+ return String::printf (STR("%" FORMAT_INT64A), value);
+ #endif
+ }
+ else
+ return String::printf ("%" FORMAT_INT64A, value);
+}
+
+//-----------------------------------------------------------------------------
+String& String::printFloat (double value)
+{
+ if (isWide)
+ {
+ char16 string[kPrintfBufferSize];
+ sprintf16 (string, STR16 ("%lf"), value);
+
+ char16* pointPtr = strrchr16 (string, STR ('.'));
+ if (pointPtr)
+ {
+ pointPtr++; // keep 1st digit after point
+ int32 index = strlen16 (string) - 1;
+ char16 zero = STR16 ('0');
+ while (pointPtr < (string + index))
+ {
+ if (string[index] == zero)
+ {
+ string[index] = 0;
+ index--;
+ }
+ else
+ break;
+ }
+ }
+ return assign (string);
+ }
+ else
+ {
+ char8 string[kPrintfBufferSize];
+ sprintf (string, "%lf", value);
+
+ char8* pointPtr = strrchr (string, '.');
+ if (pointPtr)
+ {
+ pointPtr++; // keep 1st digit after point
+ int32 index = (int32) (strlen (string) - 1);
+ while (pointPtr < (string + index))
+ {
+ if (string[index] == '0')
+ {
+ string[index] = 0;
+ index--;
+ }
+ else
+ break;
+ }
+ }
+ return assign (string);
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool String::incrementTrailingNumber (uint32 width, tchar separator, uint32 minNumber, bool applyOnlyFormat)
+{
+ if (width > 32)
+ return false;
+
+ int64 number = 1;
+ int32 index = getTrailingNumberIndex ();
+ if (index >= 0)
+ {
+ if (scanInt64 (number, index))
+ if (!applyOnlyFormat)
+ number++;
+
+ if (separator != 0 && index > 0 && testChar (index - 1, separator) == true)
+ index--;
+
+ remove (index);
+ }
+
+ if (number < minNumber)
+ number = minNumber;
+
+ if (isWide)
+ {
+ char16 format[64];
+ char16 trail[128];
+ if (separator && isEmpty () == false)
+ {
+ sprintf16 (format, STR16 ("%%c%%0%uu"), width);
+ sprintf16 (trail, format, separator, (uint32) number);
+ }
+ else
+ {
+ sprintf16 (format, STR16 ("%%0%uu"), width);
+ sprintf16 (trail, format, (uint32) number);
+ }
+ append (trail);
+ }
+ else
+ {
+ char format[64];
+ char trail[128];
+ if (separator && isEmpty () == false)
+ {
+ sprintf (format, "%%c%%0%uu", width);
+ sprintf (trail, format, separator, (uint32) number);
+ }
+ else
+ {
+ sprintf (format, "%%0%uu", width);
+ sprintf (trail, format, (uint32) number);
+ }
+ append (trail);
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void String::toLower (uint32 index)
+{
+ if (buffer && index < len)
+ {
+ if (isWide)
+ buffer16[index] = ConstString::toLower (buffer16[index]);
+ else
+ buffer8[index] = ConstString::toLower (buffer8[index]);
+ }
+}
+
+//-----------------------------------------------------------------------------
+void String::toLower ()
+{
+ int32 i = len;
+ if (buffer && i > 0)
+ {
+ if (isWide)
+ {
+#if SMTG_OS_MACOS
+ CFMutableStringRef cfStr = CFStringCreateMutableWithExternalCharactersNoCopy (kCFAllocator, (UniChar*)buffer16, len, len+1, kCFAllocatorNull);
+ CFStringLowercase (cfStr, NULL);
+ CFRelease (cfStr);
+#else
+ char16* c = buffer16;
+ while (i--)
+ {
+ *c = ConstString::toLower (*c);
+ c++;
+ }
+#endif
+ }
+ else
+ {
+ char8* c = buffer8;
+ while (i--)
+ {
+ *c = ConstString::toLower (*c);
+ c++;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+void String::toUpper (uint32 index)
+{
+ if (buffer && index < len)
+ {
+ if (isWide)
+ buffer16[index] = ConstString::toUpper (buffer16[index]);
+ else
+ buffer8[index] = ConstString::toUpper (buffer8[index]);
+ }
+}
+
+//-----------------------------------------------------------------------------
+void String::toUpper ()
+{
+ int32 i = len;
+ if (buffer && i > 0)
+ {
+ if (isWide)
+ {
+#if SMTG_OS_MACOS
+ CFMutableStringRef cfStr = CFStringCreateMutableWithExternalCharactersNoCopy (kCFAllocator, (UniChar*)buffer16, len, len+1, kCFAllocatorNull);
+ CFStringUppercase (cfStr, NULL);
+ CFRelease (cfStr);
+#else
+ char16* c = buffer16;
+ while (i--)
+ {
+ *c = ConstString::toUpper (*c);
+ c++;
+ }
+#endif
+ }
+ else
+ {
+ char8* c = buffer8;
+ while (i--)
+ {
+ *c = ConstString::toUpper (*c);
+ c++;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool String::fromVariant (const FVariant& var)
+{
+ switch (var.getType ())
+ {
+ case FVariant::kString8:
+ assign (var.getString8 ());
+ return true;
+
+ case FVariant::kString16:
+ assign (var.getString16 ());
+ return true;
+
+ case FVariant::kFloat:
+ printFloat (var.getFloat ());
+ return true;
+
+ case FVariant::kInteger:
+ printInt64 (var.getInt ());
+ return true;
+
+ default:
+ remove ();
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+void String::toVariant (FVariant& var) const
+{
+ if (isWide)
+ {
+ var.setString16 (text16 ());
+ }
+ else
+ {
+ var.setString8 (text8 ());
+ }
+}
+
+//-----------------------------------------------------------------------------
+bool String::fromAttributes (IAttributes* a, IAttrID attrID)
+{
+ FVariant variant;
+ if (a->get (attrID, variant) == kResultTrue)
+ return fromVariant (variant);
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool String::toAttributes (IAttributes* a, IAttrID attrID)
+{
+ FVariant variant;
+ toVariant (variant);
+ if (a->set (attrID, variant) == kResultTrue)
+ return true;
+ return false;
+}
+
+// "swapContent" swaps ownership of the strings pointed to
+//-----------------------------------------------------------------------------
+void String::swapContent (String& s)
+{
+ void* tmp = s.buffer;
+ uint32 tmpLen = s.len;
+ bool tmpWide = s.isWide;
+ s.buffer = buffer;
+ s.len = len;
+ s.isWide = isWide;
+ buffer = tmp;
+ len = tmpLen;
+ isWide = tmpWide;
+}
+
+//-----------------------------------------------------------------------------
+void String::take (String& other)
+{
+ resize (0, other.isWide);
+ buffer = other.buffer;
+ len = other.len;
+
+ other.buffer = 0;
+ other.len = 0;
+}
+
+//-----------------------------------------------------------------------------
+void String::take (void* b, bool wide)
+{
+ resize (0, wide);
+ buffer = b;
+ isWide = wide;
+ updateLength ();
+}
+
+//-----------------------------------------------------------------------------
+void* String::pass ()
+{
+ void* res = buffer;
+ len = 0;
+ buffer = 0;
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+void String::passToVariant (FVariant& var)
+{
+ void* passed = pass ();
+
+ if (isWide)
+ {
+ if (passed)
+ {
+ var.setString16 ((const char16*)passed);
+ var.setOwner (true);
+ }
+ else
+ var.setString16 (kEmptyString16);
+ }
+ else
+ {
+ if (passed)
+ {
+ var.setString8 ((const char8*)passed);
+ var.setOwner (true);
+ }
+ else
+ var.setString8 (kEmptyString8);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+unsigned char* String::toPascalString (unsigned char* buf)
+{
+ if (buffer)
+ {
+ if (isWide)
+ {
+ String tmp (*this);
+ tmp.toMultiByte ();
+ return tmp.toPascalString (buf);
+ }
+
+ int32 length = len;
+ if (length > 255)
+ length = 255;
+ buf[0] = (uint8)length;
+ while (length >= 0)
+ {
+ buf[length + 1] = buffer8[length];
+ length--;
+ }
+ return buf;
+ }
+ else
+ {
+ *buf = 0;
+ return buf;
+ }
+}
+
+//-----------------------------------------------------------------------------
+const String& String::fromPascalString (const unsigned char* buf)
+{
+ resize (0, false);
+ isWide = 0;
+ int32 length = buf[0];
+ resize (length + 1, false);
+ buffer8[length] = 0; // cannot be removed, because we only do the 0-termination for multibyte buffer8
+ while (--length >= 0)
+ buffer8[length] = buf[length + 1];
+ len = buf[0];
+ return *this;
+}
+
+#if SMTG_OS_MACOS
+
+//-----------------------------------------------------------------------------
+bool String::fromCFStringRef (const void* cfStr, uint32 encoding)
+{
+ if (cfStr == 0)
+ return false;
+
+ CFStringRef strRef = (CFStringRef)cfStr;
+ if (isWide)
+ {
+ CFRange range = { 0, CFStringGetLength (strRef)};
+ CFIndex usedBytes;
+ if (resize (static_cast (range.length + 1), true))
+ {
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingUnicode;
+ if (CFStringGetBytes (strRef, range, encoding, ' ', false, (UInt8*)buffer16, range.length * 2, &usedBytes) > 0)
+ {
+ buffer16[usedBytes/2] = 0;
+ this->len = strlen16 (buffer16);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (cfStr == 0)
+ return false;
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingASCII;
+ int32 len = static_cast (CFStringGetLength (strRef) * 2);
+ if (resize (++len, false))
+ {
+ if (CFStringGetCString (strRef, buffer8, len, encoding))
+ {
+ this->len = static_cast (strlen (buffer8));
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+void* ConstString::toCFStringRef (uint32 encoding, bool mutableCFString) const
+{
+ if (mutableCFString)
+ {
+ CFMutableStringRef str = CFStringCreateMutable (kCFAllocator, 0);
+ if (isWide)
+ {
+ CFStringAppendCharacters (str, (const UniChar *)buffer16, len);
+ return str;
+ }
+ else
+ {
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingASCII;
+ CFStringAppendCString (str, buffer8, encoding);
+ return str;
+ }
+ }
+ else
+ {
+ if (isWide)
+ {
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingUnicode;
+ return (void*)CFStringCreateWithBytes (kCFAllocator, (const unsigned char*)buffer16, len * 2, encoding, false);
+ }
+ else
+ {
+ if (encoding == 0xFFFF)
+ encoding = kCFStringEncodingASCII;
+ if (buffer8)
+ return (void*)CFStringCreateWithCString (kCFAllocator, buffer8, encoding);
+ else
+ return (void*)CFStringCreateWithCString (kCFAllocator, "", encoding);
+ }
+ }
+ return 0;
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+uint32 hashString8 (const char8* s, uint32 m)
+{
+ uint32 h = 0;
+ if (s)
+ {
+ for (h = 0; *s != '\0'; s++)
+ h = (64 * h + *s) % m;
+ }
+ return h;
+}
+
+//-----------------------------------------------------------------------------
+uint32 hashString16 (const char16* s, uint32 m)
+{
+ uint32 h = 0;
+ if (s)
+ {
+ for (h = 0; *s != 0; s++)
+ h = (64 * h + *s) % m;
+ }
+ return h;
+}
+
+//------------------------------------------------------------------------
+template int32 tstrnatcmp (const T* s1, const T* s2, bool caseSensitive = true)
+{
+ if (s1 == 0 && s2 == 0)
+ return 0;
+ else if (s1 == 0)
+ return -1;
+ else if (s2 == 0)
+ return 1;
+
+ while (*s1 && *s2)
+ {
+ if (ConstString::isCharDigit (*s1) && ConstString::isCharDigit (*s2))
+ {
+ int32 s1LeadingZeros = 0;
+ while (*s1 == '0')
+ {
+ s1++; // skip leading zeros
+ s1LeadingZeros++;
+ }
+ int32 s2LeadingZeros = 0;
+ while (*s2 == '0')
+ {
+ s2++; // skip leading zeros
+ s2LeadingZeros++;
+ }
+
+ int32 countS1Digits = 0;
+ while (*(s1 + countS1Digits) && ConstString::isCharDigit (*(s1 + countS1Digits)))
+ countS1Digits++;
+ int32 countS2Digits = 0;
+ while (*(s2 + countS2Digits) && ConstString::isCharDigit (*(s2 + countS2Digits)))
+ countS2Digits++;
+
+ if (countS1Digits != countS2Digits)
+ return countS1Digits - countS2Digits; // one number is longer than the other
+
+ for (int32 i = 0; i < countS1Digits; i++)
+ {
+ // countS1Digits == countS2Digits
+ if (*s1 != *s2)
+ return (int32)(*s1 - *s2); // the digits differ
+ s1++;
+ s2++;
+ }
+
+ if (s1LeadingZeros != s2LeadingZeros)
+ return s1LeadingZeros - s2LeadingZeros; // differentiate by the number of leading zeros
+ }
+ else
+ {
+ if (caseSensitive == false)
+ {
+ T srcToUpper = toupper (*s1);
+ T dstToUpper = toupper (*s2);
+ if (srcToUpper != dstToUpper)
+ return (int32)(srcToUpper - dstToUpper);
+ }
+ else if (*s1 != *s2)
+ return (int32)(*s1 - *s2);
+
+ s1++;
+ s2++;
+ }
+ }
+
+ if (*s1 == 0 && *s2 == 0)
+ return 0;
+ else if (*s1 == 0)
+ return -1;
+ else if (*s2 == 0)
+ return 1;
+ else
+ return (int32)(*s1 - *s2);
+}
+
+//------------------------------------------------------------------------
+int32 strnatcmp8 (const char8* s1, const char8* s2, bool caseSensitive /*= true*/)
+{
+ return tstrnatcmp (s1, s2, caseSensitive);
+}
+
+//------------------------------------------------------------------------
+int32 strnatcmp16 (const char16* s1, const char16* s2, bool caseSensitive /*= true*/)
+{
+ return tstrnatcmp (s1, s2, caseSensitive);
+}
+
+//-----------------------------------------------------------------------------
+// StringObject Implementation
+//-----------------------------------------------------------------------------
+void PLUGIN_API StringObject::setText (const char8* text)
+{
+ assign (text);
+}
+
+//-----------------------------------------------------------------------------
+void PLUGIN_API StringObject::setText8 (const char8* text)
+{
+ assign (text);
+}
+
+//-----------------------------------------------------------------------------
+void PLUGIN_API StringObject::setText16 (const char16* text)
+{
+ assign (text);
+}
+
+//-----------------------------------------------------------------------------
+const char8* PLUGIN_API StringObject::getText8 ()
+{
+ return text8 ();
+}
+
+//-----------------------------------------------------------------------------
+const char16* PLUGIN_API StringObject::getText16 ()
+{
+ return text16 ();
+}
+
+//-----------------------------------------------------------------------------
+void PLUGIN_API StringObject::take (void* s, bool _isWide)
+{
+ String::take (s, _isWide);
+}
+
+//-----------------------------------------------------------------------------
+bool PLUGIN_API StringObject::isWideString () const
+{
+ return String::isWideString ();
+}
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.h b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.h
new file mode 100644
index 0000000000..12cc3de47f
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/fstring.h
@@ -0,0 +1,747 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/fstring.h
+// Created by : Steinberg, 2008
+// Description : String class
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include "pluginterfaces/base/ftypes.h"
+#include "pluginterfaces/base/fstrdefs.h"
+#include "pluginterfaces/base/istringresult.h"
+#include "pluginterfaces/base/ipersistent.h"
+
+#include "base/source/fobject.h"
+
+#include
+
+namespace Steinberg {
+
+class FVariant;
+class String;
+
+#ifdef UNICODE
+static const bool kWideStringDefault = true;
+#else
+static const bool kWideStringDefault = false;
+#endif
+
+static const uint16 kBomUtf16 = 0xFEFF; ///< UTF16 Byte Order Mark
+static const char8* const kBomUtf8 = "\xEF\xBB\xBF"; ///< UTF8 Byte Order Mark
+static const int32 kBomUtf8Length = 3;
+
+
+enum MBCodePage
+{
+ kCP_ANSI = 0, ///< Default ANSI codepage.
+ kCP_MAC_ROMAN = 2, ///< Default Mac codepage.
+
+ kCP_ANSI_WEL = 1252, ///< West European Latin Encoding.
+ kCP_MAC_CEE = 10029, ///< Mac Central European Encoding.
+ kCP_Utf8 = 65001, ///< UTF8 Encoding.
+ kCP_ShiftJIS = 932, ///< Shifted Japan Industrial Standard Encoding.
+ kCP_US_ASCII = 20127, ///< US-ASCII (7-bit).
+
+ kCP_Default = kCP_ANSI ///< Default ANSI codepage.
+};
+
+enum UnicodeNormalization
+{
+ kUnicodeNormC, ///< Unicode normalization Form C, canonical composition.
+ kUnicodeNormD, ///< Unicode normalization Form D, canonical decomposition.
+ kUnicodeNormKC, ///< Unicode normalization form KC, compatibility composition.
+ kUnicodeNormKD ///< Unicode normalization form KD, compatibility decomposition.
+};
+
+//------------------------------------------------------------------------
+// Helper functions to create hash codes from string data.
+//------------------------------------------------------------------------
+extern uint32 hashString8 (const char8* s, uint32 m);
+extern uint32 hashString16 (const char16* s, uint32 m);
+inline uint32 hashString (const tchar* s, uint32 m)
+{
+#ifdef UNICODE
+ return hashString16 (s, m);
+#else
+ return hashString8 (s, m);
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+/** Invariant String.
+@ingroup adt
+
+A base class which provides methods to work with its
+member string. Neither of the operations allows modifying the member string and
+that is why all operation are declared as const.
+
+There are operations for access, comparison, find, numbers and conversion.
+
+Almost all operations exist in three versions for char8, char16 and the
+polymorphic type tchar. The type tchar can either be char8 or char16 depending
+on whether UNICODE is activated or not.*/
+//-----------------------------------------------------------------------------
+class ConstString
+{
+public:
+//-----------------------------------------------------------------------------
+ ConstString (const char8* str, int32 length = -1); ///< Assign from string of type char8 (length=-1: all)
+ ConstString (const char16* str, int32 length = -1); ///< Assign from string of type char16 (length=-1: all)
+ ConstString (const ConstString& str, int32 offset = 0, int32 length = -1); ///< Copy constructor (length=-1: all).
+ ConstString (const FVariant& var); ///< Assign a string from FVariant
+ ConstString ();
+ virtual ~ConstString () {} ///< Destructor.
+
+ // access -----------------------------------------------------------------
+ virtual int32 length () const {return static_cast (len);} ///< Return length of string
+ inline bool isEmpty () const {return buffer == 0 || len == 0;} ///< Return true if string is empty
+
+ operator const char8* () const {return text8 ();} ///< Returns pointer to string of type char8 (no modification allowed)
+ operator const char16* () const {return text16 ();} ///< Returns pointer to string of type char16(no modification allowed)
+ inline tchar operator[] (short idx) const {return getChar (static_cast (idx));} ///< Returns character at 'idx'
+ inline tchar operator[] (long idx) const {return getChar (static_cast (idx));}
+ inline tchar operator[] (int idx) const {return getChar (static_cast (idx));}
+ inline tchar operator[] (unsigned short idx) const {return getChar (idx);}
+ inline tchar operator[] (unsigned long idx) const {return getChar (static_cast (idx));}
+ inline tchar operator[] (unsigned int idx) const {return getChar (idx);}
+
+ inline virtual const char8* text8 () const; ///< Returns pointer to string of type char8
+ inline virtual const char16* text16 () const; ///< Returns pointer to string of type char16
+ inline virtual const tchar* text () const; ///< Returns pointer to string of type tchar
+ inline virtual const void* ptr () const {return buffer;} ///< Returns pointer to string of type void
+
+ inline virtual char8 getChar8 (uint32 index) const; ///< Returns character of type char16 at 'index'
+ inline virtual char16 getChar16 (uint32 index) const; ///< Returns character of type char8 at 'index'
+ inline tchar getChar (uint32 index) const; ///< Returns character of type tchar at 'index'
+ inline tchar getCharAt (uint32 index) const; ///< Returns character of type tchar at 'index', no conversion!
+
+ bool testChar8 (uint32 index, char8 c) const; ///< Returns true if character is equal at position 'index'
+ bool testChar16 (uint32 index, char16 c) const;
+ inline bool testChar (uint32 index, char8 c) const {return testChar8 (index, c);}
+ inline bool testChar (uint32 index, char16 c) const {return testChar16 (index, c);}
+
+ bool extract (String& result, uint32 idx, int32 n = -1) const; ///< Get n characters long substring starting at index (n=-1: until end)
+ int32 copyTo8 (char8* str, uint32 idx = 0, int32 n = -1) const;
+ int32 copyTo16 (char16* str, uint32 idx = 0, int32 n = -1) const;
+ int32 copyTo (tchar* str, uint32 idx = 0, int32 n = -1) const;
+ void copyTo (IStringResult* result) const; ///< Copies whole member string
+ void copyTo (IString& string) const; ///< Copies whole member string
+
+ inline uint32 hash (uint32 tsize) const
+ {
+ return isWide ? hashString16 (buffer16, tsize) : hashString8 (buffer8, tsize) ;
+ }
+ //-------------------------------------------------------------------------
+
+ // compare ----------------------------------------------------------------
+ enum CompareMode
+ {
+ kCaseSensitive, ///< Comparison is done with regard to character's case
+ kCaseInsensitive ///< Comparison is done without regard to character's case
+ };
+
+ int32 compareAt (uint32 index, const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive) const; ///< Compare n characters of str with n characters of this starting at index (return: see above)
+ int32 compare (const ConstString& str, int32 n, CompareMode m = kCaseSensitive) const; ///< Compare n characters of str with n characters of this (return: see above)
+ int32 compare (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Compare all characters of str with this (return: see above)
+
+ int32 naturalCompare (const ConstString& str, CompareMode mode = kCaseSensitive) const;
+
+ bool startsWith (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this starts with str
+ bool endsWith (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this ends with str
+ bool contains (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this contains str
+
+ // static methods
+ static bool isCharSpace (char8 character); ///< Returns true if character is a space
+ static bool isCharSpace (char16 character); ///< @copydoc isCharSpace(const char8)
+ static bool isCharAlpha (char8 character); ///< Returns true if character is an alphabetic character
+ static bool isCharAlpha (char16 character); ///< @copydoc isCharAlpha(const char8)
+ static bool isCharAlphaNum (char8 character); ///< Returns true if character is an alphanumeric character
+ static bool isCharAlphaNum (char16 character); ///< @copydoc isCharAlphaNum(const char8)
+ static bool isCharDigit (char8 character); ///< Returns true if character is a number
+ static bool isCharDigit (char16 character); ///< @copydoc isCharDigit(const char8)
+ static bool isCharAscii (char8 character); ///< Returns true if character is in ASCII range
+ static bool isCharAscii (char16 character); ///< Returns true if character is in ASCII range
+ static bool isCharUpper (char8 character);
+ static bool isCharUpper (char16 character);
+ static bool isCharLower (char8 character);
+ static bool isCharLower (char16 character);
+ //-------------------------------------------------------------------------
+
+ /** @name Find first occurrence of n characters of str in this (n=-1: all) ending at endIndex (endIndex = -1: all)*/
+ ///@{
+ inline int32 findFirst (const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, str, n, m, endIndex);}
+ inline int32 findFirst (char8 c, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, c, m, endIndex);}
+ inline int32 findFirst (char16 c, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, c, m, endIndex);}
+ ///@}
+ /** @name Find next occurrence of n characters of str starting at startIndex in this (n=-1: all) ending at endIndex (endIndex = -1: all)*/
+ ///@{
+ int32 findNext (int32 startIndex, const ConstString& str, int32 n = -1, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
+ int32 findNext (int32 startIndex, char8 c, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
+ int32 findNext (int32 startIndex, char16 c, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
+ ///@}
+ /** @name Find previous occurrence of n characters of str starting at startIndex in this (n=-1: all) */
+ ///@{
+ int32 findPrev (int32 startIndex, const ConstString& str, int32 n = -1, CompareMode = kCaseSensitive) const;
+ int32 findPrev (int32 startIndex, char8 c, CompareMode = kCaseSensitive) const;
+ int32 findPrev (int32 startIndex, char16 c, CompareMode = kCaseSensitive) const;
+ ///@}
+
+ inline int32 findLast (const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive) const {return findPrev (-1, str, n, m);} ///< Find last occurrence of n characters of str in this (n=-1: all)
+ inline int32 findLast (char8 c, CompareMode m = kCaseSensitive) const {return findPrev (-1, c, m);}
+ inline int32 findLast (char16 c, CompareMode m = kCaseSensitive) const {return findPrev (-1, c, m);}
+
+ int32 countOccurences (char8 c, uint32 startIndex, CompareMode = kCaseSensitive) const; ///< Counts occurences of c within this starting at index
+ int32 countOccurences (char16 c, uint32 startIndex, CompareMode = kCaseSensitive) const;
+ int32 getFirstDifferent (const ConstString& str, CompareMode = kCaseSensitive) const; ///< Returns position of first different character
+ //-------------------------------------------------------------------------
+
+ // numbers ----------------------------------------------------------------
+ bool isDigit (uint32 index) const; ///< Returns true if character at position is a digit
+ bool scanFloat (double& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to double value starting at offset
+ bool scanInt64 (int64& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to int64 value starting at offset
+ bool scanUInt64 (uint64& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to uint64 value starting at offset
+ bool scanInt32 (int32& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to int32 value starting at offset
+ bool scanUInt32 (uint32& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to uint32 value starting at offset
+ bool scanHex (uint8& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to hex/uint8 value starting at offset
+
+ int32 getTrailingNumberIndex (uint32 width = 0) const; ///< Returns start index of trailing number
+ int64 getTrailingNumber (int64 fallback = 0) const; ///< Returns result of scanInt64 or the fallback
+ int64 getNumber () const; ///< Returns result of scanInt64
+
+ // static methods
+ static bool scanInt64_8 (const char8* text, int64& value, bool scanToEnd = true); ///< Converts string of type char8 to int64 value
+ static bool scanInt64_16 (const char16* text, int64& value, bool scanToEnd = true); ///< Converts string of type char16 to int64 value
+ static bool scanInt64 (const tchar* text, int64& value, bool scanToEnd = true); ///< Converts string of type tchar to int64 value
+
+ static bool scanUInt64_8 (const char8* text, uint64& value, bool scanToEnd = true); ///< Converts string of type char8 to uint64 value
+ static bool scanUInt64_16 (const char16* text, uint64& value, bool scanToEnd = true); ///< Converts string of type char16 to uint64 value
+ static bool scanUInt64 (const tchar* text, uint64& value, bool scanToEnd = true); ///< Converts string of type tchar to uint64 value
+
+ static bool scanInt32_8 (const char8* text, int32& value, bool scanToEnd = true); ///< Converts string of type char8 to int32 value
+ static bool scanInt32_16 (const char16* text, int32& value, bool scanToEnd = true); ///< Converts string of type char16 to int32 value
+ static bool scanInt32 (const tchar* text, int32& value, bool scanToEnd = true); ///< Converts string of type tchar to int32 value
+
+ static bool scanUInt32_8 (const char8* text, uint32& value, bool scanToEnd = true); ///< Converts string of type char8 to int32 value
+ static bool scanUInt32_16 (const char16* text, uint32& value, bool scanToEnd = true); ///< Converts string of type char16 to int32 value
+ static bool scanUInt32 (const tchar* text, uint32& value, bool scanToEnd = true); ///< Converts string of type tchar to int32 value
+
+ static bool scanHex_8 (const char8* text, uint8& value, bool scanToEnd = true); ///< Converts string of type char8 to hex/unit8 value
+ static bool scanHex_16 (const char16* text, uint8& value, bool scanToEnd = true); ///< Converts string of type char16 to hex/unit8 value
+ static bool scanHex (const tchar* text, uint8& value, bool scanToEnd = true); ///< Converts string of type tchar to hex/unit8 value
+ //-------------------------------------------------------------------------
+
+ // conversion -------------------------------------------------------------
+ void toVariant (FVariant& var) const;
+
+ static char8 toLower (char8 c); ///< Converts to lower case
+ static char8 toUpper (char8 c); ///< Converts to upper case
+ static char16 toLower (char16 c);
+ static char16 toUpper (char16 c);
+
+ static int32 multiByteToWideString (char16* dest, const char8* source, int32 wcharCount, uint32 sourceCodePage = kCP_Default); ///< If dest is zero, this returns the maximum number of bytes needed to convert source
+ static int32 wideStringToMultiByte (char8* dest, const char16* source, int32 char8Count, uint32 destCodePage = kCP_Default); ///< If dest is zero, this returns the maximum number of bytes needed to convert source
+
+ bool isWideString () const {return isWide != 0;} ///< Returns true if string is wide
+ bool isAsciiString () const; ///< Checks if all characters in string are in ascii range
+
+ bool isNormalized (UnicodeNormalization = kUnicodeNormC); ///< On PC only kUnicodeNormC is working
+
+#if SMTG_OS_MACOS
+ virtual void* toCFStringRef (uint32 encoding = 0xFFFF, bool mutableCFString = false) const; ///< CFString conversion
+#endif
+//-------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+protected:
+
+ union
+ {
+ void* buffer;
+ char8* buffer8;
+ char16* buffer16;
+ };
+ uint32 len : 30;
+ uint32 isWide : 1;
+};
+
+//-----------------------------------------------------------------------------
+/** String.
+@ingroup adt
+
+Extends class ConstString by operations which allow modifications.
+
+\see ConstString */
+//-----------------------------------------------------------------------------
+class String : public ConstString
+{
+public:
+//-----------------------------------------------------------------------------
+ String ();
+ String (const char8* str, MBCodePage codepage, int32 n = -1, bool isTerminated = true); ///< assign n characters of str and convert to wide string by using the specified codepage
+ String (const char8* str, int32 n = -1, bool isTerminated = true); ///< assign n characters of str (-1: all)
+ String (const char16* str, int32 n = -1, bool isTerminated = true); ///< assign n characters of str (-1: all)
+ String (const String& str, int32 n = -1); ///< assign n characters of str (-1: all)
+ String (const ConstString& str, int32 n = -1); ///< assign n characters of str (-1: all)
+ String (const FVariant& var); ///< assign from FVariant
+ String (IString* str); ///< assign from IString
+ ~String ();
+
+#if SMTG_CPP11_STDLIBSUPPORT
+ String (String&& str);
+ String& operator= (String&& str);
+#endif
+
+ // access------------------------------------------------------------------
+ void updateLength (); ///< Call this when the string is truncated outside (not recommended though)
+ virtual const char8* text8 () const SMTG_OVERRIDE;
+ virtual const char16* text16 () const SMTG_OVERRIDE;
+ virtual char8 getChar8 (uint32 index) const SMTG_OVERRIDE;
+ virtual char16 getChar16 (uint32 index) const SMTG_OVERRIDE;
+
+ bool setChar8 (uint32 index, char8 c);
+ bool setChar16 (uint32 index, char16 c);
+ inline bool setChar (uint32 index, char8 c) {return setChar8 (index, c);}
+ inline bool setChar (uint32 index, char16 c) {return setChar16 (index, c);}
+ //-------------------------------------------------------------------------
+
+ // assignment--------------------------------------------------------------
+ String& operator= (const char8* str) {return assign (str);} ///< Assign from a string of type char8
+ String& operator= (const char16* str) {return assign (str);}
+ String& operator= (const ConstString& str) {return assign (str);}
+ String& operator= (const String& str) {return assign (str);}
+ String& operator= (char8 c) {return assign (c);}
+ String& operator= (char16 c) {return assign (c);}
+
+ String& assign (const ConstString& str, int32 n = -1); ///< Assign n characters of str (-1: all)
+ String& assign (const char8* str, int32 n = -1, bool isTerminated = true); ///< Assign n characters of str (-1: all)
+ String& assign (const char16* str, int32 n = -1, bool isTerminated = true); ///< Assign n characters of str (-1: all)
+ String& assign (char8 c, int32 n = 1);
+ String& assign (char16 c, int32 n = 1);
+ //-------------------------------------------------------------------------
+
+ // concat------------------------------------------------------------------
+ String& append (const ConstString& str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
+ String& append (const char8* str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
+ String& append (const char16* str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
+ String& append (const char8 c, int32 n = 1); ///< Append char c n times
+ String& append (const char16 c, int32 n = 1); ///< Append char c n times
+
+ String& insertAt (uint32 idx, const ConstString& str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
+ String& insertAt (uint32 idx, const char8* str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
+ String& insertAt (uint32 idx, const char16* str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
+ String& insertAt (uint32 idx, char8 c) {char8 str[] = {c, 0}; return insertAt (idx, str, 1);}
+ String& insertAt (uint32 idx, char16 c) {char16 str[] = {c, 0}; return insertAt (idx, str, 1);}
+
+ String& operator+= (const String& str) {return append (str);}
+ String& operator+= (const ConstString& str) {return append (str);}
+ String& operator+= (const char8* str) {return append (str);}
+ String& operator+= (const char16* str) {return append (str);}
+ String& operator+= (const char8 c) {return append (c);}
+ String& operator+= (const char16 c) {return append (c);}
+ //-------------------------------------------------------------------------
+
+ // replace-----------------------------------------------------------------
+ String& replace (uint32 idx, int32 n1, const ConstString& str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
+ String& replace (uint32 idx, int32 n1, const char8* str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
+ String& replace (uint32 idx, int32 n1, const char16* str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
+
+ int32 replace (const char8* toReplace, const char8* toReplaceWith, bool all = false, CompareMode m = kCaseSensitive); ///< Replace find string with replace string - returns number of replacements
+ int32 replace (const char16* toReplace, const char16* toReplaceWith, bool all = false, CompareMode m = kCaseSensitive); ///< Replace find string with replace string - returns number of replacements
+
+ bool replaceChars8 (const char8* toReplace, char8 toReplaceBy); ///< Returns true when any replacement was done
+ bool replaceChars16 (const char16* toReplace, char16 toReplaceBy);
+ inline bool replaceChars8 (char8 toReplace, char8 toReplaceBy) {char8 str[] = {toReplace, 0}; return replaceChars8 (str, toReplaceBy);}
+ inline bool replaceChars16 (char16 toReplace, char16 toReplaceBy) {char16 str[] = {toReplace, 0}; return replaceChars16 (str, toReplaceBy);}
+ inline bool replaceChars (char8 toReplace, char8 toReplaceBy) {return replaceChars8 (toReplace, toReplaceBy);}
+ inline bool replaceChars (char16 toReplace, char16 toReplaceBy) {return replaceChars16 (toReplace, toReplaceBy);}
+ inline bool replaceChars (const char8* toReplace, char8 toReplaceBy) {return replaceChars8 (toReplace, toReplaceBy);}
+ inline bool replaceChars (const char16* toReplace, char16 toReplaceBy) {return replaceChars16 (toReplace, toReplaceBy);}
+ //-------------------------------------------------------------------------
+
+ // remove------------------------------------------------------------------
+ String& remove (uint32 index = 0, int32 n = -1); ///< Remove n characters from string starting at index (n=-1: until end)
+ enum CharGroup {kSpace, kNotAlphaNum, kNotAlpha};
+ bool trim (CharGroup mode = kSpace); ///< Trim lead/trail.
+ void removeChars (CharGroup mode = kSpace); ///< Removes all of group.
+ bool removeChars8 (const char8* which); ///< Remove all occurrences of each char in 'which'
+ bool removeChars16 (const char16* which); ///< Remove all occurrences of each char in 'which'
+ inline bool removeChars8 (const char8 which) {char8 str[] = {which, 0}; return removeChars8 (str); }
+ inline bool removeChars16 (const char16 which) {char16 str[] = {which, 0}; return removeChars16 (str); }
+ inline bool removeChars (const char8* which) {return removeChars8 (which);}
+ inline bool removeChars (const char16* which) {return removeChars16 (which);}
+ inline bool removeChars (const char8 which) {return removeChars8 (which);}
+ inline bool removeChars (const char16 which) {return removeChars16 (which);}
+ bool removeSubString (const ConstString& subString, bool allOccurences = true);
+ //-------------------------------------------------------------------------
+
+ // print-------------------------------------------------------------------
+ String& printf (const char8* format, ...); ///< Print formatted data into string
+ String& printf (const char16* format, ...); ///< Print formatted data into string
+ String& vprintf (const char8* format, va_list args);
+ String& vprintf (const char16* format, va_list args);
+ //-------------------------------------------------------------------------
+
+ // numbers-----------------------------------------------------------------
+ String& printInt64 (int64 value);
+ String& printFloat (double value);
+ /** Increment the trailing number if present else start with minNumber, width specifies the string width format (width 2 for number 3 is 03),
+ applyOnlyFormat set to true will only format the string to the given width without incrementing the founded trailing number */
+ bool incrementTrailingNumber (uint32 width = 2, tchar separator = STR (' '), uint32 minNumber = 1, bool applyOnlyFormat = false);
+ //-------------------------------------------------------------------------
+
+ // conversion--------------------------------------------------------------
+ bool fromVariant (const FVariant& var); ///< Assigns string from FVariant
+ void toVariant (FVariant& var) const;
+ bool fromAttributes (IAttributes* a, IAttrID attrID); ///< Assigns string from FAttributes
+ bool toAttributes (IAttributes* a, IAttrID attrID);
+
+ void swapContent (String& s); ///< Swaps ownership of the strings pointed to
+ void take (String& str); ///< Take ownership of the string of 'str'
+ void take (void* _buffer, bool wide); ///< Take ownership of buffer
+ void* pass ();
+ void passToVariant (FVariant& var); ///< Pass ownership of buffer to Variant - sets Variant ownership
+
+ void toLower (uint32 index); ///< Lower case the character.
+ void toLower (); ///< Lower case the string.
+ void toUpper (uint32 index); ///< Upper case the character.
+ void toUpper (); ///< Upper case the string.
+
+ unsigned char* toPascalString (unsigned char* buf); ///< Pascal string conversion
+ const String& fromPascalString (const unsigned char* buf); ///< Pascal string conversion
+
+ bool toWideString (uint32 sourceCodePage = kCP_Default); ///< Converts to wide string according to sourceCodePage
+ bool toMultiByte (uint32 destCodePage = kCP_Default);
+
+ void fromUTF8 (const char8* utf8String); ///< Assigns from UTF8 string
+ bool normalize (UnicodeNormalization = kUnicodeNormC); ///< On PC only kUnicodeNormC is working
+
+#if SMTG_OS_MACOS
+ virtual bool fromCFStringRef (const void*, uint32 encoding = 0xFFFF); ///< CFString conversion
+#endif
+ //-------------------------------------------------------------------------
+
+ //-----------------------------------------------------------------------------
+protected:
+ bool resize (uint32 newSize, bool wide, bool fill = false);
+
+private:
+ void tryFreeBuffer ();
+ bool checkToMultiByte (uint32 destCodePage = kCP_Default) const; // to remove debug code from inline - const_cast inside!!!
+};
+
+// String concatenation functions.
+inline String operator+ (const ConstString& s1, const ConstString& s2) {return String (s1).append (s2);}
+inline String operator+ (const ConstString& s1, const char8* s2) {return String (s1).append (s2);}
+inline String operator+ (const ConstString& s1, const char16* s2) {return String (s1).append (s2);}
+inline String operator+ (const char8* s1, const ConstString& s2) {return String (s1).append (s2);}
+inline String operator+ (const char16* s1, const ConstString& s2) {return String (s1).append (s2);}
+inline String operator+ (const ConstString& s1, const String& s2) {return String (s1).append (s2);}
+inline String operator+ (const String& s1, const ConstString& s2) {return String (s1).append (s2);}
+inline String operator+ (const String& s1, const String& s2) {return String (s1).append (s2);}
+inline String operator+ (const String& s1, const char8* s2) {return String (s1).append (s2);}
+inline String operator+ (const String& s1, const char16* s2) {return String (s1).append (s2);}
+inline String operator+ (const char8* s1, const String& s2) {return String (s1).append (s2);}
+inline String operator+ (const char16* s1, const String& s2) {return String (s1).append (s2);}
+
+//-----------------------------------------------------------------------------
+// ConstString
+//-----------------------------------------------------------------------------
+inline const tchar* ConstString::text () const
+{
+#ifdef UNICODE
+ return text16 ();
+#else
+ return text8 ();
+#endif
+}
+
+//-----------------------------------------------------------------------------
+inline const char8* ConstString::text8 () const
+{
+ return (!isWide && buffer8) ? buffer8: kEmptyString8;
+}
+
+//-----------------------------------------------------------------------------
+inline const char16* ConstString::text16 () const
+{
+ return (isWide && buffer16) ? buffer16 : kEmptyString16;
+}
+
+//-----------------------------------------------------------------------------
+inline char8 ConstString::getChar8 (uint32 index) const
+{
+ if (index < len && buffer8 && !isWide)
+ return buffer8[index];
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+inline char16 ConstString::getChar16 (uint32 index) const
+{
+ if (index < len && buffer16 && isWide)
+ return buffer16[index];
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+inline tchar ConstString::getChar (uint32 index) const
+{
+#ifdef UNICODE
+ return getChar16 (index);
+#else
+ return getChar8 (index);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+inline tchar ConstString::getCharAt (uint32 index) const
+{
+#ifdef UNICODE
+ if (isWide)
+ return getChar16 (index);
+#endif
+
+ return static_cast (getChar8 (index));
+}
+
+//-----------------------------------------------------------------------------
+inline int64 ConstString::getNumber () const
+{
+ int64 tmp = 0;
+ scanInt64 (tmp);
+ return tmp;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanInt32_8 (const char8* text, int32& value, bool scanToEnd)
+{
+ int64 tmp;
+ if (scanInt64_8 (text, tmp, scanToEnd))
+ {
+ value = (int32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanInt32_16 (const char16* text, int32& value, bool scanToEnd)
+{
+ int64 tmp;
+ if (scanInt64_16 (text, tmp, scanToEnd))
+ {
+ value = (int32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanInt32 (const tchar* text, int32& value, bool scanToEnd)
+{
+ int64 tmp;
+ if (scanInt64 (text, tmp, scanToEnd))
+ {
+ value = (int32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanUInt32_8 (const char8* text, uint32& value, bool scanToEnd)
+{
+ uint64 tmp;
+ if (scanUInt64_8 (text, tmp, scanToEnd))
+ {
+ value = (uint32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanUInt32_16 (const char16* text, uint32& value, bool scanToEnd)
+{
+ uint64 tmp;
+ if (scanUInt64_16 (text, tmp, scanToEnd))
+ {
+ value = (uint32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline bool ConstString::scanUInt32 (const tchar* text, uint32& value, bool scanToEnd)
+{
+ uint64 tmp;
+ if (scanUInt64 (text, tmp, scanToEnd))
+ {
+ value = (uint32)tmp;
+ return true;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+inline const char8* String::text8 () const
+{
+ if (isWide && !isEmpty ())
+ checkToMultiByte (); // this should be avoided, since it can lead to information loss
+
+ return ConstString::text8 ();
+}
+
+//-----------------------------------------------------------------------------
+inline const char16* String::text16 () const
+{
+ if (!isWide && !isEmpty ())
+ {
+ const_cast (*this).toWideString ();
+ }
+ return ConstString::text16 ();
+}
+
+//-----------------------------------------------------------------------------
+inline char8 String::getChar8 (uint32 index) const
+{
+ if (isWide && !isEmpty ())
+ checkToMultiByte (); // this should be avoided, since it can lead to information loss
+
+ return ConstString::getChar8 (index);
+}
+
+//-----------------------------------------------------------------------------
+inline char16 String::getChar16 (uint32 index) const
+{
+ if (!isWide && !isEmpty ())
+ {
+ const_cast (*this).toWideString ();
+ }
+ return ConstString::getChar16 (index);
+}
+
+//-----------------------------------------------------------------------------
+
+
+inline bool operator< (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) < 0) ? true : false;}
+inline bool operator<= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) <= 0) ? true : false;}
+inline bool operator> (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) > 0) ? true : false;}
+inline bool operator>= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) >= 0) ? true : false;}
+inline bool operator== (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) == 0) ? true : false;}
+inline bool operator!= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) != 0) ? true : false;}
+
+inline bool operator< (const ConstString& s1, const char8* s2) {return (s1.compare (s2) < 0) ? true : false;}
+inline bool operator<= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) <= 0) ? true : false;}
+inline bool operator> (const ConstString& s1, const char8* s2) {return (s1.compare (s2) > 0) ? true : false;}
+inline bool operator>= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) >= 0) ? true : false;}
+inline bool operator== (const ConstString& s1, const char8* s2) {return (s1.compare (s2) == 0) ? true : false;}
+inline bool operator!= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) != 0) ? true : false;}
+inline bool operator< (const char8* s1, const ConstString& s2) {return (s2.compare (s1) > 0) ? true : false;}
+inline bool operator<= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) >= 0) ? true : false;}
+inline bool operator> (const char8* s1, const ConstString& s2) {return (s2.compare (s1) < 0) ? true : false;}
+inline bool operator>= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) <= 0) ? true : false;}
+inline bool operator== (const char8* s1, const ConstString& s2) {return (s2.compare (s1) == 0) ? true : false;}
+inline bool operator!= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) != 0) ? true : false;}
+
+inline bool operator< (const ConstString& s1, const char16* s2) {return (s1.compare (s2) < 0) ? true : false;}
+inline bool operator<= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) <= 0) ? true : false;}
+inline bool operator> (const ConstString& s1, const char16* s2) {return (s1.compare (s2) > 0) ? true : false;}
+inline bool operator>= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) >= 0) ? true : false;}
+inline bool operator== (const ConstString& s1, const char16* s2) {return (s1.compare (s2) == 0) ? true : false;}
+inline bool operator!= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) != 0) ? true : false;}
+inline bool operator< (const char16* s1, const ConstString& s2) {return (s2.compare (s1) > 0) ? true : false;}
+inline bool operator<= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) >= 0) ? true : false;}
+inline bool operator> (const char16* s1, const ConstString& s2) {return (s2.compare (s1) < 0) ? true : false;}
+inline bool operator>= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) <= 0) ? true : false;}
+inline bool operator== (const char16* s1, const ConstString& s2) {return (s2.compare (s1) == 0) ? true : false;}
+inline bool operator!= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) != 0) ? true : false;}
+
+// The following functions will only work with European Numbers!
+// (e.g. Arabic, Tibetan, and Khmer digits are not supported)
+extern int32 strnatcmp8 (const char8* s1, const char8* s2, bool caseSensitive = true);
+extern int32 strnatcmp16 (const char16* s1, const char16* s2, bool caseSensitive = true);
+inline int32 strnatcmp (const tchar* s1, const tchar* s2, bool caseSensitive = true)
+{
+#ifdef UNICODE
+ return strnatcmp16 (s1, s2, caseSensitive);
+#else
+ return strnatcmp8 (s1, s2, caseSensitive);
+#endif
+}
+
+//-----------------------------------------------------------------------------
+/** StringObject implements IStringResult and IString methods.
+ It can therefore be exchanged with other Steinberg objects using one or both of these
+interfaces.
+
+\see String, ConstString
+*/
+//-----------------------------------------------------------------------------
+class StringObject : public FObject, public String, public IStringResult, public IString
+{
+public:
+//-----------------------------------------------------------------------------
+ StringObject () {}
+ StringObject (const char16* str, int32 n = -1, bool isTerminated = true) : String (str, n, isTerminated) {}
+ StringObject (const char8* str, int32 n = -1, bool isTerminated = true) : String (str, n, isTerminated) {}
+ StringObject (const StringObject& str, int32 n = -1) : String (str, n) {}
+ StringObject (const String& str, int32 n = -1) : String (str, n) {}
+ StringObject (const FVariant& var) : String (var) {}
+
+ using String::operator=;
+
+ // IStringResult ----------------------------------------------------------
+ virtual void PLUGIN_API setText (const char8* text) SMTG_OVERRIDE;
+ //-------------------------------------------------------------------------
+
+ // IString-----------------------------------------------------------------
+ virtual void PLUGIN_API setText8 (const char8* text) SMTG_OVERRIDE;
+ virtual void PLUGIN_API setText16 (const char16* text) SMTG_OVERRIDE;
+
+ virtual const char8* PLUGIN_API getText8 () SMTG_OVERRIDE;
+ virtual const char16* PLUGIN_API getText16 () SMTG_OVERRIDE;
+
+ virtual void PLUGIN_API take (void* s, bool _isWide) SMTG_OVERRIDE;
+ virtual bool PLUGIN_API isWideString () const SMTG_OVERRIDE;
+ //-------------------------------------------------------------------------
+
+ OBJ_METHODS (StringObject, FObject)
+ FUNKNOWN_METHODS2 (IStringResult, IString, FObject)
+};
+
+//------------------------------------------------------------------------
+} // namespace Steinberg
diff --git a/modules/juce_audio_processors/format_types/VST3_SDK/base/source/updatehandler.cpp b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/updatehandler.cpp
new file mode 100644
index 0000000000..5d3745b664
--- /dev/null
+++ b/modules/juce_audio_processors/format_types/VST3_SDK/base/source/updatehandler.cpp
@@ -0,0 +1,721 @@
+//------------------------------------------------------------------------
+// Project : SDK Base
+// Version : 1.0
+//
+// Category : Helpers
+// Filename : base/source/updatehandler.cpp
+// Created by : Steinberg, 2008
+// Description :
+//
+//-----------------------------------------------------------------------------
+// LICENSE
+// (c) 2018, Steinberg Media Technologies GmbH, All Rights Reserved
+//-----------------------------------------------------------------------------
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Steinberg Media Technologies nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+//-----------------------------------------------------------------------------
+
+#include "base/source/updatehandler.h"
+#include "base/source/classfactoryhelpers.h"
+#include "base/source/fstring.h"
+
+#if SMTG_CPP11_STDLIBSUPPORT
+#include
+#else
+#include