From be020c27a870feff9773c348fa04be8c54873f70 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky <pfalcon@users.sourceforge.net>
Date: Fri, 21 Mar 2014 11:39:01 +0200
Subject: [PATCH] py: Make 'str' be a proper type, support standard constructor
 args.

---
 py/builtin.c | 10 ----------
 py/objstr.c  | 36 ++++++++++++++++++++++++++++++++++++
 py/runtime.c |  2 +-
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/py/builtin.c b/py/builtin.c
index 2e0627fa5..11b86111e 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -375,16 +375,6 @@ STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *k
 
 MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
 
-STATIC mp_obj_t mp_builtin_str(mp_obj_t o_in) {
-    vstr_t *vstr = vstr_new();
-    mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, o_in, PRINT_STR);
-    mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
-    vstr_free(vstr);
-    return s;
-}
-
-MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str);
-
 // TODO: This should be type, this is just quick CPython compat hack
 STATIC mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) {
     if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) {
diff --git a/py/objstr.c b/py/objstr.c
index 3c5cabe05..44e84d709 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -28,6 +28,7 @@ typedef struct _mp_obj_str_t {
 
 STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
 STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
+STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len);
 
 /******************************************************************************/
 /* str                                                                        */
@@ -78,6 +79,40 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env,
     }
 }
 
+STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
+    switch (n_args) {
+        case 0:
+            return MP_OBJ_NEW_QSTR(MP_QSTR_);
+
+        case 1:
+        {
+            vstr_t *vstr = vstr_new();
+            mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR);
+            mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false);
+            vstr_free(vstr);
+            return s;
+        }
+
+        case 2:
+        case 3:
+        {
+            // TODO: validate 2nd/3rd args
+            if (!MP_OBJ_IS_TYPE(args[0], &bytes_type)) {
+                nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
+            }
+            GET_STR_DATA_LEN(args[0], str_data, str_len);
+            GET_STR_HASH(args[0], str_hash);
+            mp_obj_str_t *o = str_new(&str_type, NULL, str_len);
+            o->data = str_data;
+            o->hash = str_hash;
+            return o;
+        }
+
+        default:
+            nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
+    }
+}
+
 // like strstr but with specified length and allows \0 bytes
 // TODO replace with something more efficient/standard
 STATIC const byte *find_subbytes(const byte *haystack, uint hlen, const byte *needle, uint nlen) {
@@ -619,6 +654,7 @@ const mp_obj_type_t str_type = {
     { &mp_type_type },
     .name = MP_QSTR_str,
     .print = str_print,
+    .make_new = str_make_new,
     .binary_op = str_binary_op,
     .getiter = mp_obj_new_str_iterator,
     .methods = str_type_methods,
diff --git a/py/runtime.c b/py/runtime.c
index c268fd546..2ab97ed18 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -102,6 +102,7 @@ STATIC const mp_builtin_elem_t builtin_table[] = {
     { MP_QSTR_list, (mp_obj_t)&list_type },
     { MP_QSTR_map, (mp_obj_t)&map_type },
     { MP_QSTR_set, (mp_obj_t)&set_type },
+    { MP_QSTR_str, (mp_obj_t)&str_type },
     { MP_QSTR_super, (mp_obj_t)&super_type },
     { MP_QSTR_tuple, (mp_obj_t)&tuple_type },
     { MP_QSTR_type, (mp_obj_t)&mp_type_type },
@@ -137,7 +138,6 @@ STATIC const mp_builtin_elem_t builtin_table[] = {
     { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj },
     { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj },
     { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj },
-    { MP_QSTR_str, (mp_obj_t)&mp_builtin_str_obj },
     { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj },
 
     // built-in exceptions
-- 
GitLab