1
0
forked from Alepha/Alepha

Fix some bugs I discovered in StringMap

I found these in an executable use case.
This commit is contained in:
2023-12-02 01:36:24 -05:00
parent 7a569f9b58
commit 6b5cfa246d

View File

@ -9,16 +9,29 @@ static_assert( __cplusplus > 2020'99 );
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
#include <Alepha/error.h>
#include <Alepha/Algorithm/string_distance.h> #include <Alepha/Algorithm/string_distance.h>
#include <Alepha/IOStreams/String.h>
namespace Alepha::Hydrogen::Utility ::detail:: StringMap_m namespace Alepha::Hydrogen::Utility ::detail:: StringMap_m
{ {
namespace C
{
const bool debug= false;
const bool debugCompare= false or C::debug;
const bool debugInsertion= false or C::debug;
}
inline namespace exports inline namespace exports
{ {
template< typename Value > template< typename Value >
class StringMap; class StringMap;
} }
using namespace Alepha::Algorithm::exports::string_distance_m;
template< typename Value > template< typename Value >
class exports::StringMap class exports::StringMap
{ {
@ -27,8 +40,9 @@ namespace Alepha::Hydrogen::Utility ::detail:: StringMap_m
template< typename Self > template< typename Self >
Value & Value &
at_impl( Self &self, const std::string_view key ) at_impl( Self &self, const std::string &key )
{ {
if( C::debugInsertion ) error() << "Map has " << storage.size() << " entries" << std::endl;
if( not storage.contains( key ) ) if( not storage.contains( key ) )
{ {
const auto closest= std::min_element( begin( storage ), end( storage ), const auto closest= std::min_element( begin( storage ), end( storage ),
@ -36,26 +50,33 @@ namespace Alepha::Hydrogen::Utility ::detail:: StringMap_m
{ {
const auto l= optimalStringDistance( lhs.first, key ); const auto l= optimalStringDistance( lhs.first, key );
const auto r= optimalStringDistance( rhs.first, key ); const auto r= optimalStringDistance( rhs.first, key );
if( C::debugCompare ) error() << "Left value: " << l << " right value: " << r << std::endl;
return l < r; return l < r;
} ); } );
if( optimalStringDistance( closest.first, key ) < sqrt( key.size() ) ) if( closest == end( storage ) ) throw std::out_of_range{ IOStreams::String() << "The key `" << key << "` could not be found." };
else if( optimalStringDistance( closest->first, key ) < sqrt( key.size() ) )
{ {
throw std::out_of_range{ Utility::String() << "The key `" << key << "` could not be found. Did you mean `" throw std::out_of_range{ IOStreams::String() << "The key `" << key << "` could not be found. Did you mean `"
<< closest.first << "`?" }; << closest->first << "`?" };
} }
throw std::out_of_range{ Utility::String() << "The key `" << key << "` could not be found." }; throw std::out_of_range{ IOStreams::String() << "The key `" << key << "` could not be found." };
} }
return storage.at( key ); return storage.at( key );
} }
public: public:
Value &at( const std::string_view key ) { return at_impl( *this, key ); } Value &at( const std::string & key ) { return at_impl( *this, key ); }
const Value &at( const std::string_view key ) const { return at_impl( *this, key ); } const Value &at( const std::string &key ) const { return at_impl( *this, key ); }
bool contains( const std::string_view key ) const { return storage.contains( key ); } bool contains( const std::string &key ) const { return storage.contains( key ); }
void insert( const std::string_view key, Value v ) { if( contains( key ) ) storage.insert( { key, std::move( v ) } ); } void
insert( const std::string &key, Value v )
{
if( not contains( key ) ) storage.emplace( key, std::move( v ) );
if( C::debugInsertion ) error() << "Map has " << storage.size() << " entries" << std::endl;
}
}; };