Coverage Report

Created: 2025-12-02 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/butil/status.cpp
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
// Date: Mon Feb  9 15:04:03 CST 2015
19
20
#include <stdio.h>
21
#include "butil/status.h"
22
23
namespace butil {
24
25
0
inline size_t status_size(size_t message_size) {
26
    // Add 1 because even if the sum of size is aligned with int, we need to
27
    // put an ending '\0'
28
0
    return ((offsetof(Status::State, message) + message_size)
29
0
            / sizeof(int) + 1) * sizeof(int);
30
0
}
31
32
0
int Status::set_errorv(int c, const char* fmt, va_list args) {
33
0
    if (0 == c) {
34
0
        free(_state);
35
0
        _state = NULL;
36
0
        return 0;
37
0
    }
38
0
    State* new_state = NULL;
39
0
    State* state = NULL;
40
0
    if (_state != NULL) {
41
0
        state = _state;
42
0
    } else {
43
0
        const size_t guess_size = std::max(strlen(fmt) * 2, 32UL);
44
0
        const size_t st_size = status_size(guess_size);
45
0
        new_state = reinterpret_cast<State*>(malloc(st_size));
46
0
        if (NULL == new_state) {
47
0
            return -1;
48
0
        }
49
0
        new_state->state_size = st_size;
50
0
        state = new_state;
51
0
    }
52
0
    const size_t cap = state->state_size - offsetof(State, message);
53
0
    va_list copied_args;
54
0
    va_copy(copied_args, args);
55
0
    const int bytes_used = vsnprintf(state->message, cap, fmt, copied_args);
56
0
    va_end(copied_args);
57
0
    if (bytes_used < 0) {
58
0
        free(new_state);
59
0
        return -1;
60
0
    } else if ((size_t)bytes_used < cap) {
61
        // There was enough room, just shrink and return.
62
0
        state->code = c;
63
0
        state->size = bytes_used;
64
0
        if (new_state == state) {
65
0
            _state = new_state;
66
0
        }
67
0
        return 0;
68
0
    } else {
69
0
        free(new_state);
70
0
        const size_t st_size = status_size(bytes_used);
71
0
        new_state = reinterpret_cast<State*>(malloc(st_size));
72
0
        if (NULL == new_state) {
73
0
            return -1;
74
0
        }
75
0
        new_state->code = c;
76
0
        new_state->size = bytes_used;
77
0
        new_state->state_size = st_size;
78
0
        const int bytes_used2 =
79
0
            vsnprintf(new_state->message, bytes_used + 1, fmt, args);
80
0
        if (bytes_used2 != bytes_used) {
81
0
            free(new_state);
82
0
            return -1;
83
0
        }
84
0
        free(_state);
85
0
        _state = new_state;
86
0
        return 0;
87
0
    }
88
0
}
89
90
0
int Status::set_error(int c, const butil::StringPiece& error_msg) {
91
0
    if (0 == c) {
92
0
        free(_state);
93
0
        _state = NULL;
94
0
        return 0;
95
0
    }
96
0
    const size_t st_size = status_size(error_msg.size());
97
0
    if (_state == NULL || _state->state_size < st_size) {
98
0
        State* new_state = reinterpret_cast<State*>(malloc(st_size));
99
0
        if (NULL == new_state) {
100
0
            return -1;
101
0
        }
102
0
        new_state->state_size = st_size;
103
0
        free(_state);
104
0
        _state = new_state;
105
0
    }
106
0
    _state->code = c;
107
0
    _state->size = error_msg.size();
108
0
    memcpy(_state->message, error_msg.data(), error_msg.size());
109
0
    _state->message[error_msg.size()] = '\0';
110
0
    return 0;
111
0
}
112
113
0
Status::State* Status::copy_state(const State* s) {
114
0
    const size_t n = status_size(s->size);
115
0
    State* s2 = reinterpret_cast<State*>(malloc(n));
116
0
    if (NULL == s2) {
117
        // TODO: If we failed to allocate, the status will be OK.
118
0
        return NULL;
119
0
    }
120
0
    s2->code = s->code;
121
0
    s2->size = s->size;
122
0
    s2->state_size = n;
123
0
    char* msg_head = s2->message;
124
0
    memcpy(msg_head, s->message, s->size);
125
0
    msg_head[s->size] = '\0';
126
0
    return s2;
127
0
};
128
129
0
std::string Status::error_str() const {
130
0
    if (_state == NULL) {
131
0
        static std::string s_ok_str = "OK";
132
0
        return s_ok_str;
133
0
    }
134
0
    return std::string(_state->message, _state->size);
135
0
}
136
137
}  // namespace butil