cpp

Coverage Report

Created: 2023-03-07 20:24

/home/andy/git/oilshell/oil/mycpp/gc_mylib.h
Line
Count
Source (jump to first uncovered line)
1
// gc_mylib.h - corresponds to mycpp/mylib.py
2
3
#ifndef MYCPP_GC_MYLIB_H
4
#define MYCPP_GC_MYLIB_H
5
6
#include <limits.h>  // CHAR_BIT
7
8
#include "mycpp/gc_alloc.h"  // gHeap
9
#include "mycpp/gc_dict.h"   // kDeletedEntry
10
#include "mycpp/gc_tuple.h"
11
12
template <class K, class V>
13
class Dict;
14
15
// https://stackoverflow.com/questions/3919995/determining-sprintf-buffer-size-whats-the-standard/11092994#11092994
16
// Notes:
17
// - Python 2.7's intobject.c has an erroneous +6
18
// - This is 13, but len('-2147483648') is 11, which means we only need 12?
19
// - This formula is valid for octal(), because 2^(3 bits) = 8
20
21
const int kIntBufSize = CHAR_BIT * sizeof(int) / 3 + 3;
22
23
namespace mylib {
24
25
void InitCppOnly();
26
27
// Wrappers around our C++ APIs
28
29
14
inline void MaybeCollect() {
30
14
  gHeap.MaybeCollect();
31
14
}
32
33
// Used by generated _build/cpp/osh_eval.cc
34
2
inline Str* StrFromC(const char* s) {
35
2
  return ::StrFromC(s);
36
2
}
37
38
void print_stderr(Str* s);
39
40
// const int kStdout = 1;
41
// const int kStderr = 2;
42
43
// void writeln(Str* s, int fd = kStdout);
44
45
Tuple2<Str*, Str*> split_once(Str* s, Str* delim);
46
47
template <typename K, typename V>
48
4
void dict_erase(Dict<K, V>* haystack, K needle) {
49
4
  int pos = haystack->position_of_key(needle);
50
4
  if (pos == -1) {
51
0
    return;
52
0
  }
53
4
  haystack->entry_->items_[pos] = kDeletedEntry;
54
  // Zero out for GC.  These could be nullptr or 0
55
4
  haystack->keys_->items_[pos] = 0;
56
4
  haystack->values_->items_[pos] = 0;
57
4
  haystack->len_--;
58
4
}
_ZN5mylib10dict_eraseIP3StriEEvP4DictIT_T0_ES4_
Line
Count
Source
48
2
void dict_erase(Dict<K, V>* haystack, K needle) {
49
2
  int pos = haystack->position_of_key(needle);
50
2
  if (pos == -1) {
51
0
    return;
52
0
  }
53
2
  haystack->entry_->items_[pos] = kDeletedEntry;
54
  // Zero out for GC.  These could be nullptr or 0
55
2
  haystack->keys_->items_[pos] = 0;
56
2
  haystack->values_->items_[pos] = 0;
57
2
  haystack->len_--;
58
2
}
_ZN5mylib10dict_eraseIP3StrS2_EEvP4DictIT_T0_ES4_
Line
Count
Source
48
2
void dict_erase(Dict<K, V>* haystack, K needle) {
49
2
  int pos = haystack->position_of_key(needle);
50
2
  if (pos == -1) {
51
0
    return;
52
0
  }
53
2
  haystack->entry_->items_[pos] = kDeletedEntry;
54
  // Zero out for GC.  These could be nullptr or 0
55
2
  haystack->keys_->items_[pos] = 0;
56
2
  haystack->values_->items_[pos] = 0;
57
2
  haystack->len_--;
58
2
}
59
60
// NOTE: Can use OverAllocatedStr for all of these, rather than copying
61
62
4
inline Str* hex_lower(int i) {
63
4
  char buf[kIntBufSize];
64
4
  int len = snprintf(buf, kIntBufSize, "%x", i);
65
4
  return ::StrFromC(buf, len);
66
4
}
67
68
4
inline Str* hex_upper(int i) {
69
4
  char buf[kIntBufSize];
70
4
  int len = snprintf(buf, kIntBufSize, "%X", i);
71
4
  return ::StrFromC(buf, len);
72
4
}
73
74
4
inline Str* octal(int i) {
75
4
  char buf[kIntBufSize];
76
4
  int len = snprintf(buf, kIntBufSize, "%o", i);
77
4
  return ::StrFromC(buf, len);
78
4
}
79
80
class LineReader {
81
 public:
82
  // Abstract type with no fields: unknown size
83
14
  LineReader() : header_(obj_header()) {
84
14
  }
85
  virtual Str* readline() = 0;
86
  virtual bool isatty() = 0;
87
  virtual void close() = 0;
88
89
14
  static constexpr ObjHeader obj_header() {
90
14
    return ObjHeader::ClassFixed(kZeroMask, sizeof(LineReader));
91
14
  }
92
93
  GC_OBJ(header_);
94
};
95
96
class BufLineReader : public LineReader {
97
 public:
98
6
  explicit BufLineReader(Str* s) : LineReader(), s_(s), pos_(0) {
99
6
    FIELD_MASK(header_) |= BufLineReader::field_mask();
100
6
  }
101
  virtual Str* readline();
102
2
  virtual bool isatty() {
103
2
    return false;
104
2
  }
105
2
  virtual void close() {
106
2
  }
107
108
  Str* s_;
109
  int pos_;
110
111
6
  static constexpr unsigned field_mask() {
112
6
    return maskbit_v(offsetof(BufLineReader, s_));
113
6
  }
114
115
  DISALLOW_COPY_AND_ASSIGN(BufLineReader)
116
};
117
118
// Wrap a FILE*
119
class CFileLineReader : public LineReader {
120
 public:
121
8
  explicit CFileLineReader(FILE* f) : LineReader(), f_(f) {
122
    // not mutating field_mask because FILE* isn't a GC object
123
8
  }
124
  virtual Str* readline();
125
  virtual bool isatty();
126
2
  void close() {
127
2
    fclose(f_);
128
2
  }
129
130
 private:
131
  FILE* f_;
132
133
  DISALLOW_COPY_AND_ASSIGN(CFileLineReader)
134
};
135
136
extern LineReader* gStdin;
137
138
2
inline LineReader* Stdin() {
139
2
  if (gStdin == nullptr) {
140
2
    gStdin = Alloc<CFileLineReader>(stdin);
141
2
  }
142
2
  return gStdin;
143
2
}
144
145
LineReader* open(Str* path);
146
147
class Writer {
148
 public:
149
  // subclasses mutate the mask (and can set obj_len length for Cheney)
150
51
  Writer() : header_(obj_header()) {
151
51
  }
152
  virtual void write(Str* s) = 0;
153
  virtual void flush() = 0;
154
  virtual bool isatty() = 0;
155
156
51
  static constexpr ObjHeader obj_header() {
157
51
    return ObjHeader::ClassFixed(kZeroMask, sizeof(Writer));
158
51
  }
159
160
  GC_OBJ(header_);
161
};
162
163
class MutableStr;
164
165
class BufWriter : public Writer {
166
 public:
167
42
  BufWriter() : Writer(), str_(nullptr), len_(0) {
168
42
    FIELD_MASK(header_) |= field_mask();
169
42
  }
170
  void write(Str* s) override;
171
2
  void flush() override {
172
2
  }
173
2
  bool isatty() override {
174
2
    return false;
175
2
  }
176
  // For cStringIO API
177
  Str* getvalue();
178
179
 private:
180
  void EnsureCapacity(int n);
181
182
  void Extend(Str* s);
183
  char* data();
184
  char* end();
185
  int capacity();
186
187
  MutableStr* str_;
188
  int len_;
189
  bool is_valid_ = true;  // It becomes invalid after getvalue() is called
190
191
42
  static constexpr unsigned field_mask() {
192
    // maskvit_v() because BufWriter has virtual methods
193
42
    return maskbit_v(offsetof(BufWriter, str_));
194
42
  }
195
};
196
197
// Wrap a FILE*
198
class CFileWriter : public Writer {
199
 public:
200
9
  explicit CFileWriter(FILE* f) : Writer(), f_(f) {
201
    // not mutating field_mask because FILE* is not a managed pointer
202
9
  }
203
  void write(Str* s) override;
204
  void flush() override;
205
  bool isatty() override;
206
207
 private:
208
  FILE* f_;
209
210
  DISALLOW_COPY_AND_ASSIGN(CFileWriter)
211
};
212
213
extern Writer* gStdout;
214
215
13
inline Writer* Stdout() {
216
13
  if (gStdout == nullptr) {
217
5
    gStdout = Alloc<CFileWriter>(stdout);
218
5
    gHeap.RootGlobalVar(gStdout);
219
5
  }
220
13
  return gStdout;
221
13
}
222
223
extern Writer* gStderr;
224
225
2
inline Writer* Stderr() {
226
2
  if (gStderr == nullptr) {
227
2
    gStderr = Alloc<CFileWriter>(stderr);
228
2
    gHeap.RootGlobalVar(gStderr);
229
2
  }
230
2
  return gStderr;
231
2
}
232
233
}  // namespace mylib
234
235
#endif  // MYCPP_GC_MYLIB_H