Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 385ea227 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Always check prefix matches array at each node"

parents edaa2877 26eba287
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -172,6 +172,9 @@ class PropertyInfoArea : private SerializedData {
  TrieNode root_node() const { return trie(header()->root_offset); }

 private:
  void CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
                        uint32_t* context_index, uint32_t* schema_index) const;

  const PropertyInfoAreaHeader* header() const {
    return reinterpret_cast<const PropertyInfoAreaHeader*>(data_base());
  }
+21 −12
Original line number Diff line number Diff line
@@ -87,6 +87,21 @@ bool TrieNode::FindChildForString(const char* name, uint32_t namelen, TrieNode*
  return true;
}

void PropertyInfoArea::CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
                                        uint32_t* context_index, uint32_t* schema_index) const {
  const uint32_t remaining_name_size = strlen(remaining_name);
  for (uint32_t i = 0; i < trie_node.num_prefixes(); ++i) {
    auto prefix_len = trie_node.prefix(i)->namelen;
    if (prefix_len > remaining_name_size) continue;

    if (!strncmp(c_string(trie_node.prefix(i)->name_offset), remaining_name, prefix_len)) {
      *context_index = trie_node.prefix(i)->context_index;
      *schema_index = trie_node.prefix(i)->schema_index;
      return;
    }
  }
}

void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* context_index,
                                              uint32_t* schema_index) const {
  uint32_t return_context_index = ~0u;
@@ -104,6 +119,10 @@ void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* contex
      return_schema_index = trie_node.schema_index();
    }

    // Check prefixes at this node.  This comes after the node check since these prefixes are by
    // definition longer than the node itself.
    CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_schema_index);

    if (sep == nullptr) {
      break;
    }
@@ -128,18 +147,8 @@ void PropertyInfoArea::GetPropertyInfoIndexes(const char* name, uint32_t* contex
    }
  }
  // Check prefix matches for prefixes not deliminated with '.'
  const uint32_t remaining_name_size = strlen(remaining_name);
  for (uint32_t i = 0; i < trie_node.num_prefixes(); ++i) {
    auto prefix_len = trie_node.prefix(i)->namelen;
    if (prefix_len > remaining_name_size) continue;

    if (!strncmp(c_string(trie_node.prefix(i)->name_offset), remaining_name, prefix_len)) {
      if (context_index != nullptr) *context_index = trie_node.prefix(i)->context_index;
      if (schema_index != nullptr) *schema_index = trie_node.prefix(i)->schema_index;
      return;
    }
  }
  // Return previously found '.' deliminated prefix match.
  CheckPrefixMatch(remaining_name, trie_node, &return_context_index, &return_schema_index);
  // Return previously found prefix match.
  if (context_index != nullptr) *context_index = return_context_index;
  if (schema_index != nullptr) *schema_index = return_schema_index;
  return;
+81 −0
Original line number Diff line number Diff line
@@ -763,5 +763,86 @@ TEST(propertyinfoserializer, RealProperties) {
  }
}

TEST(propertyinfoserializer, GetPropertyInfo_prefix_without_dot) {
  auto property_info = std::vector<PropertyInfoEntry>{
      {"persist.radio", "1st", "1st", false},
      {"persist.radio.something.else.here", "2nd", "2nd", false},
  };

  auto serialized_trie = std::string();
  auto build_trie_error = std::string();
  ASSERT_TRUE(BuildTrie(property_info, "default", "default", &serialized_trie, &build_trie_error))
      << build_trie_error;

  auto property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_trie.data());

  const char* context;
  const char* schema;
  property_info_area->GetPropertyInfo("persist.radio", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radio.subproperty", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radiowords", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radio.long.long.long.sub.property", &context,
                                      &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radio.something.else.here", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.something.else.here2", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.something.else.here.after", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.something.else.nothere", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radio.something.else", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
}

TEST(propertyinfoserializer, GetPropertyInfo_prefix_with_dot_vs_without) {
  auto property_info = std::vector<PropertyInfoEntry>{
      {"persist.", "1st", "1st", false},
      {"persist.radio", "2nd", "2nd", false},
      {"persist.radio.long.property.exact.match", "3rd", "3rd", true},
  };

  auto serialized_trie = std::string();
  auto build_trie_error = std::string();
  ASSERT_TRUE(BuildTrie(property_info, "default", "default", &serialized_trie, &build_trie_error))
      << build_trie_error;

  auto property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_trie.data());

  const char* context;
  const char* schema;
  property_info_area->GetPropertyInfo("persist.notradio", &context, &schema);
  EXPECT_STREQ("1st", context);
  EXPECT_STREQ("1st", schema);
  property_info_area->GetPropertyInfo("persist.radio", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.subproperty", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radiowords", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.long.property.prefix.match", &context, &schema);
  EXPECT_STREQ("2nd", context);
  EXPECT_STREQ("2nd", schema);
  property_info_area->GetPropertyInfo("persist.radio.long.property.exact.match", &context, &schema);
  EXPECT_STREQ("3rd", context);
  EXPECT_STREQ("3rd", schema);
}

}  // namespace properties
}  // namespace android