xref: /aosp_15_r20/external/perfetto/src/base/status.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2020 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 "perfetto/base/status.h"
18 
19 #include <algorithm>
20 #include <cstdarg>
21 #include <cstdio>
22 #include <string>
23 #include <utility>
24 
25 namespace perfetto::base {
26 
ErrStatus(const char * format,...)27 Status ErrStatus(const char* format, ...) {
28   std::string buf;
29   buf.resize(1024);
30   for (;;) {
31     va_list ap;
32     va_start(ap, format);
33     int N = vsnprintf(buf.data(), buf.size() - 1, format, ap);
34     va_end(ap);
35 
36     if (N <= 0) {
37       buf = "[printf format error]";
38       break;
39     }
40 
41     auto sN = static_cast<size_t>(N);
42     if (sN > buf.size() - 1) {
43       // Indicates that the string was truncated and sN is the "number of
44       // non-null bytes which would be needed to fit the result". This is the
45       // C99 standard behaviour in the case of truncation. In that case, resize
46       // the buffer to match the returned value (with + 1 for the null
47       // terminator) and try again.
48       buf.resize(sN + 1);
49       continue;
50     }
51     if (sN == buf.size() - 1) {
52       // Indicates that the string was likely truncated and sN is just the
53       // number of bytes written into the string. This is the behaviour of
54       // non-standard compilers (MSVC) etc. In that case, just double the
55       // storage and try again.
56       buf.resize(sN * 2);
57       continue;
58     }
59 
60     // Otherwise, indicates the string was written successfully: we need to
61     // resize to match the number of non-null bytes and return.
62     buf.resize(sN);
63     break;
64   }
65   return Status(std::move(buf));
66 }
67 
GetPayload(std::string_view type_url) const68 std::optional<std::string_view> Status::GetPayload(
69     std::string_view type_url) const {
70   if (ok()) {
71     return std::nullopt;
72   }
73   for (const auto& kv : payloads_) {
74     if (kv.type_url == type_url) {
75       return kv.payload;
76     }
77   }
78   return std::nullopt;
79 }
80 
SetPayload(std::string_view type_url,std::string value)81 void Status::SetPayload(std::string_view type_url, std::string value) {
82   if (ok()) {
83     return;
84   }
85   for (auto& kv : payloads_) {
86     if (kv.type_url == type_url) {
87       kv.payload = value;
88       return;
89     }
90   }
91   payloads_.push_back(Payload{std::string(type_url), std::move(value)});
92 }
93 
ErasePayload(std::string_view type_url)94 bool Status::ErasePayload(std::string_view type_url) {
95   if (ok()) {
96     return false;
97   }
98   auto it = std::remove_if(
99       payloads_.begin(), payloads_.end(),
100       [type_url](const Payload& p) { return p.type_url == type_url; });
101   bool erased = it != payloads_.end();
102   payloads_.erase(it, payloads_.end());
103   return erased;
104 }
105 
106 }  // namespace perfetto::base
107