text:
//------------------------------------------------------------------------
// Project     : SDK Base
// Version     : 1.0
//
// Category    : Helpers
// Filename    : base/source/fcommandline.h
// Created by  : Steinberg, 2007
// Description : Very simple command-line parser.
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, 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/fcommandline.h
	Very simple command-line parser.
	@see Steinberg::CommandLine */
//------------------------------------------------------------------------
#pragma once

#include <deque>
#include <map>
#include <vector>
#include <algorithm>
#include <sstream>

namespace Steinberg {
//------------------------------------------------------------------------
/** Very simple command-line parser.

Parses the command-line into a CommandLine::VariablesMap.\n
The command-line parser uses CommandLine::Descriptions to define the available options.

@b Example:
\code
#include "base/source/fcommandline.h"
#include <iostream>

int main (int argc, char* argv[])
{
	using namespace std;
	using namespace Steinberg;

	CommandLine::Descriptions desc;
	CommandLine::VariablesMap valueMap;

	desc.addOptions ("myTool")
		("help", "produce help message")
		("opt1", string(), "option 1")
		("opt2", string(), "option 2")
	;
	CommandLine::parse (argc, argv, desc, valueMap);

	if (valueMap.hasError () || valueMap.count ("help"))
	{
		cout << desc << "\n";
		return 1;
	}
	if (valueMap.count ("opt1"))
	{
		cout << "Value of option 1 " << valueMap["opt1"] << "\n";
	}
	if (valueMap.count ("opt2"))
	{
		cout << "Value of option 2 " << valueMap["opt2"] << "\n";
	}
	return 0;
}
\endcode
@note
This is a "header only" implementation.\n
If you need the declarations in more than one cpp file, you have to define
@c SMTG_NO_IMPLEMENTATION in all but one file.

*/
//------------------------------------------------------------------------
namespace CommandLine {

	//------------------------------------------------------------------------
	/**	Command-line parsing result.

		This is the result of the parser.\n
		- Use hasError() to check for errors.\n
		- To test if a option was specified on the command-line use: count()\n
		- To retrieve the value of an options, use operator [](const VariablesMapContainer::key_type k)\n
	*/
	//------------------------------------------------------------------------
	class VariablesMap
	{
		bool mParaError;
		typedef std::map<std::string, std::string> VariablesMapContainer;
		VariablesMapContainer mVariablesMapContainer;
	public:
		VariablesMap () : mParaError (false) {}								///< Constructor. Creates a empty VariablesMap.
		bool hasError () const { return mParaError; }						///< Returns @c true when an error has occurred.
		void setError () { mParaError = true; }								///< Sets the error state to @c true.
		std::string& operator [](const VariablesMapContainer::key_type k);	///< Retrieve the value of option @c k.
		const std::string& operator [](const VariablesMapContainer::key_type k) const;	///< Retrieve the value of option @c k.
		VariablesMapContainer::size_type count (const VariablesMapContainer::key_type k) const; ///< Returns @c != @c 0 if command-line contains option @c k.
	};

	//! type of the list of elements on the command line that are not handled by options parsing
	typedef std::vector<std::string> FilesVector;

	//------------------------------------------------------------------------
	/** The description of one single command-line option.

		Normally you rarely use a Description directly.\n
		In most cases you will use the Descriptions::addOptions (const std::string&) method to create and add descriptions.
	*/
	//------------------------------------------------------------------------
	class Description : public std::string
	{
	public:
		Description (const std::string& name, const std::string& help, const std::string& valueType ); ///< Construct a Description
		std::string mHelp; ///< The help string for this option.
		std::string mType; ///< The type of this option (kBool, kString).
		static const std::string kBool;
		static const std::string kString;
	};
	//------------------------------------------------------------------------
	/** List of command-line option descriptions.

		Use addOptions(const std::string&) to add Descriptions.
	*/
	//------------------------------------------------------------------------
	class Descriptions
	{
		typedef std::deque<Description> DescriptionsList;
		DescriptionsList mDescriptions;
		std::string mCaption;
	public:
		Descriptions& addOptions (const std::string& caption = "");  ///< Sets the command-line tool caption and starts adding Descriptions.
		bool parse (int ac, char* av[], VariablesMap& result, FilesVector* files = 0) const; ///< Parse the command-line.
		void print (std::ostream& os) const;						 ///< Print a brief description for the command-line tool into the stream @c os.
		Descriptions& operator() (const std::string& name, const std::string& help); ///< Add a new switch. Only
		template <typename Type> Descriptions& operator() (const std::string& name, const Type& inType, std::string help);  ///< Add a new option of type @c inType. Currently only std::string is supported.
	};

//------------------------------------------------------------------------
// If you need the declarations in more than one cpp file you have to define
// SMTG_NO_IMPLEMENTATION in all but one file.
//------------------------------------------------------------------------
#ifndef SMTG_NO_IMPLEMENTATION

