Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ Increment the:

## [Unreleased]

* [API/SDK] Add ASCII helpers and remove regex from InstrumentMetaDataValidator
[#4715](https://github.com/open-telemetry/opentelemetry-cpp/pull/4715)

* [SDK] Release provider mutexes before construction-failure diagnostics so
custom log handlers can retrieve cached or noop tracers, loggers, and meters
from the same provider without deadlocking.
Expand Down
30 changes: 8 additions & 22 deletions api/include/opentelemetry/baggage/baggage.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

#pragma once

#include <cctype>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/common/kv_properties.h"
#include "opentelemetry/common/macros.h"
#include "opentelemetry/nostd/shared_ptr.h"
Expand Down Expand Up @@ -215,16 +214,11 @@ class OPENTELEMETRY_EXPORT Baggage
// Implementation inspired from : https://golang.org/src/net/url/url.go?s=7851:7884#L264
static std::string UrlEncode(nostd::string_view str)
{
auto to_hex = [](char c) -> char {
static const char *hex = "0123456789ABCDEF";
return hex[c & 15];
};

std::string ret;

for (auto c : str)
{
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
if (common::detail::IsAsciiAlnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
{
ret.push_back(c);
}
Expand All @@ -235,8 +229,8 @@ class OPENTELEMETRY_EXPORT Baggage
else
{
ret.push_back('%');
ret.push_back(to_hex(static_cast<char>(c >> 4)));
ret.push_back(to_hex(static_cast<char>(c & 15)));
ret.push_back(common::detail::UpperHexDigit(static_cast<unsigned char>(c) >> 4));
ret.push_back(common::detail::UpperHexDigit(c));
}
}

Expand All @@ -246,29 +240,21 @@ class OPENTELEMETRY_EXPORT Baggage
// Uri decode key value pairs after extracting from header
static std::string UrlDecode(nostd::string_view str, bool &err)
{
auto IsHex = [](char c) {
return std::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
};

auto from_hex = [](char c) -> char {
// c - '0' produces integer type which could trigger error/warning when casting to char,
// but the cast is safe here.
return static_cast<char>(std::isdigit(c) ? c - '0' : std::toupper(c) - 'A' + 10);
};

std::string ret;
ret.reserve(str.size());

for (size_t i = 0; i < str.size(); i++)
{
if (str[i] == '%')
{
if (i + 2 >= str.size() || !IsHex(str[i + 1]) || !IsHex(str[i + 2]))
if (i + 2 >= str.size() || !common::detail::IsAsciiHexDigit(str[i + 1]) ||
!common::detail::IsAsciiHexDigit(str[i + 2]))
{
err = true;
return "";
}
ret.push_back(static_cast<char>(from_hex(str[i + 1]) << 4 | from_hex(str[i + 2])));
ret.push_back(static_cast<char>(common::detail::HexDigitValue(str[i + 1]) << 4 |
common::detail::HexDigitValue(str[i + 2])));
i += 2;
}
else if (str[i] == '+')
Expand Down
106 changes: 106 additions & 0 deletions api/include/opentelemetry/common/detail/ascii.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <cstdint>

#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace common
{
namespace detail
{

// Character classes for protocol and specification text, which define them over
// ASCII. The <cctype> functions depend on the global locale, and passing them a
// negative char is undefined behavior.

constexpr bool IsAsciiDigit(char c) noexcept
{
return c >= '0' && c <= '9';
}

constexpr bool IsAsciiLower(char c) noexcept
{
return c >= 'a' && c <= 'z';
}

constexpr bool IsAsciiUpper(char c) noexcept
{
return c >= 'A' && c <= 'Z';
}

constexpr bool IsAsciiAlpha(char c) noexcept
{
return IsAsciiLower(c) || IsAsciiUpper(c);
}

constexpr bool IsAsciiAlnum(char c) noexcept
{
return IsAsciiAlpha(c) || IsAsciiDigit(c);
}

// Indexed by byte value: hexadecimal digits are decoded on the propagation hot
// path, where a lookup is faster than range comparisons.
constexpr int8_t kHexDigitValues[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};

// Returns the value of a hexadecimal digit of either case, or -1 if c is not one.
constexpr int HexDigitValue(char c) noexcept
{
return kHexDigitValues[static_cast<unsigned char>(c)];
}

constexpr bool IsAsciiHexDigit(char c) noexcept
{
return HexDigitValue(c) >= 0;
}

// Returns the hexadecimal digit for the low four bits of value.
constexpr char LowerHexDigit(int value) noexcept
{
return "0123456789abcdef"[value & 0xF];
}

constexpr char UpperHexDigit(int value) noexcept
{
return "0123456789ABCDEF"[value & 0xF];
}

// 0x00 to 0x1F and 0x7F: what std::iscntrl accepts in the "C" locale.
constexpr bool IsAsciiControl(char c) noexcept
{
return static_cast<unsigned char>(c) < 0x20 || c == '\x7f';
}

// Space, \t, \n, \v, \f and \r: what std::isspace accepts in the "C" locale.
constexpr bool IsAsciiSpace(char c) noexcept
{
return c == ' ' || (c >= '\t' && c <= '\r');
}

constexpr char ToAsciiLower(char c) noexcept
{
return IsAsciiUpper(c) ? static_cast<char>(c - 'A' + 'a') : c;
}

constexpr char ToAsciiUpper(char c) noexcept
{
return IsAsciiLower(c) ? static_cast<char>(c - 'a' + 'A') : c;
}

} // namespace detail
} // namespace common
OPENTELEMETRY_END_NAMESPACE
7 changes: 3 additions & 4 deletions api/include/opentelemetry/common/string_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@

#pragma once

#include <cctype>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/common/macros.h"

#if OPENTELEMETRY_HAVE_EXCEPTIONS
Expand All @@ -29,11 +28,11 @@ class StringUtil
{
return nostd::string_view();
}
while (left <= right && std::isspace(str[left]))
while (left <= right && detail::IsAsciiSpace(str[left]))
{
left++;
}
while (left <= right && std::isspace(str[right]))
while (left <= right && detail::IsAsciiSpace(str[right]))
{
right--;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>
#include <string>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/context/propagation/text_map_propagator.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"
Expand Down Expand Up @@ -135,17 +136,13 @@ class EnvironmentCarrier : public TextMapCarrier
std::string result(key);
for (auto &c : result)
{
unsigned char uc = static_cast<unsigned char>(c);
if (uc >= 'a' && uc <= 'z')
{
c = static_cast<char>(uc - ('a' - 'A'));
}
else if (!((uc >= 'A' && uc <= 'Z') || (uc >= '0' && uc <= '9') || uc == '_'))
c = common::detail::ToAsciiUpper(c);
if (!common::detail::IsAsciiUpper(c) && !common::detail::IsAsciiDigit(c) && c != '_')
{
c = '_';
}
}
if (result[0] >= '0' && result[0] <= '9')
if (common::detail::IsAsciiDigit(result[0]))
{
result.insert(result.begin(), '_');
}
Expand Down
27 changes: 5 additions & 22 deletions api/include/opentelemetry/trace/propagation/detail/hex.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <cstdint>
#include <cstring>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/version.h"

Expand All @@ -20,28 +21,9 @@ namespace propagation
namespace detail
{

constexpr int8_t kHexDigits[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

inline int8_t HexToInt(char c)
{
return kHexDigits[static_cast<uint8_t>(c)];
}

inline bool IsValidHex(nostd::string_view s)
{
return std::all_of(s.begin(), s.end(), [](char c) { return HexToInt(c) != -1; });
return std::all_of(s.begin(), s.end(), [](char c) { return common::detail::IsAsciiHexDigit(c); });
}

/**
Expand All @@ -66,12 +48,13 @@ inline bool HexToBinary(nostd::string_view hex, uint8_t *buffer, size_t buffer_s

if (is_hex_size_odd)
{
buffer[buffer_pos++] = HexToInt(hex[i++]);
buffer[buffer_pos++] = static_cast<uint8_t>(common::detail::HexDigitValue(hex[i++]));
}

for (; i < last_hex_pos; i += 2)
{
buffer[buffer_pos++] = (HexToInt(hex[i]) << 4) | HexToInt(hex[i + 1]);
buffer[buffer_pos++] = static_cast<uint8_t>((common::detail::HexDigitValue(hex[i]) << 4) |
common::detail::HexDigitValue(hex[i + 1]));
}

return true;
Expand Down
6 changes: 3 additions & 3 deletions api/include/opentelemetry/trace/span_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstdint>
#include <cstring>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/version.h"

Expand All @@ -31,11 +32,10 @@ class SpanId final
// Populates the buffer with the lowercase base16 representation of the ID.
void ToLowerBase16(nostd::span<char, 2 * kSize> buffer) const noexcept
{
constexpr char kHex[] = "0123456789abcdef";
for (size_t i = 0; i < kSize; ++i)
{
buffer[i * 2 + 0] = kHex[(rep_[i] >> 4) & 0xF];
buffer[i * 2 + 1] = kHex[(rep_[i] >> 0) & 0xF];
buffer[i * 2 + 0] = common::detail::LowerHexDigit(rep_[i] >> 4);
buffer[i * 2 + 1] = common::detail::LowerHexDigit(rep_[i]);
}
}

Expand Down
6 changes: 3 additions & 3 deletions api/include/opentelemetry/trace/trace_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <cstdint>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/version.h"

Expand Down Expand Up @@ -44,9 +45,8 @@ class TraceFlags final
// Populates the buffer with the lowercase base16 representation of the flags.
void ToLowerBase16(nostd::span<char, 2> buffer) const noexcept
{
constexpr char kHex[] = "0123456789ABCDEF";
buffer[0] = kHex[(rep_ >> 4) & 0xF];
buffer[1] = kHex[(rep_ >> 0) & 0xF];
buffer[0] = common::detail::UpperHexDigit(rep_ >> 4);
buffer[1] = common::detail::UpperHexDigit(rep_);
}

uint8_t flags() const noexcept { return rep_; }
Expand Down
6 changes: 3 additions & 3 deletions api/include/opentelemetry/trace/trace_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstdint>
#include <cstring>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/nostd/span.h"
#include "opentelemetry/version.h"

Expand Down Expand Up @@ -34,11 +35,10 @@ class TraceId final
// Populates the buffer with the lowercase base16 representation of the ID.
void ToLowerBase16(nostd::span<char, 2 * kSize> buffer) const noexcept
{
constexpr char kHex[] = "0123456789abcdef";
for (size_t i = 0; i < kSize; ++i)
{
buffer[i * 2 + 0] = kHex[(rep_[i] >> 4) & 0xF];
buffer[i * 2 + 1] = kHex[(rep_[i] >> 0) & 0xF];
buffer[i * 2 + 0] = common::detail::LowerHexDigit(rep_[i] >> 4);
buffer[i * 2 + 1] = common::detail::LowerHexDigit(rep_[i]);
}
}

Expand Down
4 changes: 2 additions & 2 deletions api/include/opentelemetry/trace/trace_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

#pragma once

#include <cctype>
#include <cstddef>
#include <string>
#include <vector>

#include "opentelemetry/common/detail/ascii.h"
#include "opentelemetry/common/kv_properties.h"
#include "opentelemetry/nostd/function_ref.h"
#include "opentelemetry/nostd/shared_ptr.h"
Expand Down Expand Up @@ -298,7 +298,7 @@ class OPENTELEMETRY_EXPORT TraceState

static bool IsLowerCaseAlphaOrDigit(char c) noexcept
{
return std::isdigit(c) || std::islower(c);
return common::detail::IsAsciiDigit(c) || common::detail::IsAsciiLower(c);
}

private:
Expand Down
Loading
Loading