Skip to content

Commit ff1d4a5

Browse files
committed
Improve string conversion helpers
1 parent 9e4a69b commit ff1d4a5

File tree

9 files changed

+64
-76
lines changed

9 files changed

+64
-76
lines changed

src/_pythonscript.pyx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ include "_pythonscript_editor.pxi"
1515
# godot_pluginscript_language_data,
1616
# )
1717
# from godot.hazmat.internal cimport set_pythonscript_verbose, get_pythonscript_verbose
18-
from godot.builtins cimport GDString, Vector2, pystr_to_gdstr, gdstr_to_pystr
18+
from godot.builtins cimport GDString, Vector2
1919

2020
# def _setup_config_entry(name, default_value):
2121
# gdname = GDString(name)
@@ -53,8 +53,8 @@ cdef api void _pythonscript_free_instance(
5353
cdef api void _pythonscript_initialize() with gil:
5454
import sys
5555
from godot._version import __version__ as pythonscript_version
56-
r = gdstr_to_pystr(<GDNativeStringPtr*>&pystr_to_gdstr("foo")._gd_data)
57-
if r == "foo":
56+
cdef GDString r = GDString("foo")
57+
if r.to_pystr() == "foo":
5858
pythonscript_gdapi.print_error("ok", "<function>", "<file>", 0)
5959
else:
6060
pythonscript_gdapi.print_error("ko", "<function>", "<file>", 0)

src/_pythonscript_editor.pxi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ cdef api gd_packed_string_array_t _pythonscript_get_reserved_words():
4040
"yield",
4141
]
4242
for keyword in keywords:
43-
string = gd_string_from_utf8(keyword, keyword.len())
43+
string = gdstring_from_utf8(keyword, keyword.len())
4444
gd_packed_string_array_append(&arr, &string)
4545
gd_string_del(&string)
4646
return arr

src/godot/builtins.pxd.j2

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@ cdef extern from "Python.h":
99
from .hazmat.gdapi cimport *
1010

1111

12-
# Godot internally uses utf32 encoding format
13-
# CPython is more complex (uses different encodings to save space), but leans toward UTF8
14-
15-
16-
cdef inline GDString pystr_to_gdstr(object pystr):
17-
cdef size_t buffsize
18-
cdef const char *buff = PyUnicode_AsUTF8AndSize(pystr, &buffsize)
19-
cdef GDString gdstr = GDString.__new__(GDString)
20-
pythonscript_gdapi.string_new_with_utf8_chars_and_len(&gdstr._gd_data, buff, buffsize)
21-
return gdstr
22-
23-
24-
cdef inline object gdstr_to_pystr(GDNativeStringPtr *gdstr):
25-
cdef GDNativeInt l = pythonscript_gdapi.string_to_utf32_chars(gdstr, NULL, 0)
26-
cdef const char32_t *gdbuff = pythonscript_gdapi.string_operator_index_const(gdstr, 0)
27-
return PyUnicode_DecodeUTF32(<char *>gdbuff, l * cython.sizeof(char32_t), NULL, NULL)
12+
cdef inline GDString ensure_is_gdstring(object gdstring_or_pystr):
13+
cdef GDString gdstring_converted
14+
try:
15+
return <GDString?>gdstring_or_pystr
16+
except TypeError:
17+
try:
18+
return GDString(gdstring_or_pystr)
19+
except TypeError:
20+
raise TypeError(f"Invalid value {gdstring_or_pystr!r}, must be str or GDString")
21+
22+
23+
cdef inline NodePath ensure_is_nodepath(object nodepath_or_pystr):
24+
cdef NodePath NodePath_converted
25+
try:
26+
return <NodePath?>nodepath_or_pystr
27+
except TypeError:
28+
try:
29+
return NodePath(nodepath_or_pystr)
30+
except TypeError:
31+
raise TypeError(f"Invalid value {nodepath_or_pystr!r}, must be str or NodePath")
2832
{% for spec in api["builtins"] if not spec.is_scalar %}
2933

3034

@@ -39,4 +43,8 @@ cdef class {{ spec.name }}:
3943
cdef {{ spec.name }} ret = {{ spec.name }}.__new__({{ spec.name }})
4044
__{{ spec.name }}_constructor_0(&ret._gd_data, NULL)
4145
return ret
46+
{% if spec.name == "GDString" %}
47+
cdef inline gd_string_t to_pystr(self):
48+
return gdstring_to_pystr(&self._gd_data)
49+
{% endif %}
4250
{% endfor %}

src/godot/builtins_pyx/class.pxi.j2

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ cdef class {{ spec.name }}:
200200
# TODO: finish me...
201201
# pythonscript_gdapi.variant_stringify(&self._gd_data)
202202
return "<{{ spec.name }}>"
203-
203+
{% if spec.name == "GDString" %}
204+
def __str__(self):
205+
self.to_pystr()
206+
{% endif %}
204207
{% if spec.constants %}
205208
# Constants
206209