	//------------------------------------------------------------------------
	/*! If command-line contains option @c k more than once, only the last value will survive. */
	//------------------------------------------------------------------------
	std::string& VariablesMap::operator [](const VariablesMapContainer::key_type k)
	{
		return mVariablesMapContainer[k];
	}

	//------------------------------------------------------------------------
	/*! If command-line contains option @c k more than once, only the last value will survive. */
	//------------------------------------------------------------------------
	const std::string& VariablesMap::operator [](const VariablesMapContainer::key_type k) const
	{
		return (*const_cast<VariablesMap*>(this))[k];
	}

	//------------------------------------------------------------------------
	VariablesMap::VariablesMapContainer::size_type VariablesMap::count (const VariablesMapContainer::key_type k) const
	{
		return mVariablesMapContainer.count (k);
	}

	//------------------------------------------------------------------------
	/** Add a new option with a string as parameter. */
	//------------------------------------------------------------------------
	template <> Descriptions& Descriptions::operator() (const std::string& name, const std::string& inType, std::string help)
	{
		mDescriptions.push_back (Description (name, help, inType));
		return *this;
	}
	bool parse (int ac, char* av[], const Descriptions& desc, VariablesMap& result, FilesVector* files = 0); ///< Parse the command-line.
    std::ostream& operator<< (std::ostream& os, const Descriptions& desc);			 ///< Make Descriptions stream able.

	const std::string Description::kBool = "bool";
	const std::string Description::kString = "string";

	//------------------------------------------------------------------------
	/*! In most cases you will use the Descriptions::addOptions (const std::string&) method to create and add descriptions.

		@param[in] name of the option.
		@param[in] help a help description for this option.
		@param[out] valueType Description::kBool or Description::kString.
	*/
	//------------------------------------------------------------------------
	Description::Description (const std::string& name, const std::string& help, const std::string& valueType)
	: std::string (name)
	, mHelp (help)
	, mType (valueType)
	{
	}

	//------------------------------------------------------------------------
	/*! Returning a reverence to *this, enables chaining of calls to operator()(const std::string&, const std::string&).

		@param[in] name of the added option.
		@param[in] help a help description for this option.
		@return a reverence to *this.
	*/
	Descriptions& Descriptions::operator() (const std::string& name, const std::string& help)
	{
		mDescriptions.push_back (Description (name, help, Description::kBool));
		return *this;
	}

	//------------------------------------------------------------------------
	/*!	<b>Usage example:</b>
																@code
	CommandLine::Descriptions desc;
	desc.addOptions ("myTool")           // Set caption to "myTool"
	    ("help", "produce help message") // add switch -help
	    ("opt1", string(), "option 1")   // add string option -opt1
	    ("opt2", string(), "option 2")   // add string option -opt2
	;
																@endcode
	@note
		The operator() is used for every additional option.
	@param[in] caption the caption of the command-line tool.
	@return a reverense to *this.
	*/
	//------------------------------------------------------------------------
	Descriptions& Descriptions::addOptions (const std::string& caption)
	{
		mCaption = caption;
		return *this;
	}

