[utils] add ChildMask class (#5206)

This commit adds the ChildMask class so that it can be reused by other
modules.
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index c956ba3..7906bf2 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -424,6 +424,7 @@
     thread/address_resolver.hpp              \
     thread/announce_begin_server.hpp         \
     thread/announce_sender.hpp               \
+    thread/child_mask.hpp                    \
     thread/child_table.hpp                   \
     thread/discover_scanner.hpp              \
     thread/dua_manager.hpp                   \
diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp
index 0accf3c..a70e84a 100644
--- a/src/core/common/message.cpp
+++ b/src/core/common/message.cpp
@@ -637,36 +637,22 @@
 
 bool Message::GetChildMask(uint16_t aChildIndex) const
 {
-    OT_ASSERT(aChildIndex < sizeof(GetMetadata().mChildMask) * 8);
-    return (GetMetadata().mChildMask[aChildIndex / 8] & (0x80 >> (aChildIndex % 8))) != 0;
+    return GetMetadata().mChildMask.Get(aChildIndex);
 }
 
 void Message::ClearChildMask(uint16_t aChildIndex)
 {
-    OT_ASSERT(aChildIndex < sizeof(GetMetadata().mChildMask) * 8);
-    GetMetadata().mChildMask[aChildIndex / 8] &= ~(0x80 >> (aChildIndex % 8));
+    GetMetadata().mChildMask.Clear(aChildIndex);
 }
 
 void Message::SetChildMask(uint16_t aChildIndex)
 {
-    OT_ASSERT(aChildIndex < sizeof(GetMetadata().mChildMask) * 8);
-    GetMetadata().mChildMask[aChildIndex / 8] |= 0x80 >> (aChildIndex % 8);
+    GetMetadata().mChildMask.Set(aChildIndex);
 }
 
 bool Message::IsChildPending(void) const
 {
-    bool rval = false;
-
-    for (size_t i = 0; i < sizeof(GetMetadata().mChildMask); i++)
-    {
-        if (GetMetadata().mChildMask[i] != 0)
-        {
-            ExitNow(rval = true);
-        }
-    }
-
-exit:
-    return rval;
+    return GetMetadata().mChildMask.HasAny();
 }
 
 uint16_t Message::UpdateChecksum(uint16_t aChecksum, uint16_t aValue)
diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp
index c863b75..1d15ec8 100644
--- a/src/core/common/message.hpp
+++ b/src/core/common/message.hpp
@@ -48,6 +48,7 @@
 #include "common/non_copyable.hpp"
 #include "common/pool.hpp"
 #include "mac/mac_types.hpp"
+#include "thread/child_mask.hpp"
 #include "thread/link_quality.hpp"
 
 namespace ot {
@@ -64,9 +65,8 @@
 
 enum
 {
-    kNumBuffers     = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS,
-    kBufferSize     = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE,
-    kChildMaskBytes = BitVectorBytes(OPENTHREAD_CONFIG_MLE_MAX_CHILDREN),
+    kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS,
+    kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE,
 };
 
 class Message;
@@ -96,9 +96,9 @@
     uint16_t    mOffset;      ///< A byte offset within the message.
     RssAverager mRssAverager; ///< The averager maintaining the received signal strength (RSS) average.
 
-    uint8_t  mChildMask[kChildMaskBytes]; ///< A bit-vector to indicate which sleepy children need to receive this.
-    uint16_t mMeshDest;                   ///< Used for unicast non-link-local messages.
-    uint8_t  mTimeout;                    ///< Seconds remaining before dropping the message.
+    ChildMask mChildMask; ///< A ChildMask to indicate which sleepy children need to receive this.
+    uint16_t  mMeshDest;  ///< Used for unicast non-link-local messages.
+    uint8_t   mTimeout;   ///< Seconds remaining before dropping the message.
     union
     {
         uint16_t mPanId;   ///< Used for MLE Discover Request and Response messages.
diff --git a/src/core/thread/child_mask.hpp b/src/core/thread/child_mask.hpp
new file mode 100644
index 0000000..6eedbbb
--- /dev/null
+++ b/src/core/thread/child_mask.hpp
@@ -0,0 +1,142 @@
+/*
+ *  Copyright (c) 2020, The OpenThread Authors.
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the copyright holder nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ *   This file includes definitions for a child mask.
+ */
+
+#ifndef CHILD_MASK_HPP_
+#define CHILD_MASK_HPP_
+
+#include "openthread-core-config.h"
+
+#include <openthread/error.h>
+
+#include "common/code_utils.hpp"
+#include "common/debug.hpp"
+#include "common/encoding.hpp"
+
+namespace ot {
+
+/**
+ * @addtogroup core-child-mask
+ *
+ * @brief
+ *   This module includes definitions for OpenThread Child Mask.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This class represents a bit-vector of child mask.
+ *
+ */
+class ChildMask
+{
+public:
+    /**
+     * This method returns if a given Child index is masked.
+     *
+     * @param[in] aChildIndex  The Child index.
+     *
+     * @retval TRUE   If the given Child index is set.
+     * @retval FALSE  If the given Child index is clear.
+     *
+     */
+    bool Get(uint16_t aChildIndex) const
+    {
+        OT_ASSERT(aChildIndex < OPENTHREAD_CONFIG_MLE_MAX_CHILDREN);
+        return (mMask[aChildIndex / 8] & (0x80 >> (aChildIndex % 8))) != 0;
+    }
+
+    /**
+     * This method sets the mask of a given Child index.
+     *
+     * @param[in] aChildIndex  The Child index.
+     *
+     */
+    void Set(uint16_t aChildIndex)
+    {
+        OT_ASSERT(aChildIndex < OPENTHREAD_CONFIG_MLE_MAX_CHILDREN);
+        mMask[aChildIndex / 8] |= 0x80 >> (aChildIndex % 8);
+    }
+
+    /**
+     * This method clears the mask of a given Child index.
+     *
+     * @param[in] aChildIndex  The Child index.
+     *
+     */
+    void Clear(uint16_t aChildIndex)
+    {
+        OT_ASSERT(aChildIndex < OPENTHREAD_CONFIG_MLE_MAX_CHILDREN);
+        mMask[aChildIndex / 8] &= ~(0x80 >> (aChildIndex % 8));
+    }
+
+    /**
+     * This method returns if any Child mask is set.
+     *
+     * @retval TRUE   If any Child index is set.
+     * @retval FALSE  If all Child indexes are clear.
+     *
+     */
+    bool HasAny(void) const
+    {
+        bool rval = false;
+
+        for (size_t i = 0; i < sizeof(mMask); i++)
+        {
+            if (mMask[i] != 0)
+            {
+                ExitNow(rval = true);
+            }
+        }
+
+    exit:
+        return rval;
+    }
+
+private:
+    enum
+    {
+        kChildMaskBytes = BitVectorBytes(OPENTHREAD_CONFIG_MLE_MAX_CHILDREN)
+    };
+
+    uint8_t mMask[kChildMaskBytes];
+};
+
+/**
+ * @}
+ *
+ */
+
+} // namespace ot
+
+#endif // CHILD_MASK_HPP_