• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tstack / lnav / 25603066199-3032

09 May 2026 02:05PM UTC coverage: 70.204% (+0.04%) from 70.162%
25603066199-3032

push

github

tstack
[tabular] multi-line support

238 of 261 new or added lines in 9 files covered. (91.19%)

10 existing lines in 3 files now uncovered.

57551 of 81977 relevant lines covered (70.2%)

634088.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.59
/src/shared_buffer.cc
1
/**
2
 * Copyright (c) 2014, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * @file shared_buffer.cc
30
 */
31

32
#include "config.h"
33

34
#ifdef HAVE_EXECINFO_H
35
// clang-format off
36
#    include <sys/types.h>
37
// clang-format on
38

39
#    include <execinfo.h>
40
#endif
41

42
#include <algorithm>
43

44
#include "base/ansi_scrubber.hh"
45
#include "shared_buffer.hh"
46

47
void
48
shared_buffer_ref::share(shared_buffer& sb, const char* data, size_t len)
155,671✔
49
{
50
#if SHARED_BUFFER_TRACE
51
    void* frames[128];
52
    int rc;
53

54
    rc = backtrace(frames, 128);
55
    this->sb_backtrace.reset(backtrace_symbols(frames, rc));
56
#endif
57

58
    this->disown();
155,671✔
59

60
    sb.add_ref(*this);
155,671✔
61
    this->sb_owner = &sb;
155,671✔
62
    this->sb_data = data;
155,671✔
63
    this->sb_length = len;
155,671✔
64

65
    ensure(this->sb_length < (10 * 1024 * 1024));
155,671✔
66
}
155,671✔
67

68
bool
69
shared_buffer_ref::subset(shared_buffer_ref& other, off_t offset, size_t len)
×
70
{
71
    this->disown();
×
72

73
    if (offset != -1) {
×
74
        this->sb_owner = other.sb_owner;
×
75
        this->sb_length = len;
×
76
        if (this->sb_owner == nullptr) {
×
77
            if ((this->sb_data = (char*) malloc(this->sb_length)) == nullptr) {
×
78
                return false;
×
79
            }
80

81
            memcpy(
×
82
                const_cast<char*>(this->sb_data), &other.sb_data[offset], len);
×
83
        } else {
84
            this->sb_owner->add_ref(*this);
×
85
            this->sb_data = &other.sb_data[offset];
×
86
        }
87
    }
88
    return true;
×
89
}
90

91
shared_buffer_ref::
750,998✔
92
shared_buffer_ref(shared_buffer_ref&& other) noexcept
750,998✔
93
{
94
    if (other.sb_data == nullptr) {
750,998✔
95
        this->sb_owner = nullptr;
×
96
        this->sb_data = nullptr;
×
97
        this->sb_length = 0;
×
98
    } else if (other.sb_owner != nullptr) {
750,998✔
99
        auto owner_ref_iter = std::find(other.sb_owner->sb_refs.rbegin(),
750,998✔
100
                                        other.sb_owner->sb_refs.rend(),
1,501,996✔
101
                                        &other);
1,501,996✔
102
        *owner_ref_iter = this;
750,998✔
103
        this->sb_owner = std::exchange(other.sb_owner, nullptr);
750,998✔
104
        this->sb_data = std::exchange(other.sb_data, nullptr);
750,998✔
105
        this->sb_length = std::exchange(other.sb_length, 0);
750,998✔
106
    } else {
UNCOV
107
        this->sb_owner = nullptr;
×
UNCOV
108
        this->sb_data = other.sb_data;
×
UNCOV
109
        this->sb_length = other.sb_length;
×
UNCOV
110
        other.sb_data = nullptr;
×
UNCOV
111
        other.sb_length = 0;
×
112
    }
113
    this->sb_metadata = other.sb_metadata;
750,998✔
114
    other.sb_metadata = {};
750,998✔
115
}
750,998✔
116

