Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / support / SerializableIntegerSet.cpp
1 /*
2  *
3  *    Copyright (c) 2020 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
19 #include "SerializableIntegerSet.h"
20
21 #include <core/CHIPEncoding.h>
22
23 namespace chip {
24
25 const char * SerializableU64SetBase::SerializeBase64(char * buf, uint16_t & buflen)
26 {
27     char * out = nullptr;
28     size_t len = sizeof(uint64_t) * mNextAvailable;
29     VerifyOrExit(buflen >= SerializedSize(), buflen = SerializedSize());
30     VerifyOrExit(buf != nullptr, buflen = SerializedSize());
31
32     // Swap to little endian order if needed.
33     SwapByteOrderIfNeeded();
34
35     buflen      = Base64Encode(reinterpret_cast<const uint8_t *>(mData), static_cast<uint16_t>(len), buf);
36     buf[buflen] = '\0';
37     out         = buf;
38
39     // Swap back to the original order
40     SwapByteOrderIfNeeded();
41
42 exit:
43     return out;
44 }
45
46 CHIP_ERROR SerializableU64SetBase::DeserializeBase64(const char * serialized, uint16_t buflen)
47 {
48     CHIP_ERROR err     = CHIP_NO_ERROR;
49     uint16_t decodelen = 0;
50     VerifyOrExit(buflen <= MaxSerializedSize(), err = CHIP_ERROR_INVALID_ARGUMENT);
51
52     decodelen = Base64Decode(serialized, buflen, reinterpret_cast<uint8_t *>(mData));
53     VerifyOrExit(decodelen <= sizeof(uint64_t) * mCapacity, err = CHIP_ERROR_INVALID_ARGUMENT);
54     VerifyOrExit(decodelen % sizeof(uint64_t) == 0, err = CHIP_ERROR_INVALID_ARGUMENT);
55
56     mNextAvailable = decodelen / static_cast<uint16_t>(sizeof(uint64_t));
57
58     // Swap from little endian if needed
59     SwapByteOrderIfNeeded();
60
61 exit:
62     return err;
63 }
64
65 void SerializableU64SetBase::SwapByteOrderIfNeeded()
66 {
67     /**
68      *  The data is serialized in LittleEndian byte order in the set. This will enable
69      *  different machine architectures to interpret a given set in a consistent manner,
70      *  for serialize and deserialize operations.
71      */
72     if (nl::ByteOrder::GetCurrent() != nl::ByteOrder::LittleEndian)
73     {
74         for (uint16_t i = 0; i < mNextAvailable; i++)
75         {
76             mData[i] = Encoding::LittleEndian::HostSwap64(mData[i]);
77         }
78     }
79 }
80
81 uint16_t SerializableU64SetBase::FindIndex(uint64_t value)
82 {
83     for (uint16_t i = 0; i < mNextAvailable; i++)
84     {
85         if (mData[i] == value)
86         {
87             return i;
88         }
89     }
90
91     return mCapacity;
92 }
93
94 CHIP_ERROR SerializableU64SetBase::Insert(uint64_t value)
95 {
96     CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
97     uint16_t index = 0;
98     VerifyOrExit(value != mEmptyValue, err = CHIP_ERROR_INVALID_ARGUMENT);
99
100     index = FirstAvailableForUniqueId(value);
101     if (index < mCapacity)
102     {
103         mData[index] = value;
104         if (index == mNextAvailable)
105         {
106             mNextAvailable = static_cast<uint16_t>(index + 1);
107         }
108         err = CHIP_NO_ERROR;
109     }
110
111 exit:
112     return err;
113 }
114
115 void SerializableU64SetBase::Remove(uint64_t value)
116 {
117     if (value != mEmptyValue)
118     {
119         uint16_t index = FindIndex(value);
120         if (index < mCapacity)
121         {
122             mData[index] = mEmptyValue;
123             if ((index + 1) == mNextAvailable)
124             {
125                 mNextAvailable = index;
126                 while (mNextAvailable > 0 && mData[mNextAvailable - 1] == mEmptyValue)
127                     mNextAvailable--;
128             }
129         }
130     }
131 }
132
133 uint16_t SerializableU64SetBase::FirstAvailableForUniqueId(uint64_t value)
134 {
135     uint16_t available = mNextAvailable;
136     for (uint16_t i = 0; i < mNextAvailable; i++)
137     {
138         if (mData[i] == value)
139         {
140             return i;
141         }
142
143         if (mData[i] == mEmptyValue && i < available)
144         {
145             // Don't return here, as we want to make sure there are no duplicate
146             // entries in the set.
147             available = i;
148         }
149     }
150
151     return available;
152 }
153
154 } // namespace chip