summaryrefslogtreecommitdiffstatshomepage
path: root/py/objstr.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/objstr.c')
-rw-r--r--py/objstr.c72
1 files changed, 68 insertions, 4 deletions
diff --git a/py/objstr.c b/py/objstr.c
index 59547e3cd6..a1d139e83a 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -7,6 +7,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
+#include "mpqstr.h"
#include "obj.h"
#include "runtime0.h"
#include "runtime.h"
@@ -16,6 +17,11 @@ typedef struct _mp_obj_str_t {
qstr qstr;
} mp_obj_str_t;
+static mp_obj_t mp_obj_new_str_iterator(mp_obj_str_t *str, int cur);
+
+/******************************************************************************/
+/* str */
+
void str_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_str_t *self = self_in;
// TODO need to escape chars etc
@@ -41,16 +47,27 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
int len = strlen(lhs_str);
if (start < 0) {
start = len + start;
+ if (start < 0) {
+ start = 0;
+ }
+ } else if (start > len) {
+ start = len;
}
if (stop <= 0) {
stop = len + stop;
+ // CPython returns empty string in such case
+ if (stop < 0) {
+ stop = start;
+ }
+ } else if (stop > len) {
+ stop = len;
}
return mp_obj_new_str(qstr_from_strn_copy(lhs_str + start, stop - start));
#endif
} else {
// Message doesn't match CPython, but we don't have so much bytes as they
// to spend them on verbose wording
- nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "index must be int"));
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "index must be int"));
}
case RT_BINARY_OP_ADD:
@@ -73,6 +90,10 @@ mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return MP_OBJ_NULL; // op not supported
}
+static mp_obj_t str_getiter(mp_obj_t o_in) {
+ return mp_obj_new_str_iterator(o_in, 0);
+}
+
mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
assert(MP_OBJ_IS_TYPE(self_in, &str_type));
mp_obj_str_t *self = self_in;
@@ -123,7 +144,7 @@ mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
return mp_obj_new_str(qstr_from_str_take(joined_str, required_len + 1));
bad_arg:
- nlr_jump(mp_obj_new_exception_msg(rt_q_TypeError, "?str.join expecting a list of str's"));
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "?str.join expecting a list of str's"));
}
void vstr_printf_wrapper(void *env, const char *fmt, ...) {
@@ -147,7 +168,7 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) {
vstr_add_char(vstr, '{');
} else if (*str == '}') {
if (arg_i >= n_args) {
- nlr_jump(mp_obj_new_exception_msg(rt_q_IndexError, "tuple index out of range"));
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range"));
}
mp_obj_print_helper(vstr_printf_wrapper, vstr, args[arg_i]);
arg_i++;
@@ -167,10 +188,11 @@ const mp_obj_type_t str_type = {
{ &mp_const_type },
"str",
str_print, // print
+ NULL, // make_new
NULL, // call_n
NULL, // unary_op
str_binary_op, // binary_op
- NULL, // getiter
+ str_getiter, // getiter
NULL, // iternext
{ // method list
{ "join", &str_join_obj },
@@ -191,3 +213,45 @@ qstr mp_obj_str_get(mp_obj_t self_in) {
mp_obj_str_t *self = self_in;
return self->qstr;
}
+
+/******************************************************************************/
+/* str iterator */
+
+typedef struct _mp_obj_str_it_t {
+ mp_obj_base_t base;
+ mp_obj_str_t *str;
+ machine_uint_t cur;
+} mp_obj_str_it_t;
+
+mp_obj_t str_it_iternext(mp_obj_t self_in) {
+ mp_obj_str_it_t *self = self_in;
+ const char *str = qstr_str(self->str->qstr);
+ if (self->cur < strlen(str)) {
+ mp_obj_t o_out = mp_obj_new_str(qstr_from_strn_copy(str + self->cur, 1));
+ self->cur += 1;
+ return o_out;
+ } else {
+ return mp_const_stop_iteration;
+ }
+}
+
+static const mp_obj_type_t str_it_type = {
+ { &mp_const_type },
+ "str_iterator",
+ NULL, // print
+ NULL, // make_new
+ NULL, // call_n
+ NULL, // unary_op
+ NULL, // binary_op
+ NULL, // getiter
+ str_it_iternext, // iternext
+ { { NULL, NULL }, }, // method str
+};
+
+mp_obj_t mp_obj_new_str_iterator(mp_obj_str_t *str, int cur) {
+ mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
+ o->base.type = &str_it_type;
+ o->str = str;
+ o->cur = cur;
+ return o;
+}