BaseAndGeckoProfilerDetail.cpp (2933B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/BaseAndGeckoProfilerDetail.h" 8 9 #include <limits> 10 #include <string_view> 11 12 namespace mozilla::profiler::detail { 13 14 constexpr std::string_view scPidPrefix = "pid:"; 15 16 // Convert a C string to a BaseProfilerProcessId. Return unspecified 17 // BaseProfilerProcessId if the string is not exactly a valid pid. 18 static baseprofiler::BaseProfilerProcessId StringToPid(const char* aString) { 19 if (!aString || aString[0] == '\0') { 20 // Null or empty. 21 return baseprofiler::BaseProfilerProcessId{}; 22 } 23 24 if (aString[0] == '0') { 25 if (aString[1] != '\0') { 26 // Don't accept leading zeroes. 27 return baseprofiler::BaseProfilerProcessId{}; 28 } 29 return baseprofiler::BaseProfilerProcessId::FromNumber(0); 30 } 31 32 using PidNumber = baseprofiler::BaseProfilerProcessId::NumberType; 33 PidNumber pid = 0; 34 for (;;) { 35 const char c = *aString; 36 if (c == '\0') { 37 break; 38 } 39 if (c < '0' || c > '9') { 40 // Only accept decimal digits. 41 return baseprofiler::BaseProfilerProcessId{}; 42 } 43 static_assert(!std::numeric_limits<PidNumber>::is_signed, 44 "The following relies on unsigned arithmetic"); 45 PidNumber newPid = pid * 10u + PidNumber(c - '0'); 46 if (newPid < pid) { 47 // Unsigned overflow. 48 return baseprofiler::BaseProfilerProcessId{}; 49 } 50 pid = newPid; 51 ++aString; 52 } 53 return baseprofiler::BaseProfilerProcessId::FromNumber(pid); 54 } 55 56 [[nodiscard]] MFBT_API bool FilterHasPid( 57 const char* aFilter, baseprofiler::BaseProfilerProcessId aPid) { 58 if (strncmp(aFilter, scPidPrefix.data(), scPidPrefix.length()) != 0) { 59 // The filter is not starting with "pid:". 60 return false; 61 } 62 63 return StringToPid(aFilter + scPidPrefix.length()) == aPid; 64 } 65 66 [[nodiscard]] MFBT_API bool FiltersExcludePid( 67 Span<const char* const> aFilters, 68 baseprofiler::BaseProfilerProcessId aPid) { 69 if (aFilters.empty()) { 70 return false; 71 } 72 73 // First, check if the list only contains "pid:..." strings. 74 for (const char* const filter : aFilters) { 75 if (strncmp(filter, scPidPrefix.data(), scPidPrefix.length()) != 0) { 76 // At least one filter is *not* a "pid:...", our pid is not excluded. 77 return false; 78 } 79 } 80 81 // Here, all filters start with "pid:". Check if the given pid is included. 82 for (const char* const filter : aFilters) { 83 if (StringToPid(filter + scPidPrefix.length()) == aPid) { 84 // Our pid is present, so it's not excluded. 85 return false; 86 } 87 } 88 // Our pid was not in a list of only pids, so it's excluded. 89 return true; 90 } 91 92 } // namespace mozilla::profiler::detail