Skip to content

Commit e374eec

Browse files
committed
Implement concat
1 parent 77b81cb commit e374eec

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

src/cstring.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,35 @@ static Py_ssize_t cstring_len(PyObject *self) {
3232
return Py_SIZE(self) - 1;
3333
}
3434

35+
static PyTypeObject cstring_type;
36+
37+
static int _ensure_cstring(PyObject *self) {
38+
if(Py_TYPE(self) == &cstring_type)
39+
return 1;
40+
PyErr_Format(
41+
PyExc_TypeError,
42+
"Object must have type cstring, not %s.",
43+
Py_TYPE(self)->tp_name);
44+
return 0;
45+
}
46+
47+
static PyObject *cstring_concat(PyObject *left, PyObject *right) {
48+
if(!_ensure_cstring(left))
49+
return NULL;
50+
if(!_ensure_cstring(right))
51+
return NULL;
52+
53+
Py_ssize_t size = cstring_len(left) + cstring_len(right) + 1;
54+
55+
struct cstring *new = Py_TYPE(left)->tp_alloc(Py_TYPE(left), size);
56+
memcpy(new->value, CSTRING_VALUE(left), Py_SIZE(left));
57+
memcpy(&new->value[cstring_len(left)], CSTRING_VALUE(right), Py_SIZE(right));
58+
return (PyObject *)new;
59+
}
60+
3561
static PySequenceMethods cstring_as_sequence = {
3662
.sq_length = cstring_len,
63+
.sq_concat = cstring_concat,
3764
};
3865

3966
static PyTypeObject cstring_type = {

test/test_cstring.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pytest
12
from cstring import cstring
23

34

@@ -10,3 +11,13 @@ def test_len():
1011
result = cstring('hello, world')
1112
assert len(result) == 12
1213

14+
15+
def test_concat():
16+
result = cstring('hello') + cstring(', ') + cstring('world')
17+
assert 'hello, world' == str(result)
18+
19+
20+
def test_concat_TypeError():
21+
with pytest.raises(TypeError, match='^Object must have type cstring, not str.$'):
22+
cstring('hello') + 'world'
23+

0 commit comments

Comments
 (0)