Line data Source code
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 <lib/core/CHIPEncoding.h> 22 : #include <lib/support/CodeUtils.h> 23 : 24 : namespace chip { 25 : 26 1 : CHIP_ERROR SerializableU64SetBase::Deserialize(ByteSpan serialized) 27 : { 28 1 : VerifyOrReturnError(serialized.size() <= MaxSerializedSize(), CHIP_ERROR_INVALID_ARGUMENT); 29 1 : memcpy(mData, serialized.data(), serialized.size()); 30 1 : mNextAvailable = static_cast<uint16_t>(serialized.size() / sizeof(uint64_t)); 31 : 32 : // Our serialized data is always little-endian; swap to native. 33 1 : SwapByteOrderIfNeeded(); 34 1 : return CHIP_NO_ERROR; 35 : } 36 : 37 5 : void SerializableU64SetBase::SwapByteOrderIfNeeded() 38 : { 39 : /** 40 : * The data is serialized in LittleEndian byte order in the set. This will enable 41 : * different machine architectures to interpret a given set in a consistent manner, 42 : * for serialize and deserialize operations. 43 : */ 44 5 : if (nl::ByteOrder::GetCurrent() != nl::ByteOrder::LittleEndian) 45 : { 46 0 : for (uint16_t i = 0; i < mNextAvailable; i++) 47 : { 48 0 : mData[i] = Encoding::LittleEndian::HostSwap64(mData[i]); 49 : } 50 : } 51 5 : } 52 : 53 56 : uint16_t SerializableU64SetBase::FindIndex(uint64_t value) 54 : { 55 208 : for (uint16_t i = 0; i < mNextAvailable; i++) 56 : { 57 200 : if (mData[i] == value) 58 : { 59 48 : return i; 60 : } 61 : } 62 : 63 8 : return mCapacity; 64 : } 65 : 66 27 : CHIP_ERROR SerializableU64SetBase::Insert(uint64_t value) 67 : { 68 27 : VerifyOrReturnError(value != mEmptyValue, CHIP_ERROR_INVALID_ARGUMENT); 69 : 70 26 : const uint16_t index = FirstAvailableForUniqueId(value); 71 26 : if (index < mCapacity) 72 : { 73 25 : mData[index] = value; 74 25 : if (index == mNextAvailable) 75 : { 76 23 : mNextAvailable = static_cast<uint16_t>(index + 1); 77 : } 78 25 : return CHIP_NO_ERROR; 79 : } 80 : 81 1 : return CHIP_ERROR_NO_MEMORY; 82 : } 83 : 84 18 : void SerializableU64SetBase::Remove(uint64_t value) 85 : { 86 18 : if (value != mEmptyValue) 87 : { 88 17 : const uint16_t index = FindIndex(value); 89 17 : if (index < mCapacity) 90 : { 91 17 : mData[index] = mEmptyValue; 92 17 : if ((index + 1) == mNextAvailable) 93 : { 94 4 : mNextAvailable = index; 95 17 : while (mNextAvailable > 0 && mData[mNextAvailable - 1] == mEmptyValue) 96 13 : mNextAvailable--; 97 : } 98 : } 99 : } 100 18 : } 101 : 102 26 : uint16_t SerializableU64SetBase::FirstAvailableForUniqueId(uint64_t value) 103 : { 104 26 : uint16_t available = mNextAvailable; 105 98 : for (uint16_t i = 0; i < mNextAvailable; i++) 106 : { 107 74 : if (mData[i] == value) 108 : { 109 2 : return i; 110 : } 111 : 112 72 : if (mData[i] == mEmptyValue && i < available) 113 : { 114 : // Don't return here, as we want to make sure there are no duplicate 115 : // entries in the set. 116 0 : available = i; 117 : } 118 : } 119 : 120 24 : return available; 121 : } 122 : 123 : } // namespace chip