	//------------------------------------------------------------------------
	/*!	@param[in] ac count of command-line parameters
		@param[in] av command-line as array of strings
		@param[out] result the parsing result
		@param[out] files optional list of elements on the command line that are not handled by options parsing
	*/
	//------------------------------------------------------------------------
	bool Descriptions::parse (int ac, char* av[], VariablesMap& result, FilesVector* files) const
	{
		using namespace std;

		int i;
		for (i = 1; i < ac; i++)
		{
			string current = av[i];
			if (current[0] == '-')
			{
				int pos = current[1] == '-' ? 2 : 1;
				current = current.substr (pos, string::npos);

				DescriptionsList::const_iterator found =
					find (mDescriptions.begin (), mDescriptions.end (), current);
				if (found != mDescriptions.end ())
				{
					result[*found] = "true";
					if (found->mType != Description::kBool)
					{
						if (((i + 1) < ac) && *av[i + 1] != '-')
						{
							result[*found] = av[++i];
						}
						else
						{
							result[*found] = "error!";
							result.setError ();
							return false;
						}
					}
				}
				else
				{
					result.setError ();
					return false;
				}

			}
			else if (files)
				files->push_back (av[i]);
		}
		return true;
	}
	//------------------------------------------------------------------------
	/*!	The description includes the help strings for all options. */
	//------------------------------------------------------------------------
	void Descriptions::print (std::ostream& os) const
	{
		if (!mCaption.empty())
			os << mCaption << ":\n";

		unsigned int i;
		for (i = 0; i < mDescriptions.size (); ++i)
		{
			const Description& opt = mDescriptions[i];
			os << "-" << opt << ":\t" << opt.mHelp << "\n";
		}
	}

	//------------------------------------------------------------------------
    std::ostream& operator<< (std::ostream& os, const Descriptions& desc)
	{
        desc.print (os);
        return os;
	}

	//------------------------------------------------------------------------
	/*! @param[in] ac count of command-line parameters
		@param[in] av command-line as array of strings
		@param[in] desc Descriptions including all allowed options
		@param[out] result the parsing result
		@param[out] files optional list of elements on the command line that are not handled by options parsing
	*/
	bool parse (int ac, char* av[], const Descriptions& desc, VariablesMap& result, FilesVector* files)
	{
		return desc.parse (ac, av, result, files);
	}
#endif

} //namespace CommandLine
} //namespace Steinberg


text:
//------------------------------------------------------------------------
// Project     : SDK Base
// Version     : 1.0
//
// Category    : Helpers
// Filename    : base/source/fbuffer.h
// Created by  : Steinberg, 2008
// Description :
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, 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 <cstring>

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

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
//------------------------------------------------------------------------
// Project     : SDK Base
// Version     : 1.0
//
// Category    : Helpers
// Filename    : base/source/flock.cpp
// Created by  : Steinberg, 1995
// Description : Locks
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, 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.
//-----------------------------------------------------------------------------

#define DEBUG_LOCK 0

#include "base/source/flock.h"
#include "base/source/fdebug.h"

//------------------------------------------------------------------------
#if WINDOWS
//------------------------------------------------------------------------
#ifndef WINVER
#define WINVER 0x0500
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT WINVER
#endif

#include <windows.h>
#include <objbase.h>
#define INIT_CS(cs) \
	InitializeCriticalSection ((LPCRITICAL_SECTION)&cs);

#endif

