Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
9e37fb79
Commit
9e37fb79
authored
Apr 08, 2016
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avoid intermediate PyInt/Long creation when formatting C integer values
parent
f7f6dd3d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
5 deletions
+136
-5
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+18
-1
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+32
-0
Cython/Utility/TypeConversion.c
Cython/Utility/TypeConversion.c
+62
-0
tests/run/fstring.pyx
tests/run/fstring.pyx
+24
-4
No files found.
Cython/Compiler/ExprNodes.py
View file @
9e37fb79
...
...
@@ -3028,9 +3028,12 @@ class FormattedValueNode(ExprNode):
return
False
def
analyse_types
(
self
,
env
):
self
.
value
=
self
.
value
.
analyse_types
(
env
)
.
coerce_to_pyobject
(
env
)
self
.
value
=
self
.
value
.
analyse_types
(
env
)
if
self
.
format_spec
:
self
.
format_spec
=
self
.
format_spec
.
analyse_types
(
env
).
coerce_to_pyobject
(
env
)
elif
not
self
.
conversion_char
and
self
.
value
.
type
.
can_coerce_to_pyunicode
(
env
):
return
FormattedCValueNode
(
self
.
pos
,
value
=
self
.
value
)
self
.
value
=
self
.
value
.
coerce_to_pyobject
(
env
)
return
self
def
generate_result_code
(
self
,
code
):
...
...
@@ -3064,6 +3067,20 @@ class FormattedValueNode(ExprNode):
code
.
put_gotref
(
self
.
py_result
())
class
FormattedCValueNode
(
FormattedValueNode
):
conversion_char
=
None
format_spec
=
None
def
generate_result_code
(
self
,
code
):
convert_func
=
self
.
value
.
type
.
to_pyunicode_utility_code
(
code
)
code
.
putln
(
"%s = %s(%s); %s"
%
(
self
.
result
(),
convert_func
,
self
.
value
.
result
(),
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
#-------------------------------------------------------------------
#
# Parallel nodes (cython.parallel.thread(savailable|id))
...
...
Cython/Compiler/PyrexTypes.py
View file @
9e37fb79
...
...
@@ -30,6 +30,9 @@ class BaseType(object):
def
can_coerce_to_pyobject
(
self
,
env
):
return
False
def
can_coerce_to_pyunicode
(
self
,
env
):
return
False
def
cast_code
(
self
,
expr_code
):
return
"((%s)%s)"
%
(
self
.
empty_declaration_code
(),
expr_code
)
...
...
@@ -1620,11 +1623,28 @@ class CIntType(CNumericType):
typedef_flag
=
0
to_py_function
=
None
from_py_function
=
None
to_pyunicode_utility
=
None
exception_value
=
-
1
def
can_coerce_to_pyobject
(
self
,
env
):
return
True
def
can_coerce_to_pyunicode
(
self
,
env
):
return
True
def
to_pyunicode_utility_code
(
self
,
code
):
if
self
.
to_pyunicode_utility
is
None
:
utility_code_name
=
"__Pyx_PyUnicode_From_"
+
self
.
specialization_name
()
to_pyunicode_utility
=
TempitaUtilityCode
.
load_cached
(
"CIntToPyUnicode"
,
"TypeConversion.c"
,
context
=
{
"TYPE"
:
self
.
empty_declaration_code
(),
"TO_PY_FUNCTION"
:
utility_code_name
})
self
.
to_pyunicode_utility
=
(
utility_code_name
,
to_pyunicode_utility
)
else
:
utility_code_name
,
to_pyunicode_utility
=
self
.
to_pyunicode_utility
code
.
globalstate
.
use_utility_code
(
to_pyunicode_utility
)
return
utility_code_name
def
create_to_py_utility_code
(
self
,
env
):
if
type
(
self
).
to_py_function
is
None
:
self
.
to_py_function
=
"__Pyx_PyInt_From_"
+
self
.
specialization_name
()
...
...
@@ -1732,6 +1752,9 @@ class CReturnCodeType(CIntType):
is_returncode
=
True
exception_check
=
False
def
can_coerce_to_pyunicode
(
self
,
env
):
return
False
class
CBIntType
(
CIntType
):
...
...
@@ -1739,6 +1762,9 @@ class CBIntType(CIntType):
from_py_function
=
"__Pyx_PyObject_IsTrue"
exception_check
=
1
# for C++ bool
def
can_coerce_to_pyunicode
(
self
,
env
):
return
False
def
declaration_code
(
self
,
entity_code
,
for_display
=
0
,
dll_linkage
=
None
,
pyrex
=
0
):
if
for_display
:
...
...
@@ -1773,6 +1799,9 @@ class CPyUCS4IntType(CIntType):
to_py_function
=
"PyUnicode_FromOrdinal"
from_py_function
=
"__Pyx_PyObject_AsPy_UCS4"
def
can_coerce_to_pyunicode
(
self
,
env
):
return
False
def
create_from_py_utility_code
(
self
,
env
):
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"ObjectAsUCS4"
,
"TypeConversion.c"
))
return
True
...
...
@@ -1794,6 +1823,9 @@ class CPyUnicodeIntType(CIntType):
to_py_function
=
"PyUnicode_FromOrdinal"
from_py_function
=
"__Pyx_PyObject_AsPy_UNICODE"
def
can_coerce_to_pyunicode
(
self
,
env
):
return
False
def
create_from_py_utility_code
(
self
,
env
):
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"ObjectAsPyUnicode"
,
"TypeConversion.c"
))
return
True
...
...
Cython/Utility/TypeConversion.c
View file @
9e37fb79
...
...
@@ -568,6 +568,68 @@ static CYTHON_INLINE PyObject* {{TO_PY_FUNCTION}}({{TYPE}} value) {
}
/////////////// CIntToPyUnicode.proto ///////////////
static
CYTHON_INLINE
PyObject
*
{{
TO_PY_FUNCTION
}}({{
TYPE
}}
value
);
/////////////// CIntToPyUnicode ///////////////
static
CYTHON_INLINE
PyObject
*
{{
TO_PY_FUNCTION
}}({{
TYPE
}}
value
)
{
// simple and conservative string allocation on the stack
char
digits
[
sizeof
({{
TYPE
}})
*
3
+
2
];
int
length
=
-
1
;
const
{{
TYPE
}}
neg_one
=
({{
TYPE
}})
-
1
,
const_zero
=
({{
TYPE
}})
0
;
const
int
is_unsigned
=
neg_one
>
const_zero
;
if
(
is_unsigned
)
{
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
unsigned
int
))
{
length
=
sprintf
(
digits
,
"%u"
,
(
unsigned
int
)
value
);
}
else
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
unsigned
long
))
{
length
=
sprintf
(
digits
,
"%lu"
,
(
unsigned
long
)
value
);
}
else
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
unsigned
PY_LONG_LONG
))
{
length
=
sprintf
(
digits
,
"%llu"
,
(
unsigned
PY_LONG_LONG
)
value
);
}
}
else
{
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
int
))
{
length
=
sprintf
(
digits
,
"%d"
,
(
int
)
value
);
}
else
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
long
))
{
length
=
sprintf
(
digits
,
"%ld"
,
(
long
)
value
);
}
else
if
(
sizeof
({{
TYPE
}})
<=
sizeof
(
PY_LONG_LONG
))
{
length
=
sprintf
(
digits
,
"%lld"
,
(
PY_LONG_LONG
)
value
);
}
}
if
(
unlikely
(
length
<
0
))
{
// huge integer type or (unlikely) error in sprintf() => use slow conversion
PyObject
*
pylong
,
*
uval
=
NULL
;
int
one
=
1
;
int
little
=
(
int
)
*
(
unsigned
char
*
)
&
one
;
unsigned
char
*
bytes
=
(
unsigned
char
*
)
&
value
;
pylong
=
_PyLong_FromByteArray
(
bytes
,
sizeof
({{
TYPE
}}),
little
,
!
is_unsigned
);
if
(
likely
(
pylong
))
{
#if PY_MAJOR_VERSION >= 3
uval
=
PyObject_Str
(
pylong
);
#else
uval
=
PyObject_Unicode
(
pylong
);
#endif
Py_DECREF
(
pylong
);
}
return
uval
;
}
return
PyUnicode_DecodeASCII
(
digits
,
length
,
NULL
);
}
/////////////// NewOwnedRef.proto ///////////////
static
CYTHON_INLINE
PyObject
*
__Pyx_NewOwnedRef
(
PyObject
*
value
);
/////////////// NewOwnedRef ///////////////
static
CYTHON_INLINE
PyObject
*
__Pyx_NewOwnedRef
(
PyObject
*
value
)
{
Py_INCREF
(
value
);
return
value
;
}
/////////////// PyIntFromDouble.proto ///////////////
#if PY_MAJOR_VERSION < 3
...
...
tests/run/fstring.pyx
View file @
9e37fb79
...
...
@@ -32,11 +32,11 @@ def format2(ab, cd):
return
a
,
b
,
c
def
format_c_numbers
(
int
n
,
float
f
,
double
d
):
def
format_c_numbers
(
char
c
,
short
s
,
int
n
,
long
l
,
float
f
,
double
d
):
"""
>>> s1, s2, s3, s4 = format_c_numbers(12, 2.3456, 3.1415926)
>>> s1, s2, s3, s4 = format_c_numbers(12
3, 135, 12, 12312312
, 2.3456, 3.1415926)
>>> print(s1)
122.35
12
3 1351231231212
2.35
>>> print(s2)
3.14 2.3
>>> print(s3)
...
...
@@ -45,7 +45,7 @@ def format_c_numbers(int n, float f, double d):
C 3.14
"""
s1
=
f"
{
n
}{
f
:.
3
}
"
s1
=
f"
{
c
}{
s
:
4
}{
l
}{
n
}{
f
:.
3
}
"
assert
isinstance
(
s1
,
unicode
),
type
(
s1
)
s2
=
f"
{
d
:.
3
}{
f
:
4.2
}
"
assert
isinstance
(
s2
,
unicode
),
type
(
s2
)
...
...
@@ -56,6 +56,26 @@ def format_c_numbers(int n, float f, double d):
return
s1
,
s2
,
s3
,
s4
def
format_c_values
(
Py_UCS4
uchar
,
Py_UNICODE
pyunicode
):
"""
>>> s, s1, s2 = format_c_values(b'A'.decode('ascii'), b'X'.decode('ascii'))
>>> print(s)
AXAX
>>> print(s1)
A
>>> print(s2)
X
"""
s
=
f"
{
uchar
}{
pyunicode
}{
uchar
!
s
}{
pyunicode
!
s
}
"
assert
isinstance
(
s
,
unicode
),
type
(
s
)
s1
=
f"
{
uchar
}
"
assert
isinstance
(
s1
,
unicode
),
type
(
s1
)
s2
=
f"
{
pyunicode
}
"
assert
isinstance
(
s2
,
unicode
),
type
(
s2
)
return
s
,
s1
,
s2
def
format_strings
(
str
s
,
unicode
u
):
"""
>>> a, b, c, d = format_strings('abc', b'xyz'.decode('ascii'))
...
...
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