Loading...
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
 *
 * Copyright (c) 2021 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_LICENSE_HEADER_END@
 */

#include <TargetConditionals.h>

#if !TARGET_OS_EXCLAVEKIT

#include <bit>

#include "Defines.h"
#include "BitUtils.h"
#include "PVLEInt64.h"

namespace lsl {
void emitPVLEUInt64(uint64_t value, Vector<std::byte>& data) {
    auto valueBytes = (std::byte*)&value;
    const uint8_t activeBits = std::max<uint8_t>(lsl::bit_width(value),1);
    if (activeBits > 56) {
        data.push_back((std::byte)0);
        std::copy(&valueBytes[0], &valueBytes[8], std::back_inserter(data));
        return;
    }
    const uint8_t bytes = (activeBits+6)/7;
    value <<= bytes;
    value |= 1<<(bytes-1);
    std::copy(&valueBytes[0], &valueBytes[bytes], std::back_inserter(data));
}

bool readPVLEUInt64(std::span<std::byte>& data, uint64_t& result) {
    result = 0;
    if (data.size() == 0) {
        return false;
    }
    const uint8_t additionalByteCount = std::countr_zero((uint8_t)data[0]);
    if (data.size() < additionalByteCount+1) {
        return false;
    }
    if (additionalByteCount == 8) {
        std::copy(data.begin()+1, data.begin()+9, (std::byte*)&result);
        data = data.last(data.size()-9);
        return true;
    }
    const uint8_t extraBitCount     = 8 - (additionalByteCount+1);
    const uint8_t extraBits         = (((uint8_t)(data[0]))>>(additionalByteCount+1)) & ((1<<extraBitCount)-1);
    std::copy(data.begin()+1, data.begin()+additionalByteCount+1, (std::byte*)&result);
    result <<= extraBitCount;
    result |= extraBits;
    data = data.last(data.size()-(additionalByteCount+1));
    return true;
}

};

#endif // !TARGET_OS_EXCLAVEKIT