//------------------------------------------------------------------------
namespace Steinberg {

//------------------------------------------------------------------------
//	FLock implementation
//------------------------------------------------------------------------
FLock::FLock (const char8* name)
{
#if PTHREADS
	pthread_mutexattr_t mutexAttr;
	pthread_mutexattr_init (&mutexAttr);
	pthread_mutexattr_settype (&mutexAttr, PTHREAD_MUTEX_RECURSIVE);
	if (pthread_mutex_init (&mutex, &mutexAttr) != 0)
		{WARNING("mutex_init failed")}
	pthread_mutexattr_destroy (&mutexAttr);

#elif WINDOWS
	INIT_CS (section)
#else
#warning implement FLock!
#endif
}

//------------------------------------------------------------------------
FLock::~FLock ()
{
#if PTHREADS
	pthread_mutex_destroy (&mutex);

#elif WINDOWS
	DeleteCriticalSection ((LPCRITICAL_SECTION)&section);

#endif
}

//------------------------------------------------------------------------
void FLock::lock ()
{
#if DEBUG_LOCK
	FDebugPrint ("FLock::lock () %x\n", this);
#endif

#if PTHREADS
	pthread_mutex_lock (&mutex);

#elif WINDOWS
	EnterCriticalSection ((LPCRITICAL_SECTION)&section);

#endif
}

//------------------------------------------------------------------------
void FLock::unlock ()
{
#if DEBUG_LOCK
	FDebugPrint ("FLock::unlock () %x\n", this);
#endif

#if PTHREADS
	pthread_mutex_unlock (&mutex);

#elif WINDOWS
	LeaveCriticalSection ((LPCRITICAL_SECTION)&section);

#endif
}

//------------------------------------------------------------------------
bool FLock::trylock ()
{
#if PTHREADS
	return pthread_mutex_trylock (&mutex) == 0;

#elif WINDOWS
	return TryEnterCriticalSection ((LPCRITICAL_SECTION)&section) != 0 ? true : false;

#else
	return false;
#endif
}

//------------------------------------------------------------------------
} // namespace Steinberg


text:
//------------------------------------------------------------------------
// Project     : SDK Base
// Version     : 1.0
//
// Category    : Helpers
// Filename    : base/source/fstdmethods.h
// Created by  : Steinberg, 2007
// Description : Convenient macros to create setter and getter methods.
//
//-----------------------------------------------------------------------------
// LICENSE
// (c) 2017, 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/fstdmethods.h
	Convenient macros to create setter and getter methods. */
//------------------------------------------------------------------------
#pragma once

//----------------------------------------------------------------------------------
/**	@name Methods for flags.
	Macros to create setter and getter methods for flags.

	Usage example with DEFINE_STATE:
										\code
	class MyClass
	{
	public:
		MyClass () : flags (0) {}
		DEFINE_FLAG (flags, isFlagged, 1<<0)
		DEFINE_FLAG (flags, isMine, 1<<1)
	private:
		uint32 flags;
	};
	void someFunction ()
	{
		MyClass c;
		if (c.isFlagged ())        // check the flag
			c.isFlagged (false);   // set the flag
	}
										\endcode
*/
//----------------------------------------------------------------------------------
///@{

/** Create Methods with @c get and @c set prefix. */
#define DEFINE_STATE(flagVar,methodName,value)\
void set##methodName (bool state) { if (state) flagVar |= (value); else flagVar &= ~(value); }\
bool get##methodName ()const { return (flagVar & (value)) != 0; }

/** Create Methods with @c get prefix.
	There is only a 'get' method. */
#define DEFINE_GETSTATE(flagVar,methodName,value)\
bool get##methodName ()const { return (flagVar & (value)) != 0; }

/** Create Methods.
	Same name for the getter and setter. */
#define DEFINE_FLAG(flagVar,methodName,value)\
void methodName (bool state) { if (state) flagVar |= (value); else flagVar &= ~(value); }\
bool methodName ()const { return (flagVar & (value)) != 0; }

/** Create Methods.
	There is only a 'get' method. */
#define DEFINE_GETFLAG(flagVar,methodName,value)\
bool methodName ()const { return (flagVar & (value)) != 0; }

/** Create @c static Methods.
	Same name for the getter and setter. */
#define DEFINE_FLAG_STATIC(flagVar,methodName,value)\
static void methodName (bool __state) { if (__state) flagVar |= (value); else flagVar &= ~(value); }\
static bool methodName () { return (flagVar & (value)) != 0; }
///@}

//----------------------------------------------------------------------------------
/**	@name Methods for data members.
	Macros to create setter and getter methods for class members.

	<b>Examples:</b>
										\code
	class MyClass
	{
	public:
		DATA_MEMBER (double, distance, Distance)
		STRING_MEMBER (Steinberg::String, name, Name)
		SHARED_MEMBER (FUnknown, userData, UserData)
		CLASS_MEMBER (Steinberg::Buffer, bufferData, BufferData)
		POINTER_MEMBER (Steinberg::FObject, refOnly, RefOnly)
	};
										\endcode
*/
//--------------------------------------------------------------------------------------
///@{

