~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_chunks_to_lines_pyx.pyx

  • Committer: John Arbash Meinel
  • Date: 2008-12-11 18:26:16 UTC
  • mto: This revision was merged to the branch mainline in revision 3895.
  • Revision ID: john@arbash-meinel.com-20081211182616-l9m9rjnea3bebaor
If we split into 2 loops, we get 440us for already lines, and the
same time when it is not.
The only downside is that it requires looping over the same data twice.

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
    """
53
53
    cdef char *c_str
54
54
    cdef char *newline
55
 
    cdef char *c_last # the last valid character of the string
 
55
    cdef char *c_last
56
56
    cdef Py_ssize_t the_len
57
 
    cdef Py_ssize_t chunks_len
58
57
    cdef int last_no_newline
59
 
    cdef int is_already_lines
60
58
 
61
59
    # Check to see if the chunks are already lines
62
 
    chunks_len = len(chunks)
63
 
    if chunks_len == 0:
64
 
        return chunks
65
 
 
66
 
    lines = []
67
 
    tail = None # Any remainder from the previous chunk
68
60
    last_no_newline = 0
69
 
    is_already_lines = 1
70
61
    for chunk in chunks:
71
62
        if last_no_newline:
72
63
            # We have a chunk which followed a chunk without a newline, so this
73
64
            # is not a simple list of lines.
74
 
            is_already_lines = 0
75
 
        if tail is not None:
76
 
            chunk = tail + chunk
77
 
            tail = None
 
65
            break
78
66
        # Switching from PyString_AsStringAndSize to PyString_CheckExact and
79
67
        # then the macros GET_SIZE and AS_STRING saved us 40us / 470us.
80
68
        # It seems PyString_AsStringAndSize can actually trigger a conversion,
83
71
            raise TypeError('chunk is not a string')
84
72
        the_len = PyString_GET_SIZE(chunk)
85
73
        if the_len == 0:
 
74
            # An empty string is never a valid line
 
75
            break
 
76
        c_str = PyString_AS_STRING(chunk)
 
77
        c_last = c_str + the_len - 1
 
78
        newline = <char *>memchr(c_str, c'\n', the_len)
 
79
        if newline != c_last:
 
80
            if newline == NULL:
 
81
                # Missing a newline. Only valid as the last line
 
82
                last_no_newline = 1
 
83
            else:
 
84
                # There is a newline in the middle, we must resplit
 
85
                break
 
86
    else:
 
87
        # Everything was already a list of lines
 
88
        return chunks
 
89
 
 
90
    # We know we need to create a new list of lines
 
91
    lines = []
 
92
    tail = None # Any remainder from the previous chunk
 
93
    for chunk in chunks:
 
94
        if tail is not None:
 
95
            chunk = tail + chunk
 
96
            tail = None
 
97
        if not PyString_CheckExact(chunk):
 
98
            raise TypeError('chunk is not a string')
 
99
        the_len = PyString_GET_SIZE(chunk)
 
100
        if the_len == 0:
86
101
            # An empty string is never a valid line, and we don't need to
87
102
            # append anything
88
 
            is_already_lines = 0
89
103
            continue
90
104
        c_str = PyString_AS_STRING(chunk)
91
105
        c_last = c_str + the_len - 1
97
111
            # A chunk without a newline, if this is the last entry, then we
98
112
            # allow it
99
113
            tail = chunk
100
 
            last_no_newline = 1
101
114
        else:
102
115
            # We have a newline in the middle, loop until we've consumed all
103
116
            # lines
104
 
            is_already_lines = 0
105
117
            while newline != NULL:
106
118
                line = PyString_FromStringAndSize(c_str, newline - c_str + 1)
107
119
                PyList_Append(lines, line)
113
125
                if newline == NULL:
114
126
                    tail = PyString_FromStringAndSize(c_str, the_len)
115
127
                    break
116
 
    if is_already_lines:
117
 
        return chunks
118
128
    if tail is not None:
119
129
        PyList_Append(lines, tail)
120
130
    return lines