xref: /aosp_15_r20/external/perfetto/src/base/status.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/status.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
20*6dbdd20aSAndroid Build Coastguard Worker #include <cstdarg>
21*6dbdd20aSAndroid Build Coastguard Worker #include <cstdio>
22*6dbdd20aSAndroid Build Coastguard Worker #include <string>
23*6dbdd20aSAndroid Build Coastguard Worker #include <utility>
24*6dbdd20aSAndroid Build Coastguard Worker 
25*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto::base {
26*6dbdd20aSAndroid Build Coastguard Worker 
ErrStatus(const char * format,...)27*6dbdd20aSAndroid Build Coastguard Worker Status ErrStatus(const char* format, ...) {
28*6dbdd20aSAndroid Build Coastguard Worker   std::string buf;
29*6dbdd20aSAndroid Build Coastguard Worker   buf.resize(1024);
30*6dbdd20aSAndroid Build Coastguard Worker   for (;;) {
31*6dbdd20aSAndroid Build Coastguard Worker     va_list ap;
32*6dbdd20aSAndroid Build Coastguard Worker     va_start(ap, format);
33*6dbdd20aSAndroid Build Coastguard Worker     int N = vsnprintf(buf.data(), buf.size() - 1, format, ap);
34*6dbdd20aSAndroid Build Coastguard Worker     va_end(ap);
35*6dbdd20aSAndroid Build Coastguard Worker 
36*6dbdd20aSAndroid Build Coastguard Worker     if (N <= 0) {
37*6dbdd20aSAndroid Build Coastguard Worker       buf = "[printf format error]";
38*6dbdd20aSAndroid Build Coastguard Worker       break;
39*6dbdd20aSAndroid Build Coastguard Worker     }
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker     auto sN = static_cast<size_t>(N);
42*6dbdd20aSAndroid Build Coastguard Worker     if (sN > buf.size() - 1) {
43*6dbdd20aSAndroid Build Coastguard Worker       // Indicates that the string was truncated and sN is the "number of
44*6dbdd20aSAndroid Build Coastguard Worker       // non-null bytes which would be needed to fit the result". This is the
45*6dbdd20aSAndroid Build Coastguard Worker       // C99 standard behaviour in the case of truncation. In that case, resize
46*6dbdd20aSAndroid Build Coastguard Worker       // the buffer to match the returned value (with + 1 for the null
47*6dbdd20aSAndroid Build Coastguard Worker       // terminator) and try again.
48*6dbdd20aSAndroid Build Coastguard Worker       buf.resize(sN + 1);
49*6dbdd20aSAndroid Build Coastguard Worker       continue;
50*6dbdd20aSAndroid Build Coastguard Worker     }
51*6dbdd20aSAndroid Build Coastguard Worker     if (sN == buf.size() - 1) {
52*6dbdd20aSAndroid Build Coastguard Worker       // Indicates that the string was likely truncated and sN is just the
53*6dbdd20aSAndroid Build Coastguard Worker       // number of bytes written into the string. This is the behaviour of
54*6dbdd20aSAndroid Build Coastguard Worker       // non-standard compilers (MSVC) etc. In that case, just double the
55*6dbdd20aSAndroid Build Coastguard Worker       // storage and try again.
56*6dbdd20aSAndroid Build Coastguard Worker       buf.resize(sN * 2);
57*6dbdd20aSAndroid Build Coastguard Worker       continue;
58*6dbdd20aSAndroid Build Coastguard Worker     }
59*6dbdd20aSAndroid Build Coastguard Worker 
60*6dbdd20aSAndroid Build Coastguard Worker     // Otherwise, indicates the string was written successfully: we need to
61*6dbdd20aSAndroid Build Coastguard Worker     // resize to match the number of non-null bytes and return.
62*6dbdd20aSAndroid Build Coastguard Worker     buf.resize(sN);
63*6dbdd20aSAndroid Build Coastguard Worker     break;
64*6dbdd20aSAndroid Build Coastguard Worker   }
65*6dbdd20aSAndroid Build Coastguard Worker   return Status(std::move(buf));
66*6dbdd20aSAndroid Build Coastguard Worker }
67*6dbdd20aSAndroid Build Coastguard Worker 
GetPayload(std::string_view type_url) const68*6dbdd20aSAndroid Build Coastguard Worker std::optional<std::string_view> Status::GetPayload(
69*6dbdd20aSAndroid Build Coastguard Worker     std::string_view type_url) const {
70*6dbdd20aSAndroid Build Coastguard Worker   if (ok()) {
71*6dbdd20aSAndroid Build Coastguard Worker     return std::nullopt;
72*6dbdd20aSAndroid Build Coastguard Worker   }
73*6dbdd20aSAndroid Build Coastguard Worker   for (const auto& kv : payloads_) {
74*6dbdd20aSAndroid Build Coastguard Worker     if (kv.type_url == type_url) {
75*6dbdd20aSAndroid Build Coastguard Worker       return kv.payload;
76*6dbdd20aSAndroid Build Coastguard Worker     }
77*6dbdd20aSAndroid Build Coastguard Worker   }
78*6dbdd20aSAndroid Build Coastguard Worker   return std::nullopt;
79*6dbdd20aSAndroid Build Coastguard Worker }
80*6dbdd20aSAndroid Build Coastguard Worker 
SetPayload(std::string_view type_url,std::string value)81*6dbdd20aSAndroid Build Coastguard Worker void Status::SetPayload(std::string_view type_url, std::string value) {
82*6dbdd20aSAndroid Build Coastguard Worker   if (ok()) {
83*6dbdd20aSAndroid Build Coastguard Worker     return;
84*6dbdd20aSAndroid Build Coastguard Worker   }
85*6dbdd20aSAndroid Build Coastguard Worker   for (auto& kv : payloads_) {
86*6dbdd20aSAndroid Build Coastguard Worker     if (kv.type_url == type_url) {
87*6dbdd20aSAndroid Build Coastguard Worker       kv.payload = value;
88*6dbdd20aSAndroid Build Coastguard Worker       return;
89*6dbdd20aSAndroid Build Coastguard Worker     }
90*6dbdd20aSAndroid Build Coastguard Worker   }
91*6dbdd20aSAndroid Build Coastguard Worker   payloads_.push_back(Payload{std::string(type_url), std::move(value)});
92*6dbdd20aSAndroid Build Coastguard Worker }
93*6dbdd20aSAndroid Build Coastguard Worker 
ErasePayload(std::string_view type_url)94*6dbdd20aSAndroid Build Coastguard Worker bool Status::ErasePayload(std::string_view type_url) {
95*6dbdd20aSAndroid Build Coastguard Worker   if (ok()) {
96*6dbdd20aSAndroid Build Coastguard Worker     return false;
97*6dbdd20aSAndroid Build Coastguard Worker   }
98*6dbdd20aSAndroid Build Coastguard Worker   auto it = std::remove_if(
99*6dbdd20aSAndroid Build Coastguard Worker       payloads_.begin(), payloads_.end(),
100*6dbdd20aSAndroid Build Coastguard Worker       [type_url](const Payload& p) { return p.type_url == type_url; });
101*6dbdd20aSAndroid Build Coastguard Worker   bool erased = it != payloads_.end();
102*6dbdd20aSAndroid Build Coastguard Worker   payloads_.erase(it, payloads_.end());
103*6dbdd20aSAndroid Build Coastguard Worker   return erased;
104*6dbdd20aSAndroid Build Coastguard Worker }
105*6dbdd20aSAndroid Build Coastguard Worker 
106*6dbdd20aSAndroid Build Coastguard Worker }  // namespace perfetto::base
107