summaryrefslogtreecommitdiffstats
path: root/mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp')
-rw-r--r--mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp b/mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp
new file mode 100644
index 0000000000..213f25cf16
--- /dev/null
+++ b/mozglue/baseprofiler/core/BaseAndGeckoProfilerDetail.cpp
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/BaseAndGeckoProfilerDetail.h"
+
+#include <limits>
+#include <string_view>
+
+namespace mozilla::profiler::detail {
+
+constexpr std::string_view scPidPrefix = "pid:";
+
+// Convert a C string to a BaseProfilerProcessId. Return unspecified
+// BaseProfilerProcessId if the string is not exactly a valid pid.
+static baseprofiler::BaseProfilerProcessId StringToPid(const char* aString) {
+ if (!aString || aString[0] == '\0') {
+ // Null or empty.
+ return baseprofiler::BaseProfilerProcessId{};
+ }
+
+ if (aString[0] == '0') {
+ if (aString[1] != '\0') {
+ // Don't accept leading zeroes.
+ return baseprofiler::BaseProfilerProcessId{};
+ }
+ return baseprofiler::BaseProfilerProcessId::FromNumber(0);
+ }
+
+ using PidNumber = baseprofiler::BaseProfilerProcessId::NumberType;
+ PidNumber pid = 0;
+ for (;;) {
+ const char c = *aString;
+ if (c == '\0') {
+ break;
+ }
+ if (c < '0' || c > '9') {
+ // Only accept decimal digits.
+ return baseprofiler::BaseProfilerProcessId{};
+ }
+ static_assert(!std::numeric_limits<PidNumber>::is_signed,
+ "The following relies on unsigned arithmetic");
+ PidNumber newPid = pid * 10u + PidNumber(c - '0');
+ if (newPid < pid) {
+ // Unsigned overflow.
+ return baseprofiler::BaseProfilerProcessId{};
+ }
+ pid = newPid;
+ ++aString;
+ }
+ return baseprofiler::BaseProfilerProcessId::FromNumber(pid);
+}
+
+[[nodiscard]] MFBT_API bool FilterHasPid(
+ const char* aFilter, baseprofiler::BaseProfilerProcessId aPid) {
+ if (strncmp(aFilter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
+ // The filter is not starting with "pid:".
+ return false;
+ }
+
+ return StringToPid(aFilter + scPidPrefix.length()) == aPid;
+}
+
+[[nodiscard]] MFBT_API bool FiltersExcludePid(
+ Span<const char* const> aFilters,
+ baseprofiler::BaseProfilerProcessId aPid) {
+ if (aFilters.empty()) {
+ return false;
+ }
+
+ // First, check if the list only contains "pid:..." strings.
+ for (const char* const filter : aFilters) {
+ if (strncmp(filter, scPidPrefix.data(), scPidPrefix.length()) != 0) {
+ // At least one filter is *not* a "pid:...", our pid is not excluded.
+ return false;
+ }
+ }
+
+ // Here, all filters start with "pid:". Check if the given pid is included.
+ for (const char* const filter : aFilters) {
+ if (StringToPid(filter + scPidPrefix.length()) == aPid) {
+ // Our pid is present, so it's not excluded.
+ return false;
+ }
+ }
+ // Our pid was not in a list of only pids, so it's excluded.
+ return true;
+}
+
+} // namespace mozilla::profiler::detail