117
shared_buffer_ref&
118
shared_buffer_ref::operator=(shared_buffer_ref&& other) noexcept
40,362✔
119
{
120
    this->disown();
40,362✔
121

122
    if (other.sb_data == nullptr) {
40,362✔
123
        this->sb_owner = nullptr;
502✔
124
        this->sb_data = nullptr;
502✔
125
        this->sb_length = 0;
502✔
126
    } else if (other.sb_owner != nullptr) {
39,860✔
127
        auto owner_ref_iter = std::find(other.sb_owner->sb_refs.rbegin(),
39,860✔
128
                                        other.sb_owner->sb_refs.rend(),
79,720✔
129
                                        &other);
79,720✔
130
        *owner_ref_iter = this;
39,860✔
131
        this->sb_owner = std::exchange(other.sb_owner, nullptr);
39,860✔
132
        this->sb_data = std::exchange(other.sb_data, nullptr);
39,860✔
133
        this->sb_length = std::exchange(other.sb_length, 0);
39,860✔
134
    } else {
135
        this->sb_owner = nullptr;
×
136
        this->sb_data = other.sb_data;
×
137
        this->sb_length = other.sb_length;
×
138
        other.sb_data = nullptr;
×
139
        other.sb_length = 0;
×
140
    }
141
    this->sb_metadata = other.sb_metadata;
40,362✔
142
    other.sb_metadata = {};
40,362✔
143

144
    return *this;
40,362✔
145
}
146

147
bool
148
shared_buffer_ref::take_ownership(size_t length)
1,874✔
149
{
150
    if ((this->sb_owner != nullptr && this->sb_data != nullptr)
1,874✔
151
        || this->sb_length != length)
×
152
    {
153
        auto* new_data = (char*) malloc(length);
1,874✔
154
        if (new_data == nullptr) {
1,874✔
155
            return false;
×
156
        }
157

158
        memcpy(new_data, this->sb_data, std::min(length, this->sb_length));
1,874✔
159
        this->sb_length = length;
1,874✔
160
        this->sb_data = new_data;
1,874✔
161
        this->sb_owner->sb_refs.erase(find(this->sb_owner->sb_refs.begin(),
1,874✔
162
                                           this->sb_owner->sb_refs.end(),
1,874✔
163
                                           this));
1,874✔
164
        this->sb_owner = nullptr;
1,874✔
165
    }
166
    return true;
1,874✔
167
}
168

169
void
170
shared_buffer_ref::disown()
1,265,617✔
171
{
172
    if (this->sb_owner == nullptr) {
1,265,617✔
173
        if (this->sb_data != nullptr) {
1,111,820✔
174
            free(const_cast<char*>(this->sb_data));
1,898✔
175
        }
176
    } else {
177
        this->sb_owner->sb_refs.erase(find(this->sb_owner->sb_refs.begin(),
153,797✔
178
                                           this->sb_owner->sb_refs.end(),
153,797✔
179
                                           this));
307,594✔
180
    }
181
    this->sb_owner = nullptr;
1,265,617✔
182
    this->sb_data = nullptr;
1,265,617✔
183
    this->sb_length = 0;
1,265,617✔
184
    this->sb_metadata = {};
1,265,617✔
185
}
1,265,617✔
186

187
void
188
shared_buffer_ref::copy_ref(const shared_buffer_ref& other)
8,047✔
189
{
190
    if (other.sb_data == nullptr) {
8,047✔
191
        this->sb_owner = nullptr;
2,519✔
192
        this->sb_data = nullptr;
2,519✔
193
        this->sb_length = 0;
2,519✔
194
    } else if (other.sb_owner != nullptr) {
5,528✔
195
        this->share(*other.sb_owner, other.sb_data, other.sb_length);
5,504✔
196
    } else {
197
        this->sb_owner = nullptr;
24✔
198
        this->sb_data = (char*) malloc(other.sb_length);
24✔
199
        memcpy(
24✔
200
            const_cast<char*>(this->sb_data), other.sb_data, other.sb_length);
24✔
201
        this->sb_length = other.sb_length;
24✔
202
    }
203
    this->sb_metadata = other.sb_metadata;
8,047✔
204
}
8,047✔
205

206
shared_buffer_ref::narrow_result
207
shared_buffer_ref::narrow(size_t new_data, size_t new_length)
×
208
{
209
    return std::make_pair(
×
210
        std::exchange(this->sb_data, this->sb_data + new_data),
×
211
        std::exchange(this->sb_length, new_length));
×
212
}
213

214
void
215
shared_buffer_ref::widen(narrow_result old_data_length)
×
216
{
217
    this->sb_data = old_data_length.first;
×
218
    this->sb_length = old_data_length.second;
×
219
}
220

221
void
222
shared_buffer_ref::erase_ansi()
45,044✔
223
{
224
    if (!this->sb_metadata.m_valid_utf || !this->sb_metadata.m_has_ansi) {
45,044✔
225
        return;
44,848✔
226
    }
227

228
    auto* writable_data = this->get_writable_data();
196✔
229
    auto new_len = erase_ansi_escapes(
196✔
230
        string_fragment::from_bytes(writable_data, this->sb_length));
231

232
    this->sb_length = new_len;
196✔
233
    this->sb_metadata.m_has_ansi = false;
196✔
234
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc