summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/python/py_tdbpack.c243
1 files changed, 56 insertions, 187 deletions
diff --git a/source3/python/py_tdbpack.c b/source3/python/py_tdbpack.c
index 7180c3e12c..d8c3d46773 100644
--- a/source3/python/py_tdbpack.c
+++ b/source3/python/py_tdbpack.c
@@ -31,7 +31,7 @@ static PyObject * pytdbpack_number(char ch, PyObject *val_iter, PyObject *packed
static PyObject * pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list);
static PyObject * pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list);
-static PyObject *pytdbpack_unpack_item(char, char **pbuf, int *plen, PyObject *);
+static PyObject *pytdbunpack_item(char, char **pbuf, int *plen, PyObject *);
static PyObject *pytdbpack_data(const char *format_str,
PyObject *val_seq,
@@ -117,7 +117,7 @@ notes:
";
-static char const pytdbpack_unpack_doc[] =
+static char const pytdbunpack_doc[] =
"unpack(format, buffer) -> (values, rest)
Unpack Samba binary data according to format string.
@@ -145,6 +145,7 @@ notes:
";
+const char *pytdb_string_encoding = "cp850";
/*
@@ -324,7 +325,7 @@ pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list)
val_obj = NULL;
}
- if (!(cp850_str = PyUnicode_AsEncodedString(unicode_obj, "cp850", NULL)))
+ if (!(cp850_str = PyUnicode_AsEncodedString(unicode_obj, pytdb_string_encoding, NULL)))
goto out;
if (!nul_str)
@@ -378,45 +379,47 @@ pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list)
}
-#if 0
-else if (ch == 'B') {
- long size;
- char *sval;
-
- if (!PyNumber_Check(val_obj)) {
- pytdbpack_bad_type(ch, "Number", val_obj);
- return NULL;
- }
+static PyObject *pytdbpack_bad_type(char ch,
+ const char *expected,
+ PyObject *val_obj)
+{
+ PyObject *r = PyObject_Repr(val_obj);
+ if (!r)
+ return NULL;
+ PyErr_Format(PyExc_TypeError,
+ "tdbpack: format '%c' requires %s, not %s",
+ ch, expected, PyString_AS_STRING(r));
+ Py_DECREF(r);
+ return val_obj;
+}
- if (!(val_obj = PyNumber_Long(val_obj)))
- return NULL;
- size = PyLong_AsLong(val_obj);
- pack_le_uint32(size, &packed);
+/*
+ XXX: glib and Samba have quicker macro for doing the endianness conversions,
+ but I don't know of one in plain libc, and it's probably not a big deal. I
+ realize this is kind of dumb because we'll almost always be on x86, but
+ being safe is important.
+*/
+static void pack_le_uint32(unsigned long val_long, unsigned char *pbuf)
+{
+ pbuf[0] = val_long & 0xff;
+ pbuf[1] = (val_long >> 8) & 0xff;
+ pbuf[2] = (val_long >> 16) & 0xff;
+ pbuf[3] = (val_long >> 24) & 0xff;
+}
- /* Release the new reference created by the cast */
- Py_DECREF(val_obj);
- val_obj = PySequence_GetItem(val_seq, val_i++);
- if (!val_obj)
- return NULL;
-
- sval = PyString_AsString(val_obj);
- if (!sval)
- return NULL;
-
- pack_bytes(size, sval, &packed); /* do not include nul */
- }
- else {
-
- }
-
- return Py_None;
+static void pack_bytes(long len, const char *from,
+ unsigned char **pbuf)
+{
+ memcpy(*pbuf, from, len);
+ (*pbuf) += len;
}
-#endif
+
+
static PyObject *
-pytdbpack_unpack(PyObject *self,
+pytdbunpack(PyObject *self,
PyObject *args)
{
char *format_str, *packed_str, *ppacked;
@@ -445,7 +448,7 @@ pytdbpack_unpack(PyObject *self,
for (ppacked = packed_str, i = 0; i < format_len && format_str[i] != '$'; i++) {
last_format = format_str[i];
/* packed_len is reduced in place */
- if (!pytdbpack_unpack_item(format_str[i], &ppacked, &packed_len, val_list))
+ if (!pytdbunpack_item(format_str[i], &ppacked, &packed_len, val_list))
goto failed;
}
@@ -458,7 +461,7 @@ pytdbpack_unpack(PyObject *self,
return NULL;
}
while (packed_len > 0)
- if (!pytdbpack_unpack_item(last_format, &ppacked, &packed_len, val_list))
+ if (!pytdbunpack_item(last_format, &ppacked, &packed_len, val_list))
goto failed;
}
@@ -484,142 +487,8 @@ pytdbpack_unpack(PyObject *self,
}
-
-#if 0
-/*
- Internal routine that calculates how many bytes will be required to
- encode the values in the format.
-
- Also checks that the value list is the right size for the format list.
-
- Returns number of bytes (may be 0), or -1 if there's something wrong, in
- which case a Python exception has been raised.
-
- Arguments:
-
- val_seq: a Fast Sequence (list or tuple), being all the values
-*/
-static int
-pytdbpack_calc_reqd_len(char *format_str,
- PyObject *val_seq)
-{
- int len = 0;
- char *p;
- int val_i;
- int val_len;
-
- val_len = PySequence_Length(val_seq);
- if (val_len == -1)
- return -1;
-
- for (p = format_str, val_i = 0; *p; p++, val_i++) {
- char ch = *p;
-
- if (val_i >= val_len) {
- PyErr_Format(PyExc_IndexError,
- "%s: value list is too short for format string",
- __FUNCTION__);
- return -1;
- }
-
- /* borrow a reference to the item */
- if (ch == 'd' || ch == 'p')
- len += 4;
- else if (ch == 'w')
- len += 2;
- else if (ch == 'f' || ch == 'P') {
- /* nul-terminated 8-bit string */
- int item_len;
- PyObject *str_obj;
-
- str_obj = PySequence_GetItem(val_seq, val_i);
- if (!str_obj)
- return -1;
-
- if (!PyString_Check(str_obj) || ((item_len = PyString_Size(str_obj)) == -1)) {
- pytdbpack_bad_type(ch, "String", str_obj);
- return -1;
- }
-
- len += 1 + item_len;
- }
- else if (ch == 'B') {
- /* length-preceded byte buffer: n bytes, plus a preceding
- * word */
- PyObject *len_obj;
- long len_val;
-
- len_obj = PySequence_GetItem(val_seq, val_i);
- val_i++; /* skip over buffer */
-
- if (!PyNumber_Check(len_obj)) {
- pytdbpack_bad_type(ch, "Number", len_obj);
- return -1;
- }
-
- len_val = PyInt_AsLong(len_obj);
- if (len_val < 0) {
- PyErr_Format(PyExc_ValueError,
- "%s: format 'B' requires positive integer", __FUNCTION__);
- return -1;
- }
-
- len += 4 + len_val;
- }
- else {
- PyErr_Format(PyExc_ValueError,
- "%s: format character '%c' is not supported",
- __FUNCTION__, ch);
-
- return -1;
- }
- }
-
- return len;
-}
-#endif
-
-
-static PyObject *pytdbpack_bad_type(char ch,
- const char *expected,
- PyObject *val_obj)
-{
- PyObject *r = PyObject_Repr(val_obj);
- if (!r)
- return NULL;
- PyErr_Format(PyExc_TypeError,
- "tdbpack: format '%c' requires %s, not %s",
- ch, expected, PyString_AS_STRING(r));
- Py_DECREF(r);
- return val_obj;
-}
-
-
-/*
- XXX: glib and Samba have quicker macro for doing the endianness conversions,
- but I don't know of one in plain libc, and it's probably not a big deal. I
- realize this is kind of dumb because we'll almost always be on x86, but
- being safe is important.
-*/
-static void pack_le_uint32(unsigned long val_long, unsigned char *pbuf)
-{
- pbuf[0] = val_long & 0xff;
- pbuf[1] = (val_long >> 8) & 0xff;
- pbuf[2] = (val_long >> 16) & 0xff;
- pbuf[3] = (val_long >> 24) & 0xff;
-}
-
-
-static void pack_bytes(long len, const char *from,
- unsigned char **pbuf)
-{
- memcpy(*pbuf, from, len);
- (*pbuf) += len;
-}
-
-
static void
-unpack_err_too_short(void)
+pytdbunpack_err_too_short(void)
{
PyErr_Format(PyExc_IndexError,
__FUNCTION__ ": data too short for unpack format");
@@ -627,13 +496,13 @@ unpack_err_too_short(void)
static PyObject *
-unpack_uint32(char **pbuf, int *plen)
+pytdbunpack_uint32(char **pbuf, int *plen)
{
unsigned long v;
unsigned char *b;
if (*plen < 4) {
- unpack_err_too_short();
+ pytdbunpack_err_too_short();
return NULL;
}
@@ -647,13 +516,13 @@ unpack_uint32(char **pbuf, int *plen)
}
-static PyObject *unpack_int16(char **pbuf, int *plen)
+static PyObject *pytdbunpack_int16(char **pbuf, int *plen)
{
long v;
unsigned char *b;
if (*plen < 2) {
- unpack_err_too_short();
+ pytdbunpack_err_too_short();
return NULL;
}
@@ -668,7 +537,7 @@ static PyObject *unpack_int16(char **pbuf, int *plen)
static PyObject *
-unpack_string(char **pbuf, int *plen)
+pytdbunpack_string(char **pbuf, int *plen)
{
int len;
char *nul_ptr, *start;
@@ -677,7 +546,7 @@ unpack_string(char **pbuf, int *plen)
nul_ptr = memchr(start, '\0', *plen);
if (!nul_ptr) {
- unpack_err_too_short();
+ pytdbunpack_err_too_short();
return NULL;
}
@@ -686,12 +555,12 @@ unpack_string(char **pbuf, int *plen)
*pbuf += len + 1; /* skip \0 */
*plen -= len + 1;
- return PyString_FromStringAndSize(start, len);
+ return PyString_Decode(start, len, pytdb_string_encoding, NULL);
}
static PyObject *
-unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
+pytdbunpack_buffer(char **pbuf, int *plen, PyObject *val_list)
{
/* first get 32-bit len */
long slen;
@@ -700,7 +569,7 @@ unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
PyObject *str_obj = NULL, *len_obj = NULL;
if (*plen < 4) {
- unpack_err_too_short();
+ pytdbunpack_err_too_short();
return NULL;
}
@@ -757,7 +626,7 @@ unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
Returns a reference to None, or NULL for failure.
*/
-static PyObject *pytdbpack_unpack_item(char ch,
+static PyObject *pytdbunpack_item(char ch,
char **pbuf,
int *plen,
PyObject *val_list)
@@ -765,17 +634,17 @@ static PyObject *pytdbpack_unpack_item(char ch,
PyObject *result;
if (ch == 'w') { /* 16-bit int */
- result = unpack_int16(pbuf, plen);
+ result = pytdbunpack_int16(pbuf, plen);
}
else if (ch == 'd' || ch == 'p') { /* 32-bit int */
/* pointers can just come through as integers */
- result = unpack_uint32(pbuf, plen);
+ result = pytdbunpack_uint32(pbuf, plen);
}
else if (ch == 'f' || ch == 'P') { /* nul-term string */
- result = unpack_string(pbuf, plen);
+ result = pytdbunpack_string(pbuf, plen);
}
else if (ch == 'B') { /* length, buffer */
- return unpack_buffer(pbuf, plen, val_list);
+ return pytdbunpack_buffer(pbuf, plen, val_list);
}
else {
PyErr_Format(PyExc_ValueError,
@@ -801,7 +670,7 @@ static PyObject *pytdbpack_unpack_item(char ch,
static PyMethodDef pytdbpack_methods[] = {
{ "pack", pytdbpack, METH_VARARGS, (char *) pytdbpack_doc },
- { "unpack", pytdbpack_unpack, METH_VARARGS, (char *) pytdbpack_unpack_doc },
+ { "unpack", pytdbunpack, METH_VARARGS, (char *) pytdbunpack_doc },
};
DL_EXPORT(void)