/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/_rio_pyx.pyx

  • Committer: Richard Wilbur
  • Date: 2016-02-04 19:07:28 UTC
  • mto: This revision was merged to the branch mainline in revision 6618.
  • Revision ID: richard.wilbur@gmail.com-20160204190728-p0zvfii6zase0fw7
Update COPYING.txt from the original http://www.gnu.org/licenses/gpl-2.0.txt  (Only differences were in whitespace.)  Thanks to Petr Stodulka for pointing out the discrepancy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Pyrex implementation of _read_stanza_*."""
18
18
 
19
 
from __future__ import absolute_import
20
 
 
21
 
 
 
19
#python2.4 support
22
20
cdef extern from "python-compat.h":
23
21
    pass
24
22
 
25
 
from cpython.bytes cimport (
26
 
    PyBytes_CheckExact,
27
 
    PyBytes_FromStringAndSize,
28
 
    PyBytes_AS_STRING,
29
 
    PyBytes_GET_SIZE,
30
 
    )
31
 
from cpython.unicode cimport (
32
 
    PyUnicode_CheckExact,
33
 
    PyUnicode_DecodeUTF8,
34
 
    # Deprecated after PEP 393 changes
35
 
    PyUnicode_AS_UNICODE,
36
 
    PyUnicode_FromUnicode,
37
 
    PyUnicode_GET_SIZE,
38
 
    )
39
 
from cpython.list cimport (
40
 
    PyList_Append,
41
 
    )
42
 
from cpython.mem cimport (
43
 
    PyMem_Free,
44
 
    PyMem_Malloc,
45
 
    PyMem_Realloc,
46
 
    )
47
 
from cpython.version cimport (
48
 
    PY_MAJOR_VERSION,
49
 
    )
 
23
cdef extern from "stdlib.h":
 
24
    void *malloc(int)
 
25
    void *realloc(void *, int)
 
26
    void free(void *)
50
27
 
51
28
cdef extern from "Python.h":
 
29
    ctypedef int Py_ssize_t # Required for older pyrex versions
52
30
    ctypedef int Py_UNICODE
 
31
    char *PyString_AS_STRING(object s)
 
32
    Py_ssize_t PyString_GET_SIZE(object t) except -1
 
33
    object PyUnicode_DecodeUTF8(char *string, Py_ssize_t length, char *errors)
 
34
    object PyString_FromStringAndSize(char *s, Py_ssize_t len)
 
35
    int PyString_CheckExact(object)
 
36
    int PyUnicode_CheckExact(object)
 
37
    object PyUnicode_Join(object, object)
53
38
    object PyUnicode_EncodeASCII(Py_UNICODE *, int, char *)
 
39
    Py_UNICODE *PyUnicode_AS_UNICODE(object)
 
40
    Py_UNICODE *PyUnicode_AsUnicode(object)
 
41
    Py_ssize_t PyUnicode_GET_SIZE(object) except -1
 
42
    int PyList_Append(object, object) except -1    
54
43
    int Py_UNICODE_ISLINEBREAK(Py_UNICODE)
55
 
 
56
 
    # GZ 2017-09-11: Not sure why cython unicode module lacks this?
57
 
    object PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size)
58
 
 
59
 
    # Python 3.3 or later unicode handling
60
 
    char* PyUnicode_AsUTF8AndSize(object unicode, Py_ssize_t *size)
61
 
 
62
 
from libc.string cimport (
63
 
    memcpy,
64
 
    )
65
 
 
66
 
from .rio import Stanza
67
 
 
 
44
    object PyUnicode_FromUnicode(Py_UNICODE *, int)
 
45
    void *Py_UNICODE_COPY(Py_UNICODE *, Py_UNICODE *, int)
 
46
 
 
47
cdef extern from "string.h":
 
48
    void *memcpy(void *, void *, int)
 
49
 
 
50
from bzrlib.rio import Stanza
68
51
 
