diff --git a/tensorflow/lite/toco/tflite/BUILD b/tensorflow/lite/toco/tflite/BUILD index f27f0f999da..4fff36fc43f 100644 --- a/tensorflow/lite/toco/tflite/BUILD +++ b/tensorflow/lite/toco/tflite/BUILD @@ -146,6 +146,7 @@ cc_library( ":operator", "//tensorflow/lite/toco:model", "//tensorflow/lite/toco:tooling_util", + "@com_google_absl//absl/strings", ], ) diff --git a/tensorflow/lite/toco/tflite/op_version.cc b/tensorflow/lite/toco/tflite/op_version.cc index 09ffa8c30fb..870f57b7a0f 100644 --- a/tensorflow/lite/toco/tflite/op_version.cc +++ b/tensorflow/lite/toco/tflite/op_version.cc @@ -15,7 +15,10 @@ limitations under the License. #include "tensorflow/lite/toco/tflite/op_version.h" #include +#include +#include "absl/strings/numbers.h" +#include "absl/strings/str_split.h" #include "tensorflow/lite/toco/model.h" #include "tensorflow/lite/toco/tflite/operator.h" #include "tensorflow/lite/toco/tooling_util.h" @@ -23,6 +26,23 @@ limitations under the License. namespace toco { namespace tflite { +bool CompareVersion(const string& v1, const string& v2) { + const std::vector& vec1 = absl::StrSplit(v1, '.'); + const std::vector& vec2 = absl::StrSplit(v2, '.'); + int i = 0; + while (i < vec1.size() && i < vec2.size()) { + int v1_val, v2_val; + if (absl::SimpleAtoi(vec1[i], &v1_val) && + absl::SimpleAtoi(vec2[i], &v2_val)) { + if (v1_val != v2_val) return v1_val < v2_val; + } + ++i; + } + // If there are remaining items in v2 not being compared, then v1 should + // precede v2. + return i < vec2.size(); +} + string GetMinimumRuntimeVersionForModel(const Model& model) { // Use this as the placeholder string if a particular op is not yet included // in any Tensorflow's RC/Final release source package. Once that op is @@ -193,7 +213,7 @@ string GetMinimumRuntimeVersionForModel(const Model& model) { // doesn't have a minimum runtime version associated, continue. continue; } - if (strcmp(model_min_version.c_str(), it->second.c_str()) < 0) { + if (CompareVersion(model_min_version, it->second)) { // Current min model runtime version should be bumped if we see a higher // op version. model_min_version = it->second; diff --git a/tensorflow/lite/toco/tflite/op_version.h b/tensorflow/lite/toco/tflite/op_version.h index 54a77501b14..7b644c19db1 100644 --- a/tensorflow/lite/toco/tflite/op_version.h +++ b/tensorflow/lite/toco/tflite/op_version.h @@ -20,6 +20,11 @@ limitations under the License. namespace toco { namespace tflite { +// Returns true if the first version string precedes the second. +// For example, '1.14' should precede '1.9', also '1.14.1' should precede +// '1.14'. If two version string is equal, then false will be returned. +bool CompareVersion(const string&, const string&); + // Get the minimum TF Lite runtime required to run a model. Each built-in // operator in the model will have its own minimum requirement of a runtime, and // the model's minimum requirement of runtime is defined as the maximum of all diff --git a/tensorflow/lite/toco/tflite/op_version_test.cc b/tensorflow/lite/toco/tflite/op_version_test.cc index daacc71fa3e..ce40959f54c 100644 --- a/tensorflow/lite/toco/tflite/op_version_test.cc +++ b/tensorflow/lite/toco/tflite/op_version_test.cc @@ -134,6 +134,18 @@ TEST(OpVersionTest, MinimumVersionForMixedOpVersions) { EXPECT_EQ(GetMinimumRuntimeVersionForModel(model), "1.10.0"); } +TEST(OpVersionTest, CompareVersionString) { + EXPECT_TRUE(CompareVersion("1.9", "1.13")); + EXPECT_FALSE(CompareVersion("1.13", "1.13")); + EXPECT_TRUE(CompareVersion("1.14", "1.14.1")); + EXPECT_FALSE(CompareVersion("1.14.1", "1.14")); + EXPECT_FALSE(CompareVersion("1.14.1", "1.9")); + EXPECT_FALSE(CompareVersion("1.0.9", "1.0.8")); + EXPECT_FALSE(CompareVersion("2.1.0", "1.2.0")); + EXPECT_TRUE(CompareVersion("", "1.13")); + EXPECT_FALSE(CompareVersion("", "")); +} + } // namespace } // namespace tflite } // namespace toco