Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 08ef20c

Browse files
committed
Implement join method
1 parent 4895fcc commit 08ef20c

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

src/cstring.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,24 @@ static PyObject *_cstring_new(PyTypeObject *type, const char *value, Py_ssize_t
3636
return (PyObject *)new;
3737
}
3838

39+
static PyObject *_cstring_realloc(PyObject *self, Py_ssize_t len) {
40+
struct cstring *new = (struct cstring *)PyObject_Realloc(self, sizeof(struct cstring) + len + 1);
41+
if(!new)
42+
return PyErr_NoMemory();
43+
Py_SET_SIZE(new, len + 1);
44+
new->hash = -1;
45+
return (PyObject *)new;
46+
}
47+
48+
static PyObject *_cstring_copy(PyObject *self) {
49+
return _cstring_new(Py_TYPE(self), CSTRING_VALUE(self), Py_SIZE(self) - 1);
50+
}
51+
3952
static PyObject *cstring_new_empty(void) {
4053
return _cstring_new(&cstring_type, "", 0);
4154
}
4255

56+
4357
static const char *_obj_as_string_and_size(PyObject *o, Py_ssize_t *s) {
4458
if(PyUnicode_Check(o))
4559
return PyUnicode_AsUTF8AndSize(o, s);
@@ -147,6 +161,29 @@ static Py_ssize_t cstring_len(PyObject *self) {
147161
return Py_SIZE(self) - 1;
148162
}
149163

164+
static PyObject *_concat_in_place(PyObject *self, PyObject *other) {
165+
if(!other)
166+
return PyErr_BadArgument(), NULL;
167+
if(!_ensure_cstring(other))
168+
return NULL;
169+
if(!self)
170+
return _cstring_copy(other); /* new (mutable) copy with refcnt=1 */
171+
if(!_ensure_cstring(self))
172+
return NULL;
173+
if(Py_REFCNT(self) > 1)
174+
return PyErr_BadInternalCall(), NULL;
175+
176+
Py_ssize_t origlen = cstring_len(self);
177+
Py_ssize_t newlen = origlen + cstring_len(other);
178+
PyObject *new = _cstring_realloc(self, newlen);
179+
if(!new)
180+
return NULL;
181+
182+
memcpy(CSTRING_VALUE_AT(new, origlen), CSTRING_VALUE(other), cstring_len(other));
183+
*CSTRING_VALUE_AT(new, newlen) = '\0';
184+
return new;
185+
}
186+
150187
static PyObject *cstring_concat(PyObject *left, PyObject *right) {
151188
if(!_ensure_cstring(left))
152189
return NULL;
@@ -456,6 +493,37 @@ PyObject *cstring_isupper(PyObject *self, PyObject *args) {
456493
Py_RETURN_FALSE;
457494
}
458495

496+
PyDoc_STRVAR(join__doc__, "");
497+
PyObject *cstring_join(PyObject *self, PyObject *arg) {
498+
PyObject *iter = PyObject_GetIter(arg);
499+
if(!iter)
500+
return NULL;
501+
502+
PyObject *result = NULL;
503+
PyObject *item = NULL;
504+
505+
while((item = PyIter_Next(iter)) != NULL) {
506+
if(result) {
507+
PyObject *next = _concat_in_place(result, self);
508+
if(!next)
509+
goto fail;
510+
result = next;
511+
}
512+
PyObject *next = _concat_in_place(result, item);
513+
if(!next)
514+
goto fail;
515+
Py_DECREF(item);
516+
result = next;
517+
}
518+
519+
return result;
520+
521+
fail:
522+
Py_XDECREF(item);
523+
Py_XDECREF(result);
524+
return NULL;
525+
}
526+
459527
PyDoc_STRVAR(lower__doc__, "");
460528
PyObject *cstring_lower(PyObject *self, PyObject *args) {
461529
struct cstring *new = CSTRING_ALLOC(Py_TYPE(self), Py_SIZE(self));
@@ -589,7 +657,7 @@ static PyMethodDef cstring_methods[] = {
589657
{"isspace", cstring_isspace, METH_NOARGS, isspace__doc__},
590658
/* TODO: istitle */
591659
{"isupper", cstring_isupper, METH_NOARGS, isupper__doc__},
592-
/* TODO: join */
660+
{"join", cstring_join, METH_O, join__doc__},
593661
/* TODO: ljust */
594662
{"lower", cstring_lower, METH_NOARGS, lower__doc__},
595663
/* TODO: lstrip */

test/test_methods.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ def test_isupper_alnum_lc():
138138
assert target.isupper() == False
139139

140140

141+
def test_join():
142+
sep = cstring(', ')
143+
items = [cstring('hello'), cstring('world')]
144+
assert sep.join(items) == cstring('hello, world')
145+
146+
141147
def test_lower():
142148
target = cstring('HELLO123')
143149
assert target.lower() == cstring('hello123')

0 commit comments

Comments
 (0)