/home/andy/git/oilshell/oil/mycpp/leaky_types.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #ifdef LEAKY_BINDINGS |
2 | | #include "mycpp/mylib_old.h" |
3 | | using gc_heap::StackRoots; // no-op |
4 | | using mylib::AllocStr; |
5 | | #else |
6 | | #include "mycpp/gc_builtins.h" |
7 | | #include "mycpp/gc_types.h" |
8 | | using gc_heap::kEmptyString; |
9 | | using gc_heap::StackRoots; |
10 | | using gc_heap::Str; |
11 | | #endif |
12 | | |
13 | | #include <ctype.h> // isalpha(), isdigit() |
14 | | |
15 | | #ifndef LEAKY_BINDINGS |
16 | | namespace gc_heap { |
17 | | #endif |
18 | | |
19 | | enum class StripWhere { |
20 | | Left, |
21 | | Right, |
22 | | Both, |
23 | | }; |
24 | | |
25 | | const int kWhitespace = -1; |
26 | | |
27 | 61 | bool OmitChar(uint8_t ch, int what) { |
28 | 61 | if (what == kWhitespace) { |
29 | 51 | return isspace(ch); |
30 | 51 | } else { |
31 | 10 | return what == ch; |
32 | 10 | } |
33 | 61 | } Line | Count | Source | 27 | 55 | bool OmitChar(uint8_t ch, int what) { | 28 | 55 | if (what == kWhitespace) { | 29 | 45 | return isspace(ch); | 30 | 45 | } else { | 31 | 10 | return what == ch; | 32 | 10 | } | 33 | 55 | } |
Line | Count | Source | 27 | 6 | bool OmitChar(uint8_t ch, int what) { | 28 | 6 | if (what == kWhitespace) { | 29 | 6 | return isspace(ch); | 30 | 6 | } else { | 31 | 0 | return what == ch; | 32 | 0 | } | 33 | 6 | } |
|
34 | | |
35 | | // StripAny is modeled after CPython's do_strip() in stringobject.c, and can |
36 | | // implement 6 functions: |
37 | | // |
38 | | // strip / lstrip / rstrip |
39 | | // strip(char) / lstrip(char) / rstrip(char) |
40 | | // |
41 | | // Args: |
42 | | // where: which ends to strip from |
43 | | // what: kWhitespace, or an ASCII code 0-255 |
44 | | |
45 | 24 | Str* StripAny(Str* s, StripWhere where, int what) { |
46 | 24 | StackRoots _roots({&s}); |
47 | | |
48 | 24 | int length = len(s); |
49 | 24 | const char* char_data = s->data(); |
50 | | |
51 | 24 | int i = 0; |
52 | 24 | if (where != StripWhere::Right) { |
53 | 21 | while (i < length && OmitChar(char_data[i], what)) { |
54 | 9 | i++; |
55 | 9 | } |
56 | 12 | } |
57 | | |
58 | 24 | int j = length; |
59 | 24 | if (where != StripWhere::Left) { |
60 | 51 | do { |
61 | 51 | j--; |
62 | 51 | } while (j >= i && OmitChar(char_data[j], what)); |
63 | 24 | j++; |
64 | 24 | } |
65 | | |
66 | 24 | if (i == j) { // Optimization to reuse existing object |
67 | 7 | return kEmptyString; |
68 | 7 | } |
69 | | |
70 | 17 | if (i == 0 && j == length) { // nothing stripped |
71 | 3 | return s; |
72 | 3 | } |
73 | | |
74 | | // Note: makes a copy in leaky version, and will in GC version too |
75 | 14 | int new_len = j - i; |
76 | 14 | Str* result = AllocStr(new_len); |
77 | 14 | memcpy(result->data(), s->data() + i, new_len); |
78 | 14 | return result; |
79 | 17 | } _ZN7gc_heap8StripAnyEPNS_3StrENS_10StripWhereEi Line | Count | Source | 45 | 22 | Str* StripAny(Str* s, StripWhere where, int what) { | 46 | 22 | StackRoots _roots({&s}); | 47 | | | 48 | 22 | int length = len(s); | 49 | 22 | const char* char_data = s->data(); | 50 | | | 51 | 22 | int i = 0; | 52 | 22 | if (where != StripWhere::Right) { | 53 | 19 | while (i < length && OmitChar(char_data[i], what)) { | 54 | 9 | i++; | 55 | 9 | } | 56 | 10 | } | 57 | | | 58 | 22 | int j = length; | 59 | 22 | if (where != StripWhere::Left) { | 60 | 47 | do { | 61 | 47 | j--; | 62 | 47 | } while (j >= i && OmitChar(char_data[j], what)); | 63 | 22 | j++; | 64 | 22 | } | 65 | | | 66 | 22 | if (i == j) { // Optimization to reuse existing object | 67 | 7 | return kEmptyString; | 68 | 7 | } | 69 | | | 70 | 15 | if (i == 0 && j == length) { // nothing stripped | 71 | 3 | return s; | 72 | 3 | } | 73 | | | 74 | | // Note: makes a copy in leaky version, and will in GC version too | 75 | 12 | int new_len = j - i; | 76 | 12 | Str* result = AllocStr(new_len); | 77 | 12 | memcpy(result->data(), s->data() + i, new_len); | 78 | 12 | return result; | 79 | 15 | } |
_Z8StripAnyP3Str10StripWherei Line | Count | Source | 45 | 2 | Str* StripAny(Str* s, StripWhere where, int what) { | 46 | 2 | StackRoots _roots({&s}); | 47 | | | 48 | 2 | int length = len(s); | 49 | 2 | const char* char_data = s->data(); | 50 | | | 51 | 2 | int i = 0; | 52 | 2 | if (where != StripWhere::Right) { | 53 | 2 | while (i < length && OmitChar(char_data[i], what)) { | 54 | 0 | i++; | 55 | 0 | } | 56 | 2 | } | 57 | | | 58 | 2 | int j = length; | 59 | 2 | if (where != StripWhere::Left) { | 60 | 4 | do { | 61 | 4 | j--; | 62 | 4 | } while (j >= i && OmitChar(char_data[j], what)); | 63 | 2 | j++; | 64 | 2 | } | 65 | | | 66 | 2 | if (i == j) { // Optimization to reuse existing object | 67 | 0 | return kEmptyString; | 68 | 0 | } | 69 | | | 70 | 2 | if (i == 0 && j == length) { // nothing stripped | 71 | 0 | return s; | 72 | 0 | } | 73 | | | 74 | | // Note: makes a copy in leaky version, and will in GC version too | 75 | 2 | int new_len = j - i; | 76 | 2 | Str* result = AllocStr(new_len); | 77 | 2 | memcpy(result->data(), s->data() + i, new_len); | 78 | 2 | return result; | 79 | 2 | } |
|
80 | | |
81 | 12 | Str* Str::strip() { |
82 | 12 | return StripAny(this, StripWhere::Both, kWhitespace); |
83 | 12 | } Line | Count | Source | 81 | 10 | Str* Str::strip() { | 82 | 10 | return StripAny(this, StripWhere::Both, kWhitespace); | 83 | 10 | } |
Line | Count | Source | 81 | 2 | Str* Str::strip() { | 82 | 2 | return StripAny(this, StripWhere::Both, kWhitespace); | 83 | 2 | } |
|
84 | | |
85 | | // Used for CommandSub in osh/cmd_exec.py |
86 | 4 | Str* Str::rstrip(Str* chars) { |
87 | 4 | assert(len(chars) == 1); |
88 | 0 | int c = chars->data_[0]; |
89 | 4 | return StripAny(this, StripWhere::Right, c); |
90 | 4 | } _ZN7gc_heap3Str6rstripEPS0_ Line | Count | Source | 86 | 4 | Str* Str::rstrip(Str* chars) { | 87 | 4 | assert(len(chars) == 1); | 88 | 0 | int c = chars->data_[0]; | 89 | 4 | return StripAny(this, StripWhere::Right, c); | 90 | 4 | } |
Unexecuted instantiation: _ZN3Str6rstripEPS_ |
91 | | |
92 | 8 | Str* Str::rstrip() { |
93 | 8 | return StripAny(this, StripWhere::Right, kWhitespace); |
94 | 8 | } Line | Count | Source | 92 | 8 | Str* Str::rstrip() { | 93 | 8 | return StripAny(this, StripWhere::Right, kWhitespace); | 94 | 8 | } |
Unexecuted instantiation: _ZN3Str6rstripEv |
95 | | |
96 | | #if 0 |
97 | | Str* Str::lstrip(Str* chars) { |
98 | | assert(len(chars) == 1); |
99 | | int c = chars->data_[0]; |
100 | | return StripAny(this, StripWhere::Left, c); |
101 | | } |
102 | | |
103 | | Str* Str::lstrip() { |
104 | | return StripAny(this, StripWhere::Left, kWhitespace); |
105 | | } |
106 | | #endif |
107 | | |
108 | | #ifndef LEAKY_BINDINGS |
109 | | } // namespace gc_heap |
110 | | #endif |