1.1 --- a/encoders.py Mon Dec 12 00:33:33 2016 +0100
1.2 +++ b/encoders.py Mon Dec 12 00:37:28 2016 +0100
1.3 @@ -306,6 +306,15 @@
1.4
1.5 return "__const%d" % n
1.6
1.7 +def encode_literal_constant_size(value):
1.8 +
1.9 + "Encode a size for the literal constant with the given 'value'."
1.10 +
1.11 + if isinstance(value, basestring):
1.12 + return len(value)
1.13 + else:
1.14 + return 0
1.15 +
1.16 def encode_literal_constant_member(value):
1.17
1.18 "Encode the member name for the 'value' in the final program."
2.1 --- a/generator.py Mon Dec 12 00:33:33 2016 +0100
2.2 +++ b/generator.py Mon Dec 12 00:37:28 2016 +0100
2.3 @@ -23,7 +23,7 @@
2.4 from encoders import encode_bound_reference, encode_function_pointer, \
2.5 encode_instantiator_pointer, \
2.6 encode_literal_constant, encode_literal_constant_member, \
2.7 - encode_literal_constant_value, \
2.8 + encode_literal_constant_size, encode_literal_constant_value, \
2.9 encode_literal_data_initialiser, \
2.10 encode_literal_instantiator, encode_literal_reference, \
2.11 encode_path, \
2.12 @@ -873,8 +873,10 @@
2.13 # Special internal data member.
2.14
2.15 elif attrname == "__data__":
2.16 - structure.append("{0, .%s=%s}" % (encode_literal_constant_member(attr),
2.17 - encode_literal_constant_value(attr)))
2.18 + structure.append("{.size=%d, .%s=%s}" % (
2.19 + encode_literal_constant_size(attr),
2.20 + encode_literal_constant_member(attr),
2.21 + encode_literal_constant_value(attr)))
2.22 continue
2.23
2.24 # Special internal key member.
3.1 --- a/templates/native/buffer.c Mon Dec 12 00:33:33 2016 +0100
3.2 +++ b/templates/native/buffer.c Mon Dec 12 00:37:28 2016 +0100
3.3 @@ -16,7 +16,7 @@
3.4 this program. If not, see <http://www.gnu.org/licenses/>.
3.5 */
3.6
3.7 -#include <string.h> /* strcmp, strncpy, strlen */
3.8 +#include <string.h> /* strcmp, memcpy */
3.9 #include "native/common.h"
3.10 #include "types.h"
3.11 #include "exceptions.h"
3.12 @@ -32,11 +32,12 @@
3.13 /* _data interpreted as buffer */
3.14 __fragment *data = _data->seqvalue;
3.15 unsigned int size = 0, i, j, n;
3.16 - char *s, *o;
3.17 + char *s;
3.18 + __attr o;
3.19
3.20 /* Calculate the size of the string. */
3.21 for (i = 0; i < data->size; i++)
3.22 - size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);
3.23 + size += __load_via_object(data->attrs[i].value, __pos___data__).size;
3.24
3.25 /* Reserve space for a new string. */
3.26 s = (char *) __ALLOCATE(size + 1, sizeof(char));
3.27 @@ -44,14 +45,14 @@
3.28 /* Build a single string from the buffer contents. */
3.29 for (i = 0, j = 0; i < data->size; i++)
3.30 {
3.31 - o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;
3.32 - n = strlen(o);
3.33 - strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */
3.34 + o = __load_via_object(data->attrs[i].value, __pos___data__);
3.35 + n = o.size;
3.36 + memcpy(s + j, o.strvalue, n); /* does not null terminate but final byte should be zero */
3.37 j += n;
3.38 }
3.39
3.40 /* Return a new string. */
3.41 - return __new_str(s);
3.42 + return __new_str(s, size);
3.43 }
3.44
3.45 /* Module initialisation. */
4.1 --- a/templates/native/common.c Mon Dec 12 00:33:33 2016 +0100
4.2 +++ b/templates/native/common.c Mon Dec 12 00:37:28 2016 +0100
4.3 @@ -34,10 +34,11 @@
4.4 return attr;
4.5 }
4.6
4.7 -__attr __new_str(char *s)
4.8 +__attr __new_str(char *s, size_t size)
4.9 {
4.10 /* Create a new string and mutate the __data__ and __key__ attributes. */
4.11 __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));
4.12 + attr.value->attrs[__pos___data__].size = size;
4.13 attr.value->attrs[__pos___data__].strvalue = s;
4.14 attr.value->attrs[__pos___key__] = (__attr) {0, 0};
4.15 return attr;
5.1 --- a/templates/native/common.h Mon Dec 12 00:33:33 2016 +0100
5.2 +++ b/templates/native/common.h Mon Dec 12 00:37:28 2016 +0100
5.3 @@ -24,7 +24,7 @@
5.4 /* Utility functions. */
5.5
5.6 __attr __new_int(int i);
5.7 -__attr __new_str(char *s);
5.8 +__attr __new_str(char *s, size_t size);
5.9 __attr __new_list(__fragment *f);
5.10 __fragment *__fragment_append(__fragment *data, __attr * const value);
5.11
6.1 --- a/templates/native/int.c Mon Dec 12 00:33:33 2016 +0100
6.2 +++ b/templates/native/int.c Mon Dec 12 00:37:28 2016 +0100
6.3 @@ -268,7 +268,7 @@
6.4 snprintf(s, n, "%d", i);
6.5
6.6 /* Return a new string. */
6.7 - return __new_str(s);
6.8 + return __new_str(s, n);
6.9 }
6.10
6.11 /* Module initialisation. */
7.1 --- a/templates/native/io.c Mon Dec 12 00:33:33 2016 +0100
7.2 +++ b/templates/native/io.c Mon Dec 12 00:37:28 2016 +0100
7.3 @@ -17,7 +17,7 @@
7.4 */
7.5
7.6 #include <unistd.h> /* read, write */
7.7 -#include <string.h> /* strcmp, strncpy, strlen */
7.8 +#include <string.h> /* strcmp, memcpy */
7.9 #include <stdio.h> /* fdopen, snprintf */
7.10 #include <errno.h> /* errno */
7.11 #include "native/common.h"
7.12 @@ -128,8 +128,8 @@
7.13 /* Reserve space for a new string. */
7.14
7.15 s = __ALLOCATE(have_read + 1, sizeof(char));
7.16 - strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
7.17 - return __new_str(s);
7.18 + memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
7.19 + return __new_str(s, have_read);
7.20 }
7.21
7.22 __attr __fn_native_io_fwrite(__attr __args[])
7.23 @@ -139,8 +139,9 @@
7.24 /* fp interpreted as FILE reference */
7.25 FILE *f = (FILE *) fp->datavalue;
7.26 /* str.__data__ interpreted as string */
7.27 - char *s = __load_via_object(str->value, __pos___data__).strvalue;
7.28 - size_t to_write = strlen(s);
7.29 + __attr sa = __load_via_object(str->value, __pos___data__);
7.30 + char *s = sa.strvalue;
7.31 + size_t to_write = sa.size;
7.32 size_t have_written = fwrite(s, sizeof(char), to_write, f);
7.33 int error;
7.34
7.35 @@ -189,8 +190,8 @@
7.36 /* Reserve space for a new string. */
7.37
7.38 s = __ALLOCATE(have_read + 1, 1);
7.39 - strncpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
7.40 - return __new_str(s);
7.41 + memcpy(s, (char *) buf, have_read); /* does not null terminate but final byte should be zero */
7.42 + return __new_str(s, have_read);
7.43 }
7.44
7.45 __attr __fn_native_io_write(__attr __args[])
7.46 @@ -200,11 +201,12 @@
7.47 /* fd.__data__ interpreted as int */
7.48 int i = __load_via_object(fd->value, __pos___data__).intvalue;
7.49 /* str.__data__ interpreted as string */
7.50 - char *s = __load_via_object(str->value, __pos___data__).strvalue;
7.51 + __attr sa = __load_via_object(str->value, __pos___data__);
7.52 + char *s = sa.strvalue;
7.53 ssize_t have_written;
7.54
7.55 errno = 0;
7.56 - have_written = write(i, s, sizeof(char) * strlen(s));
7.57 + have_written = write(i, s, sizeof(char) * sa.size);
7.58
7.59 if (have_written == -1)
7.60 __raise_io_error(__new_int(errno));
8.1 --- a/templates/native/locale.c Mon Dec 12 00:33:33 2016 +0100
8.2 +++ b/templates/native/locale.c Mon Dec 12 00:37:28 2016 +0100
8.3 @@ -46,7 +46,7 @@
8.4 out = __ALLOCATE(length + 1, sizeof(char));
8.5 strncpy(out, result, length);
8.6
8.7 - return __new_str(result);
8.8 + return __new_str(result, length);
8.9 }
8.10
8.11 __attr __fn_native_locale_setlocale(__attr __args[])
8.12 @@ -69,7 +69,7 @@
8.13 out = __ALLOCATE(length + 1, sizeof(char));
8.14 strncpy(out, result, length);
8.15
8.16 - return __new_str(result);
8.17 + return __new_str(result, length);
8.18 }
8.19
8.20 /* Module initialisation. */
9.1 --- a/templates/native/str.c Mon Dec 12 00:33:33 2016 +0100
9.2 +++ b/templates/native/str.c Mon Dec 12 00:37:28 2016 +0100
9.3 @@ -16,7 +16,7 @@
9.4 this program. If not, see <http://www.gnu.org/licenses/>.
9.5 */
9.6
9.7 -#include <string.h> /* strcmp, strncpy, strlen */
9.8 +#include <string.h> /* strcmp, memcpy */
9.9 #include "native/common.h"
9.10 #include "types.h"
9.11 #include "exceptions.h"
9.12 @@ -35,14 +35,14 @@
9.13 /* _data, other interpreted as string */
9.14 char *s = _data->strvalue;
9.15 char *o = other->strvalue;
9.16 - int n = strlen(s) + strlen(o) + 1;
9.17 - char *r = (char *) __ALLOCATE(n, sizeof(char));
9.18 + int n = _data->size + other->size;
9.19 + char *r = (char *) __ALLOCATE(n + 1, sizeof(char));
9.20
9.21 - strncpy(r, s, n);
9.22 - strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */
9.23 + memcpy(r, s, _data->size);
9.24 + memcpy(r + _data->size, o, other->size);
9.25
9.26 /* Return a new string. */
9.27 - return __new_str(r);
9.28 + return __new_str(r, n);
9.29 }
9.30
9.31 __attr __fn_native_str_str_lt(__attr __args[])
9.32 @@ -88,7 +88,7 @@
9.33 char *s = _data->strvalue;
9.34
9.35 /* Return the new integer. */
9.36 - return __new_int(strlen(s));
9.37 + return __new_int(_data->size);
9.38 }
9.39
9.40 __attr __fn_native_str_str_nonempty(__attr __args[])
9.41 @@ -97,7 +97,7 @@
9.42 /* _data interpreted as string */
9.43 char *s = _data->strvalue;
9.44
9.45 - return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;
9.46 + return _data->size ? __builtins___boolean_True : __builtins___boolean_False;
9.47 }
9.48
9.49 __attr __fn_native_str_str_ord(__attr __args[])
9.50 @@ -123,8 +123,8 @@
9.51
9.52 /* Reserve space for a new string. */
9.53 sub = (char *) __ALLOCATE(l + 1, sizeof(char));
9.54 - strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */
9.55 - return __new_str(sub);
9.56 + memcpy(sub, s + i, l); /* does not null terminate but final byte should be zero */
9.57 + return __new_str(sub, l);
9.58 }
9.59
9.60 /* Module initialisation. */
10.1 --- a/templates/types.h Mon Dec 12 00:33:33 2016 +0100
10.2 +++ b/templates/types.h Mon Dec 12 00:37:28 2016 +0100
10.3 @@ -19,6 +19,8 @@
10.4 #ifndef __TYPES_H__
10.5 #define __TYPES_H__
10.6
10.7 +#include <stddef.h> /* size_t */
10.8 +
10.9 /* Attribute tables are lists of codes confirming the presence of attributes. */
10.10
10.11 typedef struct __table
10.12 @@ -55,9 +57,11 @@
10.13 union
10.14 {
10.15 __obj * context; /* attribute context */
10.16 + __obj * b; /* bound callable object */
10.17 unsigned int min; /* minimum number of parameters */
10.18 - __obj * b; /* bound callable object */
10.19 unsigned int code; /* parameter table code for key */
10.20 +
10.21 + size_t size; /* size of value */
10.22 };
10.23
10.24 /* One of... */
11.1 --- a/tests/string.py Mon Dec 12 00:33:33 2016 +0100
11.2 +++ b/tests/string.py Mon Dec 12 00:37:28 2016 +0100
11.3 @@ -1,9 +1,11 @@
11.4 s = "Hello"
11.5 s += " world!"
11.6 print s # Hello world!
11.7 +print len(s) # 12
11.8
11.9 s2 = "Hello worlds!"
11.10 print s2 # Hello worlds!
11.11 +print len(s2) # 13
11.12 print s < s2 # True
11.13 print s <= s2 # True
11.14 print s == s2 # False
11.15 @@ -24,11 +26,18 @@
11.16 l = ["Hello", "world!"]
11.17 s3 = " ".join(l)
11.18 print s3 # Hello world!
11.19 +print len(s3) # 12
11.20
11.21 s4 = "".join(l)
11.22 print s4 # Helloworld!
11.23 +print len(s4) # 11
11.24 +
11.25 +s5 = "--".join(l)
11.26 +print s5 # Hello--world!
11.27 +print len(s5) # 13
11.28
11.29 print hash(s)
11.30 print hash(s2)
11.31 print hash(s3)
11.32 print hash(s4)
11.33 +print hash(s5)