xref: /aosp_15_r20/external/perfetto/src/trace_processor/util/build_id.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/util/build_id.h"
18 
19 #include <cctype>
20 #include <cstddef>
21 #include <string>
22 
23 #include "perfetto/base/logging.h"
24 #include "perfetto/ext/base/string_utils.h"
25 #include "perfetto/ext/base/string_view.h"
26 
27 namespace perfetto {
28 namespace trace_processor {
29 namespace {
HexToBinary(char c)30 uint8_t HexToBinary(char c) {
31   switch (c) {
32     case '0':
33       return 0;
34     case '1':
35       return 1;
36     case '2':
37       return 2;
38     case '3':
39       return 3;
40     case '4':
41       return 4;
42     case '5':
43       return 5;
44     case '6':
45       return 6;
46     case '7':
47       return 7;
48     case '8':
49       return 8;
50     case '9':
51       return 9;
52     case 'a':
53     case 'A':
54       return 10;
55     case 'b':
56     case 'B':
57       return 11;
58     case 'c':
59     case 'C':
60       return 12;
61     case 'd':
62     case 'D':
63       return 13;
64     case 'e':
65     case 'E':
66       return 14;
67     case 'f':
68     case 'F':
69       return 15;
70     default:
71       PERFETTO_CHECK(false);
72   }
73 }
74 
HexToBinary(base::StringView hex)75 std::string HexToBinary(base::StringView hex) {
76   std::string res;
77   res.reserve((hex.size() + 1) / 2);
78   auto it = hex.begin();
79 
80   if (hex.size() % 2 != 0) {
81     res.push_back(static_cast<char>(HexToBinary(*it)));
82     ++it;
83   }
84 
85   while (it != hex.end()) {
86     if (*it == '-') {
87       ++it;
88       continue;
89     }
90     int v = (HexToBinary(*it++) << 4);
91     v += HexToBinary(*it++);
92     res.push_back(static_cast<char>(v));
93   }
94   return res;
95 }
96 
97 // Returns whether this string is of a hex chrome module or not to decide
98 // whether to convert the module to/from hex.
99 // TODO(b/148109467): Remove workaround once all active Chrome versions
100 // write raw bytes instead of a string as build_id.
IsHexModuleId(base::StringView module)101 bool IsHexModuleId(base::StringView module) {
102   return module.size() == 33;
103 }
104 
105 }  // namespace
106 
107 // static
FromHex(base::StringView data)108 BuildId BuildId::FromHex(base::StringView data) {
109   if (IsHexModuleId(data)) {
110     return BuildId(data.ToStdString());
111   }
112   return BuildId(HexToBinary(data));
113 }
114 
ToHex() const115 std::string BuildId::ToHex() const {
116   if (IsHexModuleId(base::StringView(raw_))) {
117     return raw_;
118   }
119   return base::ToHex(raw_.data(), raw_.size());
120 }
121 
122 }  // namespace trace_processor
123 }  // namespace perfetto
124