cpp

Coverage Report

Created: 2023-09-13 01:07

/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() {
84
14
  }
85
  virtual Str* readline() = 0;
86
  virtual bool isatty() = 0;
87
  virtual void close() = 0;
88
89
0
  static constexpr ObjHeader obj_header() {
90
0
    return ObjHeader::ClassFixed(field_mask(), sizeof(LineReader));
91
0
  }
92
93
14
  static constexpr uint32_t field_mask() {
94
14
    return kZeroMask;
95
14
  }
96
};
97
98
class BufLineReader : public LineReader {
99
 public:
100
6
  explicit BufLineReader(Str* s) : LineReader(), s_(s), pos_(0) {
101
6
  }
102
  virtual Str* readline();
103
2
  virtual bool isatty() {
104
2
    return false;
105
2
  }
106
2
  virtual void close() {
107
2
  }
108
109
  Str* s_;
110
  int pos_;
111
112
6
  static constexpr ObjHeader obj_header() {
113
6
    return ObjHeader::ClassFixed(field_mask(), sizeof(LineReader));
114
6
  }
115
116
6
  static constexpr uint32_t field_mask() {
117
6
    return LineReader::field_mask() | maskbit(offsetof(BufLineReader, s_));
118
6
  }
119
120
  DISALLOW_COPY_AND_ASSIGN(BufLineReader)
121
};
122
123
// Wrap a FILE*
124
class CFileLineReader : public LineReader {
125
 public:
126
8
  explicit CFileLineReader(FILE* f) : LineReader(), f_(f) {
127
8
  }
128
  virtual Str* readline();
129
  virtual bool isatty();
130
2
  void close() {
131
2
    fclose(f_);
132
2
  }
133
134
8
  static constexpr ObjHeader obj_header() {
135
8
    return ObjHeader::ClassFixed(field_mask(), sizeof(LineReader));
136
8
  }
137
138
8
  static constexpr uint32_t field_mask() {
139
    // not mutating field_mask because FILE* isn't a GC object
140
8
    return LineReader::field_mask();
141
8
  }
142
143
 private:
144
  FILE* f_;
145
146
  DISALLOW_COPY_AND_ASSIGN(CFileLineReader)
147
};
148
149
extern LineReader* gStdin;
150
151
2
inline LineReader* Stdin() {
152
2
  if (gStdin == nullptr) {
153
2
    gStdin = Alloc<CFileLineReader>(stdin);
154
2
  }
155
2
  return gStdin;
156
2
}
157
158
LineReader* open(Str* path);
159
160
class Writer {
161
 public:
162
86
  Writer() {
163
86
  }
164
  virtual void write(Str* s) = 0;
165
  virtual void flush() = 0;
166
  virtual bool isatty() = 0;
167
168
9
  static constexpr ObjHeader obj_header() {
169
9
    return ObjHeader::ClassFixed(field_mask(), sizeof(Writer));
170
9
  }
171
172
86
  static constexpr uint32_t field_mask() {
173
86
    return kZeroMask;
174
86
  }
175
};
176
177
class MutableStr;
178
179
class BufWriter : public Writer {
180
 public:
181
77
  BufWriter() : Writer(), str_(nullptr), len_(0) {
182
77
  }
183
  void write(Str* s) override;
184
2
  void flush() override {
185
2
  }
186
2
  bool isatty() override {
187
2
    return false;
188
2
  }
189
  // For cStringIO API
190
  Str* getvalue();
191
192
77
  static constexpr ObjHeader obj_header() {
193
77
    return ObjHeader::ClassFixed(field_mask(), sizeof(BufWriter));
194
77
  }
195
196
77
  static constexpr unsigned field_mask() {
197
    // maskvit_v() because BufWriter has virtual methods
198
77
    return Writer::field_mask() | maskbit(offsetof(BufWriter, str_));
199
77
  }
200
201
 private:
202
  void EnsureCapacity(int n);
203
204
  void Extend(Str* s);
205
  char* data();
206
  char* end();
207
  int capacity();
208
209
  MutableStr* str_;
210
  int len_;
211
  bool is_valid_ = true;  // It becomes invalid after getvalue() is called
212
};
213
214
// Wrap a FILE*
215
class CFileWriter : public Writer {
216
 public:
217
9
  explicit CFileWriter(FILE* f) : Writer(), f_(f) {
218
    // not mutating field_mask because FILE* is not a managed pointer
219
9
  }
220
  void write(Str* s) override;
221
  void flush() override;
222
  bool isatty() override;
223
224
 private:
225
  FILE* f_;
226
227
  DISALLOW_COPY_AND_ASSIGN(CFileWriter)
228
};
229
230
extern Writer* gStdout;
231
232
13
inline Writer* Stdout() {
233
13
  if (gStdout == nullptr) {
234
5
    gStdout = Alloc<CFileWriter>(stdout);
235
5
    gHeap.RootGlobalVar(gStdout);
236
5
  }
237
13
  return gStdout;
238
13
}
239
240
extern Writer* gStderr;
241
242
2
inline Writer* Stderr() {
243
2
  if (gStderr == nullptr) {
244
2
    gStderr = Alloc<CFileWriter>(stderr);
245
2
    gHeap.RootGlobalVar(gStderr);
246
2
  }
247
2
  return gStderr;
248
2
}
249
250
class UniqueObjects {
251
  // Can't be expressed in typed Python because we don't have uint64_t for
252
  // addresses
253
254
 public:
255
0
  UniqueObjects() {
256
0
  }
257
0
  void Add(void* obj) {
258
0
  }
259
0
  int Get(void* obj) {
260
0
    return -1;
261
0
  }
262
263
0
  static constexpr ObjHeader obj_header() {
264
0
    return ObjHeader::ClassFixed(field_mask(), sizeof(UniqueObjects));
265
0
  }
266
267
  // SPECIAL CASE? We should never have a unique reference to an object?  So
268
  // don't bother tracing
269
0
  static constexpr uint32_t field_mask() {
270
0
    return kZeroMask;
271
0
  }
272
273
 private:
274
  // address -> small integer ID
275
  Dict<void*, int> addresses_;
276
};
277
278
}  // namespace mylib
279
280
#endif  // MYCPP_GC_MYLIB_H