src/godot/builtins_pyx/constructor.pxi.j2

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ def __cinit__(self, s=None):
6767
if s is None:
6868
__GDString_constructor_0(&self._gd_data, NULL)
6969
elif isinstance(s, str):
70-
{# pyobj_to_godot_string(s, &self._gd_data) # TODO: implement me ! #}
71-
raise NotImplementedError("Not available yet :'(")
70+
self._gd_data = gdstring_from_unchecked_pystr(s)
7271
else:
7372
try:
7473
args[0] = &(<GDString?>s)._gd_data

src/godot/hazmat/gdapi.conversion.pxd.j2

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@ cdef object gdtype_to_pytype(GDNativeVariantType gdtype)
77
cdef GDNativeVariantType pytype_to_gdtype(object pytype)
88

99

10-
cdef inline GDString ensure_is_gdstring(object gdstring_or_pystr):
11-
cdef GDString gdstring_converted
12-
try:
13-
return <GDString?>gdstring_or_pystr
14-
except TypeError:
15-
try:
16-
return GDString(gdstring_or_pystr)
17-
except TypeError:
18-
raise TypeError(f"Invalid value {gdstring_or_pystr!r}, must be str or GDString")
19-
20-
21-
cdef inline NodePath ensure_is_nodepath(object nodepath_or_pystr):
22-
cdef NodePath NodePath_converted
23-
try:
24-
return <NodePath?>nodepath_or_pystr
25-
except TypeError:
26-
try:
27-
return NodePath(nodepath_or_pystr)
28-
except TypeError:
29-
raise TypeError(f"Invalid value {nodepath_or_pystr!r}, must be str or NodePath")
10+
cdef extern from "Python.h":
11+
const char* PyUnicode_AsUTF8AndSize(object, size_t*)
12+
object PyUnicode_DecodeUTF32(const char *s, size_t size, const char *errors, int *byteorder)
13+
14+
15+
cdef inline gd_string_t gdstring_from_utf8(const char *cstr, size_t cstr_size):
16+
cdef gd_string_t gdstr
17+
pythonscript_gdapi.string_new_with_utf8_chars_and_len(&gdstr, cstr, cstr_size)
18+
return gdstr
19+
20+
21+
cdef inline gd_string_t gdstring_from_unchecked_pystr(object pystr):
22+
cdef size_t buffsize
23+
cdef const char *buff = PyUnicode_AsUTF8AndSize(pystr, &buffsize)
24+
return gdstring_from_utf8(buff, buffsize)
25+
26+
27+
cdef inline object gdstring_to_pystr(gd_string_t *gdstr):
28+
cdef GDNativeInt l = pythonscript_gdapi.string_to_utf32_chars(gdstr, NULL, 0)
29+
cdef const char32_t *gdbuff = pythonscript_gdapi.string_operator_index_const(gdstr, 0)
30+
return PyUnicode_DecodeUTF32(<char *>gdbuff, l * cython.sizeof(char32_t), NULL, NULL)

src/godot/hazmat/gdapi.conversion.pyx.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ cdef inline void _pyobj_to_gdvariant_int({{ api.int_spec.cy_type }} val, gd_vari
133133

134134

135135
cdef inline void _pyobj_to_gdvariant_pystr(object pyobj, gd_variant_t *p_gdvar):
136-
cdef gd_string_t gdstr = gd_string_from_unchecked_pystr(pyobj)
136+
cdef gd_string_t gdstr = gdstring_from_unchecked_pystr(pyobj)
137137
try:
138138
__GDString_to_variant(p_gdvar, &gdstr)
139139
finally:

src/godot/hazmat/gdapi.pxd.j2

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ cdef extern from * nogil:
3535
cdef const GDNativeExtensionClassLibraryPtr pythonscript_gdlibrary
3636

3737

38+
##############################################################################
39+
# Conversion helpers #
40+
##############################################################################
41+
42+
43+
{% include 'gdapi.conversion.pxd.j2' %}
44+
45+
3846
##############################################################################
3947
# Builtins #
4048
##############################################################################
@@ -52,10 +60,6 @@ cdef extern from *:
5260
{% endfor %}
5361

5462

55-
# String conversion helpers defined in the jungle below
56-
# gd_string_t gd_string_from_utf8(const char *cstr, size_t cstr_size)
57-
# gd_string_t gd_string_from_pystr(object pystr)
58-
# object gd_string_to_pystr(gd_string_t *gdstr)
5963
{% for spec in api["builtins"] if not spec.is_scalar %}
6064

6165

@@ -110,34 +114,6 @@ cdef extern from *:
110114
# and nicer inline function
111115

112116

113-
##############################################################################
114-
# Inline defs: String conversion helpers #
115-
##############################################################################
116-
117-
118-
cdef extern from "Python.h":
119-
const char* PyUnicode_AsUTF8AndSize(object, size_t*)
120-
object PyUnicode_DecodeUTF32(const char *s, size_t size, const char *errors, int *byteorder)
121-
122-
123-
cdef inline gd_string_t gd_string_from_utf8(const char *cstr, size_t cstr_size):
124-
cdef gd_string_t gdstr
125-
pythonscript_gdapi.string_new_with_utf8_chars_and_len(&gdstr, cstr, cstr_size)
126-
return gdstr
127-
128-
129-
cdef inline gd_string_t gd_string_from_unchecked_pystr(object pystr):
130-
cdef size_t buffsize
131-
cdef const char *buff = PyUnicode_AsUTF8AndSize(pystr, &buffsize)
132-
return gd_string_from_utf8(buff, buffsize)
133-
134-
135-
cdef inline object gd_string_to_pystr(gd_string_t *gdstr):
136-
cdef GDNativeInt l = pythonscript_gdapi.string_to_utf32_chars(gdstr, NULL, 0)
137-
cdef const char32_t *gdbuff = pythonscript_gdapi.string_operator_index_const(gdstr, 0)
138-
return PyUnicode_DecodeUTF32(<char *>gdbuff, l * cython.sizeof(char32_t), NULL, NULL)
139-
140-
141117
##############################################################################
142118
# Inline defs: Utility functions #
143119
##############################################################################

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pxd_godot_hazmat_gdapi = custom_target(
7474
files(
7575
'godot/hazmat/gdapi.pxd.j2',
7676
'godot/hazmat/gdapi.macros.pxd.j2',
77+
'godot/hazmat/gdapi.conversion.pxd.j2',
7778
),
7879
],
7980
command: generate_tmpl_cmd,

0 commit comments

Comments
 (0)