blob: ec42ef38224dc2b260643517f435bb00ea6980f5 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cinttypes>
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/uint128.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/uuid.h"
#ifndef SCNx8
#define SCNx8 "hhx"
#endif
namespace bt {
namespace {
// Format string that can be passed to sscanf. This allows sscanf to convert
// each octet into a uint8_t.
constexpr char kScanUuidFormatString[] =
"%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8
"-"
"%2" SCNx8 "%2" SCNx8
"-"
"%2" SCNx8 "%2" SCNx8
"-"
"%2" SCNx8 "%2" SCNx8
"-"
"%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8 "%2" SCNx8;
// Parses the contents of a |uuid_string| and returns the result in |out_bytes|.
// Returns false if |uuid_string| does not represent a valid UUID.
// TODO(armansito): After having used UUID in camel-case words all over the
// place, I've decided that it sucks. I'm explicitly naming this using the
// "Uuid" style as a reminder to fix style elsewhere.
bool ParseUuidString(const std::string& uuid_string, UInt128* out_bytes) {
BT_DEBUG_ASSERT(out_bytes);
if (uuid_string.length() == 4) {
// Possibly a 16-bit short UUID, parse it in context of the Base UUID.
return ParseUuidString(
"0000" + uuid_string + "-0000-1000-8000-00805F9B34FB", out_bytes);
}
// This is a 36 character string, including 4 "-" characters and two
// characters for each of the 16-octets that form the 128-bit UUID.
if (uuid_string.length() != 36)
return false;
int result = std::sscanf(uuid_string.c_str(),
kScanUuidFormatString,
out_bytes->data() + 15,
out_bytes->data() + 14,
out_bytes->data() + 13,
out_bytes->data() + 12,
out_bytes->data() + 11,
out_bytes->data() + 10,
out_bytes->data() + 9,
out_bytes->data() + 8,
out_bytes->data() + 7,
out_bytes->data() + 6,
out_bytes->data() + 5,
out_bytes->data() + 4,
out_bytes->data() + 3,
out_bytes->data() + 2,
out_bytes->data() + 1,
out_bytes->data());
return (result > 0) && (static_cast<size_t>(result) == out_bytes->size());
}
} // namespace
bool IsStringValidUuid(const std::string& uuid_string) {
UInt128 bytes;
return ParseUuidString(uuid_string, &bytes);
}
bool StringToUuid(const std::string& uuid_string, UUID* out_uuid) {
BT_DEBUG_ASSERT(out_uuid);
UInt128 bytes;
if (!ParseUuidString(uuid_string, &bytes)) {
return false;
}
*out_uuid = UUID(bytes);
return true;
}
} // namespace bt