Matter SDK Coverage Report
Current view: top level - lib/format - FlatTreePosition.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 91.2 % 34 31
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2023 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : #pragma once
      19              : 
      20              : #include <lib/format/FlatTree.h>
      21              : #include <lib/support/Span.h>
      22              : 
      23              : namespace chip {
      24              : namespace FlatTree {
      25              : 
      26              : /// Represents a position inside a given tree, allowing for descending
      27              : /// and ascending.
      28              : ///
      29              : /// A possition in the tree may be undefined if descending to a non-existing leaf,
      30              : /// however the position still allows moving back again.
      31              : ///
      32              : /// DESCEND_DEPTH is the maximum remembered depth for going back up.
      33              : ///
      34              : /// General usage:
      35              : ///
      36              : ///     Position<DataType, 10> position(tree, tree_size);
      37              : ///
      38              : ///     position.Enter(ByName("foo"));
      39              : ///     position.Enter(ByName("bar"));
      40              : ///     position.Enter(ByName("baz"));
      41              : ///
      42              : ///     position.Get()  /// content of foo::bar::baz if it exists
      43              : ///
      44              : ///     position.Exit();
      45              : ///     position.Exit();
      46              : ///
      47              : ///     position.Get()  /// content of foo if it exists
      48              : ///
      49              : ///     position.Enter(ById(1234));
      50              : ///
      51              : ///     position.Get()  /// content of foo::1234
      52              : ///
      53              : template <typename CONTENT, size_t DESCEND_DEPTH>
      54              : class Position
      55              : {
      56              : public:
      57           56 :     Position(const Node<CONTENT> * tree, size_t treeSize) : mTree(tree), mTreeSize(treeSize) {}
      58              : 
      59              :     template <size_t N>
      60              :     Position(const std::array<const Node<CONTENT>, N> & tree) : mTree(tree.data()), mTreeSize(N)
      61              :     {}
      62              : 
      63              :     // Move back to the top
      64          153 :     void ResetToTop()
      65              :     {
      66          153 :         mDescendDepth        = 0;
      67          153 :         mUnknownDescendDepth = 0;
      68          153 :     }
      69              : 
      70              :     /// Attempt to find a child of the current position that matches
      71              :     /// the given matcher
      72              :     template <typename MATCHER>
      73              :     void Enter(MATCHER matcher);
      74              : 
      75              :     /// Move up the tree, undoes an 'Enter' operation.
      76              :     void Exit();
      77              : 
      78              :     /// Fetch the value where the node is positioned on or nullptr if that
      79              :     /// value is not available;
      80              :     const CONTENT * Get() const;
      81              : 
      82              :     /// Returns the entries visited so far
      83              :     ///
      84              :     /// WILL RETURN EMPTY if the descend depth has been
      85              :     /// exceeded. Callers MUST handle empty return.
      86              :     ///
      87              :     /// Span valid until one of Enter/Exit functions are called
      88              :     /// and as long as the Position is valid (points inside the object).
      89              :     chip::Span<const Entry<CONTENT> *> CurrentPath();
      90              : 
      91           24 :     bool HasValidTree() const { return mTree != nullptr; }
      92              : 
      93           11 :     size_t DescendDepth() const { return mDescendDepth + mUnknownDescendDepth; }
      94              : 
      95              : private:
      96              :     // actual tree that we visit
      97              :     const Node<CONTENT> * mTree = nullptr;
      98              :     const size_t mTreeSize      = 0;
      99              : 
     100              :     // Keeping track of descending into the tree, to be able to move back
     101              :     // last element in the array is the "current" item
     102              :     const Entry<CONTENT> * mPositions[DESCEND_DEPTH] = { nullptr };
     103              :     size_t mDescendDepth                             = 0; // filled amount of mDescendPositions
     104              : 
     105              :     // Descend past remembering memory or in not-found entries.
     106              :     size_t mUnknownDescendDepth = 0; // depth in invalid positions
     107              : };
     108              : 
     109              : template <typename CONTENT, size_t DESCEND_DEPTH>
     110          920 : const CONTENT * Position<CONTENT, DESCEND_DEPTH>::Get() const
     111              : {
     112          920 :     if (mUnknownDescendDepth > 0)
     113              :     {
     114          137 :         return nullptr;
     115              :     }
     116              : 
     117          783 :     if (mDescendDepth == 0)
     118              :     {
     119            0 :         return nullptr;
     120              :     }
     121              : 
     122          783 :     return &mPositions[mDescendDepth - 1]->data;
     123              : }
     124              : 
     125              : template <typename CONTENT, size_t DESCEND_DEPTH>
     126              : template <typename MATCHER>
     127          602 : void Position<CONTENT, DESCEND_DEPTH>::Enter(MATCHER matcher)
     128              : {
     129          602 :     if (mUnknownDescendDepth > 0)
     130              :     {
     131              :         // keep descending into the unknown
     132           66 :         mUnknownDescendDepth++;
     133           66 :         return;
     134              :     }
     135              : 
     136              :     // To be able to descend, we have to be able to remember
     137              :     // the current position
     138          536 :     if (mDescendDepth == DESCEND_DEPTH)
     139              :     {
     140            0 :         mUnknownDescendDepth = 1;
     141            0 :         return;
     142              :     }
     143              : 
     144          536 :     size_t nodeIdx = 0; // assume root node
     145          536 :     if (mDescendDepth > 0)
     146              :     {
     147          411 :         nodeIdx = mPositions[mDescendDepth - 1]->node_index;
     148              :     }
     149              : 
     150          536 :     const Entry<CONTENT> * child = FindEntry(mTree, mTreeSize, nodeIdx, matcher);
     151              : 
     152          536 :     if (child == nullptr)
     153              :     {
     154           43 :         mUnknownDescendDepth = 1;
     155           43 :         return;
     156              :     }
     157              : 
     158          493 :     mPositions[mDescendDepth++] = child;
     159              : }
     160              : 
     161              : template <typename CONTENT, size_t DESCEND_DEPTH>
     162          420 : void Position<CONTENT, DESCEND_DEPTH>::Exit()
     163              : {
     164          420 :     if (mUnknownDescendDepth > 0)
     165              :     {
     166           50 :         mUnknownDescendDepth--;
     167           50 :         return;
     168              :     }
     169              : 
     170          370 :     if (mDescendDepth > 0)
     171              :     {
     172          370 :         mDescendDepth--;
     173              :     }
     174              : }
     175              : 
     176              : template <typename CONTENT, size_t DESCEND_DEPTH>
     177              : chip::Span<const Entry<CONTENT> *> Position<CONTENT, DESCEND_DEPTH>::CurrentPath()
     178              : {
     179              :     if (mUnknownDescendDepth > 0)
     180              :     {
     181              :         return chip::Span<const Entry<CONTENT> *>();
     182              :     }
     183              : 
     184              :     // const chip::FlatTree::Entry<{anonymous}::NamedTag>* const* to
     185              :     // const chip::FlatTree::Entry<{anonymous}::NamedTag>**
     186              :     typename chip::Span<const Entry<CONTENT> *>::pointer p = mPositions;
     187              : 
     188              :     // return chip::Span<const Entry<CONTENT> *>(mPositions, mDescendDepth);
     189              :     return chip::Span<const Entry<CONTENT> *>(p, mDescendDepth);
     190              : }
     191              : 
     192              : } // namespace FlatTree
     193              : } // namespace chip
        

Generated by: LCOV version 2.0-1