/** Build-in member (pass by value). */
#define DATA_MEMBER(type,varName,methodName)\
public:void set##methodName (type v) { varName = v;}\
type get##methodName ()const { return varName; }\
protected: type varName; public:

//** Object member (pass by reference). */
#define CLASS_MEMBER(type,varName,methodName)\
public:void set##methodName (const type& v){ varName = v;}\
const type& get##methodName () const { return varName; }\
protected: type varName; public:

//** Simple pointer. */
#define POINTER_MEMBER(type,varName,methodName)\
public:void set##methodName (type* ptr){ varName = ptr;}\
type* get##methodName ()const { return varName; }\
private: type* varName; public:

//** Shared member - FUnknown / FObject /  etc */
#define SHARED_MEMBER(type,varName,methodName)\
public:void set##methodName (type* v){ varName = v;}\
type* get##methodName ()const { return varName; }\
private: IPtr<type> varName; public:

//** Owned member - FUnknown / FObject / CmObject etc */
#define OWNED_MEMBER(type,varName,methodName)\
public:void set##methodName (type* v){ varName = v;}\
type* get##methodName ()const { return varName; }\
private: OPtr<type> varName; public:

//** tchar* / String class member - set by const tchar*, return by reference */
#define STRING_MEMBER(type,varName,methodName)\
public:void set##methodName (const tchar* v){ varName = v;}\
const type& get##methodName () const { return varName; }\
protected: type varName; public:

//** char8* / String class member - set by const char8*, return by reference */
#define STRING8_MEMBER(type,varName,methodName)\
public:void set##methodName (const char8* v){ varName = v;}\
const type& get##methodName () const { return varName; }\
protected: type varName; public:

//** Standard String Member Steinberg::String */
#define STRING_MEMBER_STD(varName,methodName) STRING_MEMBER(Steinberg::String,varName,methodName)
#define STRING8_MEMBER_STD(varName,methodName) STRING8_MEMBER(Steinberg::String,varName,methodName)

///@}

// obsolete names
#define DEFINE_VARIABLE(type,varName,methodName) DATA_MEMBER(type,varName,methodName)
#define DEFINE_POINTER(type,varName,methodName) POINTER_MEMBER(type,varName,methodName)
#define DEFINE_MEMBER(type,varName,methodName) CLASS_MEMBER(type,varName,methodName)

//------------------------------------------------------------------------
// for implementing comparison operators using a class member or a compare method:
//------------------------------------------------------------------------
#define COMPARE_BY_MEMBER_METHODS(className,memberName) \
	bool operator == (const className& other) const {return (memberName == other.memberName);} \
	bool operator != (const className& other) const {return (memberName != other.memberName);} \
	bool operator < (const className& other) const {return (memberName < other.memberName);} \
	bool operator > (const className& other) const {return (memberName > other.memberName);} \
	bool operator <= (const className& other) const {return (memberName <= other.memberName);} \
	bool operator >= (const className& other) const {return (memberName >= other.memberName);}

#define COMPARE_BY_MEMORY_METHODS(className) \
	bool operator == (const className& other) const {return memcmp (this, &other, sizeof (className)) == 0;} \
	bool operator != (const className& other) const {return memcmp (this, &other, sizeof (className)) != 0;} \
	bool operator < (const className& other) const {return memcmp (this, &other, sizeof (className)) < 0;} \
	bool operator > (const className& other) const {return memcmp (this, &other, sizeof (className)) > 0;} \
	bool operator <= (const className& other) const {return memcmp (this, &other, sizeof (className)) <= 0;} \
	bool operator >= (const className& other) const {return memcmp (this, &other, sizeof (className)) >= 0;}

#define COMPARE_BY_COMPARE_METHOD(className,methodName) \
	bool operator == (const className& other) const {return methodName (other) == 0;} \
	bool operator != (const className& other) const {return methodName (other) != 0;} \
	bool operator < (const className& other) const {return methodName (other) < 0;} \
	bool operator > (const className& other) const {return methodName (other) > 0;} \
	bool operator <= (const className& other) const {return methodName (other) <= 0; } \
	bool operator >= (const className& other) const {return methodName (other) >= 0; }