3 * Copyright (c) 2020 Project CHIP Authors
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "SerializableIntegerSet.h"
21 #include <core/CHIPEncoding.h>
25 const char * SerializableU64SetBase::SerializeBase64(char * buf, uint16_t & buflen)
28 size_t len = sizeof(uint64_t) * mNextAvailable;
29 VerifyOrExit(buflen >= SerializedSize(), buflen = SerializedSize());
30 VerifyOrExit(buf != nullptr, buflen = SerializedSize());
32 // Swap to little endian order if needed.
33 SwapByteOrderIfNeeded();
35 buflen = Base64Encode(reinterpret_cast<const uint8_t *>(mData), static_cast<uint16_t>(len), buf);
39 // Swap back to the original order
40 SwapByteOrderIfNeeded();
46 CHIP_ERROR SerializableU64SetBase::DeserializeBase64(const char * serialized, uint16_t buflen)
48 CHIP_ERROR err = CHIP_NO_ERROR;
49 uint16_t decodelen = 0;
50 VerifyOrExit(buflen <= MaxSerializedSize(), err = CHIP_ERROR_INVALID_ARGUMENT);
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);
56 mNextAvailable = decodelen / static_cast<uint16_t>(sizeof(uint64_t));
58 // Swap from little endian if needed
59 SwapByteOrderIfNeeded();
65 void SerializableU64SetBase::SwapByteOrderIfNeeded()
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.
72 if (nl::ByteOrder::GetCurrent() != nl::ByteOrder::LittleEndian)
74 for (uint16_t i = 0; i < mNextAvailable; i++)
76 mData[i] = Encoding::LittleEndian::HostSwap64(mData[i]);
81 uint16_t SerializableU64SetBase::FindIndex(uint64_t value)
83 for (uint16_t i = 0; i < mNextAvailable; i++)
85 if (mData[i] == value)
94 CHIP_ERROR SerializableU64SetBase::Insert(uint64_t value)
96 CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
98 VerifyOrExit(value != mEmptyValue, err = CHIP_ERROR_INVALID_ARGUMENT);
100 index = FirstAvailableForUniqueId(value);
101 if (index < mCapacity)
103 mData[index] = value;
104 if (index == mNextAvailable)
106 mNextAvailable = static_cast<uint16_t>(index + 1);
115 void SerializableU64SetBase::Remove(uint64_t value)
117 if (value != mEmptyValue)
119 uint16_t index = FindIndex(value);
120 if (index < mCapacity)
122 mData[index] = mEmptyValue;
123 if ((index + 1) == mNextAvailable)
125 mNextAvailable = index;
126 while (mNextAvailable > 0 && mData[mNextAvailable - 1] == mEmptyValue)
133 uint16_t SerializableU64SetBase::FirstAvailableForUniqueId(uint64_t value)
135 uint16_t available = mNextAvailable;
136 for (uint16_t i = 0; i < mNextAvailable; i++)
138 if (mData[i] == value)
143 if (mData[i] == mEmptyValue && i < available)
145 // Don't return here, as we want to make sure there are no duplicate
146 // entries in the set.