4
_int_types = (c_int16, c_int32)
5
if hasattr(ctypes, 'c_int64'):
6
# Some builds of ctypes apparently do not have c_int64
7
# defined; it's a pretty good bet that these builds do not
8
# have 64-bit pointers.
9
_int_types += (c_int64,)
11
if sizeof(t) == sizeof(c_size_t):
16
class c_void(Structure):
17
# c_void_p is a buggy return type, converting to int, so
18
# POINTER(None) == c_void_p is actually written as
19
# POINTER(c_void), so it can be treated as a real pointer.
20
_fields_ = [('dummy', c_int)]
23
p = ctypes.POINTER(obj)
25
# Convert None to a real NULL pointer to work around bugs
26
# in how ctypes handles None on 64-bit platforms
27
if not isinstance(p.from_param, classmethod):
28
def from_param(cls, x):
33
p.from_param = classmethod(from_param)
38
def __init__(self, seq):
39
if isinstance(seq, basestring):
41
elif isinstance(seq, UserString):
42
self.data = seq.data[:]
45
def __str__(self): return str(self.data)
46
def __repr__(self): return repr(self.data)
47
def __int__(self): return int(self.data)
48
def __long__(self): return long(self.data)
49
def __float__(self): return float(self.data)
50
def __complex__(self): return complex(self.data)
51
def __hash__(self): return hash(self.data)
53
def __cmp__(self, string):
54
if isinstance(string, UserString):
55
return cmp(self.data, string.data)
57
return cmp(self.data, string)
58
def __contains__(self, char):
59
return char in self.data
61
def __len__(self): return len(self.data)
62
def __getitem__(self, index): return self.__class__(self.data[index])
63
def __getslice__(self, start, end):
64
start = max(start, 0); end = max(end, 0)
65
return self.__class__(self.data[start:end])
67
def __add__(self, other):
68
if isinstance(other, UserString):
69
return self.__class__(self.data + other.data)
70
elif isinstance(other, basestring):
71
return self.__class__(self.data + other)
73
return self.__class__(self.data + str(other))
74
def __radd__(self, other):
75
if isinstance(other, basestring):
76
return self.__class__(other + self.data)
78
return self.__class__(str(other) + self.data)
80
return self.__class__(self.data*n)
82
def __mod__(self, args):
83
return self.__class__(self.data % args)
85
# the following methods are defined in alphabetical order:
86
def capitalize(self): return self.__class__(self.data.capitalize())
87
def center(self, width, *args):
88
return self.__class__(self.data.center(width, *args))
89
def count(self, sub, start=0, end=sys.maxint):
90
return self.data.count(sub, start, end)
91
def decode(self, encoding=None, errors=None): # XXX improve this?
94
return self.__class__(self.data.decode(encoding, errors))
96
return self.__class__(self.data.decode(encoding))
98
return self.__class__(self.data.decode())
99
def encode(self, encoding=None, errors=None): # XXX improve this?
102
return self.__class__(self.data.encode(encoding, errors))
104
return self.__class__(self.data.encode(encoding))
106
return self.__class__(self.data.encode())
107
def endswith(self, suffix, start=0, end=sys.maxint):
108
return self.data.endswith(suffix, start, end)
109
def expandtabs(self, tabsize=8):
110
return self.__class__(self.data.expandtabs(tabsize))
111
def find(self, sub, start=0, end=sys.maxint):
112
return self.data.find(sub, start, end)
113
def index(self, sub, start=0, end=sys.maxint):
114
return self.data.index(sub, start, end)
115
def isalpha(self): return self.data.isalpha()
116
def isalnum(self): return self.data.isalnum()
117
def isdecimal(self): return self.data.isdecimal()
118
def isdigit(self): return self.data.isdigit()
119
def islower(self): return self.data.islower()
120
def isnumeric(self): return self.data.isnumeric()
121
def isspace(self): return self.data.isspace()
122
def istitle(self): return self.data.istitle()
123
def isupper(self): return self.data.isupper()
124
def join(self, seq): return self.data.join(seq)
125
def ljust(self, width, *args):
126
return self.__class__(self.data.ljust(width, *args))
127
def lower(self): return self.__class__(self.data.lower())
128
def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars))
129
def partition(self, sep):
130
return self.data.partition(sep)
131
def replace(self, old, new, maxsplit=-1):
132
return self.__class__(self.data.replace(old, new, maxsplit))
133
def rfind(self, sub, start=0, end=sys.maxint):
134
return self.data.rfind(sub, start, end)
135
def rindex(self, sub, start=0, end=sys.maxint):
136
return self.data.rindex(sub, start, end)
137
def rjust(self, width, *args):
138
return self.__class__(self.data.rjust(width, *args))
139
def rpartition(self, sep):
140
return self.data.rpartition(sep)
141
def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars))
142
def split(self, sep=None, maxsplit=-1):
143
return self.data.split(sep, maxsplit)
144
def rsplit(self, sep=None, maxsplit=-1):
145
return self.data.rsplit(sep, maxsplit)
146
def splitlines(self, keepends=0): return self.data.splitlines(keepends)
147
def startswith(self, prefix, start=0, end=sys.maxint):
148
return self.data.startswith(prefix, start, end)
149
def strip(self, chars=None): return self.__class__(self.data.strip(chars))
150
def swapcase(self): return self.__class__(self.data.swapcase())
151
def title(self): return self.__class__(self.data.title())
152
def translate(self, *args):
153
return self.__class__(self.data.translate(*args))
154
def upper(self): return self.__class__(self.data.upper())
155
def zfill(self, width): return self.__class__(self.data.zfill(width))
157
class MutableString(UserString):
158
"""mutable string objects
160
Python strings are immutable objects. This has the advantage, that
161
strings may be used as dictionary keys. If this property isn't needed
162
and you insist on changing string values in place instead, you may cheat
163
and use MutableString.
165
But the purpose of this class is an educational one: to prevent
166
people from inventing their own mutable string class derived
167
from UserString and than forget thereby to remove (override) the
168
__hash__ method inherited from UserString. This would lead to
169
errors that would be very hard to track down.
171
A faster and better solution is to rewrite your program using lists."""
172
def __init__(self, string=""):
175
raise TypeError, "unhashable type (it is mutable)"
176
def __setitem__(self, index, sub):
178
index += len(self.data)
179
if index < 0 or index >= len(self.data): raise IndexError
180
self.data = self.data[:index] + sub + self.data[index+1:]
181
def __delitem__(self, index):
183
index += len(self.data)
184
if index < 0 or index >= len(self.data): raise IndexError
185
self.data = self.data[:index] + self.data[index+1:]
186
def __setslice__(self, start, end, sub):
187
start = max(start, 0); end = max(end, 0)
188
if isinstance(sub, UserString):
189
self.data = self.data[:start]+sub.data+self.data[end:]
190
elif isinstance(sub, basestring):
191
self.data = self.data[:start]+sub+self.data[end:]
193
self.data = self.data[:start]+str(sub)+self.data[end:]
194
def __delslice__(self, start, end):
195
start = max(start, 0); end = max(end, 0)
196
self.data = self.data[:start] + self.data[end:]
198
return UserString(self.data)
199
def __iadd__(self, other):
200
if isinstance(other, UserString):
201
self.data += other.data
202
elif isinstance(other, basestring):
205
self.data += str(other)
207
def __imul__(self, n):
211
class String(MutableString, Union):
213
_fields_ = [('raw', POINTER(c_char)),
216
def __init__(self, obj=""):
217
if isinstance(obj, (str, unicode, UserString)):
223
return self.data and len(self.data) or 0
225
def from_param(cls, obj):
227
if obj is None or obj == 0:
228
return cls(POINTER(c_char)())
230
# Convert from String
231
elif isinstance(obj, String):
235
elif isinstance(obj, str):
238
# Convert from c_char_p
239
elif isinstance(obj, c_char_p):
242
# Convert from POINTER(c_char)
243
elif isinstance(obj, POINTER(c_char)):
246
# Convert from raw pointer
247
elif isinstance(obj, int):
248
return cls(cast(obj, POINTER(c_char)))
250
# Convert from object
252
return String.from_param(obj._as_parameter_)
253
from_param = classmethod(from_param)
255
def ReturnString(obj):
256
return String.from_param(obj)
258
# As of ctypes 1.0, ctypes does not support custom error-checking
259
# functions on callbacks, nor does it support custom datatypes on
260
# callbacks, so we must ensure that all callbacks return
261
# primitive datatypes.
263
# Non-primitive return values wrapped with UNCHECKED won't be
264
# typechecked, and will be converted to c_void_p.
266
if (hasattr(type, "_type_") and isinstance(type._type_, str)
267
and type._type_ != "P"):
272
# ctypes doesn't have direct support for variadic functions, so we have to write
273
# our own wrapper class
274
class _variadic_function(object):
275
def __init__(self,func,restype,argtypes):
277
self.func.restype=restype
278
self.argtypes=argtypes
279
def _as_parameter_(self):
280
# So we can pass this variadic function as a function pointer
282
def __call__(self,*args):
285
for argtype in self.argtypes:
286
# Typecheck what we can
287
fixed_args.append(argtype.from_param(args[i]))
289
return self.func(*fixed_args+list(args[i:]))