AppPkg/Applications/Python/Python-2.7.10: Initial Checkin part 3/5.
The Objects directory from the cPython 2.7.10 distribution, along with the LICENSE and README files. These files are unchanged and set the baseline for subsequent commits. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Daryl McDaniel <edk2-lists@mc2research.org> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18739 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
committed by
darylm503
parent
7eb75bccb5
commit
53b2ba5790
@@ -0,0 +1,40 @@
|
||||
bits shared by the stringobject and unicodeobject implementations (and
|
||||
possibly other modules, in a not too distant future).
|
||||
|
||||
the stuff in here is included into relevant places; see the individual
|
||||
source files for details.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
the following defines used by the different modules:
|
||||
|
||||
STRINGLIB_CHAR
|
||||
|
||||
the type used to hold a character (char or Py_UNICODE)
|
||||
|
||||
STRINGLIB_EMPTY
|
||||
|
||||
a PyObject representing the empty string, only to be used if
|
||||
STRINGLIB_MUTABLE is 0
|
||||
|
||||
Py_ssize_t STRINGLIB_LEN(PyObject*)
|
||||
|
||||
returns the length of the given string object (which must be of the
|
||||
right type)
|
||||
|
||||
PyObject* STRINGLIB_NEW(STRINGLIB_CHAR*, Py_ssize_t)
|
||||
|
||||
creates a new string object
|
||||
|
||||
STRINGLIB_CHAR* STRINGLIB_STR(PyObject*)
|
||||
|
||||
returns the pointer to the character data for the given string
|
||||
object (which must be of the right type)
|
||||
|
||||
int STRINGLIB_CHECK_EXACT(PyObject *)
|
||||
|
||||
returns true if the object is an instance of our type, not a subclass
|
||||
|
||||
STRINGLIB_MUTABLE
|
||||
|
||||
must be 0 or 1 to tell the cpp macros in stringlib code if the object
|
||||
being operated on is mutable or not
|
@@ -0,0 +1,30 @@
|
||||
/* stringlib: count implementation */
|
||||
|
||||
#ifndef STRINGLIB_COUNT_H
|
||||
#define STRINGLIB_COUNT_H
|
||||
|
||||
#ifndef STRINGLIB_FASTSEARCH_H
|
||||
#error must include "stringlib/fastsearch.h" before including this module
|
||||
#endif
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
stringlib_count(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
|
||||
Py_ssize_t maxcount)
|
||||
{
|
||||
Py_ssize_t count;
|
||||
|
||||
if (str_len < 0)
|
||||
return 0; /* start > len(str) */
|
||||
if (sub_len == 0)
|
||||
return (str_len < maxcount) ? str_len + 1 : maxcount;
|
||||
|
||||
count = fastsearch(str, str_len, sub, sub_len, maxcount, FAST_COUNT);
|
||||
|
||||
if (count < 0)
|
||||
return 0; /* no match */
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,109 @@
|
||||
/* NOTE: this API is -ONLY- for use with single byte character strings. */
|
||||
/* Do not use it with Unicode. */
|
||||
|
||||
#include "bytes_methods.h"
|
||||
|
||||
static PyObject*
|
||||
stringlib_isspace(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_isspace(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_isalpha(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_isalpha(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_isalnum(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_isalnum(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_isdigit(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_isdigit(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_islower(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_islower(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_isupper(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_isupper(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_istitle(PyObject *self)
|
||||
{
|
||||
return _Py_bytes_istitle(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
}
|
||||
|
||||
|
||||
/* functions that return a new object partially translated by ctype funcs: */
|
||||
|
||||
static PyObject*
|
||||
stringlib_lower(PyObject *self)
|
||||
{
|
||||
PyObject* newobj;
|
||||
newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));
|
||||
if (!newobj)
|
||||
return NULL;
|
||||
_Py_bytes_lower(STRINGLIB_STR(newobj), STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_upper(PyObject *self)
|
||||
{
|
||||
PyObject* newobj;
|
||||
newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));
|
||||
if (!newobj)
|
||||
return NULL;
|
||||
_Py_bytes_upper(STRINGLIB_STR(newobj), STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_title(PyObject *self)
|
||||
{
|
||||
PyObject* newobj;
|
||||
newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));
|
||||
if (!newobj)
|
||||
return NULL;
|
||||
_Py_bytes_title(STRINGLIB_STR(newobj), STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_capitalize(PyObject *self)
|
||||
{
|
||||
PyObject* newobj;
|
||||
newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));
|
||||
if (!newobj)
|
||||
return NULL;
|
||||
_Py_bytes_capitalize(STRINGLIB_STR(newobj), STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
stringlib_swapcase(PyObject *self)
|
||||
{
|
||||
PyObject* newobj;
|
||||
newobj = STRINGLIB_NEW(NULL, STRINGLIB_LEN(self));
|
||||
if (!newobj)
|
||||
return NULL;
|
||||
_Py_bytes_swapcase(STRINGLIB_STR(newobj), STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
return newobj;
|
||||
}
|
@@ -0,0 +1,160 @@
|
||||
/* stringlib: fastsearch implementation */
|
||||
|
||||
#ifndef STRINGLIB_FASTSEARCH_H
|
||||
#define STRINGLIB_FASTSEARCH_H
|
||||
|
||||
/* fast search/count implementation, based on a mix between boyer-
|
||||
moore and horspool, with a few more bells and whistles on the top.
|
||||
for some more background, see: http://effbot.org/zone/stringlib.htm */
|
||||
|
||||
/* note: fastsearch may access s[n], which isn't a problem when using
|
||||
Python's ordinary string types, but may cause problems if you're
|
||||
using this code in other contexts. also, the count mode returns -1
|
||||
if there cannot possible be a match in the target string, and 0 if
|
||||
it has actually checked for matches, but didn't find any. callers
|
||||
beware! */
|
||||
|
||||
#define FAST_COUNT 0
|
||||
#define FAST_SEARCH 1
|
||||
#define FAST_RSEARCH 2
|
||||
|
||||
#if LONG_BIT >= 128
|
||||
#define STRINGLIB_BLOOM_WIDTH 128
|
||||
#elif LONG_BIT >= 64
|
||||
#define STRINGLIB_BLOOM_WIDTH 64
|
||||
#elif LONG_BIT >= 32
|
||||
#define STRINGLIB_BLOOM_WIDTH 32
|
||||
#else
|
||||
#error "LONG_BIT is smaller than 32"
|
||||
#endif
|
||||
|
||||
#define STRINGLIB_BLOOM_ADD(mask, ch) \
|
||||
((mask |= (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))
|
||||
#define STRINGLIB_BLOOM(mask, ch) \
|
||||
((mask & (1UL << ((ch) & (STRINGLIB_BLOOM_WIDTH -1)))))
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n,
|
||||
const STRINGLIB_CHAR* p, Py_ssize_t m,
|
||||
Py_ssize_t maxcount, int mode)
|
||||
{
|
||||
unsigned long mask;
|
||||
Py_ssize_t skip, count = 0;
|
||||
Py_ssize_t i, j, mlast, w;
|
||||
|
||||
w = n - m;
|
||||
|
||||
if (w < 0 || (mode == FAST_COUNT && maxcount == 0))
|
||||
return -1;
|
||||
|
||||
/* look for special cases */
|
||||
if (m <= 1) {
|
||||
if (m <= 0)
|
||||
return -1;
|
||||
/* use special case for 1-character strings */
|
||||
if (mode == FAST_COUNT) {
|
||||
for (i = 0; i < n; i++)
|
||||
if (s[i] == p[0]) {
|
||||
count++;
|
||||
if (count == maxcount)
|
||||
return maxcount;
|
||||
}
|
||||
return count;
|
||||
} else if (mode == FAST_SEARCH) {
|
||||
for (i = 0; i < n; i++)
|
||||
if (s[i] == p[0])
|
||||
return i;
|
||||
} else { /* FAST_RSEARCH */
|
||||
for (i = n - 1; i > -1; i--)
|
||||
if (s[i] == p[0])
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
mlast = m - 1;
|
||||
skip = mlast - 1;
|
||||
mask = 0;
|
||||
|
||||
if (mode != FAST_RSEARCH) {
|
||||
|
||||
/* create compressed boyer-moore delta 1 table */
|
||||
|
||||
/* process pattern[:-1] */
|
||||
for (i = 0; i < mlast; i++) {
|
||||
STRINGLIB_BLOOM_ADD(mask, p[i]);
|
||||
if (p[i] == p[mlast])
|
||||
skip = mlast - i - 1;
|
||||
}
|
||||
/* process pattern[-1] outside the loop */
|
||||
STRINGLIB_BLOOM_ADD(mask, p[mlast]);
|
||||
|
||||
for (i = 0; i <= w; i++) {
|
||||
/* note: using mlast in the skip path slows things down on x86 */
|
||||
if (s[i+m-1] == p[m-1]) {
|
||||
/* candidate match */
|
||||
for (j = 0; j < mlast; j++)
|
||||
if (s[i+j] != p[j])
|
||||
break;
|
||||
if (j == mlast) {
|
||||
/* got a match! */
|
||||
if (mode != FAST_COUNT)
|
||||
return i;
|
||||
count++;
|
||||
if (count == maxcount)
|
||||
return maxcount;
|
||||
i = i + mlast;
|
||||
continue;
|
||||
}
|
||||
/* miss: check if next character is part of pattern */
|
||||
if (!STRINGLIB_BLOOM(mask, s[i+m]))
|
||||
i = i + m;
|
||||
else
|
||||
i = i + skip;
|
||||
} else {
|
||||
/* skip: check if next character is part of pattern */
|
||||
if (!STRINGLIB_BLOOM(mask, s[i+m]))
|
||||
i = i + m;
|
||||
}
|
||||
}
|
||||
} else { /* FAST_RSEARCH */
|
||||
|
||||
/* create compressed boyer-moore delta 1 table */
|
||||
|
||||
/* process pattern[0] outside the loop */
|
||||
STRINGLIB_BLOOM_ADD(mask, p[0]);
|
||||
/* process pattern[:0:-1] */
|
||||
for (i = mlast; i > 0; i--) {
|
||||
STRINGLIB_BLOOM_ADD(mask, p[i]);
|
||||
if (p[i] == p[0])
|
||||
skip = i - 1;
|
||||
}
|
||||
|
||||
for (i = w; i >= 0; i--) {
|
||||
if (s[i] == p[0]) {
|
||||
/* candidate match */
|
||||
for (j = mlast; j > 0; j--)
|
||||
if (s[i+j] != p[j])
|
||||
break;
|
||||
if (j == 0)
|
||||
/* got a match! */
|
||||
return i;
|
||||
/* miss: check if previous character is part of pattern */
|
||||
if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1]))
|
||||
i = i - m;
|
||||
else
|
||||
i = i - skip;
|
||||
} else {
|
||||
/* skip: check if previous character is part of pattern */
|
||||
if (i > 0 && !STRINGLIB_BLOOM(mask, s[i-1]))
|
||||
i = i - m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode != FAST_COUNT)
|
||||
return -1;
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,175 @@
|
||||
/* stringlib: find/index implementation */
|
||||
|
||||
#ifndef STRINGLIB_FIND_H
|
||||
#define STRINGLIB_FIND_H
|
||||
|
||||
#ifndef STRINGLIB_FASTSEARCH_H
|
||||
#error must include "stringlib/fastsearch.h" before including this module
|
||||
#endif
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
|
||||
Py_ssize_t offset)
|
||||
{
|
||||
Py_ssize_t pos;
|
||||
|
||||
if (str_len < 0)
|
||||
return -1;
|
||||
if (sub_len == 0)
|
||||
return offset;
|
||||
|
||||
pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
|
||||
|
||||
if (pos >= 0)
|
||||
pos += offset;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
|
||||
Py_ssize_t offset)
|
||||
{
|
||||
Py_ssize_t pos;
|
||||
|
||||
if (str_len < 0)
|
||||
return -1;
|
||||
if (sub_len == 0)
|
||||
return str_len + offset;
|
||||
|
||||
pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
|
||||
|
||||
if (pos >= 0)
|
||||
pos += offset;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* helper macro to fixup start/end slice values */
|
||||
#define ADJUST_INDICES(start, end, len) \
|
||||
if (end > len) \
|
||||
end = len; \
|
||||
else if (end < 0) { \
|
||||
end += len; \
|
||||
if (end < 0) \
|
||||
end = 0; \
|
||||
} \
|
||||
if (start < 0) { \
|
||||
start += len; \
|
||||
if (start < 0) \
|
||||
start = 0; \
|
||||
}
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
|
||||
Py_ssize_t start, Py_ssize_t end)
|
||||
{
|
||||
ADJUST_INDICES(start, end, str_len);
|
||||
return stringlib_find(str + start, end - start, sub, sub_len, start);
|
||||
}
|
||||
|
||||
Py_LOCAL_INLINE(Py_ssize_t)
|
||||
stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
|
||||
Py_ssize_t start, Py_ssize_t end)
|
||||
{
|
||||
ADJUST_INDICES(start, end, str_len);
|
||||
return stringlib_rfind(str + start, end - start, sub, sub_len, start);
|
||||
}
|
||||
|
||||
#ifdef STRINGLIB_WANT_CONTAINS_OBJ
|
||||
|
||||
Py_LOCAL_INLINE(int)
|
||||
stringlib_contains_obj(PyObject* str, PyObject* sub)
|
||||
{
|
||||
return stringlib_find(
|
||||
STRINGLIB_STR(str), STRINGLIB_LEN(str),
|
||||
STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
|
||||
) != -1;
|
||||
}
|
||||
|
||||
#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
|
||||
|
||||
/*
|
||||
This function is a helper for the "find" family (find, rfind, index,
|
||||
rindex) and for count, startswith and endswith, because they all have
|
||||
the same behaviour for the arguments.
|
||||
|
||||
It does not touch the variables received until it knows everything
|
||||
is ok.
|
||||
*/
|
||||
|
||||
#define FORMAT_BUFFER_SIZE 50
|
||||
|
||||
Py_LOCAL_INLINE(int)
|
||||
stringlib_parse_args_finds(const char * function_name, PyObject *args,
|
||||
PyObject **subobj,
|
||||
Py_ssize_t *start, Py_ssize_t *end)
|
||||
{
|
||||
PyObject *tmp_subobj;
|
||||
Py_ssize_t tmp_start = 0;
|
||||
Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
|
||||
PyObject *obj_start=Py_None, *obj_end=Py_None;
|
||||
char format[FORMAT_BUFFER_SIZE] = "O|OO:";
|
||||
size_t len = strlen(format);
|
||||
|
||||
strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
|
||||
format[FORMAT_BUFFER_SIZE - 1] = '\0';
|
||||
|
||||
if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
|
||||
return 0;
|
||||
|
||||
/* To support None in "start" and "end" arguments, meaning
|
||||
the same as if they were not passed.
|
||||
*/
|
||||
if (obj_start != Py_None)
|
||||
if (!_PyEval_SliceIndex(obj_start, &tmp_start))
|
||||
return 0;
|
||||
if (obj_end != Py_None)
|
||||
if (!_PyEval_SliceIndex(obj_end, &tmp_end))
|
||||
return 0;
|
||||
|
||||
*start = tmp_start;
|
||||
*end = tmp_end;
|
||||
*subobj = tmp_subobj;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef FORMAT_BUFFER_SIZE
|
||||
|
||||
#if STRINGLIB_IS_UNICODE
|
||||
|
||||
/*
|
||||
Wraps stringlib_parse_args_finds() and additionally ensures that the
|
||||
first argument is a unicode object.
|
||||
|
||||
Note that we receive a pointer to the pointer of the substring object,
|
||||
so when we create that object in this function we don't DECREF it,
|
||||
because it continues living in the caller functions (those functions,
|
||||
after finishing using the substring, must DECREF it).
|
||||
*/
|
||||
|
||||
Py_LOCAL_INLINE(int)
|
||||
stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
|
||||
PyUnicodeObject **substring,
|
||||
Py_ssize_t *start, Py_ssize_t *end)
|
||||
{
|
||||
PyObject *tmp_substring;
|
||||
|
||||
if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
|
||||
start, end)) {
|
||||
tmp_substring = PyUnicode_FromObject(tmp_substring);
|
||||
if (!tmp_substring)
|
||||
return 0;
|
||||
*substring = (PyUnicodeObject *)tmp_substring;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* STRINGLIB_IS_UNICODE */
|
||||
|
||||
#endif /* STRINGLIB_FIND_H */
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,110 @@
|
||||
/* stringlib: partition implementation */
|
||||
|
||||
#ifndef STRINGLIB_PARTITION_H
|
||||
#define STRINGLIB_PARTITION_H
|
||||
|
||||
#ifndef STRINGLIB_FASTSEARCH_H
|
||||
#error must include "stringlib/fastsearch.h" before including this module
|
||||
#endif
|
||||
|
||||
Py_LOCAL_INLINE(PyObject*)
|
||||
stringlib_partition(PyObject* str_obj,
|
||||
const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
PyObject* sep_obj,
|
||||
const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
|
||||
{
|
||||
PyObject* out;
|
||||
Py_ssize_t pos;
|
||||
|
||||
if (sep_len == 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "empty separator");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = PyTuple_New(3);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_SEARCH);
|
||||
|
||||
if (pos < 0) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, str_len));
|
||||
PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));
|
||||
PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(NULL, 0));
|
||||
#else
|
||||
Py_INCREF(str_obj);
|
||||
PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
|
||||
Py_INCREF(STRINGLIB_EMPTY);
|
||||
PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);
|
||||
Py_INCREF(STRINGLIB_EMPTY);
|
||||
PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY);
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
|
||||
Py_INCREF(sep_obj);
|
||||
PyTuple_SET_ITEM(out, 1, sep_obj);
|
||||
pos += sep_len;
|
||||
PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Py_LOCAL_INLINE(PyObject*)
|
||||
stringlib_rpartition(PyObject* str_obj,
|
||||
const STRINGLIB_CHAR* str, Py_ssize_t str_len,
|
||||
PyObject* sep_obj,
|
||||
const STRINGLIB_CHAR* sep, Py_ssize_t sep_len)
|
||||
{
|
||||
PyObject* out;
|
||||
Py_ssize_t pos;
|
||||
|
||||
if (sep_len == 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "empty separator");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = PyTuple_New(3);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
pos = fastsearch(str, str_len, sep, sep_len, -1, FAST_RSEARCH);
|
||||
|
||||
if (pos < 0) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(NULL, 0));
|
||||
PyTuple_SET_ITEM(out, 1, STRINGLIB_NEW(NULL, 0));
|
||||
PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str, str_len));
|
||||
#else
|
||||
Py_INCREF(STRINGLIB_EMPTY);
|
||||
PyTuple_SET_ITEM(out, 0, (PyObject*) STRINGLIB_EMPTY);
|
||||
Py_INCREF(STRINGLIB_EMPTY);
|
||||
PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);
|
||||
Py_INCREF(str_obj);
|
||||
PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj);
|
||||
#endif
|
||||
return out;
|
||||
}
|
||||
|
||||
PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
|
||||
Py_INCREF(sep_obj);
|
||||
PyTuple_SET_ITEM(out, 1, sep_obj);
|
||||
pos += sep_len;
|
||||
PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(out);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,394 @@
|
||||
/* stringlib: split implementation */
|
||||
|
||||
#ifndef STRINGLIB_SPLIT_H
|
||||
#define STRINGLIB_SPLIT_H
|
||||
|
||||
#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 *)
|
||||
stringlib_split_whitespace(PyObject* str_obj,
|
||||
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 *)
|
||||
stringlib_split_char(PyObject* str_obj,
|
||||
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 *)
|
||||
stringlib_split(PyObject* str_obj,
|
||||
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)
|
||||
return stringlib_split_char(str_obj, str, str_len, sep[0], maxcount);
|
||||
|
||||
list = PyList_New(PREALLOC_SIZE(maxcount));
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
i = j = 0;
|
||||
while (maxcount-- > 0) {
|
||||
pos = fastsearch(str+i, str_len-i, sep, sep_len, -1, FAST_SEARCH);
|
||||
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 *)
|
||||
stringlib_rsplit_whitespace(PyObject* str_obj,
|
||||
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 *)
|
||||
stringlib_rsplit_char(PyObject* str_obj,
|
||||
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 *)
|
||||
stringlib_rsplit(PyObject* str_obj,
|
||||
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)
|
||||
return stringlib_rsplit_char(str_obj, str, str_len, sep[0], maxcount);
|
||||
|
||||
list = PyList_New(PREALLOC_SIZE(maxcount));
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
j = str_len;
|
||||
while (maxcount-- > 0) {
|
||||
pos = fastsearch(str, j, sep, sep_len, -1, FAST_RSEARCH);
|
||||
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 *)
|
||||
stringlib_splitlines(PyObject* str_obj,
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
#ifndef STRINGLIB_STRINGDEFS_H
|
||||
#define STRINGLIB_STRINGDEFS_H
|
||||
|
||||
/* this is sort of a hack. there's at least one place (formatting
|
||||
floats) where some stringlib code takes a different path if it's
|
||||
compiled as unicode. */
|
||||
#define STRINGLIB_IS_UNICODE 0
|
||||
|
||||
#define STRINGLIB_OBJECT PyStringObject
|
||||
#define STRINGLIB_CHAR char
|
||||
#define STRINGLIB_TYPE_NAME "string"
|
||||
#define STRINGLIB_PARSE_CODE "S"
|
||||
#define STRINGLIB_EMPTY nullstring
|
||||
#define STRINGLIB_ISSPACE Py_ISSPACE
|
||||
#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r'))
|
||||
#define STRINGLIB_ISDECIMAL(x) ((x >= '0') && (x <= '9'))
|
||||
#define STRINGLIB_TODECIMAL(x) (STRINGLIB_ISDECIMAL(x) ? (x - '0') : -1)
|
||||
#define STRINGLIB_TOUPPER Py_TOUPPER
|
||||
#define STRINGLIB_TOLOWER Py_TOLOWER
|
||||
#define STRINGLIB_FILL memset
|
||||
#define STRINGLIB_STR PyString_AS_STRING
|
||||
#define STRINGLIB_LEN PyString_GET_SIZE
|
||||
#define STRINGLIB_NEW PyString_FromStringAndSize
|
||||
#define STRINGLIB_RESIZE _PyString_Resize
|
||||
#define STRINGLIB_CHECK PyString_Check
|
||||
#define STRINGLIB_CHECK_EXACT PyString_CheckExact
|
||||
#define STRINGLIB_TOSTR PyObject_Str
|
||||
#define STRINGLIB_GROUPING _PyString_InsertThousandsGrouping
|
||||
#define STRINGLIB_GROUPING_LOCALE _PyString_InsertThousandsGroupingLocale
|
||||
|
||||
#define STRINGLIB_WANT_CONTAINS_OBJ 1
|
||||
|
||||
#endif /* !STRINGLIB_STRINGDEFS_H */
|
@@ -0,0 +1,264 @@
|
||||
/* NOTE: this API is -ONLY- for use with single byte character strings. */
|
||||
/* Do not use it with Unicode. */
|
||||
|
||||
/* the more complicated methods. parts of these should be pulled out into the
|
||||
shared code in bytes_methods.c to cut down on duplicate code bloat. */
|
||||
|
||||
PyDoc_STRVAR(expandtabs__doc__,
|
||||
"B.expandtabs([tabsize]) -> copy of B\n\
|
||||
\n\
|
||||
Return a copy of B where all tab characters are expanded using spaces.\n\
|
||||
If tabsize is not given, a tab size of 8 characters is assumed.");
|
||||
|
||||
static PyObject*
|
||||
stringlib_expandtabs(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char *e, *p;
|
||||
char *q;
|
||||
Py_ssize_t i, j;
|
||||
PyObject *u;
|
||||
int tabsize = 8;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
|
||||
return NULL;
|
||||
|
||||
/* First pass: determine size of output string */
|
||||
i = j = 0;
|
||||
e = STRINGLIB_STR(self) + STRINGLIB_LEN(self);
|
||||
for (p = STRINGLIB_STR(self); p < e; p++) {
|
||||
if (*p == '\t') {
|
||||
if (tabsize > 0) {
|
||||
Py_ssize_t incr = tabsize - (j % tabsize);
|
||||
if (j > PY_SSIZE_T_MAX - incr)
|
||||
goto overflow;
|
||||
j += incr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (j > PY_SSIZE_T_MAX - 1)
|
||||
goto overflow;
|
||||
j++;
|
||||
if (*p == '\n' || *p == '\r') {
|
||||
if (i > PY_SSIZE_T_MAX - j)
|
||||
goto overflow;
|
||||
i += j;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i > PY_SSIZE_T_MAX - j)
|
||||
goto overflow;
|
||||
|
||||
/* Second pass: create output string and fill it */
|
||||
u = STRINGLIB_NEW(NULL, i + j);
|
||||
if (!u)
|
||||
return NULL;
|
||||
|
||||
j = 0;
|
||||
q = STRINGLIB_STR(u);
|
||||
|
||||
for (p = STRINGLIB_STR(self); p < e; p++) {
|
||||
if (*p == '\t') {
|
||||
if (tabsize > 0) {
|
||||
i = tabsize - (j % tabsize);
|
||||
j += i;
|
||||
while (i--)
|
||||
*q++ = ' ';
|
||||
}
|
||||
}
|
||||
else {
|
||||
j++;
|
||||
*q++ = *p;
|
||||
if (*p == '\n' || *p == '\r')
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return u;
|
||||
overflow:
|
||||
PyErr_SetString(PyExc_OverflowError, "result too long");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_LOCAL_INLINE(PyObject *)
|
||||
pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
|
||||
{
|
||||
PyObject *u;
|
||||
|
||||
if (left < 0)
|
||||
left = 0;
|
||||
if (right < 0)
|
||||
right = 0;
|
||||
|
||||
if (left == 0 && right == 0 && STRINGLIB_CHECK_EXACT(self)) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
/* We're defined as returning a copy; If the object is mutable
|
||||
* that means we must make an identical copy. */
|
||||
return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
#else
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
#endif /* STRINGLIB_MUTABLE */
|
||||
}
|
||||
|
||||
u = STRINGLIB_NEW(NULL,
|
||||
left + STRINGLIB_LEN(self) + right);
|
||||
if (u) {
|
||||
if (left)
|
||||
memset(STRINGLIB_STR(u), fill, left);
|
||||
Py_MEMCPY(STRINGLIB_STR(u) + left,
|
||||
STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self));
|
||||
if (right)
|
||||
memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
|
||||
fill, right);
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(ljust__doc__,
|
||||
"B.ljust(width[, fillchar]) -> copy of B\n"
|
||||
"\n"
|
||||
"Return B left justified in a string of length width. Padding is\n"
|
||||
"done using the specified fill character (default is a space).");
|
||||
|
||||
static PyObject *
|
||||
stringlib_ljust(PyObject *self, PyObject *args)
|
||||
{
|
||||
Py_ssize_t width;
|
||||
char fillchar = ' ';
|
||||
|
||||
if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
|
||||
return NULL;
|
||||
|
||||
if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
/* We're defined as returning a copy; If the object is mutable
|
||||
* that means we must make an identical copy. */
|
||||
return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
#else
|
||||
Py_INCREF(self);
|
||||
return (PyObject*) self;
|
||||
#endif
|
||||
}
|
||||
|
||||
return pad(self, 0, width - STRINGLIB_LEN(self), fillchar);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(rjust__doc__,
|
||||
"B.rjust(width[, fillchar]) -> copy of B\n"
|
||||
"\n"
|
||||
"Return B right justified in a string of length width. Padding is\n"
|
||||
"done using the specified fill character (default is a space)");
|
||||
|
||||
static PyObject *
|
||||
stringlib_rjust(PyObject *self, PyObject *args)
|
||||
{
|
||||
Py_ssize_t width;
|
||||
char fillchar = ' ';
|
||||
|
||||
if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
|
||||
return NULL;
|
||||
|
||||
if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
/* We're defined as returning a copy; If the object is mutable
|
||||
* that means we must make an identical copy. */
|
||||
return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
#else
|
||||
Py_INCREF(self);
|
||||
return (PyObject*) self;
|
||||
#endif
|
||||
}
|
||||
|
||||
return pad(self, width - STRINGLIB_LEN(self), 0, fillchar);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(center__doc__,
|
||||
"B.center(width[, fillchar]) -> copy of B\n"
|
||||
"\n"
|
||||
"Return B centered in a string of length width. Padding is\n"
|
||||
"done using the specified fill character (default is a space).");
|
||||
|
||||
static PyObject *
|
||||
stringlib_center(PyObject *self, PyObject *args)
|
||||
{
|
||||
Py_ssize_t marg, left;
|
||||
Py_ssize_t width;
|
||||
char fillchar = ' ';
|
||||
|
||||
if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
|
||||
return NULL;
|
||||
|
||||
if (STRINGLIB_LEN(self) >= width && STRINGLIB_CHECK_EXACT(self)) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
/* We're defined as returning a copy; If the object is mutable
|
||||
* that means we must make an identical copy. */
|
||||
return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
#else
|
||||
Py_INCREF(self);
|
||||
return (PyObject*) self;
|
||||
#endif
|
||||
}
|
||||
|
||||
marg = width - STRINGLIB_LEN(self);
|
||||
left = marg / 2 + (marg & width & 1);
|
||||
|
||||
return pad(self, left, marg - left, fillchar);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(zfill__doc__,
|
||||
"B.zfill(width) -> copy of B\n"
|
||||
"\n"
|
||||
"Pad a numeric string B with zeros on the left, to fill a field\n"
|
||||
"of the specified width. B is never truncated.");
|
||||
|
||||
static PyObject *
|
||||
stringlib_zfill(PyObject *self, PyObject *args)
|
||||
{
|
||||
Py_ssize_t fill;
|
||||
PyObject *s;
|
||||
char *p;
|
||||
Py_ssize_t width;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "n:zfill", &width))
|
||||
return NULL;
|
||||
|
||||
if (STRINGLIB_LEN(self) >= width) {
|
||||
if (STRINGLIB_CHECK_EXACT(self)) {
|
||||
#if STRINGLIB_MUTABLE
|
||||
/* We're defined as returning a copy; If the object is mutable
|
||||
* that means we must make an identical copy. */
|
||||
return STRINGLIB_NEW(STRINGLIB_STR(self), STRINGLIB_LEN(self));
|
||||
#else
|
||||
Py_INCREF(self);
|
||||
return (PyObject*) self;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return STRINGLIB_NEW(
|
||||
STRINGLIB_STR(self),
|
||||
STRINGLIB_LEN(self)
|
||||
);
|
||||
}
|
||||
|
||||
fill = width - STRINGLIB_LEN(self);
|
||||
|
||||
s = pad(self, fill, 0, '0');
|
||||
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
|
||||
p = STRINGLIB_STR(s);
|
||||
if (p[fill] == '+' || p[fill] == '-') {
|
||||
/* move sign to beginning of string */
|
||||
p[0] = p[fill];
|
||||
p[fill] = '0';
|
||||
}
|
||||
|
||||
return (PyObject*) s;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
#ifndef STRINGLIB_UNICODEDEFS_H
|
||||
#define STRINGLIB_UNICODEDEFS_H
|
||||
|
||||
/* this is sort of a hack. there's at least one place (formatting
|
||||
floats) where some stringlib code takes a different path if it's
|
||||
compiled as unicode. */
|
||||
#define STRINGLIB_IS_UNICODE 1
|
||||
|
||||
#define STRINGLIB_OBJECT PyUnicodeObject
|
||||
#define STRINGLIB_CHAR Py_UNICODE
|
||||
#define STRINGLIB_TYPE_NAME "unicode"
|
||||
#define STRINGLIB_PARSE_CODE "U"
|
||||
#define STRINGLIB_EMPTY unicode_empty
|
||||
#define STRINGLIB_ISSPACE Py_UNICODE_ISSPACE
|
||||
#define STRINGLIB_ISLINEBREAK BLOOM_LINEBREAK
|
||||
#define STRINGLIB_ISDECIMAL Py_UNICODE_ISDECIMAL
|
||||
#define STRINGLIB_TODECIMAL Py_UNICODE_TODECIMAL
|
||||
#define STRINGLIB_TOUPPER Py_UNICODE_TOUPPER
|
||||
#define STRINGLIB_TOLOWER Py_UNICODE_TOLOWER
|
||||
#define STRINGLIB_FILL Py_UNICODE_FILL
|
||||
#define STRINGLIB_STR PyUnicode_AS_UNICODE
|
||||
#define STRINGLIB_LEN PyUnicode_GET_SIZE
|
||||
#define STRINGLIB_NEW PyUnicode_FromUnicode
|
||||
#define STRINGLIB_RESIZE PyUnicode_Resize
|
||||
#define STRINGLIB_CHECK PyUnicode_Check
|
||||
#define STRINGLIB_CHECK_EXACT PyUnicode_CheckExact
|
||||
#define STRINGLIB_GROUPING _PyUnicode_InsertThousandsGrouping
|
||||
|
||||
#if PY_VERSION_HEX < 0x03000000
|
||||
#define STRINGLIB_TOSTR PyObject_Unicode
|
||||
#else
|
||||
#define STRINGLIB_TOSTR PyObject_Str
|
||||
#endif
|
||||
|
||||
#define STRINGLIB_WANT_CONTAINS_OBJ 1
|
||||
|
||||
#endif /* !STRINGLIB_UNICODEDEFS_H */
|
Reference in New Issue
Block a user