@@ -6,8 +6,9 @@ struct cstring {
66 char value [];
77};
88
9- #define CSTRING_HASH (self ) (((struct cstring *)self)->hash)
10- #define CSTRING_VALUE (self ) (((struct cstring *)self)->value)
9+ #define CSTRING_HASH (self ) (((struct cstring *)self)->hash)
10+ #define CSTRING_VALUE (self ) (((struct cstring *)self)->value)
11+
1112
1213static PyObject * _cstring_new (PyTypeObject * type , const char * value , size_t len ) {
1314 struct cstring * new = type -> tp_alloc (type , len + 1 );
@@ -17,6 +18,8 @@ static PyObject *_cstring_new(PyTypeObject *type, const char *value, size_t len)
1718 return (PyObject * )new ;
1819}
1920
21+ #define CSTRING_NEW_EMPTY (tp ) (_cstring_new(tp, "", 0))
22+
2023static PyObject * cstring_new (PyTypeObject * type , PyObject * args , PyObject * * kwargs ) {
2124 char * value = NULL ;
2225 if (!PyArg_ParseTuple (args , "s" , & value ))
@@ -101,7 +104,7 @@ static PyObject *cstring_repeat(PyObject *self, Py_ssize_t count) {
101104 if (!_ensure_cstring (self ))
102105 return NULL ;
103106 if (count <= 0 )
104- return _cstring_new (Py_TYPE (self ), "" , 0 );
107+ return CSTRING_NEW_EMPTY (Py_TYPE (self ));
105108
106109 Py_ssize_t size = (cstring_len (self ) * count ) + 1 ;
107110
@@ -133,6 +136,42 @@ static int cstring_contains(PyObject *self, PyObject *arg) {
133136 return 0 ;
134137}
135138
139+ static PyObject * _cstring_subscript_index (PyObject * self , PyObject * index ) {
140+ Py_ssize_t i = PyNumber_AsSsize_t (index , PyExc_IndexError );
141+ if (PyErr_Occurred ())
142+ return NULL ;
143+ if (i < 0 )
144+ i += cstring_len (self );
145+ return cstring_item (self , i );
146+ }
147+
148+ static PyObject * _cstring_subscript_slice (PyObject * self , PyObject * slice ) {
149+ Py_ssize_t start , stop , step ;
150+ if (PySlice_Unpack (slice , & start , & stop , & step ) < 0 )
151+ return NULL ;
152+ Py_ssize_t slicelen = PySlice_AdjustIndices (cstring_len (self ), & start , & stop , step );
153+ assert (slicelen >= 0 );
154+
155+ struct cstring * new = Py_TYPE (self )-> tp_alloc (Py_TYPE (self ), slicelen + 1 );
156+ char * src = & CSTRING_VALUE (self )[start ];
157+ for (Py_ssize_t i = 0 ; i < slicelen ; ++ i ) {
158+ new -> value [i ] = * src ;
159+ src += step ;
160+ }
161+ new -> value [slicelen ] = '\0' ;
162+ return (PyObject * )new ;
163+ }
164+
165+ static PyObject * cstring_subscript (PyObject * self , PyObject * key ) {
166+ if (PyIndex_Check (key ))
167+ return _cstring_subscript_index (self , key );
168+ if (PySlice_Check (key ))
169+ return _cstring_subscript_slice (self , key );
170+
171+ PyErr_SetString (PyExc_TypeError , "Subscript must be int or slice." );
172+ return NULL ;
173+ }
174+
136175static PySequenceMethods cstring_as_sequence = {
137176 .sq_length = cstring_len ,
138177 .sq_concat = cstring_concat ,
@@ -143,6 +182,7 @@ static PySequenceMethods cstring_as_sequence = {
143182
144183static PyMappingMethods cstring_as_mapping = {
145184 .mp_length = cstring_len ,
185+ .mp_subscript = cstring_subscript ,
146186};
147187
148188static PyTypeObject cstring_type = {
0 commit comments