From 70c48986487a2a1fb534d699955730267dee0f14 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 22 May 2021 13:11:12 -0400 Subject: [PATCH] Move class wxArrayStringEx to its own files --- src/CMakeLists.txt | 2 + src/Languages.cpp | 4 +- src/MemoryX.h | 57 ---- src/PluginManager.h | 3 +- src/Prefs.h | 2 +- src/import/ImportPlugin.h | 3 +- src/widgets/FileHistory.h | 2 +- src/wxArrayStringEx.cpp | 13 + src/wxArrayStringEx.h | 690 ++------------------------------------ 9 files changed, 43 insertions(+), 733 deletions(-) create mode 100644 src/wxArrayStringEx.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e7b263fbc..071ad7ea6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -349,6 +349,8 @@ list( APPEND SOURCES ZoomInfo.cpp ZoomInfo.h float_cast.h + wxArrayStringEx.cpp + wxArrayStringEx.h wxFileNameWrapper.h # Commands diff --git a/src/Languages.cpp b/src/Languages.cpp index a9d73fc8f..841d492da 100644 --- a/src/Languages.cpp +++ b/src/Languages.cpp @@ -32,7 +32,8 @@ #include "Languages.h" -#include "MemoryX.h" +#include +#include "wxArrayStringEx.h" #include "Internat.h" @@ -41,6 +42,7 @@ #include #include #include +#include // for wxSetEnv #include #include diff --git a/src/MemoryX.h b/src/MemoryX.h index c80b74a15..cb8f36458 100644 --- a/src/MemoryX.h +++ b/src/MemoryX.h @@ -657,63 +657,6 @@ OutContainer transform_container( InContainer &inContainer, Function &&fn ) inContainer.begin(), inContainer.end(), fn ); } -// Extend wxArrayString with move operations and construction and insertion from -// std::initializer_list -class wxArrayStringEx : public wxArrayString -{ -public: - using wxArrayString::wxArrayString; - wxArrayStringEx() = default; - - template< typename Iterator > - wxArrayStringEx( Iterator start, Iterator finish ) - { - this->reserve( std::distance( start, finish ) ); - while( start != finish ) - this->push_back( *start++ ); - } - - template< typename T > - wxArrayStringEx( std::initializer_list< T > items ) - { - this->reserve( this->size() + items.size() ); - for ( const auto &item : items ) - this->push_back( item ); - } - - // The move operations can take arguments of the base class wxArrayString - wxArrayStringEx( wxArrayString &&other ) - { - swap( other ); - } - - wxArrayStringEx &operator= ( wxArrayString &&other ) - { - if ( this != &other ) { - clear(); - swap( other ); - } - return *this; - } - - using wxArrayString::insert; - - template< typename T > - iterator insert( const_iterator pos, std::initializer_list< T > items ) - { - const auto index = pos - ((const wxArrayString*)this)->begin(); - this->wxArrayString::Insert( {}, index, items.size() ); - auto result = this->begin() + index, iter = result; - for ( auto pItem = items.begin(), pEnd = items.end(); - pItem != pEnd; - ++pItem, ++iter - ) { - *iter = *pItem; - } - return result; - } -}; - // These macros are used widely, so declared here. #define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate)) // dB - linear amplitude conversions diff --git a/src/PluginManager.h b/src/PluginManager.h index 26a97590d..d7ac23417 100644 --- a/src/PluginManager.h +++ b/src/PluginManager.h @@ -13,8 +13,9 @@ #include -#include "MemoryX.h" +#include "wxArrayStringEx.h" #include +#include #include "audacity/EffectInterface.h" #include "audacity/ImporterInterface.h" diff --git a/src/Prefs.h b/src/Prefs.h index 0a71d2e94..d1a46e63c 100644 --- a/src/Prefs.h +++ b/src/Prefs.h @@ -39,7 +39,7 @@ #include #include "../include/audacity/ComponentInterface.h" -#include "MemoryX.h" // for wxArrayStringEx +#include "wxArrayStringEx.h" #include "widgets/FileConfig.h" #include diff --git a/src/import/ImportPlugin.h b/src/import/ImportPlugin.h index 30897632e..e9909c4d5 100644 --- a/src/import/ImportPlugin.h +++ b/src/import/ImportPlugin.h @@ -47,10 +47,11 @@ but little else. +#include #include "audacity/Types.h" #include "../Identifier.h" #include "../Internat.h" -#include "../MemoryX.h" +#include "../wxArrayStringEx.h" class AudacityProject; class ProgressDialog; diff --git a/src/widgets/FileHistory.h b/src/widgets/FileHistory.h index 9cbae0d7a..ee5dab007 100644 --- a/src/widgets/FileHistory.h +++ b/src/widgets/FileHistory.h @@ -17,7 +17,7 @@ #include // member variable #include "Identifier.h" -#include "../MemoryX.h" +#include "../wxArrayStringEx.h" class wxConfigBase; class wxMenu; diff --git a/src/wxArrayStringEx.cpp b/src/wxArrayStringEx.cpp new file mode 100644 index 000000000..2d320bd46 --- /dev/null +++ b/src/wxArrayStringEx.cpp @@ -0,0 +1,13 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + @file wxArrayStringEx.cpp + + Paul Licameli split from MemoryX.h + + **********************************************************************/ + +// This .cpp exists just to ensure there is at least one that includes +// the header before any other header, and compiles +#include "wxArrayStringEx.h" diff --git a/src/wxArrayStringEx.h b/src/wxArrayStringEx.h index c80b74a15..6896bef7d 100644 --- a/src/wxArrayStringEx.h +++ b/src/wxArrayStringEx.h @@ -1,664 +1,19 @@ -#ifndef __AUDACITY_MEMORY_X_H__ -#define __AUDACITY_MEMORY_X_H__ - -// C++ standard header with a few extensions -#include -#include // Needed for free. -#ifndef safenew -#define safenew new -#endif - -#include - -#if !(_MSC_VER >= 1800 || __cplusplus >= 201402L) -/* replicate the very useful C++14 make_unique for those build environments -that don't implement it yet. -typical usage: -auto p = std::make_unique(ctorArg1, ctorArg2, ... ctorArgN); -p->DoSomething(); -auto q = std::make_unique(count); -q[0].DoSomethingElse(); - -The first hides naked NEW and DELETE from the source code. -The second hides NEW[] and DELETE[]. Both of course ensure destruction if -you don't use something like std::move(p) or q.release(). Both expressions require -that you identify the type only once, which is brief and less error prone. - -(Whereas this omission of [] might invite a runtime error: -std::unique_ptr q { safenew Myclass[count] }; ) - -Some C++11 tricks needed here are (1) variadic argument lists and -(2) making the compile-time dispatch work correctly. You can't have -a partially specialized template function, but you get the effect of that -by other metaprogramming means. -*/ - -namespace std { - // For overloading resolution - template struct __make_unique_result { - using scalar_case = unique_ptr; - }; - - // Partial specialization of the struct for array case - template struct __make_unique_result { - using array_case = unique_ptr; - using element = X; - }; - - // Now the scalar version of unique_ptr - template inline - typename __make_unique_result::scalar_case - make_unique(Args&&... args) - { - return typename __make_unique_result::scalar_case - { safenew X(forward(args)...) }; - } - - // Now the array version of unique_ptr - // The compile-time dispatch trick is that the non-existence - // of the scalar_case type makes the above overload - // unavailable when the template parameter is explicit - template inline - typename __make_unique_result::array_case - make_unique(size_t count) - { - return typename __make_unique_result::array_case - { safenew typename __make_unique_result::element[count] }; - } -} -#endif - -/* - * ArrayOf - * Not to be confused with std::array (which takes a fixed size) or std::vector - * This maintains a pointer allocated by NEW X[]. It's cheap: only one pointer, - * with no size and capacity information for resizing as for vector, and if X is - * a built-in numeric or pointer type, by default there is no zero filling at - * allocation time. - */ - -template -class ArrayOf : public std::unique_ptr -{ -public: - ArrayOf() {} - - template - explicit ArrayOf(Integral count, bool initialize = false) - { - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - reinit(count, initialize); - } - - //ArrayOf(const ArrayOf&) PROHIBITED; - ArrayOf(const ArrayOf&) = delete; - ArrayOf(ArrayOf&& that) - : std::unique_ptr < X[] > - (std::move((std::unique_ptr < X[] >&)(that))) - { - } - ArrayOf& operator= (ArrayOf &&that) - { - std::unique_ptr::operator=(std::move(that)); - return *this; - } - ArrayOf& operator= (std::unique_ptr &&that) - { - std::unique_ptr::operator=(std::move(that)); - return *this; - } - - template< typename Integral > - void reinit(Integral count, - bool initialize = false) - { - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - if (initialize) - // Initialize elements (usually, to zero for a numerical type) - std::unique_ptr::reset(safenew X[count]{}); - else - // Avoid the slight initialization overhead - std::unique_ptr::reset(safenew X[count]); - } -}; - -/** - \class ArrayOf - - ArraysOf - - \brief This simplifies arrays of arrays, each array separately allocated with NEW[] - But it might be better to use std::Array, N> for some small constant N - Or use just one array when sub-arrays have a common size and are not large. - */ -template -class ArraysOf : public ArrayOf> -{ -public: - ArraysOf() {} - - template - explicit ArraysOf(Integral N) - : ArrayOf>( N ) - {} - - template - ArraysOf(Integral1 N, Integral2 M, bool initialize = false) - : ArrayOf>( N ) - { - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - for (size_t ii = 0; ii < N; ++ii) - (*this)[ii] = ArrayOf{ M, initialize }; - } - - //ArraysOf(const ArraysOf&) PROHIBITED; - ArraysOf(const ArraysOf&) =delete; - ArraysOf& operator= (ArraysOf&& that) - { - ArrayOf>::operator=(std::move(that)); - return *this; - } - - template< typename Integral > - void reinit(Integral count) - { - ArrayOf>::reinit( count ); - } - - template< typename Integral > - void reinit(Integral count, bool initialize) - { - ArrayOf>::reinit( count, initialize ); - } - - template - void reinit(Integral1 countN, Integral2 countM, bool initialize = false) - { - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - static_assert(std::is_unsigned::value, "Unsigned arguments only"); - reinit(countN, false); - for (size_t ii = 0; ii < countN; ++ii) - (*this)[ii].reinit(countM, initialize); - } -}; - -/** - \class Optional - \brief Like a smart pointer, allows for object to not exist (nullptr) - \brief emulating some of std::optional of C++17 - - template class Optional - Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed. - You might also use it as a member. - Initialize with emplace(), then use like a smart pointer, - with *, ->, reset(), or in if() - */ - -// Placement-NEW is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio -#ifdef _DEBUG -#ifdef _MSC_VER -#undef new - -// wx/any.h also uses Placement-NEW so include it before redefining "new" at comment: -// "Restore definition of debug new" -#include -#endif -#endif - -template -class Optional { -public: - - using value_type = X; - - // Construct as NULL - Optional() {} - - // Supply the copy and move, so you might use this as a class member too - Optional(const Optional &that) - { - if (that) - emplace(*that); - } - - Optional& operator= (const Optional &that) - { - if (this != &that) { - if (that) - emplace(*that); - else - reset(); - } - return *this; - } - - Optional(Optional &&that) - { - if (that) - emplace(::std::move(*that)); - } - - Optional& operator= (Optional &&that) - { - if (this != &that) { - if (that) - emplace(::std::move(*that)); - else - reset(); - } - return *this; - } - - /// Make an object in the buffer, passing constructor arguments, - /// but destroying any previous object first - /// Note that if constructor throws, we remain in a consistent - /// NULL state -- giving exception safety but only weakly - /// (previous value was lost if present) - template - X& emplace(Args&&... args) - { - // Lose any old value - reset(); - // emplace NEW value - pp = safenew(address()) X(std::forward(args)...); - return **this; - } - - // Destroy any object that was built in it - ~Optional() - { - reset(); - } - - // Pointer-like operators - - /// Dereference, with the usual bad consequences if NULL - X &operator* () const - { - return *pp; - } - - X *operator-> () const - { - return pp; - } - - void reset() - { - if (pp) - pp->~X(), pp = nullptr; - } - - // So you can say if(ptr) - explicit operator bool() const - { - return pp != nullptr; - } - - bool has_value() const - { - return pp != nullptr; - } - -private: - X* address() - { - return reinterpret_cast(&storage); - } - - // Data -#if 0 - typename ::std::aligned_storage< - sizeof(X) - // , alignof(X) // Not here yet in all compilers - >::type storage{}; -#else - union { - double d; - char storage[sizeof(X)]; - }; -#endif - X* pp{ nullptr }; -}; - -// Restore definition of debug new -#ifdef _DEBUG -#ifdef _MSC_VER -#undef THIS_FILE -static const char THIS_FILE[] = __FILE__; -#define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) -#endif -#endif - -/** - A deleter for pointers obtained with malloc - */ -struct freer { void operator() (void *p) const { free(p); } }; - -/** - A useful alias for holding the result of malloc - */ -template< typename T > -using MallocPtr = std::unique_ptr< T, freer >; - -/** - A useful alias for holding the result of strup and similar - */ -template -using MallocString = std::unique_ptr< Character[], freer >; - -/** - \brief A deleter class to supply the second template parameter of unique_ptr for - classes like wxWindow that should be sent a message called Destroy rather - than be deleted directly - */ -template -struct Destroyer { - void operator () (T *p) const { if (p) p->Destroy(); } -}; - -/** - \brief a convenience for using Destroyer - */ -template -using Destroy_ptr = std::unique_ptr>; - -/** - \brief "finally" as in The C++ Programming Language, 4th ed., p. 358 - Useful for defining ad-hoc RAII actions. - typical usage: - auto cleanup = finally([&]{ ... code; ... }); - */ - -// Construct this from any copyable function object, such as a lambda -template -struct Final_action { - Final_action(F f) : clean( f ) {} - ~Final_action() { clean(); } - F clean; -}; - -/// \brief Function template with type deduction lets you construct Final_action -/// without typing any angle brackets -template -Final_action finally (F f) -{ - return Final_action(f); -} - -#include // for wxMin, wxMax -#include - -/** - \brief Structure used by ValueRestorer - */ -template< typename T > -struct RestoreValue { - T oldValue; - void operator () ( T *p ) const { if (p) *p = oldValue; } -}; - - -/** - \brief Set a variable temporarily in a scope - */ -template< typename T > -class ValueRestorer : public std::unique_ptr< T, RestoreValue > -{ - using std::unique_ptr< T, RestoreValue >::reset; // make private - // But release() remains public and can be useful to commit a changed value -public: - explicit ValueRestorer( T &var ) - : std::unique_ptr< T, RestoreValue >( &var, { var } ) - {} - explicit ValueRestorer( T &var, const T& newValue ) - : std::unique_ptr< T, RestoreValue >( &var, { var } ) - { var = newValue; } - ValueRestorer(ValueRestorer &&that) - : std::unique_ptr < T, RestoreValue > ( std::move(that) ) {}; - ValueRestorer & operator= (ValueRestorer &&that) - { - if (this != &that) - std::unique_ptr < T, RestoreValue >::operator=(std::move(that)); - return *this; - } -}; - -/// inline functions provide convenient parameter type deduction -template< typename T > -ValueRestorer< T > valueRestorer( T& var ) -{ return ValueRestorer< T >{ var }; } - -template< typename T > -ValueRestorer< T > valueRestorer( T& var, const T& newValue ) -{ return ValueRestorer< T >{ var, newValue }; } - -/** - \brief A convenience for defining iterators that return rvalue types, so that - they cooperate correctly with stl algorithms and std::reverse_iterator - */ -template< typename Value, typename Category = std::forward_iterator_tag > -using ValueIterator = std::iterator< - Category, const Value, ptrdiff_t, - // void pointer type so that operator -> is disabled - void, - // make "reference type" really the same as the value type - const Value ->; - -/** - \brief A convenience for use with range-for - */ -template -struct IteratorRange : public std::pair { - using iterator = Iterator; - using reverse_iterator = std::reverse_iterator; - - IteratorRange (const Iterator &a, const Iterator &b) - : std::pair ( a, b ) {} - - IteratorRange (Iterator &&a, Iterator &&b) - : std::pair ( std::move(a), std::move(b) ) {} - - IteratorRange< reverse_iterator > reversal () const - { return { this->rbegin(), this->rend() }; } - - Iterator begin() const { return this->first; } - Iterator end() const { return this->second; } - - reverse_iterator rbegin() const { return reverse_iterator{ this->second }; } - reverse_iterator rend() const { return reverse_iterator{ this->first }; } - - bool empty() const { return this->begin() == this->end(); } - explicit operator bool () const { return !this->empty(); } - size_t size() const { return std::distance(this->begin(), this->end()); } - - template iterator find(const T &t) const - { return std::find(this->begin(), this->end(), t); } - - template long index(const T &t) const - { - auto iter = this->find(t); - if (iter == this->end()) - return -1; - return std::distance(this->begin(), iter); - } - - template bool contains(const T &t) const - { return this->end() != this->find(t); } - - template iterator find_if(const F &f) const - { return std::find_if(this->begin(), this->end(), f); } - - template long index_if(const F &f) const - { - auto iter = this->find_if(f); - if (iter == this->end()) - return -1; - return std::distance(this->begin(), iter); - } - - // to do: use std::all_of, any_of, none_of when available on all platforms - template bool all_of(const F &f) const - { - auto notF = - [&](typename std::iterator_traits::reference v) - { return !f(v); }; - return !this->any_of( notF ); - } - - template bool any_of(const F &f) const - { return this->end() != this->find_if(f); } - - template bool none_of(const F &f) const - { return !this->any_of(f); } - - template struct identity - { const T&& operator () (T &&v) const { return std::forward(v); } }; - - // Like std::accumulate, but the iterators implied, and with another - // unary operation on the iterator value, pre-composed - template< - typename R, - typename Binary = std::plus< R >, - typename Unary = identity< decltype( *std::declval() ) > - > - R accumulate( - R init, - Binary binary_op = {}, - Unary unary_op = {} - ) const - { - R result = init; - for (auto&& v : *this) - result = binary_op(result, unary_op(v)); - return result; - } - - // An overload making it more convenient to use with pointers to member - // functions - template< - typename R, - typename Binary = std::plus< R >, - typename R2, typename C - > - R accumulate( - R init, - Binary binary_op, - R2 (C :: * pmf) () const - ) const - { - return this->accumulate( init, binary_op, std::mem_fn( pmf ) ); - } - - // Some accumulations frequent enough to be worth abbreviation: - template< - typename Unary = identity< decltype( *std::declval() ) >, - typename R = decltype( std::declval()( *std::declval() ) ) - > - R min( Unary unary_op = {} ) const - { - return this->accumulate( - std::numeric_limits< R >::max(), - (const R&(*)(const R&, const R&)) std::min, - unary_op - ); - } - - template< - typename R2, typename C, - typename R = R2 - > - R min( R2 (C :: * pmf) () const ) const - { - return this->min( std::mem_fn( pmf ) ); - } - - template< - typename Unary = identity< decltype( *std::declval() ) >, - typename R = decltype( std::declval()( *std::declval() ) ) - > - R max( Unary unary_op = {} ) const - { - return this->accumulate( - std::numeric_limits< R >::lowest(), - (const R&(*)(const R&, const R&)) std::max, - unary_op - ); - } - - template< - typename R2, typename C, - typename R = R2 - > - R max( R2 (C :: * pmf) () const ) const - { - return this->max( std::mem_fn( pmf ) ); - } - - template< - typename Unary = identity< decltype( *std::declval() ) >, - typename R = decltype( std::declval()( *std::declval() ) ) - > - R sum( Unary unary_op = {} ) const - { - return this->accumulate( - R{ 0 }, - std::plus< R >{}, - unary_op - ); - } - - template< - typename R2, typename C, - typename R = R2 - > - R sum( R2 (C :: * pmf) () const ) const - { - return this->sum( std::mem_fn( pmf ) ); - } -}; - -template< typename Iterator> -IteratorRange< Iterator > -make_iterator_range( const Iterator &i1, const Iterator &i2 ) -{ - return { i1, i2 }; -} - -template< typename Container > -IteratorRange< typename Container::iterator > -make_iterator_range( Container &container ) -{ - return { container.begin(), container.end() }; -} - -template< typename Container > -IteratorRange< typename Container::const_iterator > -make_iterator_range( const Container &container ) -{ - return { container.begin(), container.end() }; -} - -// A utility function building a container of results -template< typename Container, typename Iterator, typename Function > -Container transform_range( Iterator first, Iterator last, Function &&fn ) -{ - Container result; - std::transform( first, last, std::back_inserter( result ), fn ); - return result; -} -// A utility function, often constructing a vector from another vector -template< typename OutContainer, typename InContainer, typename Function > -OutContainer transform_container( InContainer &inContainer, Function &&fn ) -{ - return transform_range( - inContainer.begin(), inContainer.end(), fn ); -} - -// Extend wxArrayString with move operations and construction and insertion from -// std::initializer_list +/********************************************************************** + + Audacity: A Digital Audio Editor + + @file wxArrayStringEx.h + + Paul Licameli split from MemoryX.h + + **********************************************************************/ + +#ifndef __AUDACITY_WX_ARRAY_STRING_EX__ +#define __AUDACITY_WX_ARRAY_STRING_EX__ + +#include + +//! Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list class wxArrayStringEx : public wxArrayString { public: @@ -681,12 +36,13 @@ public: this->push_back( item ); } - // The move operations can take arguments of the base class wxArrayString + //! The move operations can take arguments of the base class wxArrayString wxArrayStringEx( wxArrayString &&other ) { swap( other ); } + //! The move operations can take arguments of the base class wxArrayString wxArrayStringEx &operator= ( wxArrayString &&other ) { if ( this != &other ) { @@ -714,12 +70,4 @@ public: } }; -// These macros are used widely, so declared here. -#define QUANTIZED_TIME(time, rate) (floor(((double)(time) * (rate)) + 0.5) / (rate)) -// dB - linear amplitude conversions -#define DB_TO_LINEAR(x) (pow(10.0, (x) / 20.0)) -#define LINEAR_TO_DB(x) (20.0 * log10(x)) - -#define MAX_AUDIO (1. - 1./(1<<15)) - -#endif // __AUDACITY_MEMORY_X_H__ +#endif