69
52
cdef int _valid_tag_char(char c): # cannot_raise
70
 
    return (c == c'_' or c == c'-' or
 
53
    return (c == c'_' or c == c'-' or 
71
54
            (c >= c'a' and c <= c'z') or
72
55
            (c >= c'A' and c <= c'Z') or
73
56
            (c >= c'0' and c <= c'9'))
77
60
    cdef char *c_tag
78
61
    cdef Py_ssize_t c_len
79
62
    cdef int i
80
 
    # GZ 2017-09-11: Encapsulate native string as ascii tag somewhere neater
81
 
    if PY_MAJOR_VERSION >= 3:
82
 
        if not PyUnicode_CheckExact(tag):
83
 
            raise TypeError(tag)
84
 
        c_tag = PyUnicode_AsUTF8AndSize(tag, &c_len)
85
 
    else:
86
 
        if not PyBytes_CheckExact(tag):
87
 
            raise TypeError(tag)
88
 
        c_tag = PyBytes_AS_STRING(tag)
89
 
        c_len = PyBytes_GET_SIZE(tag)
 
63
    if not PyString_CheckExact(tag):
 
64
        raise TypeError(tag)
 
65
    c_tag = PyString_AS_STRING(tag)
 
66
    c_len = PyString_GET_SIZE(tag)
90
67
    if c_len < 1:
91
68
        return False
92
69
    for i from 0 <= i < c_len:
95
72
    return True
96
73
 
97
74
 
98
 
cdef object _split_first_line_utf8(char *line, int len,
 
75
cdef object _split_first_line_utf8(char *line, int len, 
99
76
                                   char *value, Py_ssize_t *value_len):
100
77
    cdef int i
101
78
    for i from 0 <= i < len:
104
81
                raise ValueError("invalid tag in line %r" % line)
105
82
            memcpy(value, line+i+2, len-i-2)
106
83
            value_len[0] = len-i-2
107
 
            if PY_MAJOR_VERSION >= 3:
108
 
                return PyUnicode_FromStringAndSize(line, i)
109
 
            return PyBytes_FromStringAndSize(line, i)
 
84
            return PyString_FromStringAndSize(line, i)
110
85
    raise ValueError('tag/value separator not found in line %r' % line)
111
86
 
112
87
 
113
 
cdef object _split_first_line_unicode(Py_UNICODE *line, int len,
 
88
cdef object _split_first_line_unicode(Py_UNICODE *line, int len, 
114
89
                                      Py_UNICODE *value, Py_ssize_t *value_len):
115
90
    cdef int i
116
91
    for i from 0 <= i < len:
120
95
                                 PyUnicode_FromUnicode(line, len))
121
96
            memcpy(value, &line[i+2], (len-i-2) * sizeof(Py_UNICODE))
122
97
            value_len[0] = len-i-2
123
 
            if PY_MAJOR_VERSION >= 3:
124
 
                return PyUnicode_FromUnicode(line, i)
125
98
            return PyUnicode_EncodeASCII(line, i, "strict")
126
99
    raise ValueError("tag/value separator not found in line %r" %
127
100
                     PyUnicode_FromUnicode(line, len))
136
109
    tag = None
137
110
    accum_len = 0
138
111
    accum_size = 4096
139
 
    accum_value = <char *>PyMem_Malloc(accum_size)
 
112
    accum_value = <char *>malloc(accum_size)
140
113
    if accum_value == NULL:
141
114
        raise MemoryError
142
115
    try:
143
116
        for line in line_iter:
144
117
            if line is None:
145
118
                break # end of file
146
 
            if not PyBytes_CheckExact(line):
 
119
            if not PyString_CheckExact(line):
147
120
                raise TypeError("%r is not a plain string" % line)
148
 
            c_line = PyBytes_AS_STRING(line)
149
 
            c_len = PyBytes_GET_SIZE(line)
 
121
            c_line = PyString_AS_STRING(line)
 
122
            c_len = PyString_GET_SIZE(line)
150
123
            if c_len < 1:
151
124
                break       # end of file
152
125
            if c_len == 1 and c_line[0] == c"\n":
153
126
                break       # end of stanza
154
127
            if accum_len + c_len > accum_size:
155
128
                accum_size = (accum_len + c_len)
156
 
                new_accum_value = <char *>PyMem_Realloc(accum_value, accum_size)
 
129
                new_accum_value = <char *>realloc(accum_value, accum_size)
157
130
                if new_accum_value == NULL:
158
131
                    raise MemoryError
159
132
                else:
165
138
                accum_len = accum_len + c_len-1
166
139
            else: # new tag:value line
167
140
                if tag is not None:
168
 
                    PyList_Append(pairs,
169
 
                        (tag, PyUnicode_DecodeUTF8(accum_value, accum_len-1,
 
141
                    PyList_Append(pairs, 
 
142
                        (tag, PyUnicode_DecodeUTF8(accum_value, accum_len-1, 
170
143
                                                   "strict")))
171
 
                tag = _split_first_line_utf8(c_line, c_len, accum_value,
 
144
                tag = _split_first_line_utf8(c_line, c_len, accum_value, 
172
145
                                             &accum_len)
173
146
                if not _valid_tag(tag):
174
147
                    raise ValueError("invalid rio tag %r" % (tag,))
175
148
        if tag is not None: # add last tag-value
176
 
            PyList_Append(pairs,
 
149
            PyList_Append(pairs, 
177
150
                (tag, PyUnicode_DecodeUTF8(accum_value, accum_len-1, "strict")))
178
151
            return Stanza.from_pairs(pairs)
179
152
        else:     # didn't see any content
180
153
            return None
181
154
    finally:
182
 
        PyMem_Free(accum_value)
 
155
        free(accum_value)
183
156
 
184
157
 
185
158
def _read_stanza_unicode(unicode_iter):
191
164
    tag = None
192
165
    accum_len = 0
193
166
    accum_size = 4096
194
 
    accum_value = <Py_UNICODE *>PyMem_Malloc(accum_size*sizeof(Py_UNICODE))
 
167
    accum_value = <Py_UNICODE *>malloc(accum_size*sizeof(Py_UNICODE))
195
168
    if accum_value == NULL:
196
169
        raise MemoryError
197
170
    try:
208
181
                break       # end of stanza
209
182
            if accum_len + c_len > accum_size:
210
183
                accum_size = accum_len + c_len
211
 
                new_accum_value = <Py_UNICODE *>PyMem_Realloc(accum_value,
 
184
                new_accum_value = <Py_UNICODE *>realloc(accum_value, 
212
185
                    accum_size*sizeof(Py_UNICODE))
213
186
                if new_accum_value == NULL:
214
187
                    raise MemoryError
222
195
                accum_len = accum_len + (c_len-1)
223
196
            else: # new tag:value line
224
197
                if tag is not None:
225
 
                    PyList_Append(pairs,
 
198
                    PyList_Append(pairs, 
226
199
                        (tag, PyUnicode_FromUnicode(accum_value, accum_len-1)))
227
 
                tag = _split_first_line_unicode(c_line, c_len, accum_value,
 
200
                tag = _split_first_line_unicode(c_line, c_len, accum_value, 
228
201
                                                &accum_len)
229
202
                if not _valid_tag(tag):
230
203
                    raise ValueError("invalid rio tag %r" % (tag,))
235
208
        else:     # didn't see any content
236
209
            return None
237
210
    finally:
238
 
        PyMem_Free(accum_value)
 
211
        free(accum_value)