| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  | /* stringlib: split implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef STRINGLIB_FASTSEARCH_H
 | 
					
						
							|  |  |  | #error must include "stringlib/fastsearch.h" before including this module
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Overallocate the initial list to reduce the number of reallocs for small
 | 
					
						
							|  |  |  |    split sizes.  Eg, "A A A A A A A A A A".split() (10 elements) has three | 
					
						
							|  |  |  |    resizes, to sizes 4, 8, then 16.  Most observed string splits are for human | 
					
						
							|  |  |  |    text (roughly 11 words per line) and field delimited data (usually 1-10 | 
					
						
							|  |  |  |    fields).  For large strings the split algorithms are bandwidth limited | 
					
						
							|  |  |  |    so increasing the preallocation likely will not improve things.*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_PREALLOC 12
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 5 splits gives 6 elements */ | 
					
						
							|  |  |  | #define PREALLOC_SIZE(maxsplit) \
 | 
					
						
							|  |  |  |     (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SPLIT_APPEND(data, left, right)         \
 | 
					
						
							|  |  |  |     sub = STRINGLIB_NEW((data) + (left),        \ | 
					
						
							|  |  |  |                         (right) - (left));      \ | 
					
						
							|  |  |  |     if (sub == NULL)                            \ | 
					
						
							|  |  |  |         goto onError;                           \ | 
					
						
							|  |  |  |     if (PyList_Append(list, sub)) {             \ | 
					
						
							|  |  |  |         Py_DECREF(sub);                         \ | 
					
						
							|  |  |  |         goto onError;                           \ | 
					
						
							|  |  |  |     }                                           \ | 
					
						
							|  |  |  |     else                                        \ | 
					
						
							|  |  |  |         Py_DECREF(sub); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define SPLIT_ADD(data, left, right) {          \
 | 
					
						
							|  |  |  |     sub = STRINGLIB_NEW((data) + (left),        \ | 
					
						
							|  |  |  |                         (right) - (left));      \ | 
					
						
							|  |  |  |     if (sub == NULL)                            \ | 
					
						
							|  |  |  |         goto onError;                           \ | 
					
						
							|  |  |  |     if (count < MAX_PREALLOC) {                 \ | 
					
						
							|  |  |  |         PyList_SET_ITEM(list, count, sub);      \ | 
					
						
							|  |  |  |     } else {                                    \ | 
					
						
							|  |  |  |         if (PyList_Append(list, sub)) {         \ | 
					
						
							|  |  |  |             Py_DECREF(sub);                     \ | 
					
						
							|  |  |  |             goto onError;                       \ | 
					
						
							|  |  |  |         }                                       \ | 
					
						
							|  |  |  |         else                                    \ | 
					
						
							|  |  |  |             Py_DECREF(sub);                     \ | 
					
						
							|  |  |  |     }                                           \ | 
					
						
							|  |  |  |     count++; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Always force the list to the expected size. */ | 
					
						
							|  |  |  | #define FIX_PREALLOC_SIZE(list) Py_SIZE(list) = count
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(split_whitespace)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                            const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                            Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, j, count=0; | 
					
						
							|  |  |  |     PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     PyObject *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = j = 0; | 
					
						
							|  |  |  |     while (maxcount-- > 0) { | 
					
						
							|  |  |  |         while (i < str_len && STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  |         if (i == str_len) break; | 
					
						
							|  |  |  |         j = i; i++; | 
					
						
							|  |  |  |         while (i < str_len && !STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |         if (j == 0 && i == str_len && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |             /* No whitespace in str_obj, so just use it as list[0] */ | 
					
						
							|  |  |  |             Py_INCREF(str_obj); | 
					
						
							|  |  |  |             PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |             count++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         SPLIT_ADD(str, j, i); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i < str_len) { | 
					
						
							|  |  |  |         /* Only occurs when maxcount was reached */ | 
					
						
							|  |  |  |         /* Skip any remaining whitespace and copy to end of string */ | 
					
						
							|  |  |  |         while (i < str_len && STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  |         if (i != str_len) | 
					
						
							|  |  |  |             SPLIT_ADD(str, i, str_len); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(split_char)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                      const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                      const STRINGLIB_CHAR ch, | 
					
						
							|  |  |  |                      Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, j, count=0; | 
					
						
							|  |  |  |     PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     PyObject *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = j = 0; | 
					
						
							|  |  |  |     while ((j < str_len) && (maxcount-- > 0)) { | 
					
						
							|  |  |  |         for(; j < str_len; j++) { | 
					
						
							|  |  |  |             /* I found that using memchr makes no difference */ | 
					
						
							|  |  |  |             if (str[j] == ch) { | 
					
						
							|  |  |  |                 SPLIT_ADD(str, i, j); | 
					
						
							|  |  |  |                 i = j = j + 1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |     if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |         /* ch not in str_obj, so just use str_obj as list[0] */ | 
					
						
							|  |  |  |         Py_INCREF(str_obj); | 
					
						
							|  |  |  |         PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |         count++; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if (i <= str_len) { | 
					
						
							|  |  |  |         SPLIT_ADD(str, i, str_len); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(split)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                 const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                 const STRINGLIB_CHAR* sep, Py_ssize_t sep_len, | 
					
						
							|  |  |  |                 Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, j, pos, count=0; | 
					
						
							|  |  |  |     PyObject *list, *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sep_len == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "empty separator"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sep_len == 1) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |         return STRINGLIB(split_char)(str_obj, str, str_len, sep[0], maxcount); | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = j = 0; | 
					
						
							|  |  |  |     while (maxcount-- > 0) { | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |         pos = FASTSEARCH(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH); | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |         if (pos < 0) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         j = i + pos; | 
					
						
							|  |  |  |         SPLIT_ADD(str, i, j); | 
					
						
							|  |  |  |         i = j + sep_len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |     if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |         /* No match in str_obj, so just use it as list[0] */ | 
					
						
							|  |  |  |         Py_INCREF(str_obj); | 
					
						
							|  |  |  |         PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |         count++; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         SPLIT_ADD(str, i, str_len); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(rsplit_whitespace)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                             const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                             Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, j, count=0; | 
					
						
							|  |  |  |     PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     PyObject *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = j = str_len - 1; | 
					
						
							|  |  |  |     while (maxcount-- > 0) { | 
					
						
							|  |  |  |         while (i >= 0 && STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i--; | 
					
						
							|  |  |  |         if (i < 0) break; | 
					
						
							|  |  |  |         j = i; i--; | 
					
						
							|  |  |  |         while (i >= 0 && !STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i--; | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |         if (j == str_len - 1 && i < 0 && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |             /* No whitespace in str_obj, so just use it as list[0] */ | 
					
						
							|  |  |  |             Py_INCREF(str_obj); | 
					
						
							|  |  |  |             PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |             count++; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         SPLIT_ADD(str, i + 1, j + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (i >= 0) { | 
					
						
							|  |  |  |         /* Only occurs when maxcount was reached */ | 
					
						
							|  |  |  |         /* Skip any remaining whitespace and copy to beginning of string */ | 
					
						
							|  |  |  |         while (i >= 0 && STRINGLIB_ISSPACE(str[i])) | 
					
						
							|  |  |  |             i--; | 
					
						
							|  |  |  |         if (i >= 0) | 
					
						
							|  |  |  |             SPLIT_ADD(str, 0, i + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     if (PyList_Reverse(list) < 0) | 
					
						
							|  |  |  |         goto onError; | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(rsplit_char)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                       const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                       const STRINGLIB_CHAR ch, | 
					
						
							|  |  |  |                       Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, j, count=0; | 
					
						
							|  |  |  |     PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     PyObject *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = j = str_len - 1; | 
					
						
							|  |  |  |     while ((i >= 0) && (maxcount-- > 0)) { | 
					
						
							|  |  |  |         for(; i >= 0; i--) { | 
					
						
							|  |  |  |             if (str[i] == ch) { | 
					
						
							|  |  |  |                 SPLIT_ADD(str, i + 1, j + 1); | 
					
						
							|  |  |  |                 j = i = i - 1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |     if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |         /* ch not in str_obj, so just use str_obj as list[0] */ | 
					
						
							|  |  |  |         Py_INCREF(str_obj); | 
					
						
							|  |  |  |         PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |         count++; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     if (j >= -1) { | 
					
						
							|  |  |  |         SPLIT_ADD(str, 0, j + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     if (PyList_Reverse(list) < 0) | 
					
						
							|  |  |  |         goto onError; | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(rsplit)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                  const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                  const STRINGLIB_CHAR* sep, Py_ssize_t sep_len, | 
					
						
							|  |  |  |                  Py_ssize_t maxcount) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t j, pos, count=0; | 
					
						
							|  |  |  |     PyObject *list, *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (sep_len == 0) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ValueError, "empty separator"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (sep_len == 1) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |         return STRINGLIB(rsplit_char)(str_obj, str, str_len, sep[0], maxcount); | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     list = PyList_New(PREALLOC_SIZE(maxcount)); | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     j = str_len; | 
					
						
							|  |  |  |     while (maxcount-- > 0) { | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  |         pos = FASTSEARCH(str, j, sep, sep_len, -1, FAST_RSEARCH); | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |         if (pos < 0) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         SPLIT_ADD(str, pos + sep_len, j); | 
					
						
							|  |  |  |         j = pos; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |     if (count == 0 && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |         /* No match in str_obj, so just use it as list[0] */ | 
					
						
							|  |  |  |         Py_INCREF(str_obj); | 
					
						
							|  |  |  |         PyList_SET_ITEM(list, 0, (PyObject *)str_obj); | 
					
						
							|  |  |  |         count++; | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         SPLIT_ADD(str, 0, j); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     FIX_PREALLOC_SIZE(list); | 
					
						
							|  |  |  |     if (PyList_Reverse(list) < 0) | 
					
						
							|  |  |  |         goto onError; | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_LOCAL_INLINE(PyObject *) | 
					
						
							| 
									
										
										
										
											2011-09-28 07:41:54 +02:00
										 |  |  | STRINGLIB(splitlines)(PyObject* str_obj, | 
					
						
							| 
									
										
										
										
											2010-01-13 08:07:53 +00:00
										 |  |  |                      const STRINGLIB_CHAR* str, Py_ssize_t str_len, | 
					
						
							|  |  |  |                      int keepends) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* This does not use the preallocated list because splitlines is
 | 
					
						
							|  |  |  |        usually run with hundreds of newlines.  The overhead of | 
					
						
							|  |  |  |        switching between PyList_SET_ITEM and append causes about a | 
					
						
							|  |  |  |        2-3% slowdown for that common case.  A smarter implementation | 
					
						
							|  |  |  |        could move the if check out, so the SET_ITEMs are done first | 
					
						
							|  |  |  |        and the appends only done when the prealloc buffer is full. | 
					
						
							|  |  |  |        That's too much work for little gain.*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     register Py_ssize_t i; | 
					
						
							|  |  |  |     register Py_ssize_t j; | 
					
						
							|  |  |  |     PyObject *list = PyList_New(0); | 
					
						
							|  |  |  |     PyObject *sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (list == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = j = 0; i < str_len; ) { | 
					
						
							|  |  |  |         Py_ssize_t eol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Find a line and append it */ | 
					
						
							|  |  |  |         while (i < str_len && !STRINGLIB_ISLINEBREAK(str[i])) | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Skip the line break reading CRLF as one line break */ | 
					
						
							|  |  |  |         eol = i; | 
					
						
							|  |  |  |         if (i < str_len) { | 
					
						
							|  |  |  |             if (str[i] == '\r' && i + 1 < str_len && str[i+1] == '\n') | 
					
						
							|  |  |  |                 i += 2; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 i++; | 
					
						
							|  |  |  |             if (keepends) | 
					
						
							|  |  |  |                 eol = i; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #ifndef STRINGLIB_MUTABLE
 | 
					
						
							|  |  |  |         if (j == 0 && eol == str_len && STRINGLIB_CHECK_EXACT(str_obj)) { | 
					
						
							|  |  |  |             /* No linebreak in str_obj, so just use it as list[0] */ | 
					
						
							|  |  |  |             if (PyList_Append(list, str_obj)) | 
					
						
							|  |  |  |                 goto onError; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         SPLIT_APPEND(str, j, eol); | 
					
						
							|  |  |  |         j = i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onError: | 
					
						
							|  |  |  |     Py_DECREF(list); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |