From: Mikko Rasa <tdb@tdb.fi>
Date: Mon, 3 Jun 2019 08:16:18 +0000 (+0300)
Subject: Prefer exact type match when looking for Loader actions
X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=5520420ecb8da0f6528b2681569f7504f75ddf38;p=libs%2Fdatafile.git

Prefer exact type match when looking for Loader actions

Previosuly the first matching action in alphabetical signature order was
taken, which causes a float overload to be chosen for an int value even
if an int overload was also available.
---

diff --git a/source/loader.cpp b/source/loader.cpp
index 997e7c9..a05e5f0 100644
--- a/source/loader.cpp
+++ b/source/loader.cpp
@@ -8,37 +8,37 @@ using namespace std;
 
 namespace {
 
-bool signature_match(char s, char a)
+int signature_match(char s, char a)
 {
 	if(s==a)
-		return true;
+		return 3;
 	if(s==Msp::DataFile::IntType::signature && a==Msp::DataFile::FloatType::signature)
-		return true;
-	return false;
+		return 1;
+	return 0;
 }
 
-bool signature_match(const string &st_sig, const string &act_sig)
+int signature_match(const string &st_sig, const string &act_sig)
 {
 	if(act_sig=="*")
-		return true;
+		return 1;
 	else if(act_sig.size()==2 && act_sig[1]=='*')
 	{
-		for(string::const_iterator i=st_sig.begin(); i!=st_sig.end(); ++i)
-			if(!signature_match(*i, act_sig[0]))
-				return false;
+		int match = 3;
+		for(string::const_iterator i=st_sig.begin(); (i!=st_sig.end() && match); ++i)
+			match = min(match, signature_match(*i, act_sig[0]));
 
-		return true;
+		return match;
 	}
 	else if(st_sig.size()==act_sig.size())
 	{
-		for(unsigned i=0; i<st_sig.size(); ++i)
-			if(!signature_match(st_sig[i], act_sig[i]))
-				return false;
+		int match = 3;
+		for(unsigned i=0; (i<st_sig.size() && match); ++i)
+			match = min(match, signature_match(st_sig[i], act_sig[i]));
 
-		return true;
+		return match ? match+1 : 0;
 	}
 	else
-		return false;
+		return 0;
 }
 
 }
@@ -191,11 +191,22 @@ LoaderAction *Loader::find_action(const StatementKey &key) const
 	if(begin==end)
 		throw unknown_keyword(key.keyword);
 
+	LoaderAction *act = 0;
+	int match = 0;
 	for(ActionMap::const_iterator i=begin; i!=end; ++i)
-		if(signature_match(key.signature, i->first.signature))
-			return i->second;
+	{
+		int m = signature_match(key.signature, i->first.signature);
+		if(m>match)
+		{
+			act = i->second;
+			match = m;
+		}
+	}
+
+	if(!act)
+		throw invalid_signature(key.keyword, key.signature);
 
-	throw invalid_signature(key.keyword, key.signature);
+	return act;
 }
 
 const string &Loader::get_source() const