1 /* D-Bus Byte and ByteArray types.
3 * Copyright (C) 2006 Collabora Ltd.
5 * Licensed under the Academic Free License version 2.1
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 static PyTypeObject ByteType
, ByteArrayType
;
27 static inline int Byte_Check(PyObject
*o
)
29 return (o
->ob_type
== &ByteType
)
30 || PyObject_IsInstance(o
, (PyObject
*)&ByteType
);
33 static inline int ByteArray_Check(PyObject
*o
)
35 return (o
->ob_type
== &ByteArrayType
)
36 || PyObject_IsInstance(o
, (PyObject
*)&ByteArrayType
);
39 PyDoc_STRVAR(Byte_tp_doc
,
40 "Byte(integer or str of length 1[, variant_level])\n"
42 "Byte is a subtype of int, with range restricted to [0, 255].\n"
44 "A Byte b may be converted to a str of length 1 via str(b) == chr(b).\n"
48 Byte_new(PyTypeObject
*cls
, PyObject
*args
, PyObject
*kwargs
)
53 static char *argnames
[] = {"variant_level", NULL
};
55 if (PyTuple_Size(args
) > 1) {
56 PyErr_SetString(PyExc_TypeError
, "Byte constructor takes no more "
57 "than one positional argument");
60 if (!PyArg_ParseTupleAndKeywords(empty_tuple
, kwargs
,
61 "|l:__new__", argnames
,
62 &variantness
)) return NULL
;
63 if (variantness
< 0) {
64 PyErr_SetString(PyExc_ValueError
,
65 "variant_level must be non-negative");
69 /* obj is only a borrowed ref for the moment */
70 obj
= PyTuple_GetItem(args
, 0);
72 if (PyString_Check(obj
)) {
73 /* string of length 1, we hope */
74 if (PyString_GET_SIZE(obj
) != 1) {
77 obj
= PyInt_FromLong((unsigned char)(PyString_AS_STRING(obj
)[0]));
79 else if (PyInt_Check(obj
)) {
80 long i
= PyInt_AS_LONG(obj
);
82 if (obj
->ob_type
== cls
&&
83 ((DBusPythonInt
*)obj
)->variant_level
== variantness
) {
87 if (i
< 0 || i
> 255) goto bad_range
;
88 /* else make it a new reference */
95 tuple
= Py_BuildValue("(O)", obj
);
96 if (!tuple
) return NULL
;
100 obj
= DBusPythonIntType
.tp_new(cls
, tuple
, kwargs
);
106 PyErr_SetString(PyExc_TypeError
, "Expected a string of length 1, "
107 "or an int in the range 0-255");
110 PyErr_SetString(PyExc_ValueError
, "Integer outside range 0-255");
115 Byte_tp_str(PyObject
*self
)
117 unsigned char str
[2] = { (unsigned char)PyInt_AS_LONG(self
), 0 };
118 return PyString_FromStringAndSize((char *)str
, 1);
121 static PyTypeObject ByteType
= {
122 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
132 DBusPythonInt_tp_repr
, /* tp_repr */
133 0, /* tp_as_number */
134 0, /* tp_as_sequence */
135 0, /* tp_as_mapping */
138 Byte_tp_str
, /* tp_str */
141 0, /* tp_as_buffer */
142 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
143 Byte_tp_doc
, /* tp_doc */
146 0, /* tp_richcompare */
147 0, /* tp_weaklistoffset */
153 DEFERRED_ADDRESS(&PyInt_Type
), /* tp_base */
155 0, /* tp_descr_get */
156 0, /* tp_descr_set */
157 0, /* tp_dictoffset */
160 Byte_new
, /* tp_new */
163 PyDoc_STRVAR(ByteArray_tp_doc
,
166 "ByteArray is a subtype of str which can be used when you want an\n"
167 "efficient immutable representation of a D-Bus byte array (signature 'ay').\n"
169 "The subscript operation byte_array[i] returns Byte instances. Otherwise,\n"
170 "it's just a string.\n"
174 ByteArray_sq_item (PyObject
*self
, int i
)
179 if (i
< 0 || i
>= PyString_GET_SIZE(self
)) {
180 PyErr_SetString(PyExc_IndexError
, "ByteArray index out of range");
183 c
= ((unsigned char *)PyString_AS_STRING(self
))[i
];
184 args
= Py_BuildValue("(l)", (long)c
);
187 return PyObject_Call((PyObject
*)&ByteType
, args
, NULL
);
191 ByteArray_mp_subscript(PyObject
*self
, PyObject
*other
)
194 if (PyInt_Check(other
)) {
195 i
= PyInt_AS_LONG(other
);
196 if (i
< 0) i
+= PyString_GET_SIZE (self
);
197 return ByteArray_sq_item(self
, i
);
199 else if (PyLong_Check(other
)) {
200 i
= PyLong_AsLong(other
);
201 if (i
== -1 && PyErr_Occurred()) return NULL
;
202 if (i
< 0) i
+= PyString_GET_SIZE(self
);
203 return ByteArray_sq_item(self
, i
);
206 /* slices just return strings */
207 return (PyString_Type
.tp_as_mapping
->mp_subscript
)(self
, other
);
211 static PyMappingMethods ByteArray_tp_as_mapping
= {
213 ByteArray_mp_subscript
, /* mp_subscript */
214 0, /* mp_ass_subscript */
217 static PySequenceMethods ByteArray_tp_as_sequence
= {
221 ByteArray_sq_item
, /* sq_item */
224 0, /* sq_ass_slice */
228 static PyTypeObject ByteArrayType
= {
229 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type
))
240 0, /* tp_as_number */
241 &ByteArray_tp_as_sequence
, /* tp_as_sequence */
242 &ByteArray_tp_as_mapping
, /* tp_as_mapping */
248 0, /* tp_as_buffer */
249 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_BASETYPE
, /* tp_flags */
250 ByteArray_tp_doc
, /* tp_doc */
253 0, /* tp_richcompare */
254 0, /* tp_weaklistoffset */
260 DEFERRED_ADDRESS(&DBusPythonStringType
), /* tp_base */
262 0, /* tp_descr_get */
263 0, /* tp_descr_set */
264 0, /* tp_dictoffset */
271 init_byte_types(void)
273 ByteType
.tp_base
= &DBusPythonIntType
;
274 if (PyType_Ready(&ByteType
) < 0) return 0;
275 ByteType
.tp_print
= NULL
;
277 ByteArrayType
.tp_base
= &DBusPythonStringType
;
278 if (PyType_Ready(&ByteArrayType
) < 0) return 0;
279 ByteArrayType
.tp_print
= NULL
;
285 insert_byte_types(PyObject
*this_module
)
287 Py_INCREF(&ByteType
);
288 if (PyModule_AddObject(this_module
, "Byte",
289 (PyObject
*)&ByteType
) < 0) return 0;
290 Py_INCREF(&ByteArrayType
);
291 if (PyModule_AddObject(this_module
, "ByteArray",
292 (PyObject
*)&ByteArrayType
) < 0) return 0;
297 /* vim:set ft=c cino< sw=4 sts=4 et: */