Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
dc914e07
Commit
dc914e07
authored
Dec 17, 2014
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Copied over CPython's str.__mod__
parent
c3a27c8b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
621 additions
and
174 deletions
+621
-174
include/pyport.h
include/pyport.h
+15
-0
include/stringobject.h
include/stringobject.h
+2
-1
src/runtime/capi.cpp
src/runtime/capi.cpp
+9
-2
src/runtime/int.cpp
src/runtime/int.cpp
+4
-0
src/runtime/str.cpp
src/runtime/str.cpp
+590
-171
test/tests/str_functions.py
test/tests/str_functions.py
+1
-0
No files found.
include/pyport.h
View file @
dc914e07
...
...
@@ -271,6 +271,21 @@ typedef ssize_t Py_ssize_t;
#endif
#endif
#if defined(_MSC_VER)
#define Py_MEMCPY(target, source, length) do { \
size_t i_, n_ = (length); \
char *t_ = (void*) (target); \
const char *s_ = (void*) (source); \
if (n_ >= 16) \
memcpy(t_, s_, n_); \
else \
for (i_ = 0; i_ < n_; i_++) \
t_[i_] = s_[i_]; \
} while (0)
#else
#define Py_MEMCPY memcpy
#endif
#endif
/* Py_PYPORT_H */
include/stringobject.h
View file @
dc914e07
...
...
@@ -86,8 +86,9 @@ PyAPI_FUNC(void) PyString_ConcatAndDel(PyObject **, PyObject *);
PyAPI_FUNC
(
int
)
_PyString_Resize
(
PyObject
**
,
Py_ssize_t
);
PyAPI_FUNC
(
int
)
_PyString_Eq
(
PyObject
*
,
PyObject
*
);
PyAPI_FUNC
(
PyObject
*
)
PyString_Format
(
PyObject
*
,
PyObject
*
);
// Pyston change: added const
PyAPI_FUNC
(
PyObject
*
)
_PyString_FormatLong
(
PyObject
*
,
int
,
int
,
int
,
char
**
,
int
*
);
int
,
c
onst
c
har
**
,
int
*
);
PyAPI_FUNC
(
PyObject
*
)
PyString_DecodeEscape
(
const
char
*
,
Py_ssize_t
,
const
char
*
,
Py_ssize_t
,
const
char
*
);
...
...
src/runtime/capi.cpp
View file @
dc914e07
...
...
@@ -725,8 +725,15 @@ extern "C" void PyMem_Free(void* ptr) {
gc_compat_free
(
ptr
);
}
extern
"C"
int
PyNumber_Check
(
PyObject
*
)
{
Py_FatalError
(
"unimplemented"
);
extern
"C"
int
PyNumber_Check
(
PyObject
*
obj
)
{
assert
(
obj
&&
obj
->
cls
);
// Our check, since we don't currently fill in tp_as_number:
if
(
isSubclass
(
obj
->
cls
,
int_cls
)
||
isSubclass
(
obj
->
cls
,
long_cls
))
return
true
;
// The CPython check:
return
obj
->
cls
->
tp_as_number
&&
(
obj
->
cls
->
tp_as_number
->
nb_int
||
obj
->
cls
->
tp_as_number
->
nb_float
);
}
extern
"C"
PyObject
*
PyNumber_Add
(
PyObject
*
lhs
,
PyObject
*
rhs
)
{
...
...
src/runtime/int.cpp
View file @
dc914e07
...
...
@@ -62,6 +62,10 @@ extern "C" PyAPI_FUNC(PyObject*) _PyInt_Format(PyIntObject* v, int base, int new
Py_FatalError
(
"unimplemented"
);
}
extern
"C"
int
_PyInt_AsInt
(
PyObject
*
)
{
Py_FatalError
(
"unimplemented"
);
}
BoxedInt
*
interned_ints
[
NUM_INTERNED_INTS
];
// If we don't have fast overflow-checking builtins, provide some slow variants:
...
...
src/runtime/str.cpp
View file @
dc914e07
...
...
@@ -47,203 +47,621 @@ extern "C" BoxedString* strAdd(BoxedString* lhs, Box* _rhs) {
return
new
BoxedString
(
lhs
->
s
+
rhs
->
s
);
}
extern
"C"
Box
*
strMod
(
BoxedString
*
lhs
,
Box
*
rhs
)
{
assert
(
lhs
->
cls
==
str_cls
);
/* Format codes
* F_LJUST '-'
* F_SIGN '+'
* F_BLANK ' '
* F_ALT '#'
* F_ZERO '0'
*/
#define F_LJUST (1 << 0)
#define F_SIGN (1 << 1)
#define F_BLANK (1 << 2)
#define F_ALT (1 << 3)
#define F_ZERO (1 << 4)
Py_LOCAL_INLINE
(
PyObject
*
)
getnextarg
(
PyObject
*
args
,
Py_ssize_t
arglen
,
Py_ssize_t
*
p_argidx
)
{
Py_ssize_t
argidx
=
*
p_argidx
;
if
(
argidx
<
arglen
)
{
(
*
p_argidx
)
++
;
if
(
arglen
<
0
)
return
args
;
else
return
PyTuple_GetItem
(
args
,
argidx
);
}
PyErr_SetString
(
PyExc_TypeError
,
"not enough arguments for format string"
);
return
NULL
;
}
const
BoxedTuple
::
GCVector
*
elts
;
BoxedTuple
::
GCVector
_elts
;
if
(
rhs
->
cls
==
tuple_cls
)
{
elts
=
&
static_cast
<
BoxedTuple
*>
(
rhs
)
->
elts
;
}
else
{
elts
=
&
_elts
;
_elts
.
push_back
(
rhs
);
extern
"C"
PyObject
*
_PyString_FormatLong
(
PyObject
*
,
int
,
int
,
int
,
const
char
**
,
int
*
)
{
Py_FatalError
(
"unimplemented"
);
}
static
PyObject
*
formatfloat
(
PyObject
*
v
,
int
flags
,
int
prec
,
int
type
)
{
char
*
p
;
PyObject
*
result
;
double
x
;
x
=
PyFloat_AsDouble
(
v
);
if
(
x
==
-
1.0
&&
PyErr_Occurred
())
{
PyErr_Format
(
PyExc_TypeError
,
"float argument required, "
"not %.200s"
,
Py_TYPE
(
v
)
->
tp_name
);
return
NULL
;
}
BoxedDict
*
dict
=
NULL
;
if
(
rhs
->
cls
==
dict_cls
)
dict
=
static_cast
<
BoxedDict
*>
(
rhs
);
if
(
prec
<
0
)
prec
=
6
;
const
char
*
fmt
=
lhs
->
s
.
c_str
();
const
char
*
fmt_end
=
fmt
+
lhs
->
s
.
size
();
p
=
PyOS_double_to_string
(
x
,
type
,
prec
,
(
flags
&
F_ALT
)
?
Py_DTSF_ALT
:
0
,
NULL
);
int
elt_num
=
0
;
int
num_elts
=
elts
->
size
();
if
(
p
==
NULL
)
return
NULL
;
result
=
PyString_FromStringAndSize
(
p
,
strlen
(
p
));
PyMem_Free
(
p
);
return
result
;
}
std
::
ostringstream
os
(
""
);
while
(
fmt
<
fmt_end
)
{
if
(
*
fmt
!=
'%'
)
{
os
<<
(
*
fmt
);
fmt
++
;
}
else
{
fmt
++
;
Py_LOCAL_INLINE
(
int
)
formatint
(
char
*
buf
,
size_t
buflen
,
int
flags
,
int
prec
,
int
type
,
PyObject
*
v
)
{
/* fmt = '%#.' + `prec` + 'l' + `type`
worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
+ 1 + 1 = 24 */
char
fmt
[
64
];
/* plenty big enough! */
const
char
*
sign
;
long
x
;
x
=
PyInt_AsLong
(
v
);
if
(
x
==
-
1
&&
PyErr_Occurred
())
{
PyErr_Format
(
PyExc_TypeError
,
"int argument required, not %.200s"
,
Py_TYPE
(
v
)
->
tp_name
);
return
-
1
;
}
if
(
x
<
0
&&
type
==
'u'
)
{
type
=
'd'
;
}
if
(
x
<
0
&&
(
type
==
'x'
||
type
==
'X'
||
type
==
'o'
))
sign
=
"-"
;
else
sign
=
""
;
if
(
prec
<
0
)
prec
=
1
;
if
((
flags
&
F_ALT
)
&&
(
type
==
'x'
||
type
==
'X'
))
{
/* When converting under %#x or %#X, there are a number
* of issues that cause pain:
* - when 0 is being converted, the C standard leaves off
* the '0x' or '0X', which is inconsistent with other
* %#x/%#X conversions and inconsistent with Python's
* hex() function
* - there are platforms that violate the standard and
* convert 0 with the '0x' or '0X'
* (Metrowerks, Compaq Tru64)
* - there are platforms that give '0x' when converting
* under %#X, but convert 0 in accordance with the
* standard (OS/2 EMX)
*
* We can achieve the desired consistency by inserting our
* own '0x' or '0X' prefix, and substituting %x/%X in place
* of %#x/%#X.
*
* Note that this is the same approach as used in
* formatint() in unicodeobject.c
*/
PyOS_snprintf
(
fmt
,
sizeof
(
fmt
),
"%s0%c%%.%dl%c"
,
sign
,
type
,
prec
,
type
);
}
else
{
PyOS_snprintf
(
fmt
,
sizeof
(
fmt
),
"%s%%%s.%dl%c"
,
sign
,
(
flags
&
F_ALT
)
?
"#"
:
""
,
prec
,
type
);
}
/* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))
* worst case buf = '-0x' + [0-9]*prec, where prec >= 11
*/
if
(
buflen
<=
14
||
buflen
<=
(
size_t
)
3
+
(
size_t
)
prec
)
{
PyErr_SetString
(
PyExc_OverflowError
,
"formatted integer is too long (precision too large?)"
);
return
-
1
;
}
if
(
sign
[
0
])
PyOS_snprintf
(
buf
,
buflen
,
fmt
,
-
x
);
else
PyOS_snprintf
(
buf
,
buflen
,
fmt
,
x
);
return
(
int
)
strlen
(
buf
);
}
int
nspace
=
0
;
int
ndot
=
0
;
int
nzero
=
0
;
int
mode
=
0
;
while
(
true
)
{
RELEASE_ASSERT
(
fmt
<
fmt_end
,
""
);
Py_LOCAL_INLINE
(
int
)
formatchar
(
char
*
buf
,
size_t
buflen
,
PyObject
*
v
)
{
/* presume that the buffer is at least 2 characters long */
if
(
PyString_Check
(
v
))
{
if
(
!
PyArg_Parse
(
v
,
"c;%c requires int or char"
,
&
buf
[
0
]))
return
-
1
;
}
else
{
if
(
!
PyArg_Parse
(
v
,
"b;%c requires int or char"
,
&
buf
[
0
]))
return
-
1
;
}
buf
[
1
]
=
'\0'
;
return
1
;
}
Box
*
val_to_use
=
NULL
;
if
(
*
fmt
==
'('
)
{
if
(
dict
==
NULL
)
raiseExcHelper
(
TypeError
,
"format requires a mapping"
);
#define FORMATBUFLEN (size_t)120
extern
"C"
PyObject
*
PyString_Format
(
PyObject
*
format
,
PyObject
*
args
)
{
char
*
fmt
,
*
res
;
Py_ssize_t
arglen
,
argidx
;
Py_ssize_t
reslen
,
rescnt
,
fmtcnt
;
int
args_owned
=
0
;
PyObject
*
result
,
*
orig_args
;
#ifdef Py_USING_UNICODE
PyObject
*
v
,
*
w
;
#endif
PyObject
*
dict
=
NULL
;
if
(
format
==
NULL
||
!
PyString_Check
(
format
)
||
args
==
NULL
)
{
PyErr_BadInternalCall
();
return
NULL
;
}
orig_args
=
args
;
fmt
=
PyString_AS_STRING
(
format
);
fmtcnt
=
PyString_GET_SIZE
(
format
);
reslen
=
rescnt
=
fmtcnt
+
100
;
result
=
PyString_FromStringAndSize
((
char
*
)
NULL
,
reslen
);
if
(
result
==
NULL
)
return
NULL
;
res
=
PyString_AsString
(
result
);
if
(
PyTuple_Check
(
args
))
{
arglen
=
PyTuple_GET_SIZE
(
args
);
argidx
=
0
;
}
else
{
arglen
=
-
1
;
argidx
=
-
2
;
}
if
(
Py_TYPE
(
args
)
->
tp_as_mapping
&&
Py_TYPE
(
args
)
->
tp_as_mapping
->
mp_subscript
&&
!
PyTuple_Check
(
args
)
&&
!
PyObject_TypeCheck
(
args
,
&
PyBaseString_Type
))
dict
=
args
;
while
(
--
fmtcnt
>=
0
)
{
if
(
*
fmt
!=
'%'
)
{
if
(
--
rescnt
<
0
)
{
rescnt
=
fmtcnt
+
100
;
reslen
+=
rescnt
;
if
(
_PyString_Resize
(
&
result
,
reslen
))
return
NULL
;
res
=
PyString_AS_STRING
(
result
)
+
reslen
-
rescnt
;
--
rescnt
;
}
*
res
++
=
*
fmt
++
;
}
else
{
/* Got a format specifier */
int
flags
=
0
;
Py_ssize_t
width
=
-
1
;
int
prec
=
-
1
;
int
c
=
'\0'
;
int
fill
;
int
isnumok
;
PyObject
*
v
=
NULL
;
PyObject
*
temp
=
NULL
;
const
char
*
pbuf
;
int
sign
;
Py_ssize_t
len
;
char
formatbuf
[
FORMATBUFLEN
];
/* For format{int,char}() */
#ifdef Py_USING_UNICODE
char
*
fmt_start
=
fmt
;
Py_ssize_t
argidx_start
=
argidx
;
#endif
int
pcount
=
1
;
fmt
++
;
if
(
*
fmt
==
'('
)
{
char
*
keystart
;
Py_ssize_t
keylen
;
PyObject
*
key
;
int
pcount
=
1
;
if
(
dict
==
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"format requires a mapping"
);
goto
error
;
}
++
fmt
;
--
fmtcnt
;
keystart
=
fmt
;
/* Skip over balanced parentheses */
while
(
pcount
>
0
&&
--
fmtcnt
>=
0
)
{
if
(
*
fmt
==
')'
)
--
pcount
;
else
if
(
*
fmt
==
'('
)
++
pcount
;
fmt
++
;
const
char
*
keystart
=
fmt
;
while
(
pcount
>
0
&&
fmt
<
fmt_end
)
{
char
c
=
*
fmt
;
if
(
c
==
')'
)
pcount
--
;
else
if
(
c
==
'('
)
pcount
++
;
fmt
++
;
}
keylen
=
fmt
-
keystart
-
1
;
if
(
fmtcnt
<
0
||
pcount
>
0
)
{
PyErr_SetString
(
PyExc_ValueError
,
"incomplete format key"
);
goto
error
;
}
key
=
PyString_FromStringAndSize
(
keystart
,
keylen
);
if
(
key
==
NULL
)
goto
error
;
if
(
args_owned
)
{
Py_DECREF
(
args
);
args_owned
=
0
;
}
args
=
PyObject_GetItem
(
dict
,
key
);
Py_DECREF
(
key
);
if
(
args
==
NULL
)
{
goto
error
;
}
args_owned
=
1
;
arglen
=
-
1
;
argidx
=
-
2
;
}
while
(
--
fmtcnt
>=
0
)
{
switch
(
c
=
*
fmt
++
)
{
case
'-'
:
flags
|=
F_LJUST
;
continue
;
case
'+'
:
flags
|=
F_SIGN
;
continue
;
case
' '
:
flags
|=
F_BLANK
;
continue
;
case
'#'
:
flags
|=
F_ALT
;
continue
;
case
'0'
:
flags
|=
F_ZERO
;
continue
;
}
break
;
}
if
(
c
==
'*'
)
{
v
=
getnextarg
(
args
,
arglen
,
&
argidx
);
if
(
v
==
NULL
)
goto
error
;
if
(
!
PyInt_Check
(
v
))
{
PyErr_SetString
(
PyExc_TypeError
,
"* wants int"
);
goto
error
;
}
width
=
PyInt_AsSsize_t
(
v
);
if
(
width
==
-
1
&&
PyErr_Occurred
())
goto
error
;
if
(
width
<
0
)
{
flags
|=
F_LJUST
;
width
=
-
width
;
}
if
(
--
fmtcnt
>=
0
)
c
=
*
fmt
++
;
}
else
if
(
c
>=
0
&&
isdigit
(
c
))
{
width
=
c
-
'0'
;
while
(
--
fmtcnt
>=
0
)
{
c
=
Py_CHARMASK
(
*
fmt
++
);
if
(
!
isdigit
(
c
))
break
;
if
(
width
>
(
PY_SSIZE_T_MAX
-
((
int
)
c
-
'0'
))
/
10
)
{
PyErr_SetString
(
PyExc_ValueError
,
"width too big"
);
goto
error
;
}
if
(
pcount
>
0
)
raiseExcHelper
(
ValueError
,
"incomplete format key"
);
BoxedString
*
key
=
boxStrConstantSize
(
keystart
,
fmt
-
keystart
-
1
);
val_to_use
=
dictGetitem
(
dict
,
key
);
width
=
width
*
10
+
(
c
-
'0'
);
}
char
c
=
*
fmt
;
fmt
++
;
if
(
c
==
' '
)
{
assert
(
mode
==
0
);
mode
=
1
;
}
else
if
(
c
==
'.'
)
{
assert
(
mode
==
0
);
mode
=
2
;
}
else
if
(
mode
==
0
&&
c
==
'0'
)
{
mode
=
3
;
}
else
if
(
'0'
<=
c
&&
c
<=
'9'
)
{
assert
(
mode
==
1
||
mode
==
2
||
mode
==
3
);
if
(
mode
==
1
)
{
nspace
=
nspace
*
10
+
c
-
'0'
;
}
else
if
(
mode
==
2
)
{
ndot
=
ndot
*
10
+
c
-
'0'
;
}
else
if
(
mode
==
3
)
{
nzero
=
nzero
*
10
+
c
-
'0'
;
}
else
{
assert
(
0
);
}
if
(
c
==
'.'
)
{
prec
=
0
;
if
(
--
fmtcnt
>=
0
)
c
=
*
fmt
++
;
if
(
c
==
'*'
)
{
v
=
getnextarg
(
args
,
arglen
,
&
argidx
);
if
(
v
==
NULL
)
goto
error
;
if
(
!
PyInt_Check
(
v
))
{
PyErr_SetString
(
PyExc_TypeError
,
"* wants int"
);
goto
error
;
}
}
else
if
(
c
==
'%'
)
{
for
(
int
i
=
1
;
i
<
nspace
;
i
++
)
{
os
<<
' '
;
prec
=
_PyInt_AsInt
(
v
);
if
(
prec
==
-
1
&&
PyErr_Occurred
())
goto
error
;
if
(
prec
<
0
)
prec
=
0
;
if
(
--
fmtcnt
>=
0
)
c
=
*
fmt
++
;
}
else
if
(
c
>=
0
&&
isdigit
(
c
))
{
prec
=
c
-
'0'
;
while
(
--
fmtcnt
>=
0
)
{
c
=
Py_CHARMASK
(
*
fmt
++
);
if
(
!
isdigit
(
c
))
break
;
if
(
prec
>
(
INT_MAX
-
((
int
)
c
-
'0'
))
/
10
)
{
PyErr_SetString
(
PyExc_ValueError
,
"prec too big"
);
goto
error
;
}
prec
=
prec
*
10
+
(
c
-
'0'
);
}
os
<<
'%'
;
}
}
/* prec */
if
(
fmtcnt
>=
0
)
{
if
(
c
==
'h'
||
c
==
'l'
||
c
==
'L'
)
{
if
(
--
fmtcnt
>=
0
)
c
=
*
fmt
++
;
}
}
if
(
fmtcnt
<
0
)
{
PyErr_SetString
(
PyExc_ValueError
,
"incomplete format"
);
goto
error
;
}
if
(
c
!=
'%'
)
{
v
=
getnextarg
(
args
,
arglen
,
&
argidx
);
if
(
v
==
NULL
)
goto
error
;
}
sign
=
0
;
fill
=
' '
;
switch
(
c
)
{
case
'%'
:
pbuf
=
"%"
;
len
=
1
;
break
;
}
else
if
(
c
==
's'
||
c
==
'r'
)
{
RELEASE_ASSERT
(
ndot
==
0
,
""
);
RELEASE_ASSERT
(
nzero
==
0
,
""
);
RELEASE_ASSERT
(
nspace
==
0
,
""
);
if
(
!
val_to_use
)
{
if
(
elt_num
>=
num_elts
)
raiseExcHelper
(
TypeError
,
"not enough arguments for format string"
);
val_to_use
=
(
*
elts
)[
elt_num
];
elt_num
++
;
case
's'
:
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
v
))
{
fmt
=
fmt_start
;
argidx
=
argidx_start
;
goto
unicode
;
}
BoxedString
*
s
;
if
(
c
==
's'
)
s
=
str
(
val_to_use
);
else
s
=
repr
(
val_to_use
);
os
<<
s
->
s
;
break
;
}
else
if
(
c
==
'c'
)
{
if
(
!
val_to_use
)
{
if
(
elt_num
>=
num_elts
)
raiseExcHelper
(
TypeError
,
"not enough arguments for format string"
);
val_to_use
=
(
*
elts
)[
elt_num
];
elt_num
++
;
#endif
temp
=
_PyObject_Str
(
v
);
#ifdef Py_USING_UNICODE
if
(
temp
!=
NULL
&&
PyUnicode_Check
(
temp
))
{
Py_DECREF
(
temp
);
fmt
=
fmt_start
;
argidx
=
argidx_start
;
goto
unicode
;
}
RELEASE_ASSERT
(
isSubclass
(
val_to_use
->
cls
,
int_cls
),
"unsupported"
);
RELEASE_ASSERT
(
nspace
==
0
,
"unsupported"
);
RELEASE_ASSERT
(
ndot
==
0
,
"unsupported"
);
RELEASE_ASSERT
(
nzero
==
0
,
"unsupported"
);
int64_t
n
=
static_cast
<
BoxedInt
*>
(
val_to_use
)
->
n
;
if
(
n
<
0
)
raiseExcHelper
(
OverflowError
,
"unsigned byte integer is less than minimum"
);
if
(
n
>=
256
)
raiseExcHelper
(
OverflowError
,
"unsigned byte integer is greater than maximum"
);
os
<<
(
char
)
n
;
break
;
}
else
if
(
c
==
'd'
||
c
==
'i'
)
{
if
(
!
val_to_use
)
{
if
(
elt_num
>=
num_elts
)
raiseExcHelper
(
TypeError
,
"not enough arguments for format string"
);
val_to_use
=
(
*
elts
)[
elt_num
];
elt_num
++
;
#endif
/* Fall through */
case
'r'
:
if
(
c
==
'r'
)
temp
=
PyObject_Repr
(
v
);
if
(
temp
==
NULL
)
goto
error
;
if
(
!
PyString_Check
(
temp
))
{
PyErr_SetString
(
PyExc_TypeError
,
"%s argument has non-string str()"
);
Py_DECREF
(
temp
);
goto
error
;
}
RELEASE_ASSERT
(
isSubclass
(
val_to_use
->
cls
,
int_cls
),
"unsupported"
);
std
::
ostringstream
fmt
(
""
);
fmt
<<
'%'
;
if
(
nspace
)
fmt
<<
' '
<<
nspace
;
else
if
(
ndot
)
fmt
<<
'.'
<<
ndot
;
else
if
(
nzero
)
fmt
<<
'0'
<<
nzero
;
fmt
<<
"ld"
;
char
buf
[
20
];
snprintf
(
buf
,
20
,
fmt
.
str
().
c_str
(),
static_cast
<
BoxedInt
*>
(
val_to_use
)
->
n
);
os
<<
std
::
string
(
buf
);
pbuf
=
PyString_AS_STRING
(
temp
);
len
=
PyString_GET_SIZE
(
temp
);
if
(
prec
>=
0
&&
len
>
prec
)
len
=
prec
;
break
;
}
else
if
(
c
==
'f'
)
{
if
(
!
val_to_use
)
{
if
(
elt_num
>=
num_elts
)
raiseExcHelper
(
TypeError
,
"not enough arguments for format string"
);
val_to_use
=
(
*
elts
)[
elt_num
];
elt_num
++
;
case
'i'
:
case
'd'
:
case
'u'
:
case
'o'
:
case
'x'
:
case
'X'
:
if
(
c
==
'i'
)
c
=
'd'
;
isnumok
=
0
;
if
(
PyNumber_Check
(
v
))
{
PyObject
*
iobj
=
NULL
;
if
(
PyInt_Check
(
v
)
||
(
PyLong_Check
(
v
)))
{
iobj
=
v
;
Py_INCREF
(
iobj
);
}
else
{
iobj
=
PyNumber_Int
(
v
);
if
(
iobj
==
NULL
)
{
PyErr_Clear
();
iobj
=
PyNumber_Long
(
v
);
}
}
if
(
iobj
!=
NULL
)
{
if
(
PyInt_Check
(
iobj
))
{
isnumok
=
1
;
pbuf
=
formatbuf
;
// Pyston change:
len
=
formatint
(
formatbuf
/* pbuf */
,
sizeof
(
formatbuf
),
flags
,
prec
,
c
,
iobj
);
Py_DECREF
(
iobj
);
if
(
len
<
0
)
goto
error
;
sign
=
1
;
}
else
if
(
PyLong_Check
(
iobj
))
{
int
ilen
;
isnumok
=
1
;
temp
=
_PyString_FormatLong
(
iobj
,
flags
,
prec
,
c
,
&
pbuf
,
&
ilen
);
Py_DECREF
(
iobj
);
len
=
ilen
;
if
(
!
temp
)
goto
error
;
sign
=
1
;
}
else
{
Py_DECREF
(
iobj
);
}
}
}
double
d
;
if
(
val_to_use
->
cls
==
float_cls
)
{
d
=
static_cast
<
BoxedFloat
*>
(
val_to_use
)
->
d
;
}
else
if
(
isSubclass
(
val_to_use
->
cls
,
int_cls
))
{
d
=
static_cast
<
BoxedInt
*>
(
val_to_use
)
->
n
;
}
else
{
RELEASE_ASSERT
(
0
,
"unsupported"
);
if
(
!
isnumok
)
{
PyErr_Format
(
PyExc_TypeError
,
"%%%c format: a number is required, "
"not %.200s"
,
c
,
Py_TYPE
(
v
)
->
tp_name
);
goto
error
;
}
std
::
ostringstream
fmt
(
""
);
fmt
<<
'%'
;
if
(
nspace
)
fmt
<<
' '
<<
nspace
;
else
if
(
ndot
)
fmt
<<
'.'
<<
ndot
;
else
if
(
nzero
)
fmt
<<
'0'
<<
nzero
;
fmt
<<
"f"
;
char
buf
[
20
];
snprintf
(
buf
,
20
,
fmt
.
str
().
c_str
(),
d
);
os
<<
std
::
string
(
buf
);
if
(
flags
&
F_ZERO
)
fill
=
'0'
;
break
;
}
else
{
RELEASE_ASSERT
(
0
,
"unsupported format character '%c'"
,
c
);
case
'e'
:
case
'E'
:
case
'f'
:
case
'F'
:
case
'g'
:
case
'G'
:
temp
=
formatfloat
(
v
,
flags
,
prec
,
c
);
if
(
temp
==
NULL
)
goto
error
;
pbuf
=
PyString_AS_STRING
(
temp
);
len
=
PyString_GET_SIZE
(
temp
);
sign
=
1
;
if
(
flags
&
F_ZERO
)
fill
=
'0'
;
break
;
case
'c'
:
#ifdef Py_USING_UNICODE
if
(
PyUnicode_Check
(
v
))
{
fmt
=
fmt_start
;
argidx
=
argidx_start
;
goto
unicode
;
}
#endif
pbuf
=
formatbuf
;
// Pyston change:
len
=
formatchar
(
formatbuf
/* was pbuf */
,
sizeof
(
formatbuf
),
v
);
if
(
len
<
0
)
goto
error
;
break
;
default:
PyErr_Format
(
PyExc_ValueError
,
"unsupported format character '%c' (0x%x) "
"at index %zd"
,
c
,
c
,
(
Py_ssize_t
)(
fmt
-
1
-
PyString_AsString
(
format
)));
goto
error
;
}
if
(
sign
)
{
if
(
*
pbuf
==
'-'
||
*
pbuf
==
'+'
)
{
sign
=
*
pbuf
++
;
len
--
;
}
else
if
(
flags
&
F_SIGN
)
sign
=
'+'
;
else
if
(
flags
&
F_BLANK
)
sign
=
' '
;
else
sign
=
0
;
}
if
(
width
<
len
)
width
=
len
;
if
(
rescnt
-
(
sign
!=
0
)
<
width
)
{
reslen
-=
rescnt
;
rescnt
=
width
+
fmtcnt
+
100
;
reslen
+=
rescnt
;
if
(
reslen
<
0
)
{
Py_DECREF
(
result
);
Py_XDECREF
(
temp
);
return
PyErr_NoMemory
();
}
if
(
_PyString_Resize
(
&
result
,
reslen
))
{
Py_XDECREF
(
temp
);
return
NULL
;
}
res
=
PyString_AS_STRING
(
result
)
+
reslen
-
rescnt
;
}
if
(
sign
)
{
if
(
fill
!=
' '
)
*
res
++
=
sign
;
rescnt
--
;
if
(
width
>
len
)
width
--
;
}
if
((
flags
&
F_ALT
)
&&
(
c
==
'x'
||
c
==
'X'
))
{
assert
(
pbuf
[
0
]
==
'0'
);
assert
(
pbuf
[
1
]
==
c
);
if
(
fill
!=
' '
)
{
*
res
++
=
*
pbuf
++
;
*
res
++
=
*
pbuf
++
;
}
rescnt
-=
2
;
width
-=
2
;
if
(
width
<
0
)
width
=
0
;
len
-=
2
;
}
if
(
width
>
len
&&
!
(
flags
&
F_LJUST
))
{
do
{
--
rescnt
;
*
res
++
=
fill
;
}
while
(
--
width
>
len
);
}
if
(
fill
==
' '
)
{
if
(
sign
)
*
res
++
=
sign
;
if
((
flags
&
F_ALT
)
&&
(
c
==
'x'
||
c
==
'X'
))
{
assert
(
pbuf
[
0
]
==
'0'
);
assert
(
pbuf
[
1
]
==
c
);
*
res
++
=
*
pbuf
++
;
*
res
++
=
*
pbuf
++
;
}
}
Py_MEMCPY
(
res
,
pbuf
,
len
);
res
+=
len
;
rescnt
-=
len
;
while
(
--
width
>=
len
)
{
--
rescnt
;
*
res
++
=
' '
;
}
if
(
dict
&&
(
argidx
<
arglen
)
&&
c
!=
'%'
)
{
PyErr_SetString
(
PyExc_TypeError
,
"not all arguments converted during string formatting"
);
Py_XDECREF
(
temp
);
goto
error
;
}
Py_XDECREF
(
temp
);
}
/* '%' */
}
/* until end */
if
(
argidx
<
arglen
&&
!
dict
)
{
PyErr_SetString
(
PyExc_TypeError
,
"not all arguments converted during string formatting"
);
goto
error
;
}
if
(
args_owned
)
{
Py_DECREF
(
args
);
}
if
(
_PyString_Resize
(
&
result
,
reslen
-
rescnt
))
return
NULL
;
return
result
;
#ifdef Py_USING_UNICODE
unicode:
if
(
args_owned
)
{
Py_DECREF
(
args
);
args_owned
=
0
;
}
/* Fiddle args right (remove the first argidx arguments) */
if
(
PyTuple_Check
(
orig_args
)
&&
argidx
>
0
)
{
PyObject
*
v
;
Py_ssize_t
n
=
PyTuple_GET_SIZE
(
orig_args
)
-
argidx
;
v
=
PyTuple_New
(
n
);
if
(
v
==
NULL
)
goto
error
;
while
(
--
n
>=
0
)
{
PyObject
*
w
=
PyTuple_GET_ITEM
(
orig_args
,
n
+
argidx
);
Py_INCREF
(
w
);
PyTuple_SET_ITEM
(
v
,
n
,
w
);
}
args
=
v
;
}
else
{
Py_INCREF
(
orig_args
);
args
=
orig_args
;
}
assert
(
fmt
==
fmt_end
&&
"incomplete format"
);
if
(
dict
==
NULL
&&
elt_num
<
num_elts
)
{
raiseExcHelper
(
TypeError
,
"not all arguments converted during string formatting"
);
args_owned
=
1
;
/* Take what we have of the result and let the Unicode formatting
function format the rest of the input. */
rescnt
=
res
-
PyString_AS_STRING
(
result
);
if
(
_PyString_Resize
(
&
result
,
rescnt
))
goto
error
;
fmtcnt
=
PyString_GET_SIZE
(
format
)
-
(
fmt
-
PyString_AS_STRING
(
format
));
format
=
PyUnicode_Decode
(
fmt
,
fmtcnt
,
NULL
,
NULL
);
if
(
format
==
NULL
)
goto
error
;
v
=
PyUnicode_Format
(
format
,
args
);
Py_DECREF
(
format
);
if
(
v
==
NULL
)
goto
error
;
/* Paste what we have (result) to what the Unicode formatting
function returned (v) and return the result (or error) */
w
=
PyUnicode_Concat
(
result
,
v
);
Py_DECREF
(
result
);
Py_DECREF
(
v
);
Py_DECREF
(
args
);
return
w
;
#endif
/* Py_USING_UNICODE */
error:
Py_DECREF
(
result
);
if
(
args_owned
)
{
Py_DECREF
(
args
);
}
return
boxString
(
os
.
str
());
return
NULL
;
}
extern
"C"
Box
*
strMod
(
BoxedString
*
lhs
,
Box
*
rhs
)
{
Box
*
rtn
=
PyString_Format
(
lhs
,
rhs
);
checkAndThrowCAPIException
();
assert
(
rtn
);
return
rtn
;
}
extern
"C"
Box
*
strMul
(
BoxedString
*
lhs
,
Box
*
rhs
)
{
...
...
@@ -1021,7 +1439,8 @@ BoxedString* createUninitializedString(ssize_t n) {
}
char
*
getWriteableStringContents
(
BoxedString
*
s
)
{
ASSERT
(
s
->
s
.
size
()
>
0
,
"not sure whether this is valid for strings with zero size"
);
if
(
s
->
s
.
size
()
==
0
)
return
NULL
;
// After doing some reading, I think this is ok:
// http://stackoverflow.com/questions/14290795/why-is-modifying-a-string-through-a-retrieved-pointer-to-its-data-not-allowed
...
...
test/tests/str_functions.py
View file @
dc914e07
...
...
@@ -80,3 +80,4 @@ print "hello world".partition("o")
print
"hello world"
[
False
:
True
:
True
]
print
"{hello}"
.
format
(
hello
=
"world"
)
print
"%.3s"
%
"hello world"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment