| 30 | } |
| 31 | |
| 32 | int Status::set_errorv(int c, const char* fmt, va_list args) { |
| 33 | if (0 == c) { |
| 34 | free(_state); |
| 35 | _state = NULL; |
| 36 | return 0; |
| 37 | } |
| 38 | State* new_state = NULL; |
| 39 | State* state = NULL; |
| 40 | if (_state != NULL) { |
| 41 | state = _state; |
| 42 | } else { |
| 43 | const size_t guess_size = std::max(strlen(fmt) * 2, 32UL); |
| 44 | const size_t st_size = status_size(guess_size); |
| 45 | new_state = reinterpret_cast<State*>(malloc(st_size)); |
| 46 | if (NULL == new_state) { |
| 47 | return -1; |
| 48 | } |
| 49 | new_state->state_size = st_size; |
| 50 | state = new_state; |
| 51 | } |
| 52 | const size_t cap = state->state_size - offsetof(State, message); |
| 53 | va_list copied_args; |
| 54 | va_copy(copied_args, args); |
| 55 | const int bytes_used = vsnprintf(state->message, cap, fmt, copied_args); |
| 56 | va_end(copied_args); |
| 57 | if (bytes_used < 0) { |
| 58 | free(new_state); |
| 59 | return -1; |
| 60 | } else if ((size_t)bytes_used < cap) { |
| 61 | // There was enough room, just shrink and return. |
| 62 | state->code = c; |
| 63 | state->size = bytes_used; |
| 64 | if (new_state == state) { |
| 65 | _state = new_state; |
| 66 | } |
| 67 | return 0; |
| 68 | } else { |
| 69 | free(new_state); |
| 70 | const size_t st_size = status_size(bytes_used); |
| 71 | new_state = reinterpret_cast<State*>(malloc(st_size)); |
| 72 | if (NULL == new_state) { |
| 73 | return -1; |
| 74 | } |
| 75 | new_state->code = c; |
| 76 | new_state->size = bytes_used; |
| 77 | new_state->state_size = st_size; |
| 78 | const int bytes_used2 = |
| 79 | vsnprintf(new_state->message, bytes_used + 1, fmt, args); |
| 80 | if (bytes_used2 != bytes_used) { |
| 81 | free(new_state); |
| 82 | return -1; |
| 83 | } |
| 84 | free(_state); |
| 85 | _state = new_state; |
| 86 | return 0; |
| 87 | } |
| 88 | } |
| 89 |
nothing calls this directly
no test coverage detected