23
23
cdef extern from "Python.h":
24
24
ctypedef int Py_ssize_t # Required for older pyrex versions
27
ctypedef _PyObject PyObject
25
28
char *PyString_AS_STRING(object s)
26
Py_ssize_t PyString_GET_SIZE(object t)
29
Py_ssize_t PyString_GET_SIZE(object t) except -1
30
object PyUnicode_DecodeUTF8(char *string, Py_ssize_t length, char *errors)
31
Py_ssize_t PyUnicode_GET_SIZE(object t) except -1
32
int PyUnicode_Resize(PyObject **o, Py_ssize_t size) except -1
33
object PyString_FromStringAndSize(char *s, Py_ssize_t len)
34
int PyString_CheckExact(object)
35
int PyUnicode_CheckExact(object)
36
void Py_INCREF(object)
37
void Py_DECREF(object)
38
object PyList_GetItem(object, int)
39
int PyList_SetItem(object, int, object) except -1
40
int PyList_Size(object) except -1
41
object PyUnicode_Join(object, object)
42
object PyUnicode_AsASCIIString(object)
28
44
cdef extern from "ctype.h":
29
45
int isalnum(char c)
47
cdef extern from "string.h":
48
char *strstr(char *a, char *b)
49
int strcmp(char *a, char *b)
31
52
from bzrlib.rio import Stanza
33
54
def _valid_tag(tag):
36
58
c_tag = PyString_AS_STRING(tag)
37
59
c_len = PyString_GET_SIZE(tag)
38
60
for i from 0 <= i < c_len:
51
81
# using 'assert' to process user input, or raising ValueError
52
82
# rather than a more specific error.
53
83
for line in line_iter:
54
if line is None or line == '':
86
if not PyString_CheckExact(line):
87
raise TypeError("%r is not a line" % line)
88
c_line = PyString_AS_STRING(line)
89
c_len = PyString_GET_SIZE(line)
90
if strcmp(c_line, "") == 0:
55
91
break # end of file
92
if strcmp(c_line, "\n") == 0:
57
93
break # end of stanza
58
if line[0] == '\t': # continues previous value
94
if c_line[0] == c'\t': # continues previous value
60
96
raise ValueError('invalid continuation line %r' % line)
61
accum_value.append('\n' + line[1:-1])
97
new_value = PyUnicode_DecodeUTF8(c_line+1, c_len-1, "strict")
62
98
else: # new tag:value line
63
99
if tag is not None:
64
pairs.append((tag, ''.join(accum_value).decode('utf-8')))
66
colon_index = line.index(': ')
100
pairs.append((tag, _join_utf8_strip(accum_value)))
101
colon = <char *>strstr(c_line, ": ")
68
103
raise ValueError('tag/value separator not found in line %r'
70
tag = line[:colon_index]
71
#if not _valid_tag(tag):
72
# raise ValueError("invalid rio tag %r" % (tag,))
73
accum_value = [line[colon_index+2:-1]]
105
tag = PyString_FromStringAndSize(c_line, colon-c_line)
106
if not _valid_tag(tag):
107
raise ValueError("invalid rio tag %r" % (tag,))
109
new_value = PyUnicode_DecodeUTF8(colon+2, c_len-(colon-c_line+2),
111
accum_value.append(new_value)
74
112
if tag is not None: # add last tag-value
75
pairs.append((tag, ''.join(accum_value).decode('utf-8')))
113
pairs.append((tag, _join_utf8_strip(accum_value)))
76
114
return Stanza.from_pairs(pairs)
77
115
else: # didn't see any content
81
119
def _read_stanza_unicode(unicode_iter):
86
125
# TODO: jam 20060922 This code should raise real errors rather than
87
126
# using 'assert' to process user input, or raising ValueError
88
127
# rather than a more specific error.
89
128
for line in unicode_iter:
90
if line is None or line == '':
129
if line is None or line == unicode(''):
91
130
break # end of file
131
if line == unicode('\n'):
93
132
break # end of stanza
95
if line[0] == '\t': # continues previous value
133
if line[0] == unicode('\t'): # continues previous value
97
raise ValueError('invalid continuation line %r' % real_l)
98
accum_value += '\n' + line[1:-1]
135
raise ValueError('invalid continuation line %r' % line)
136
accum_value.append(line[1:])
99
137
else: # new tag:value line
100
138
if tag is not None:
101
pairs.append((tag, accum_value))
139
pairs.append((tag, PyUnicode_Join(unicode(""), accum_value[:-1])))
103
colon_index = line.index(': ')
141
colon_index = line.index(unicode(': '))
104
142
except ValueError:
105
143
raise ValueError('tag/value separator not found in line %r'
107
tag = str(line[:colon_index])
108
#if not _valid_tag(tag):
109
# raise ValueError("invalid rio tag %r" % (tag,))
110
accum_value = line[colon_index+2:-1]
145
tag = PyUnicode_AsASCIIString(line[0:colon_index])
146
if not _valid_tag(tag):
147
raise ValueError("invalid rio tag %r" % (tag,))
148
accum_value = [line[colon_index+2:]]
112
150
if tag is not None: # add last tag-value
113
pairs.append((tag, accum_value))
151
pairs.append((tag, PyUnicode_Join(unicode(""), accum_value[:-1])))
114
152
return Stanza.from_pairs(pairs)
115
153
else: # didn't see any content