diff options
author | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 10:23:07 +0000 |
---|---|---|
committer | armansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-06 10:23:07 +0000 |
commit | 6e26d08a43a3a0126f5ff22a2f886597f8d304e3 (patch) | |
tree | 6c290e54d99d2b27defd2bd2c47696bb4565263d /device | |
parent | 07f04ffcf26b301ff73d617aae62cee4d2919968 (diff) | |
download | chromium_src-6e26d08a43a3a0126f5ff22a2f886597f8d304e3.zip chromium_src-6e26d08a43a3a0126f5ff22a2f886597f8d304e3.tar.gz chromium_src-6e26d08a43a3a0126f5ff22a2f886597f8d304e3.tar.bz2 |
device/bluetooth: Introduce class bluetooth_utils::UUID.
Added an opaque container for Bluetooth universally unique identifiers, which
are internally represented as a string. The class abstracts away conversion from
16 and 32-bit UUIDs to the 128-bit format using the existing
bluetooth_utils::CanonicalUuid function. This provides a more simple object
oriented interface for passing around UUIDs.
BUG=340524
TEST=device_unittests
Review URL: https://codereview.chromium.org/154883002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249333 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'device')
-rw-r--r-- | device/bluetooth/bluetooth_utils.cc | 94 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_utils.h | 78 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_utils_unittest.cc | 101 |
3 files changed, 229 insertions, 44 deletions
diff --git a/device/bluetooth/bluetooth_utils.cc b/device/bluetooth/bluetooth_utils.cc index b1f9f781..df0c875 100644 --- a/device/bluetooth/bluetooth_utils.cc +++ b/device/bluetooth/bluetooth_utils.cc @@ -10,49 +10,103 @@ #include "base/logging.h" #include "base/strings/string_util.h" -namespace { -static const char* kCommonUuidPostfix = "-0000-1000-8000-00805f9b34fb"; -static const char* kCommonUuidPrefix = "0000"; -static const int kUuidSize = 36; -} // namespace - namespace device { namespace bluetooth_utils { -std::string CanonicalUuid(std::string uuid) { +namespace { + +const char* kCommonUuidPostfix = "-0000-1000-8000-00805f9b34fb"; +const char* kCommonUuidPrefix = "0000"; +const int kUuidSize = 36; + +// Returns the canonical, 128-bit canonical, and the format of the UUID +// in |canonical|, |canonical_128|, and |format| based on |uuid|. +void GetCanonicalUuid(std::string uuid, + std::string* canonical, + std::string* canonical_128, + UUID::Format* format) { + // Initialize the values for the failure case. + canonical->clear(); + canonical_128->clear(); + *format = UUID::kFormatInvalid; + if (uuid.empty()) - return std::string(); + return; if (uuid.size() < 11 && uuid.find("0x") == 0) uuid = uuid.substr(2); if (!(uuid.size() == 4 || uuid.size() == 8 || uuid.size() == 36)) - return std::string(); + return; if (uuid.size() == 4 || uuid.size() == 8) { for (size_t i = 0; i < uuid.size(); ++i) { if (!IsHexDigit(uuid[i])) - return std::string(); + return; } - - if (uuid.size() == 4) - return kCommonUuidPrefix + uuid + kCommonUuidPostfix; - - return uuid + kCommonUuidPostfix; + if (uuid.size() == 4) { + canonical->assign(uuid); + canonical_128->assign(kCommonUuidPrefix + uuid + kCommonUuidPostfix); + *format = UUID::kFormat16Bit; + return; + } + canonical->assign(uuid); + canonical_128->assign(uuid + kCommonUuidPostfix); + *format = UUID::kFormat32Bit; + return; } - std::string uuid_result(uuid); for (int i = 0; i < kUuidSize; ++i) { if (i == 8 || i == 13 || i == 18 || i == 23) { if (uuid[i] != '-') - return std::string(); + return; } else { if (!IsHexDigit(uuid[i])) - return std::string(); - uuid_result[i] = tolower(uuid[i]); + return; + uuid[i] = tolower(uuid[i]); } } - return uuid_result; + + canonical->assign(uuid); + canonical_128->assign(uuid); + *format = UUID::kFormat128Bit; +} + +} // namespace + + +UUID::UUID(const std::string& uuid) { + GetCanonicalUuid(uuid, &value_, &canonical_value_, &format_); +} + +UUID::UUID() : format_(kFormatInvalid) { +} + +UUID::~UUID() { +} + +bool UUID::IsValid() const { + return format_ != kFormatInvalid; +} + +bool UUID::operator<(const UUID& uuid) const { + return canonical_value_ < uuid.canonical_value_; +} + +bool UUID::operator==(const UUID& uuid) const { + return canonical_value_ == uuid.canonical_value_; +} + +bool UUID::operator!=(const UUID& uuid) const { + return canonical_value_ != uuid.canonical_value_; +} + +std::string CanonicalUuid(std::string uuid) { + std::string value; + std::string canonical_value; + UUID::Format format; + GetCanonicalUuid(uuid, &value, &canonical_value, &format); + return canonical_value; } } // namespace bluetooth_utils diff --git a/device/bluetooth/bluetooth_utils.h b/device/bluetooth/bluetooth_utils.h index 09951601..44b52b1 100644 --- a/device/bluetooth/bluetooth_utils.h +++ b/device/bluetooth/bluetooth_utils.h @@ -12,6 +12,84 @@ namespace device { namespace bluetooth_utils { +// Opaque wrapper around a Bluetooth UUID. Instances of UUID represent the +// 128-bit universally unique identifiers (UUIDs) of profiles and attributes +// used in Bluetooth based communication, such as a peripheral's services, +// characteristics, and characteristic descriptors. An instance are +// constructed using a string representing 16, 32, or 128 bit UUID formats. +class UUID { + public: + // Possible representation formats used during construction. + enum Format { + kFormatInvalid, + kFormat16Bit, + kFormat32Bit, + kFormat128Bit + }; + + // Single argument constructor. |uuid| can be a 16, 32, or 128 bit UUID + // represented as a 4, 8, or 36 character string with the following + // formats: + // XXXX + // 0xXXXX + // XXXXXXXX + // 0xXXXXXXXX + // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + // + // 16 and 32 bit UUIDs will be internally converted to a 128 bit UUID using + // the base UUID defined in the Bluetooth specification, hence custom UUIDs + // should be provided in the 128-bit format. If |uuid| is in an unsupported + // format, the result might be invalid. Use IsValid to check for validity + // after construction. + explicit UUID(const std::string& uuid); + ~UUID(); + + // Returns true, if the UUID is in a valid canonical format. + bool IsValid() const; + + // Returns the representation format of the UUID. This reflects the format + // that was provided during construction. + Format format() const { return format_; } + + // Returns the value of the UUID as a string. The representation format is + // based on what was passed in during construction. For the supported sizes, + // this representation can have the following formats: + // - 16 bit: XXXX + // - 32 bit: XXXXXXXX + // - 128 bit: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + // where X is a lowercase hex digit. + const std::string& value() const { return value_; } + + // Returns the underlying 128-bit value as a string in the following format: + // XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + // where X is a lowercase hex digit. + const std::string& canonical_value() const { return canonical_value_; } + + // Permit sufficient comparison to allow a UUID to be used as a key in a + // std::map. + bool operator<(const UUID& uuid) const; + + // Equality operators. + bool operator==(const UUID& uuid) const; + bool operator!=(const UUID& uuid) const; + + private: + UUID(); + + // String representation of the UUID that was used during construction. For + // the supported sizes, this representation can have the following formats: + // - 16 bit: XXXX + // - 32 bit: XXXXXXXX + // - 128 bit: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + Format format_; + std::string value_; + + // The 128-bit string representation of the UUID. + std::string canonical_value_; +}; + +// DEPRECATED. Use bluetooth_utils::UUID instead. +// // Takes a 4, 8 or 36 character UUID, validates it and returns it in 36 // character format with all hex digits lower case. If |uuid| is invalid, the // empty string is returned. diff --git a/device/bluetooth/bluetooth_utils_unittest.cc b/device/bluetooth/bluetooth_utils_unittest.cc index 46d5f34..07c63b5 100644 --- a/device/bluetooth/bluetooth_utils_unittest.cc +++ b/device/bluetooth/bluetooth_utils_unittest.cc @@ -7,47 +7,100 @@ #include "testing/gtest/include/gtest/gtest.h" namespace device { +namespace bluetooth_utils { TEST(BluetoothUtilsTest, CanonicalUuid) { // Does nothing for an already canonical UUID EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("00001101-0000-1000-8000-00805f9b34fb")); + CanonicalUuid("00001101-0000-1000-8000-00805f9b34fb")); // Rejects misformatted - EXPECT_EQ("", bluetooth_utils::CanonicalUuid("1101a")); - EXPECT_EQ("", bluetooth_utils::CanonicalUuid("Z101")); - EXPECT_EQ("", bluetooth_utils::CanonicalUuid("0000-1101")); - EXPECT_EQ("", bluetooth_utils::CanonicalUuid("0000Z101")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("0001101-0000-1000-8000-00805f9b34fb")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("Z0001101-0000-1000-8000-00805f9b34fb")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("00001101 0000-1000-8000-00805f9b34fb")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("00001101-0000:1000-8000-00805f9b34fb")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("00001101-0000-1000;8000-00805f9b34fb")); - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("00001101-0000-1000-8000000805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("1101a")); + EXPECT_EQ("", CanonicalUuid("Z101")); + EXPECT_EQ("", CanonicalUuid("0000-1101")); + EXPECT_EQ("", CanonicalUuid("0000Z101")); + EXPECT_EQ("", CanonicalUuid("0001101-0000-1000-8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("Z0001101-0000-1000-8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("00001101 0000-1000-8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("00001101-0000:1000-8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("00001101-0000-1000;8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("00001101-0000-1000-8000000805f9b34fb")); // Lower case EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("00001101-0000-1000-8000-00805F9B34FB")); + CanonicalUuid("00001101-0000-1000-8000-00805F9B34FB")); // Short to full EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("1101")); + CanonicalUuid("1101")); EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("0x1101")); + CanonicalUuid("0x1101")); EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("00001101")); + CanonicalUuid("00001101")); EXPECT_EQ("00001101-0000-1000-8000-00805f9b34fb", - bluetooth_utils::CanonicalUuid("0x00001101")); + CanonicalUuid("0x00001101")); // No 0x prefix on 36 character - EXPECT_EQ("", - bluetooth_utils::CanonicalUuid("0x00001101-0000-1000-8000-00805f9b34fb")); + EXPECT_EQ("", CanonicalUuid("0x00001101-0000-1000-8000-00805f9b34fb")); } +TEST(BluetoothUtilsTest, UUID) { + const char kValid128Bit0[] = "12345678-1234-5678-9abc-def123456789"; + const char kValid128Bit1[] = "00001101-0000-1000-8000-00805f9b34fb"; + const char kInvalid36Char[] = "1234567-1234-5678-9abc-def123456789"; + const char kInvalid4Char[] = "Z101"; + const char kValid16Bit[] = "0x1101"; + const char kValid32Bit[] = "00001101"; + + // Valid 128-bit custom UUID. + UUID uuid0(kValid128Bit0); + EXPECT_TRUE(uuid0.IsValid()); + EXPECT_EQ(UUID::kFormat128Bit, uuid0.format()); + EXPECT_EQ(uuid0.value(), uuid0.canonical_value()); + + // Valid 128-bit UUID. + UUID uuid1(kValid128Bit1); + EXPECT_TRUE(uuid1.IsValid()); + EXPECT_EQ(UUID::kFormat128Bit, uuid1.format()); + EXPECT_EQ(uuid1.value(), uuid1.canonical_value()); + + EXPECT_NE(uuid0, uuid1); + + // Invalid 128-bit UUID. + UUID uuid2(kInvalid36Char); + EXPECT_FALSE(uuid2.IsValid()); + EXPECT_EQ(UUID::kFormatInvalid, uuid2.format()); + EXPECT_TRUE(uuid2.value().empty()); + EXPECT_TRUE(uuid2.canonical_value().empty()); + + // Invalid 16-bit UUID. + UUID uuid3(kInvalid4Char); + EXPECT_FALSE(uuid3.IsValid()); + EXPECT_EQ(UUID::kFormatInvalid, uuid3.format()); + EXPECT_TRUE(uuid3.value().empty()); + EXPECT_TRUE(uuid3.canonical_value().empty()); + + // Valid 16-bit UUID. + UUID uuid4(kValid16Bit); + EXPECT_TRUE(uuid4.IsValid()); + EXPECT_EQ(UUID::kFormat16Bit, uuid4.format()); + EXPECT_NE(uuid4.value(), uuid4.canonical_value()); + EXPECT_EQ("1101", uuid4.value()); + EXPECT_EQ(kValid128Bit1, uuid4.canonical_value()); + + // Valid 32-bit UUID. + UUID uuid5(kValid32Bit); + EXPECT_TRUE(uuid5.IsValid()); + EXPECT_EQ(UUID::kFormat32Bit, uuid5.format()); + EXPECT_NE(uuid5.value(), uuid5.canonical_value()); + EXPECT_EQ("00001101", uuid5.value()); + EXPECT_EQ(kValid128Bit1, uuid5.canonical_value()); + + // uuid4, uuid5, and uuid1 are equivalent. + EXPECT_EQ(uuid4, uuid5); + EXPECT_EQ(uuid1, uuid4); + EXPECT_EQ(uuid1, uuid5); +} + +} // namespace bluetooth_utils } // namespace device |