mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-17 17:26:48 +02:00
3.0 doesn't have direct wxString hash support yet, so lift an earlier version of this from the history, which was used in TranslatableString.h before and use it again. wxWidgets version is slightly different though. Signed-off-by: Mart Raudsepp <leio@gentoo.org>
254 lines
8.7 KiB
C++
254 lines
8.7 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
Identifier.h
|
|
|
|
Paul Licameli split from Types.h
|
|
|
|
**********************************************************************/
|
|
|
|
#ifndef __AUDACITY_IDENTIFIER__
|
|
#define __AUDACITY_IDENTIFIER__
|
|
|
|
#include <vector>
|
|
#include <wx/string.h>
|
|
|
|
//! An explicitly nonlocalized string, not meant for the user to see.
|
|
/*! String manipulations are discouraged, other than splitting and joining on separator characters.
|
|
Wherever GET is used to fetch the underlying wxString, there should be a comment explaining the need for it.
|
|
*/
|
|
class STRINGS_API Identifier
|
|
{
|
|
public:
|
|
|
|
Identifier() = default;
|
|
|
|
//! Allow implicit conversion to this class, but not from
|
|
Identifier(const wxString &str) : value{ str } {}
|
|
|
|
//! Allow implicit conversion to this class, but not from
|
|
Identifier(const wxChar *str) : value{ str } {}
|
|
|
|
//! Allow implicit conversion to this class, but not from
|
|
Identifier(const char *str) : value{ str } {}
|
|
|
|
// Copy construction and assignment
|
|
Identifier( const Identifier & ) = default;
|
|
Identifier &operator = ( const Identifier& ) = default;
|
|
|
|
// Move construction and assignment
|
|
Identifier( wxString && str )
|
|
{ value.swap( str ); }
|
|
Identifier( Identifier && id )
|
|
{ swap( id ); }
|
|
Identifier &operator= ( Identifier&& id )
|
|
{
|
|
if ( this != &id )
|
|
value.clear(), swap( id );
|
|
return *this;
|
|
}
|
|
|
|
// Implements moves
|
|
void swap( Identifier &id ) { value.swap( id.value ); }
|
|
|
|
//! Convenience for building concatenated identifiers.
|
|
/*! The list must have at least two members (so you don't easily circumvent the restrictions on
|
|
interconversions intended in TaggedIdentifier below) */
|
|
explicit
|
|
Identifier(std::initializer_list<Identifier> components, wxChar separator);
|
|
|
|
bool empty() const { return value.empty(); }
|
|
size_t size() const { return value.size(); }
|
|
size_t length() const { return value.length(); }
|
|
|
|
//! Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct
|
|
const wxString &GET() const { return value; }
|
|
|
|
std::vector< Identifier > split( wxChar separator ) const;
|
|
|
|
private:
|
|
wxString value;
|
|
};
|
|
|
|
//! Comparisons of Identifiers are case-sensitive
|
|
inline bool operator == ( const Identifier &x, const Identifier &y )
|
|
{ return x.GET() == y.GET(); }
|
|
|
|
inline bool operator != ( const Identifier &x, const Identifier &y )
|
|
{ return !(x == y); }
|
|
|
|
inline bool operator < ( const Identifier &x, const Identifier &y )
|
|
{ return x.GET() < y.GET(); }
|
|
|
|
inline bool operator > ( const Identifier &x, const Identifier &y )
|
|
{ return y < x; }
|
|
|
|
inline bool operator <= ( const Identifier &x, const Identifier &y )
|
|
{ return !(y < x); }
|
|
|
|
inline bool operator >= ( const Identifier &x, const Identifier &y )
|
|
{ return !(x < y); }
|
|
|
|
#if !wxCHECK_VERSION(3, 1, 0)
|
|
namespace std
|
|
{
|
|
template<> struct hash< wxString > {
|
|
size_t operator () (const wxString &str) const // noexcept
|
|
{
|
|
auto stdstr = str.ToStdWstring(); // no allocations, a cheap fetch
|
|
using Hasher = hash< decltype(stdstr) >;
|
|
return Hasher{}( stdstr );
|
|
}
|
|
};
|
|
}
|
|
#endif
|
|
|
|
namespace std
|
|
{
|
|
template<> struct hash< Identifier > {
|
|
size_t operator () ( const Identifier &id ) const // noexcept
|
|
{ return hash<wxString>{}( id.GET() ); }
|
|
};
|
|
}
|
|
|
|
//! This lets you pass Identifier into wxFileConfig::Read
|
|
inline bool wxFromString(const wxString& str, Identifier *id)
|
|
{ if (id) { *id = str; return true; } else return false; }
|
|
|
|
//! This lets you pass Identifier into wxFileConfig::Write
|
|
inline wxString wxToString( const Identifier& str ) { return str.GET(); }
|
|
|
|
//! Template generates different TaggedIdentifier classes that don't interconvert implicitly
|
|
/*! The second template parameter determines whether comparisons are case
|
|
sensitive; default is case sensitive */
|
|
template<typename Tag, bool CaseSensitive = true >
|
|
class TaggedIdentifier : public Identifier
|
|
{
|
|
public:
|
|
|
|
using TagType = Tag;
|
|
|
|
using Identifier::Identifier;
|
|
TaggedIdentifier() = default;
|
|
|
|
//! Copy allowed only for the same Tag class and case sensitivity
|
|
TaggedIdentifier( const TaggedIdentifier& ) = default;
|
|
//! Move allowed only for the same Tag class and case sensitivity
|
|
TaggedIdentifier( TaggedIdentifier&& ) = default;
|
|
//! Copy allowed only for the same Tag class and case sensitivity
|
|
TaggedIdentifier& operator= ( const TaggedIdentifier& ) = default;
|
|
//! Move allowed only for the same Tag class and case sensitivity
|
|
TaggedIdentifier& operator= ( TaggedIdentifier&& ) = default;
|
|
|
|
//! Copy prohibited for other Tag classes or case sensitivity
|
|
template< typename Tag2, bool b >
|
|
TaggedIdentifier( const TaggedIdentifier<Tag2, b>& ) PROHIBITED;
|
|
//! Move prohibited for other Tag classes or case sensitivity
|
|
template< typename Tag2, bool b >
|
|
TaggedIdentifier( TaggedIdentifier<Tag2, b>&& ) PROHIBITED;
|
|
//! Copy prohibited for other Tag classes or case sensitivity
|
|
template< typename Tag2, bool b >
|
|
TaggedIdentifier& operator= ( const TaggedIdentifier<Tag2, b>& ) PROHIBITED;
|
|
//! Move prohibited for other Tag classes or case sensitivity
|
|
template< typename Tag2, bool b >
|
|
TaggedIdentifier& operator= ( TaggedIdentifier<Tag2, b>&& ) PROHIBITED;
|
|
|
|
/*! Allow implicit conversion to this class from un-tagged Identifier,
|
|
but not from; resolution will use other overloads above if argument has a tag */
|
|
TaggedIdentifier(const Identifier &str) : Identifier{ str } {}
|
|
|
|
//! Explicit conversion to another kind of TaggedIdentifier
|
|
template<typename String, typename = typename String::TagType>
|
|
String CONVERT() const
|
|
{ return String{ this->GET() }; }
|
|
};
|
|
|
|
/*! Comparison of a TaggedIdentifier with an Identifier is allowed, resolving
|
|
to one of the operators on Identifiers, but always case sensitive.
|
|
Comparison operators for two TaggedIdentifiers require the same tags and case sensitivity. */
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator == (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{
|
|
static_assert( std::is_same< Tag1, Tag2 >::value && b1 == b2,
|
|
"TaggedIdentifiers with different tags or sensitivity are not comparable" );
|
|
// This test should be eliminated at compile time:
|
|
if ( b1 )
|
|
return x.GET(). Cmp ( y.GET() ) == 0;
|
|
else
|
|
return x.GET(). CmpNoCase ( y.GET() ) == 0;
|
|
}
|
|
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator != (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{ return !(x == y); }
|
|
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator < (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{
|
|
static_assert( std::is_same< Tag1, Tag2 >::value && b1 == b2,
|
|
"TaggedIdentifiers with different tags or sensitivity are not comparable" );
|
|
// This test should be eliminated at compile time:
|
|
if ( b1 )
|
|
return x.GET(). Cmp ( y.GET() ) < 0;
|
|
else
|
|
return x.GET(). CmpNoCase ( y.GET() ) < 0;
|
|
}
|
|
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator > (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{ return y < x; }
|
|
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator <= (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{ return !(y < x); }
|
|
|
|
template< typename Tag1, typename Tag2, bool b1, bool b2 >
|
|
inline bool operator >= (
|
|
const TaggedIdentifier< Tag1, b1 > &x, const TaggedIdentifier< Tag2, b2 > &y )
|
|
{ return !(x < y); }
|
|
|
|
namespace std
|
|
{
|
|
template<typename Tag, bool b > struct hash< TaggedIdentifier<Tag, b> >
|
|
: hash< Identifier > {};
|
|
}
|
|
|
|
/**************************************************************************//**
|
|
|
|
\brief type alias for identifying a Plugin supplied by a module, each module
|
|
defining its own interpretation of the strings, which may or may not be as a
|
|
file system path
|
|
********************************************************************************/
|
|
using PluginPath = wxString;
|
|
using PluginPaths = std::vector< PluginPath >;
|
|
|
|
// A key to be passed to wxConfigBase
|
|
using RegistryPath = wxString;
|
|
using RegistryPaths = std::vector< RegistryPath >;
|
|
|
|
class wxArrayStringEx;
|
|
|
|
//! File extension, not including any leading dot
|
|
using FileExtension = wxString;
|
|
using FileExtensions = wxArrayStringEx;
|
|
|
|
using FilePath = wxString;
|
|
using FilePaths = wxArrayStringEx;
|
|
|
|
struct CommandIdTag;
|
|
//! Identifies a menu command or macro. Case-insensitive comparison
|
|
using CommandID = TaggedIdentifier< CommandIdTag, false >;
|
|
using CommandIDs = std::vector<CommandID>;
|
|
|
|
struct ManualPageIDTag;
|
|
using ManualPageID = TaggedIdentifier< ManualPageIDTag >;
|
|
|
|
#endif
|
|
|