AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python 2.7.3 made them unavailable from the python.org web site.

These files are a subset of the python-2.7.2.tgz distribution from python.org.  Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution.

Signed-off-by: daryl.mcdaniel@intel.com


git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
darylm503
2012-04-16 22:12:42 +00:00
parent cbc6b5e545
commit 4710c53dca
2106 changed files with 871583 additions and 0 deletions

View File

@@ -0,0 +1,241 @@
/* Bisection algorithms. Drop in replacement for bisect.py
Converted to C by Dmitry Vasiliev (dima at hlabs.spb.ru).
*/
#include "Python.h"
static Py_ssize_t
internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi)
{
PyObject *litem;
Py_ssize_t mid, res;
if (lo < 0) {
PyErr_SetString(PyExc_ValueError, "lo must be non-negative");
return -1;
}
if (hi == -1) {
hi = PySequence_Size(list);
if (hi < 0)
return -1;
}
while (lo < hi) {
mid = (lo + hi) / 2;
litem = PySequence_GetItem(list, mid);
if (litem == NULL)
return -1;
res = PyObject_RichCompareBool(item, litem, Py_LT);
Py_DECREF(litem);
if (res < 0)
return -1;
if (res)
hi = mid;
else
lo = mid + 1;
}
return lo;
}
static PyObject *
bisect_right(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *list, *item;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_right",
keywords, &list, &item, &lo, &hi))
return NULL;
index = internal_bisect_right(list, item, lo, hi);
if (index < 0)
return NULL;
return PyInt_FromSsize_t(index);
}
PyDoc_STRVAR(bisect_right_doc,
"bisect_right(a, x[, lo[, hi]]) -> index\n\
\n\
Return the index where to insert item x in list a, assuming a is sorted.\n\
\n\
The return value i is such that all e in a[:i] have e <= x, and all e in\n\
a[i:] have e > x. So if x already appears in the list, i points just\n\
beyond the rightmost x already there\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");
static PyObject *
insort_right(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *list, *item, *result;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_right",
keywords, &list, &item, &lo, &hi))
return NULL;
index = internal_bisect_right(list, item, lo, hi);
if (index < 0)
return NULL;
if (PyList_CheckExact(list)) {
if (PyList_Insert(list, index, item) < 0)
return NULL;
} else {
result = PyObject_CallMethod(list, "insert", "nO",
index, item);
if (result == NULL)
return NULL;
Py_DECREF(result);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(insort_right_doc,
"insort_right(a, x[, lo[, hi]])\n\
\n\
Insert item x in list a, and keep it sorted assuming a is sorted.\n\
\n\
If x is already in a, insert it to the right of the rightmost x.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");
static Py_ssize_t
internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t hi)
{
PyObject *litem;
Py_ssize_t mid, res;
if (lo < 0) {
PyErr_SetString(PyExc_ValueError, "lo must be non-negative");
return -1;
}
if (hi == -1) {
hi = PySequence_Size(list);
if (hi < 0)
return -1;
}
while (lo < hi) {
mid = (lo + hi) / 2;
litem = PySequence_GetItem(list, mid);
if (litem == NULL)
return -1;
res = PyObject_RichCompareBool(litem, item, Py_LT);
Py_DECREF(litem);
if (res < 0)
return -1;
if (res)
lo = mid + 1;
else
hi = mid;
}
return lo;
}
static PyObject *
bisect_left(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *list, *item;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:bisect_left",
keywords, &list, &item, &lo, &hi))
return NULL;
index = internal_bisect_left(list, item, lo, hi);
if (index < 0)
return NULL;
return PyInt_FromSsize_t(index);
}
PyDoc_STRVAR(bisect_left_doc,
"bisect_left(a, x[, lo[, hi]]) -> index\n\
\n\
Return the index where to insert item x in list a, assuming a is sorted.\n\
\n\
The return value i is such that all e in a[:i] have e < x, and all e in\n\
a[i:] have e >= x. So if x already appears in the list, i points just\n\
before the leftmost x already there.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");
static PyObject *
insort_left(PyObject *self, PyObject *args, PyObject *kw)
{
PyObject *list, *item, *result;
Py_ssize_t lo = 0;
Py_ssize_t hi = -1;
Py_ssize_t index;
static char *keywords[] = {"a", "x", "lo", "hi", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kw, "OO|nn:insort_left",
keywords, &list, &item, &lo, &hi))
return NULL;
index = internal_bisect_left(list, item, lo, hi);
if (index < 0)
return NULL;
if (PyList_CheckExact(list)) {
if (PyList_Insert(list, index, item) < 0)
return NULL;
} else {
result = PyObject_CallMethod(list, "insert", "iO",
index, item);
if (result == NULL)
return NULL;
Py_DECREF(result);
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(insort_left_doc,
"insort_left(a, x[, lo[, hi]])\n\
\n\
Insert item x in list a, and keep it sorted assuming a is sorted.\n\
\n\
If x is already in a, insert it to the left of the leftmost x.\n\
\n\
Optional args lo (default 0) and hi (default len(a)) bound the\n\
slice of a to be searched.\n");
PyDoc_STRVAR(bisect_doc, "Alias for bisect_right().\n");
PyDoc_STRVAR(insort_doc, "Alias for insort_right().\n");
static PyMethodDef bisect_methods[] = {
{"bisect_right", (PyCFunction)bisect_right,
METH_VARARGS|METH_KEYWORDS, bisect_right_doc},
{"bisect", (PyCFunction)bisect_right,
METH_VARARGS|METH_KEYWORDS, bisect_doc},
{"insort_right", (PyCFunction)insort_right,
METH_VARARGS|METH_KEYWORDS, insort_right_doc},
{"insort", (PyCFunction)insort_right,
METH_VARARGS|METH_KEYWORDS, insort_doc},
{"bisect_left", (PyCFunction)bisect_left,
METH_VARARGS|METH_KEYWORDS, bisect_left_doc},
{"insort_left", (PyCFunction)insort_left,
METH_VARARGS|METH_KEYWORDS, insort_left_doc},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(module_doc,
"Bisection algorithms.\n\
\n\
This module provides support for maintaining a list in sorted order without\n\
having to sort the list after each insertion. For long lists of items with\n\
expensive comparison operations, this can be an improvement over the more\n\
common approach.\n");
PyMODINIT_FUNC
init_bisect(void)
{
Py_InitModule3("_bisect", bisect_methods, module_doc);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,402 @@
#include "Python.h"
#include "structmember.h"
/* _functools module written and maintained
by Hye-Shik Chang <perky@FreeBSD.org>
with adaptations by Raymond Hettinger <python@rcn.com>
Copyright (c) 2004, 2005, 2006 Python Software Foundation.
All rights reserved.
*/
/* reduce() *************************************************************/
static PyObject *
functools_reduce(PyObject *self, PyObject *args)
{
PyObject *seq, *func, *result = NULL, *it;
if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
return NULL;
if (result != NULL)
Py_INCREF(result);
it = PyObject_GetIter(seq);
if (it == NULL) {
PyErr_SetString(PyExc_TypeError,
"reduce() arg 2 must support iteration");
Py_XDECREF(result);
return NULL;
}
if ((args = PyTuple_New(2)) == NULL)
goto Fail;
for (;;) {
PyObject *op2;
if (args->ob_refcnt > 1) {
Py_DECREF(args);
if ((args = PyTuple_New(2)) == NULL)
goto Fail;
}
op2 = PyIter_Next(it);
if (op2 == NULL) {
if (PyErr_Occurred())
goto Fail;
break;
}
if (result == NULL)
result = op2;
else {
PyTuple_SetItem(args, 0, result);
PyTuple_SetItem(args, 1, op2);
if ((result = PyEval_CallObject(func, args)) == NULL)
goto Fail;
}
}
Py_DECREF(args);
if (result == NULL)
PyErr_SetString(PyExc_TypeError,
"reduce() of empty sequence with no initial value");
Py_DECREF(it);
return result;
Fail:
Py_XDECREF(args);
Py_XDECREF(result);
Py_DECREF(it);
return NULL;
}
PyDoc_STRVAR(reduce_doc,
"reduce(function, sequence[, initial]) -> value\n\
\n\
Apply a function of two arguments cumulatively to the items of a sequence,\n\
from left to right, so as to reduce the sequence to a single value.\n\
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
of the sequence in the calculation, and serves as a default when the\n\
sequence is empty.");
/* partial object **********************************************************/
typedef struct {
PyObject_HEAD
PyObject *fn;
PyObject *args;
PyObject *kw;
PyObject *dict;
PyObject *weakreflist; /* List of weak references */
} partialobject;
static PyTypeObject partial_type;
static PyObject *
partial_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *func;
partialobject *pto;
if (PyTuple_GET_SIZE(args) < 1) {
PyErr_SetString(PyExc_TypeError,
"type 'partial' takes at least one argument");
return NULL;
}
func = PyTuple_GET_ITEM(args, 0);
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError,
"the first argument must be callable");
return NULL;
}
/* create partialobject structure */
pto = (partialobject *)type->tp_alloc(type, 0);
if (pto == NULL)
return NULL;
pto->fn = func;
Py_INCREF(func);
pto->args = PyTuple_GetSlice(args, 1, PY_SSIZE_T_MAX);
if (pto->args == NULL) {
pto->kw = NULL;
Py_DECREF(pto);
return NULL;
}
if (kw != NULL) {
pto->kw = PyDict_Copy(kw);
if (pto->kw == NULL) {
Py_DECREF(pto);
return NULL;
}
} else {
pto->kw = Py_None;
Py_INCREF(Py_None);
}
pto->weakreflist = NULL;
pto->dict = NULL;
return (PyObject *)pto;
}
static void
partial_dealloc(partialobject *pto)
{
PyObject_GC_UnTrack(pto);
if (pto->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) pto);
Py_XDECREF(pto->fn);
Py_XDECREF(pto->args);
Py_XDECREF(pto->kw);
Py_XDECREF(pto->dict);
Py_TYPE(pto)->tp_free(pto);
}
static PyObject *
partial_call(partialobject *pto, PyObject *args, PyObject *kw)
{
PyObject *ret;
PyObject *argappl = NULL, *kwappl = NULL;
assert (PyCallable_Check(pto->fn));
assert (PyTuple_Check(pto->args));
assert (pto->kw == Py_None || PyDict_Check(pto->kw));
if (PyTuple_GET_SIZE(pto->args) == 0) {
argappl = args;
Py_INCREF(args);
} else if (PyTuple_GET_SIZE(args) == 0) {
argappl = pto->args;
Py_INCREF(pto->args);
} else {
argappl = PySequence_Concat(pto->args, args);
if (argappl == NULL)
return NULL;
}
if (pto->kw == Py_None) {
kwappl = kw;
Py_XINCREF(kw);
} else {
kwappl = PyDict_Copy(pto->kw);
if (kwappl == NULL) {
Py_DECREF(argappl);
return NULL;
}
if (kw != NULL) {
if (PyDict_Merge(kwappl, kw, 1) != 0) {
Py_DECREF(argappl);
Py_DECREF(kwappl);
return NULL;
}
}
}
ret = PyObject_Call(pto->fn, argappl, kwappl);
Py_DECREF(argappl);
Py_XDECREF(kwappl);
return ret;
}
static int
partial_traverse(partialobject *pto, visitproc visit, void *arg)
{
Py_VISIT(pto->fn);
Py_VISIT(pto->args);
Py_VISIT(pto->kw);
Py_VISIT(pto->dict);
return 0;
}
PyDoc_STRVAR(partial_doc,
"partial(func, *args, **keywords) - new function with partial application\n\
of the given arguments and keywords.\n");
#define OFF(x) offsetof(partialobject, x)
static PyMemberDef partial_memberlist[] = {
{"func", T_OBJECT, OFF(fn), READONLY,
"function object to use in future partial calls"},
{"args", T_OBJECT, OFF(args), READONLY,
"tuple of arguments to future partial calls"},
{"keywords", T_OBJECT, OFF(kw), READONLY,
"dictionary of keyword arguments to future partial calls"},
{NULL} /* Sentinel */
};
static PyObject *
partial_get_dict(partialobject *pto)
{
if (pto->dict == NULL) {
pto->dict = PyDict_New();
if (pto->dict == NULL)
return NULL;
}
Py_INCREF(pto->dict);
return pto->dict;
}
static int
partial_set_dict(partialobject *pto, PyObject *value)
{
PyObject *tmp;
/* It is illegal to del p.__dict__ */
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
"a partial object's dictionary may not be deleted");
return -1;
}
/* Can only set __dict__ to a dictionary */
if (!PyDict_Check(value)) {
PyErr_SetString(PyExc_TypeError,
"setting partial object's dictionary to a non-dict");
return -1;
}
tmp = pto->dict;
Py_INCREF(value);
pto->dict = value;
Py_XDECREF(tmp);
return 0;
}
static PyGetSetDef partial_getsetlist[] = {
{"__dict__", (getter)partial_get_dict, (setter)partial_set_dict},
{NULL} /* Sentinel */
};
/* Pickle strategy:
__reduce__ by itself doesn't support getting kwargs in the unpickle
operation so we define a __setstate__ that replaces all the information
about the partial. If we only replaced part of it someone would use
it as a hook to do strange things.
*/
PyObject *
partial_reduce(partialobject *pto, PyObject *unused)
{
return Py_BuildValue("O(O)(OOOO)", Py_TYPE(pto), pto->fn, pto->fn,
pto->args, pto->kw,
pto->dict ? pto->dict : Py_None);
}
PyObject *
partial_setstate(partialobject *pto, PyObject *args)
{
PyObject *fn, *fnargs, *kw, *dict;
if (!PyArg_ParseTuple(args, "(OOOO):__setstate__",
&fn, &fnargs, &kw, &dict))
return NULL;
Py_XDECREF(pto->fn);
Py_XDECREF(pto->args);
Py_XDECREF(pto->kw);
Py_XDECREF(pto->dict);
pto->fn = fn;
pto->args = fnargs;
pto->kw = kw;
if (dict != Py_None) {
pto->dict = dict;
Py_INCREF(dict);
} else {
pto->dict = NULL;
}
Py_INCREF(fn);
Py_INCREF(fnargs);
Py_INCREF(kw);
Py_RETURN_NONE;
}
static PyMethodDef partial_methods[] = {
{"__reduce__", (PyCFunction)partial_reduce, METH_NOARGS},
{"__setstate__", (PyCFunction)partial_setstate, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
static PyTypeObject partial_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"functools.partial", /* tp_name */
sizeof(partialobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)partial_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)partial_call, /* tp_call */
0, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
PyObject_GenericSetAttr, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
partial_doc, /* tp_doc */
(traverseproc)partial_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(partialobject, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
partial_methods, /* tp_methods */
partial_memberlist, /* tp_members */
partial_getsetlist, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(partialobject, dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
partial_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
};
/* module level code ********************************************************/
PyDoc_STRVAR(module_doc,
"Tools that operate on functions.");
static PyMethodDef module_methods[] = {
{"reduce", functools_reduce, METH_VARARGS, reduce_doc},
{NULL, NULL} /* sentinel */
};
PyMODINIT_FUNC
init_functools(void)
{
int i;
PyObject *m;
char *name;
PyTypeObject *typelist[] = {
&partial_type,
NULL
};
m = Py_InitModule3("_functools", module_methods, module_doc);
if (m == NULL)
return;
for (i=0 ; typelist[i] != NULL ; i++) {
if (PyType_Ready(typelist[i]) < 0)
return;
name = strchr(typelist[i]->tp_name, '.');
assert (name != NULL);
Py_INCREF(typelist[i]);
PyModule_AddObject(m, name+1, (PyObject *)typelist[i]);
}
}

View File

@@ -0,0 +1,597 @@
/* Module that wraps all OpenSSL hash algorithms */
/*
* Copyright (C) 2005-2010 Gregory P. Smith (greg@krypto.org)
* Licensed to PSF under a Contributor Agreement.
*
* Derived from a skeleton of shamodule.c containing work performed by:
*
* Andrew Kuchling (amk@amk.ca)
* Greg Stein (gstein@lyra.org)
*
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"
#ifdef WITH_THREAD
#include "pythread.h"
#define ENTER_HASHLIB(obj) \
if ((obj)->lock) { \
if (!PyThread_acquire_lock((obj)->lock, 0)) { \
Py_BEGIN_ALLOW_THREADS \
PyThread_acquire_lock((obj)->lock, 1); \
Py_END_ALLOW_THREADS \
} \
}
#define LEAVE_HASHLIB(obj) \
if ((obj)->lock) { \
PyThread_release_lock((obj)->lock); \
}
#else
#define ENTER_HASHLIB(obj)
#define LEAVE_HASHLIB(obj)
#endif
/* EVP is the preferred interface to hashing in OpenSSL */
#include <openssl/evp.h>
#define MUNCH_SIZE INT_MAX
/* TODO(gps): We should probably make this a module or EVPobject attribute
* to allow the user to optimize based on the platform they're using. */
#define HASHLIB_GIL_MINSIZE 2048
#ifndef HASH_OBJ_CONSTRUCTOR
#define HASH_OBJ_CONSTRUCTOR 0
#endif
/* Minimum OpenSSL version needed to support sha224 and higher. */
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x00908000)
#define _OPENSSL_SUPPORTS_SHA2
#endif
typedef struct {
PyObject_HEAD
PyObject *name; /* name of this hash algorithm */
EVP_MD_CTX ctx; /* OpenSSL message digest context */
#ifdef WITH_THREAD
PyThread_type_lock lock; /* OpenSSL context lock */
#endif
} EVPobject;
static PyTypeObject EVPtype;
#define DEFINE_CONSTS_FOR_NEW(Name) \
static PyObject *CONST_ ## Name ## _name_obj; \
static EVP_MD_CTX CONST_new_ ## Name ## _ctx; \
static EVP_MD_CTX *CONST_new_ ## Name ## _ctx_p = NULL;
DEFINE_CONSTS_FOR_NEW(md5)
DEFINE_CONSTS_FOR_NEW(sha1)
#ifdef _OPENSSL_SUPPORTS_SHA2
DEFINE_CONSTS_FOR_NEW(sha224)
DEFINE_CONSTS_FOR_NEW(sha256)
DEFINE_CONSTS_FOR_NEW(sha384)
DEFINE_CONSTS_FOR_NEW(sha512)
#endif
static EVPobject *
newEVPobject(PyObject *name)
{
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
/* save the name for .name to return */
if (retval != NULL) {
Py_INCREF(name);
retval->name = name;
#ifdef WITH_THREAD
retval->lock = NULL;
#endif
}
return retval;
}
static void
EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
{
unsigned int process;
const unsigned char *cp = (const unsigned char *)vp;
while (0 < len)
{
if (len > (Py_ssize_t)MUNCH_SIZE)
process = MUNCH_SIZE;
else
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
EVP_DigestUpdate(&self->ctx, (const void*)cp, process);
len -= process;
cp += process;
}
}
/* Internal methods for a hash object */
static void
EVP_dealloc(EVPobject *self)
{
#ifdef WITH_THREAD
if (self->lock != NULL)
PyThread_free_lock(self->lock);
#endif
EVP_MD_CTX_cleanup(&self->ctx);
Py_XDECREF(self->name);
PyObject_Del(self);
}
static void locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
{
ENTER_HASHLIB(self);
EVP_MD_CTX_copy(new_ctx_p, &self->ctx);
LEAVE_HASHLIB(self);
}
/* External methods for a hash object */
PyDoc_STRVAR(EVP_copy__doc__, "Return a copy of the hash object.");
static PyObject *
EVP_copy(EVPobject *self, PyObject *unused)
{
EVPobject *newobj;
if ( (newobj = newEVPobject(self->name))==NULL)
return NULL;
locked_EVP_MD_CTX_copy(&newobj->ctx, self);
return (PyObject *)newobj;
}
PyDoc_STRVAR(EVP_digest__doc__,
"Return the digest value as a string of binary data.");
static PyObject *
EVP_digest(EVPobject *self, PyObject *unused)
{
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD_CTX temp_ctx;
PyObject *retval;
unsigned int digest_size;
locked_EVP_MD_CTX_copy(&temp_ctx, self);
digest_size = EVP_MD_CTX_size(&temp_ctx);
EVP_DigestFinal(&temp_ctx, digest, NULL);
retval = PyString_FromStringAndSize((const char *)digest, digest_size);
EVP_MD_CTX_cleanup(&temp_ctx);
return retval;
}
PyDoc_STRVAR(EVP_hexdigest__doc__,
"Return the digest value as a string of hexadecimal digits.");
static PyObject *
EVP_hexdigest(EVPobject *self, PyObject *unused)
{
unsigned char digest[EVP_MAX_MD_SIZE];
EVP_MD_CTX temp_ctx;
PyObject *retval;
char *hex_digest;
unsigned int i, j, digest_size;
/* Get the raw (binary) digest value */
locked_EVP_MD_CTX_copy(&temp_ctx, self);
digest_size = EVP_MD_CTX_size(&temp_ctx);
EVP_DigestFinal(&temp_ctx, digest, NULL);
EVP_MD_CTX_cleanup(&temp_ctx);
/* Create a new string */
/* NOTE: not thread safe! modifying an already created string object */
/* (not a problem because we hold the GIL by default) */
retval = PyString_FromStringAndSize(NULL, digest_size * 2);
if (!retval)
return NULL;
hex_digest = PyString_AsString(retval);
if (!hex_digest) {
Py_DECREF(retval);
return NULL;
}
/* Make hex version of the digest */
for(i=j=0; i<digest_size; i++) {
char c;
c = (digest[i] >> 4) & 0xf;
c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
c = (digest[i] & 0xf);
c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
}
return retval;
}
PyDoc_STRVAR(EVP_update__doc__,
"Update this hash object's state with the provided string.");
static PyObject *
EVP_update(EVPobject *self, PyObject *args)
{
Py_buffer view;
if (!PyArg_ParseTuple(args, "s*:update", &view))
return NULL;
#ifdef WITH_THREAD
if (self->lock == NULL && view.len >= HASHLIB_GIL_MINSIZE) {
self->lock = PyThread_allocate_lock();
/* fail? lock = NULL and we fail over to non-threaded code. */
}
if (self->lock != NULL) {
Py_BEGIN_ALLOW_THREADS
PyThread_acquire_lock(self->lock, 1);
EVP_hash(self, view.buf, view.len);
PyThread_release_lock(self->lock);
Py_END_ALLOW_THREADS
}
else
#endif
{
EVP_hash(self, view.buf, view.len);
}
PyBuffer_Release(&view);
Py_RETURN_NONE;
}
static PyMethodDef EVP_methods[] = {
{"update", (PyCFunction)EVP_update, METH_VARARGS, EVP_update__doc__},
{"digest", (PyCFunction)EVP_digest, METH_NOARGS, EVP_digest__doc__},
{"hexdigest", (PyCFunction)EVP_hexdigest, METH_NOARGS, EVP_hexdigest__doc__},
{"copy", (PyCFunction)EVP_copy, METH_NOARGS, EVP_copy__doc__},
{NULL, NULL} /* sentinel */
};
static PyObject *
EVP_get_block_size(EVPobject *self, void *closure)
{
long block_size;
block_size = EVP_MD_CTX_block_size(&self->ctx);
return PyLong_FromLong(block_size);
}
static PyObject *
EVP_get_digest_size(EVPobject *self, void *closure)
{
long size;
size = EVP_MD_CTX_size(&self->ctx);
return PyLong_FromLong(size);
}
static PyMemberDef EVP_members[] = {
{"name", T_OBJECT, offsetof(EVPobject, name), READONLY, PyDoc_STR("algorithm name.")},
{NULL} /* Sentinel */
};
static PyGetSetDef EVP_getseters[] = {
{"digest_size",
(getter)EVP_get_digest_size, NULL,
NULL,
NULL},
{"block_size",
(getter)EVP_get_block_size, NULL,
NULL,
NULL},
/* the old md5 and sha modules support 'digest_size' as in PEP 247.
* the old sha module also supported 'digestsize'. ugh. */
{"digestsize",
(getter)EVP_get_digest_size, NULL,
NULL,
NULL},
{NULL} /* Sentinel */
};
static PyObject *
EVP_repr(PyObject *self)
{
char buf[100];
PyOS_snprintf(buf, sizeof(buf), "<%s HASH object @ %p>",
PyString_AsString(((EVPobject *)self)->name), self);
return PyString_FromString(buf);
}
#if HASH_OBJ_CONSTRUCTOR
static int
EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
Py_buffer view = { 0 };
char *nameStr;
const EVP_MD *digest;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s*:HASH", kwlist,
&name_obj, &view)) {
return -1;
}
if (!PyArg_Parse(name_obj, "s", &nameStr)) {
PyErr_SetString(PyExc_TypeError, "name must be a string");
PyBuffer_Release(&view);
return -1;
}
digest = EVP_get_digestbyname(nameStr);
if (!digest) {
PyErr_SetString(PyExc_ValueError, "unknown hash function");
PyBuffer_Release(&view);
return -1;
}
EVP_DigestInit(&self->ctx, digest);
self->name = name_obj;
Py_INCREF(self->name);
if (view.obj) {
if (view.len >= HASHLIB_GIL_MINSIZE) {
Py_BEGIN_ALLOW_THREADS
EVP_hash(self, view.buf, view.len);
Py_END_ALLOW_THREADS
} else {
EVP_hash(self, view.buf, view.len);
}
PyBuffer_Release(&view);
}
return 0;
}
#endif
PyDoc_STRVAR(hashtype_doc,
"A hash represents the object used to calculate a checksum of a\n\
string of information.\n\
\n\
Methods:\n\
\n\
update() -- updates the current digest with an additional string\n\
digest() -- return the current digest value\n\
hexdigest() -- return the current digest as a string of hexadecimal digits\n\
copy() -- return a copy of the current hash object\n\
\n\
Attributes:\n\
\n\
name -- the hash algorithm being used by this object\n\
digest_size -- number of bytes in this hashes output\n");
static PyTypeObject EVPtype = {
PyVarObject_HEAD_INIT(NULL, 0)
"_hashlib.HASH", /*tp_name*/
sizeof(EVPobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)EVP_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
EVP_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
hashtype_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
EVP_methods, /* tp_methods */
EVP_members, /* tp_members */
EVP_getseters, /* tp_getset */
#if 1
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
#endif
#if HASH_OBJ_CONSTRUCTOR
(initproc)EVP_tp_init, /* tp_init */
#endif
};
static PyObject *
EVPnew(PyObject *name_obj,
const EVP_MD *digest, const EVP_MD_CTX *initial_ctx,
const unsigned char *cp, Py_ssize_t len)
{
EVPobject *self;
if (!digest && !initial_ctx) {
PyErr_SetString(PyExc_ValueError, "unsupported hash type");
return NULL;
}
if ((self = newEVPobject(name_obj)) == NULL)
return NULL;
if (initial_ctx) {
EVP_MD_CTX_copy(&self->ctx, initial_ctx);
} else {
EVP_DigestInit(&self->ctx, digest);
}
if (cp && len) {
if (len >= HASHLIB_GIL_MINSIZE) {
Py_BEGIN_ALLOW_THREADS
EVP_hash(self, cp, len);
Py_END_ALLOW_THREADS
} else {
EVP_hash(self, cp, len);
}
}
return (PyObject *)self;
}
/* The module-level function: new() */
PyDoc_STRVAR(EVP_new__doc__,
"Return a new hash object using the named algorithm.\n\
An optional string argument may be provided and will be\n\
automatically hashed.\n\
\n\
The MD5 and SHA1 algorithms are always supported.\n");
static PyObject *
EVP_new(PyObject *self, PyObject *args, PyObject *kwdict)
{
static char *kwlist[] = {"name", "string", NULL};
PyObject *name_obj = NULL;
Py_buffer view = { 0 };
PyObject *ret_obj;
char *name;
const EVP_MD *digest;
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "O|s*:new", kwlist,
&name_obj, &view)) {
return NULL;
}
if (!PyArg_Parse(name_obj, "s", &name)) {
PyErr_SetString(PyExc_TypeError, "name must be a string");
return NULL;
}
digest = EVP_get_digestbyname(name);
ret_obj = EVPnew(name_obj, digest, NULL, (unsigned char*)view.buf,
view.len);
PyBuffer_Release(&view);
return ret_obj;
}
/*
* This macro generates constructor function definitions for specific
* hash algorithms. These constructors are much faster than calling
* the generic one passing it a python string and are noticably
* faster than calling a python new() wrapper. Thats important for
* code that wants to make hashes of a bunch of small strings.
*/
#define GEN_CONSTRUCTOR(NAME) \
static PyObject * \
EVP_new_ ## NAME (PyObject *self, PyObject *args) \
{ \
Py_buffer view = { 0 }; \
PyObject *ret_obj; \
\
if (!PyArg_ParseTuple(args, "|s*:" #NAME , &view)) { \
return NULL; \
} \
\
ret_obj = EVPnew( \
CONST_ ## NAME ## _name_obj, \
NULL, \
CONST_new_ ## NAME ## _ctx_p, \
(unsigned char*)view.buf, view.len); \
PyBuffer_Release(&view); \
return ret_obj; \
}
/* a PyMethodDef structure for the constructor */
#define CONSTRUCTOR_METH_DEF(NAME) \
{"openssl_" #NAME, (PyCFunction)EVP_new_ ## NAME, METH_VARARGS, \
PyDoc_STR("Returns a " #NAME \
" hash object; optionally initialized with a string") \
}
/* used in the init function to setup a constructor */
#define INIT_CONSTRUCTOR_CONSTANTS(NAME) do { \
CONST_ ## NAME ## _name_obj = PyString_FromString(#NAME); \
if (EVP_get_digestbyname(#NAME)) { \
CONST_new_ ## NAME ## _ctx_p = &CONST_new_ ## NAME ## _ctx; \
EVP_DigestInit(CONST_new_ ## NAME ## _ctx_p, EVP_get_digestbyname(#NAME)); \
} \
} while (0);
GEN_CONSTRUCTOR(md5)
GEN_CONSTRUCTOR(sha1)
#ifdef _OPENSSL_SUPPORTS_SHA2
GEN_CONSTRUCTOR(sha224)
GEN_CONSTRUCTOR(sha256)
GEN_CONSTRUCTOR(sha384)
GEN_CONSTRUCTOR(sha512)
#endif
/* List of functions exported by this module */
static struct PyMethodDef EVP_functions[] = {
{"new", (PyCFunction)EVP_new, METH_VARARGS|METH_KEYWORDS, EVP_new__doc__},
CONSTRUCTOR_METH_DEF(md5),
CONSTRUCTOR_METH_DEF(sha1),
#ifdef _OPENSSL_SUPPORTS_SHA2
CONSTRUCTOR_METH_DEF(sha224),
CONSTRUCTOR_METH_DEF(sha256),
CONSTRUCTOR_METH_DEF(sha384),
CONSTRUCTOR_METH_DEF(sha512),
#endif
{NULL, NULL} /* Sentinel */
};
/* Initialize this module. */
PyMODINIT_FUNC
init_hashlib(void)
{
PyObject *m;
OpenSSL_add_all_digests();
/* TODO build EVP_functions openssl_* entries dynamically based
* on what hashes are supported rather than listing many
* but having some be unsupported. Only init appropriate
* constants. */
Py_TYPE(&EVPtype) = &PyType_Type;
if (PyType_Ready(&EVPtype) < 0)
return;
m = Py_InitModule("_hashlib", EVP_functions);
if (m == NULL)
return;
#if HASH_OBJ_CONSTRUCTOR
Py_INCREF(&EVPtype);
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
#endif
/* these constants are used by the convenience constructors */
INIT_CONSTRUCTOR_CONSTANTS(md5);
INIT_CONSTRUCTOR_CONSTANTS(sha1);
#ifdef _OPENSSL_SUPPORTS_SHA2
INIT_CONSTRUCTOR_CONSTANTS(sha224);
INIT_CONSTRUCTOR_CONSTANTS(sha256);
INIT_CONSTRUCTOR_CONSTANTS(sha384);
INIT_CONSTRUCTOR_CONSTANTS(sha512);
#endif
}

View File

@@ -0,0 +1,697 @@
/* Drop in replacement for heapq.py
C implementation derived directly from heapq.py in Py2.3
which was written by Kevin O'Connor, augmented by Tim Peters,
annotated by François Pinard, and converted to C by Raymond Hettinger.
*/
#include "Python.h"
/* Older implementations of heapq used Py_LE for comparisons. Now, it uses
Py_LT so it will match min(), sorted(), and bisect(). Unfortunately, some
client code (Twisted for example) relied on Py_LE, so this little function
restores compatibility by trying both.
*/
static int
cmp_lt(PyObject *x, PyObject *y)
{
int cmp;
static PyObject *lt = NULL;
if (lt == NULL) {
lt = PyString_FromString("__lt__");
if (lt == NULL)
return -1;
}
if (PyObject_HasAttr(x, lt))
return PyObject_RichCompareBool(x, y, Py_LT);
cmp = PyObject_RichCompareBool(y, x, Py_LE);
if (cmp != -1)
cmp = 1 - cmp;
return cmp;
}
static int
_siftdown(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
{
PyObject *newitem, *parent;
int cmp;
Py_ssize_t parentpos;
assert(PyList_Check(heap));
if (pos >= PyList_GET_SIZE(heap)) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
newitem = PyList_GET_ITEM(heap, pos);
Py_INCREF(newitem);
/* Follow the path to the root, moving parents down until finding
a place newitem fits. */
while (pos > startpos){
parentpos = (pos - 1) >> 1;
parent = PyList_GET_ITEM(heap, parentpos);
cmp = cmp_lt(newitem, parent);
if (cmp == -1) {
Py_DECREF(newitem);
return -1;
}
if (cmp == 0)
break;
Py_INCREF(parent);
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, parent);
pos = parentpos;
}
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, newitem);
return 0;
}
static int
_siftup(PyListObject *heap, Py_ssize_t pos)
{
Py_ssize_t startpos, endpos, childpos, rightpos;
int cmp;
PyObject *newitem, *tmp;
assert(PyList_Check(heap));
endpos = PyList_GET_SIZE(heap);
startpos = pos;
if (pos >= endpos) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
newitem = PyList_GET_ITEM(heap, pos);
Py_INCREF(newitem);
/* Bubble up the smaller child until hitting a leaf. */
childpos = 2*pos + 1; /* leftmost child position */
while (childpos < endpos) {
/* Set childpos to index of smaller child. */
rightpos = childpos + 1;
if (rightpos < endpos) {
cmp = cmp_lt(
PyList_GET_ITEM(heap, childpos),
PyList_GET_ITEM(heap, rightpos));
if (cmp == -1) {
Py_DECREF(newitem);
return -1;
}
if (cmp == 0)
childpos = rightpos;
}
/* Move the smaller child up. */
tmp = PyList_GET_ITEM(heap, childpos);
Py_INCREF(tmp);
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, tmp);
pos = childpos;
childpos = 2*pos + 1;
}
/* The leaf at pos is empty now. Put newitem there, and and bubble
it up to its final resting place (by sifting its parents down). */
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, newitem);
return _siftdown(heap, startpos, pos);
}
static PyObject *
heappush(PyObject *self, PyObject *args)
{
PyObject *heap, *item;
if (!PyArg_UnpackTuple(args, "heappush", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_Append(heap, item) == -1)
return NULL;
if (_siftdown((PyListObject *)heap, 0, PyList_GET_SIZE(heap)-1) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(heappush_doc,
"Push item onto heap, maintaining the heap invariant.");
static PyObject *
heappop(PyObject *self, PyObject *heap)
{
PyObject *lastelt, *returnitem;
Py_ssize_t n;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
/* # raises appropriate IndexError if heap is empty */
n = PyList_GET_SIZE(heap);
if (n == 0) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
lastelt = PyList_GET_ITEM(heap, n-1) ;
Py_INCREF(lastelt);
PyList_SetSlice(heap, n-1, n, NULL);
n--;
if (!n)
return lastelt;
returnitem = PyList_GET_ITEM(heap, 0);
PyList_SET_ITEM(heap, 0, lastelt);
if (_siftup((PyListObject *)heap, 0) == -1) {
Py_DECREF(returnitem);
return NULL;
}
return returnitem;
}
PyDoc_STRVAR(heappop_doc,
"Pop the smallest item off the heap, maintaining the heap invariant.");
static PyObject *
heapreplace(PyObject *self, PyObject *args)
{
PyObject *heap, *item, *returnitem;
if (!PyArg_UnpackTuple(args, "heapreplace", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_GET_SIZE(heap) < 1) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
returnitem = PyList_GET_ITEM(heap, 0);
Py_INCREF(item);
PyList_SET_ITEM(heap, 0, item);
if (_siftup((PyListObject *)heap, 0) == -1) {
Py_DECREF(returnitem);
return NULL;
}
return returnitem;
}
PyDoc_STRVAR(heapreplace_doc,
"Pop and return the current smallest value, and add the new item.\n\
\n\
This is more efficient than heappop() followed by heappush(), and can be\n\
more appropriate when using a fixed-size heap. Note that the value\n\
returned may be larger than item! That constrains reasonable uses of\n\
this routine unless written as part of a conditional replacement:\n\n\
if item > heap[0]:\n\
item = heapreplace(heap, item)\n");
static PyObject *
heappushpop(PyObject *self, PyObject *args)
{
PyObject *heap, *item, *returnitem;
int cmp;
if (!PyArg_UnpackTuple(args, "heappushpop", 2, 2, &heap, &item))
return NULL;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
if (PyList_GET_SIZE(heap) < 1) {
Py_INCREF(item);
return item;
}
cmp = cmp_lt(PyList_GET_ITEM(heap, 0), item);
if (cmp == -1)
return NULL;
if (cmp == 0) {
Py_INCREF(item);
return item;
}
returnitem = PyList_GET_ITEM(heap, 0);
Py_INCREF(item);
PyList_SET_ITEM(heap, 0, item);
if (_siftup((PyListObject *)heap, 0) == -1) {
Py_DECREF(returnitem);
return NULL;
}
return returnitem;
}
PyDoc_STRVAR(heappushpop_doc,
"Push item on the heap, then pop and return the smallest item\n\
from the heap. The combined action runs more efficiently than\n\
heappush() followed by a separate call to heappop().");
static PyObject *
heapify(PyObject *self, PyObject *heap)
{
Py_ssize_t i, n;
if (!PyList_Check(heap)) {
PyErr_SetString(PyExc_TypeError, "heap argument must be a list");
return NULL;
}
n = PyList_GET_SIZE(heap);
/* Transform bottom-up. The largest index there's any point to
looking at is the largest with a child index in-range, so must
have 2*i + 1 < n, or i < (n-1)/2. If n is even = 2*j, this is
(2*j-1)/2 = j-1/2 so j-1 is the largest, which is n//2 - 1. If
n is odd = 2*j+1, this is (2*j+1-1)/2 = j so j-1 is the largest,
and that's again n//2-1.
*/
for (i=n/2-1 ; i>=0 ; i--)
if(_siftup((PyListObject *)heap, i) == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(heapify_doc,
"Transform list into a heap, in-place, in O(len(heap)) time.");
static PyObject *
nlargest(PyObject *self, PyObject *args)
{
PyObject *heap=NULL, *elem, *iterable, *sol, *it, *oldelem;
Py_ssize_t i, n;
int cmp;
if (!PyArg_ParseTuple(args, "nO:nlargest", &n, &iterable))
return NULL;
it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
heap = PyList_New(0);
if (heap == NULL)
goto fail;
for (i=0 ; i<n ; i++ ){
elem = PyIter_Next(it);
if (elem == NULL) {
if (PyErr_Occurred())
goto fail;
else
goto sortit;
}
if (PyList_Append(heap, elem) == -1) {
Py_DECREF(elem);
goto fail;
}
Py_DECREF(elem);
}
if (PyList_GET_SIZE(heap) == 0)
goto sortit;
for (i=n/2-1 ; i>=0 ; i--)
if(_siftup((PyListObject *)heap, i) == -1)
goto fail;
sol = PyList_GET_ITEM(heap, 0);
while (1) {
elem = PyIter_Next(it);
if (elem == NULL) {
if (PyErr_Occurred())
goto fail;
else
goto sortit;
}
cmp = cmp_lt(sol, elem);
if (cmp == -1) {
Py_DECREF(elem);
goto fail;
}
if (cmp == 0) {
Py_DECREF(elem);
continue;
}
oldelem = PyList_GET_ITEM(heap, 0);
PyList_SET_ITEM(heap, 0, elem);
Py_DECREF(oldelem);
if (_siftup((PyListObject *)heap, 0) == -1)
goto fail;
sol = PyList_GET_ITEM(heap, 0);
}
sortit:
if (PyList_Sort(heap) == -1)
goto fail;
if (PyList_Reverse(heap) == -1)
goto fail;
Py_DECREF(it);
return heap;
fail:
Py_DECREF(it);
Py_XDECREF(heap);
return NULL;
}
PyDoc_STRVAR(nlargest_doc,
"Find the n largest elements in a dataset.\n\
\n\
Equivalent to: sorted(iterable, reverse=True)[:n]\n");
static int
_siftdownmax(PyListObject *heap, Py_ssize_t startpos, Py_ssize_t pos)
{
PyObject *newitem, *parent;
int cmp;
Py_ssize_t parentpos;
assert(PyList_Check(heap));
if (pos >= PyList_GET_SIZE(heap)) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
newitem = PyList_GET_ITEM(heap, pos);
Py_INCREF(newitem);
/* Follow the path to the root, moving parents down until finding
a place newitem fits. */
while (pos > startpos){
parentpos = (pos - 1) >> 1;
parent = PyList_GET_ITEM(heap, parentpos);
cmp = cmp_lt(parent, newitem);
if (cmp == -1) {
Py_DECREF(newitem);
return -1;
}
if (cmp == 0)
break;
Py_INCREF(parent);
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, parent);
pos = parentpos;
}
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, newitem);
return 0;
}
static int
_siftupmax(PyListObject *heap, Py_ssize_t pos)
{
Py_ssize_t startpos, endpos, childpos, rightpos;
int cmp;
PyObject *newitem, *tmp;
assert(PyList_Check(heap));
endpos = PyList_GET_SIZE(heap);
startpos = pos;
if (pos >= endpos) {
PyErr_SetString(PyExc_IndexError, "index out of range");
return -1;
}
newitem = PyList_GET_ITEM(heap, pos);
Py_INCREF(newitem);
/* Bubble up the smaller child until hitting a leaf. */
childpos = 2*pos + 1; /* leftmost child position */
while (childpos < endpos) {
/* Set childpos to index of smaller child. */
rightpos = childpos + 1;
if (rightpos < endpos) {
cmp = cmp_lt(
PyList_GET_ITEM(heap, rightpos),
PyList_GET_ITEM(heap, childpos));
if (cmp == -1) {
Py_DECREF(newitem);
return -1;
}
if (cmp == 0)
childpos = rightpos;
}
/* Move the smaller child up. */
tmp = PyList_GET_ITEM(heap, childpos);
Py_INCREF(tmp);
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, tmp);
pos = childpos;
childpos = 2*pos + 1;
}
/* The leaf at pos is empty now. Put newitem there, and and bubble
it up to its final resting place (by sifting its parents down). */
Py_DECREF(PyList_GET_ITEM(heap, pos));
PyList_SET_ITEM(heap, pos, newitem);
return _siftdownmax(heap, startpos, pos);
}
static PyObject *
nsmallest(PyObject *self, PyObject *args)
{
PyObject *heap=NULL, *elem, *iterable, *los, *it, *oldelem;
Py_ssize_t i, n;
int cmp;
if (!PyArg_ParseTuple(args, "nO:nsmallest", &n, &iterable))
return NULL;
it = PyObject_GetIter(iterable);
if (it == NULL)
return NULL;
heap = PyList_New(0);
if (heap == NULL)
goto fail;
for (i=0 ; i<n ; i++ ){
elem = PyIter_Next(it);
if (elem == NULL) {
if (PyErr_Occurred())
goto fail;
else
goto sortit;
}
if (PyList_Append(heap, elem) == -1) {
Py_DECREF(elem);
goto fail;
}
Py_DECREF(elem);
}
n = PyList_GET_SIZE(heap);
if (n == 0)
goto sortit;
for (i=n/2-1 ; i>=0 ; i--)
if(_siftupmax((PyListObject *)heap, i) == -1)
goto fail;
los = PyList_GET_ITEM(heap, 0);
while (1) {
elem = PyIter_Next(it);
if (elem == NULL) {
if (PyErr_Occurred())
goto fail;
else
goto sortit;
}
cmp = cmp_lt(elem, los);
if (cmp == -1) {
Py_DECREF(elem);
goto fail;
}
if (cmp == 0) {
Py_DECREF(elem);
continue;
}
oldelem = PyList_GET_ITEM(heap, 0);
PyList_SET_ITEM(heap, 0, elem);
Py_DECREF(oldelem);
if (_siftupmax((PyListObject *)heap, 0) == -1)
goto fail;
los = PyList_GET_ITEM(heap, 0);
}
sortit:
if (PyList_Sort(heap) == -1)
goto fail;
Py_DECREF(it);
return heap;
fail:
Py_DECREF(it);
Py_XDECREF(heap);
return NULL;
}
PyDoc_STRVAR(nsmallest_doc,
"Find the n smallest elements in a dataset.\n\
\n\
Equivalent to: sorted(iterable)[:n]\n");
static PyMethodDef heapq_methods[] = {
{"heappush", (PyCFunction)heappush,
METH_VARARGS, heappush_doc},
{"heappushpop", (PyCFunction)heappushpop,
METH_VARARGS, heappushpop_doc},
{"heappop", (PyCFunction)heappop,
METH_O, heappop_doc},
{"heapreplace", (PyCFunction)heapreplace,
METH_VARARGS, heapreplace_doc},
{"heapify", (PyCFunction)heapify,
METH_O, heapify_doc},
{"nlargest", (PyCFunction)nlargest,
METH_VARARGS, nlargest_doc},
{"nsmallest", (PyCFunction)nsmallest,
METH_VARARGS, nsmallest_doc},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(module_doc,
"Heap queue algorithm (a.k.a. priority queue).\n\
\n\
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for\n\
all k, counting elements from 0. For the sake of comparison,\n\
non-existing elements are considered to be infinite. The interesting\n\
property of a heap is that a[0] is always its smallest element.\n\
\n\
Usage:\n\
\n\
heap = [] # creates an empty heap\n\
heappush(heap, item) # pushes a new item on the heap\n\
item = heappop(heap) # pops the smallest item from the heap\n\
item = heap[0] # smallest item on the heap without popping it\n\
heapify(x) # transforms list into a heap, in-place, in linear time\n\
item = heapreplace(heap, item) # pops and returns smallest item, and adds\n\
# new item; the heap size is unchanged\n\
\n\
Our API differs from textbook heap algorithms as follows:\n\
\n\
- We use 0-based indexing. This makes the relationship between the\n\
index for a node and the indexes for its children slightly less\n\
obvious, but is more suitable since Python uses 0-based indexing.\n\
\n\
- Our heappop() method returns the smallest item, not the largest.\n\
\n\
These two make it possible to view the heap as a regular Python list\n\
without surprises: heap[0] is the smallest item, and heap.sort()\n\
maintains the heap invariant!\n");
PyDoc_STRVAR(__about__,
"Heap queues\n\
\n\
[explanation by Fran<61>ois Pinard]\n\
\n\
Heaps are arrays for which a[k] <= a[2*k+1] and a[k] <= a[2*k+2] for\n\
all k, counting elements from 0. For the sake of comparison,\n\
non-existing elements are considered to be infinite. The interesting\n\
property of a heap is that a[0] is always its smallest element.\n"
"\n\
The strange invariant above is meant to be an efficient memory\n\
representation for a tournament. The numbers below are `k', not a[k]:\n\
\n\
0\n\
\n\
1 2\n\
\n\
3 4 5 6\n\
\n\
7 8 9 10 11 12 13 14\n\
\n\
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30\n\
\n\
\n\
In the tree above, each cell `k' is topping `2*k+1' and `2*k+2'. In\n\
an usual binary tournament we see in sports, each cell is the winner\n\
over the two cells it tops, and we can trace the winner down the tree\n\
to see all opponents s/he had. However, in many computer applications\n\
of such tournaments, we do not need to trace the history of a winner.\n\
To be more memory efficient, when a winner is promoted, we try to\n\
replace it by something else at a lower level, and the rule becomes\n\
that a cell and the two cells it tops contain three different items,\n\
but the top cell \"wins\" over the two topped cells.\n"
"\n\
If this heap invariant is protected at all time, index 0 is clearly\n\
the overall winner. The simplest algorithmic way to remove it and\n\
find the \"next\" winner is to move some loser (let's say cell 30 in the\n\
diagram above) into the 0 position, and then percolate this new 0 down\n\
the tree, exchanging values, until the invariant is re-established.\n\
This is clearly logarithmic on the total number of items in the tree.\n\
By iterating over all items, you get an O(n ln n) sort.\n"
"\n\
A nice feature of this sort is that you can efficiently insert new\n\
items while the sort is going on, provided that the inserted items are\n\
not \"better\" than the last 0'th element you extracted. This is\n\
especially useful in simulation contexts, where the tree holds all\n\
incoming events, and the \"win\" condition means the smallest scheduled\n\
time. When an event schedule other events for execution, they are\n\
scheduled into the future, so they can easily go into the heap. So, a\n\
heap is a good structure for implementing schedulers (this is what I\n\
used for my MIDI sequencer :-).\n"
"\n\
Various structures for implementing schedulers have been extensively\n\
studied, and heaps are good for this, as they are reasonably speedy,\n\
the speed is almost constant, and the worst case is not much different\n\
than the average case. However, there are other representations which\n\
are more efficient overall, yet the worst cases might be terrible.\n"
"\n\
Heaps are also very useful in big disk sorts. You most probably all\n\
know that a big sort implies producing \"runs\" (which are pre-sorted\n\
sequences, which size is usually related to the amount of CPU memory),\n\
followed by a merging passes for these runs, which merging is often\n\
very cleverly organised[1]. It is very important that the initial\n\
sort produces the longest runs possible. Tournaments are a good way\n\
to that. If, using all the memory available to hold a tournament, you\n\
replace and percolate items that happen to fit the current run, you'll\n\
produce runs which are twice the size of the memory for random input,\n\
and much better for input fuzzily ordered.\n"
"\n\
Moreover, if you output the 0'th item on disk and get an input which\n\
may not fit in the current tournament (because the value \"wins\" over\n\
the last output value), it cannot fit in the heap, so the size of the\n\
heap decreases. The freed memory could be cleverly reused immediately\n\
for progressively building a second heap, which grows at exactly the\n\
same rate the first heap is melting. When the first heap completely\n\
vanishes, you switch heaps and start a new run. Clever and quite\n\
effective!\n\
\n\
In a word, heaps are useful memory structures to know. I use them in\n\
a few applications, and I think it is good to keep a `heap' module\n\
around. :-)\n"
"\n\
--------------------\n\
[1] The disk balancing algorithms which are current, nowadays, are\n\
more annoying than clever, and this is a consequence of the seeking\n\
capabilities of the disks. On devices which cannot seek, like big\n\
tape drives, the story was quite different, and one had to be very\n\
clever to ensure (far in advance) that each tape movement will be the\n\
most effective possible (that is, will best participate at\n\
\"progressing\" the merge). Some tapes were even able to read\n\
backwards, and this was also used to avoid the rewinding time.\n\
Believe me, real good tape sorts were quite spectacular to watch!\n\
From all times, sorting has always been a Great Art! :-)\n");
PyMODINIT_FUNC
init_heapq(void)
{
PyObject *m;
m = Py_InitModule3("_heapq", heapq_methods, module_doc);
if (m == NULL)
return;
PyModule_AddObject(m, "__about__", PyString_FromString(__about__));
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,768 @@
/*
An implementation of the new I/O lib as defined by PEP 3116 - "New I/O"
Classes defined here: UnsupportedOperation, BlockingIOError.
Functions defined here: open().
Mostly written by Amaury Forgeot d'Arc
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"
#include "_iomodule.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /* HAVE_SYS_STAT_H */
/* Various interned strings */
PyObject *_PyIO_str_close;
PyObject *_PyIO_str_closed;
PyObject *_PyIO_str_decode;
PyObject *_PyIO_str_encode;
PyObject *_PyIO_str_fileno;
PyObject *_PyIO_str_flush;
PyObject *_PyIO_str_getstate;
PyObject *_PyIO_str_isatty;
PyObject *_PyIO_str_newlines;
PyObject *_PyIO_str_nl;
PyObject *_PyIO_str_read;
PyObject *_PyIO_str_read1;
PyObject *_PyIO_str_readable;
PyObject *_PyIO_str_readinto;
PyObject *_PyIO_str_readline;
PyObject *_PyIO_str_reset;
PyObject *_PyIO_str_seek;
PyObject *_PyIO_str_seekable;
PyObject *_PyIO_str_setstate;
PyObject *_PyIO_str_tell;
PyObject *_PyIO_str_truncate;
PyObject *_PyIO_str_writable;
PyObject *_PyIO_str_write;
PyObject *_PyIO_empty_str;
PyObject *_PyIO_empty_bytes;
PyObject *_PyIO_zero;
PyDoc_STRVAR(module_doc,
"The io module provides the Python interfaces to stream handling. The\n"
"builtin open function is defined in this module.\n"
"\n"
"At the top of the I/O hierarchy is the abstract base class IOBase. It\n"
"defines the basic interface to a stream. Note, however, that there is no\n"
"seperation between reading and writing to streams; implementations are\n"
"allowed to throw an IOError if they do not support a given operation.\n"
"\n"
"Extending IOBase is RawIOBase which deals simply with the reading and\n"
"writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide\n"
"an interface to OS files.\n"
"\n"
"BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its\n"
"subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer\n"
"streams that are readable, writable, and both respectively.\n"
"BufferedRandom provides a buffered interface to random access\n"
"streams. BytesIO is a simple stream of in-memory bytes.\n"
"\n"
"Another IOBase subclass, TextIOBase, deals with the encoding and decoding\n"
"of streams into text. TextIOWrapper, which extends it, is a buffered text\n"
"interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO\n"
"is a in-memory stream for text.\n"
"\n"
"Argument names are not part of the specification, and only the arguments\n"
"of open() are intended to be used as keyword arguments.\n"
"\n"
"data:\n"
"\n"
"DEFAULT_BUFFER_SIZE\n"
"\n"
" An int containing the default buffer size used by the module's buffered\n"
" I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n"
" possible.\n"
);
/*
* BlockingIOError extends IOError
*/
static int
blockingioerror_init(PyBlockingIOErrorObject *self, PyObject *args,
PyObject *kwds)
{
PyObject *myerrno = NULL, *strerror = NULL;
PyObject *baseargs = NULL;
Py_ssize_t written = 0;
assert(PyTuple_Check(args));
self->written = 0;
if (!PyArg_ParseTuple(args, "OO|n:BlockingIOError",
&myerrno, &strerror, &written))
return -1;
baseargs = PyTuple_Pack(2, myerrno, strerror);
if (baseargs == NULL)
return -1;
/* This will take care of initializing of myerrno and strerror members */
if (((PyTypeObject *)PyExc_IOError)->tp_init(
(PyObject *)self, baseargs, kwds) == -1) {
Py_DECREF(baseargs);
return -1;
}
Py_DECREF(baseargs);
self->written = written;
return 0;
}
static PyMemberDef blockingioerror_members[] = {
{"characters_written", T_PYSSIZET, offsetof(PyBlockingIOErrorObject, written), 0},
{NULL} /* Sentinel */
};
static PyTypeObject _PyExc_BlockingIOError = {
PyVarObject_HEAD_INIT(NULL, 0)
"BlockingIOError", /*tp_name*/
sizeof(PyBlockingIOErrorObject), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare */
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
PyDoc_STR("Exception raised when I/O would block "
"on a non-blocking I/O stream"), /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
blockingioerror_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)blockingioerror_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
PyObject *PyExc_BlockingIOError = (PyObject *)&_PyExc_BlockingIOError;
/*
* The main open() function
*/
PyDoc_STRVAR(open_doc,
"Open file and return a stream. Raise IOError upon failure.\n"
"\n"
"file is either a text or byte string giving the name (and the path\n"
"if the file isn't in the current working directory) of the file to\n"
"be opened or an integer file descriptor of the file to be\n"
"wrapped. (If a file descriptor is given, it is closed when the\n"
"returned I/O object is closed, unless closefd is set to False.)\n"
"\n"
"mode is an optional string that specifies the mode in which the file\n"
"is opened. It defaults to 'r' which means open for reading in text\n"
"mode. Other common values are 'w' for writing (truncating the file if\n"
"it already exists), and 'a' for appending (which on some Unix systems,\n"
"means that all writes append to the end of the file regardless of the\n"
"current seek position). In text mode, if encoding is not specified the\n"
"encoding used is platform dependent. (For reading and writing raw\n"
"bytes use binary mode and leave encoding unspecified.) The available\n"
"modes are:\n"
"\n"
"========= ===============================================================\n"
"Character Meaning\n"
"--------- ---------------------------------------------------------------\n"
"'r' open for reading (default)\n"
"'w' open for writing, truncating the file first\n"
"'a' open for writing, appending to the end of the file if it exists\n"
"'b' binary mode\n"
"'t' text mode (default)\n"
"'+' open a disk file for updating (reading and writing)\n"
"'U' universal newline mode (for backwards compatibility; unneeded\n"
" for new code)\n"
"========= ===============================================================\n"
"\n"
"The default mode is 'rt' (open for reading text). For binary random\n"
"access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n"
"'r+b' opens the file without truncation.\n"
"\n"
"Python distinguishes between files opened in binary and text modes,\n"
"even when the underlying operating system doesn't. Files opened in\n"
"binary mode (appending 'b' to the mode argument) return contents as\n"
"bytes objects without any decoding. In text mode (the default, or when\n"
"'t' is appended to the mode argument), the contents of the file are\n"
"returned as strings, the bytes having been first decoded using a\n"
"platform-dependent encoding or using the specified encoding if given.\n"
"\n"
"buffering is an optional integer used to set the buffering policy.\n"
"Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n"
"line buffering (only usable in text mode), and an integer > 1 to indicate\n"
"the size of a fixed-size chunk buffer. When no buffering argument is\n"
"given, the default buffering policy works as follows:\n"
"\n"
"* Binary files are buffered in fixed-size chunks; the size of the buffer\n"
" is chosen using a heuristic trying to determine the underlying device's\n"
" \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n"
" On many systems, the buffer will typically be 4096 or 8192 bytes long.\n"
"\n"
"* \"Interactive\" text files (files for which isatty() returns True)\n"
" use line buffering. Other text files use the policy described above\n"
" for binary files.\n"
"\n"
"encoding is the name of the encoding used to decode or encode the\n"
"file. This should only be used in text mode. The default encoding is\n"
"platform dependent, but any encoding supported by Python can be\n"
"passed. See the codecs module for the list of supported encodings.\n"
"\n"
"errors is an optional string that specifies how encoding errors are to\n"
"be handled---this argument should not be used in binary mode. Pass\n"
"'strict' to raise a ValueError exception if there is an encoding error\n"
"(the default of None has the same effect), or pass 'ignore' to ignore\n"
"errors. (Note that ignoring encoding errors can lead to data loss.)\n"
"See the documentation for codecs.register for a list of the permitted\n"
"encoding error strings.\n"
"\n"
"newline controls how universal newlines works (it only applies to text\n"
"mode). It can be None, '', '\\n', '\\r', and '\\r\\n'. It works as\n"
"follows:\n"
"\n"
"* On input, if newline is None, universal newlines mode is\n"
" enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n"
" these are translated into '\\n' before being returned to the\n"
" caller. If it is '', universal newline mode is enabled, but line\n"
" endings are returned to the caller untranslated. If it has any of\n"
" the other legal values, input lines are only terminated by the given\n"
" string, and the line ending is returned to the caller untranslated.\n"
"\n"
"* On output, if newline is None, any '\\n' characters written are\n"
" translated to the system default line separator, os.linesep. If\n"
" newline is '', no translation takes place. If newline is any of the\n"
" other legal values, any '\\n' characters written are translated to\n"
" the given string.\n"
"\n"
"If closefd is False, the underlying file descriptor will be kept open\n"
"when the file is closed. This does not work when a file name is given\n"
"and must be True in that case.\n"
"\n"
"open() returns a file object whose type depends on the mode, and\n"
"through which the standard file operations such as reading and writing\n"
"are performed. When open() is used to open a file in a text mode ('w',\n"
"'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n"
"a file in a binary mode, the returned class varies: in read binary\n"
"mode, it returns a BufferedReader; in write binary and append binary\n"
"modes, it returns a BufferedWriter, and in read/write mode, it returns\n"
"a BufferedRandom.\n"
"\n"
"It is also possible to use a string or bytearray as a file for both\n"
"reading and writing. For strings StringIO can be used like a file\n"
"opened in a text mode, and for bytes a BytesIO can be used like a file\n"
"opened in a binary mode.\n"
);
static PyObject *
io_open(PyObject *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"file", "mode", "buffering",
"encoding", "errors", "newline",
"closefd", NULL};
PyObject *file;
char *mode = "r";
int buffering = -1, closefd = 1;
char *encoding = NULL, *errors = NULL, *newline = NULL;
unsigned i;
int reading = 0, writing = 0, appending = 0, updating = 0;
int text = 0, binary = 0, universal = 0;
char rawmode[5], *m;
int line_buffering, isatty;
PyObject *raw, *modeobj = NULL, *buffer = NULL, *wrapper = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzzi:open", kwlist,
&file, &mode, &buffering,
&encoding, &errors, &newline,
&closefd)) {
return NULL;
}
if (!PyUnicode_Check(file) &&
!PyBytes_Check(file) &&
!PyNumber_Check(file)) {
PyObject *repr = PyObject_Repr(file);
if (repr != NULL) {
PyErr_Format(PyExc_TypeError, "invalid file: %s",
PyString_AS_STRING(repr));
Py_DECREF(repr);
}
return NULL;
}
/* Decode mode */
for (i = 0; i < strlen(mode); i++) {
char c = mode[i];
switch (c) {
case 'r':
reading = 1;
break;
case 'w':
writing = 1;
break;
case 'a':
appending = 1;
break;
case '+':
updating = 1;
break;
case 't':
text = 1;
break;
case 'b':
binary = 1;
break;
case 'U':
universal = 1;
reading = 1;
break;
default:
goto invalid_mode;
}
/* c must not be duplicated */
if (strchr(mode+i+1, c)) {
invalid_mode:
PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode);
return NULL;
}
}
m = rawmode;
if (reading) *(m++) = 'r';
if (writing) *(m++) = 'w';
if (appending) *(m++) = 'a';
if (updating) *(m++) = '+';
*m = '\0';
/* Parameters validation */
if (universal) {
if (writing || appending) {
PyErr_SetString(PyExc_ValueError,
"can't use U and writing mode at once");
return NULL;
}
reading = 1;
}
if (text && binary) {
PyErr_SetString(PyExc_ValueError,
"can't have text and binary mode at once");
return NULL;
}
if (reading + writing + appending > 1) {
PyErr_SetString(PyExc_ValueError,
"must have exactly one of read/write/append mode");
return NULL;
}
if (binary && encoding != NULL) {
PyErr_SetString(PyExc_ValueError,
"binary mode doesn't take an encoding argument");
return NULL;
}
if (binary && errors != NULL) {
PyErr_SetString(PyExc_ValueError,
"binary mode doesn't take an errors argument");
return NULL;
}
if (binary && newline != NULL) {
PyErr_SetString(PyExc_ValueError,
"binary mode doesn't take a newline argument");
return NULL;
}
/* Create the Raw file stream */
raw = PyObject_CallFunction((PyObject *)&PyFileIO_Type,
"Osi", file, rawmode, closefd);
if (raw == NULL)
return NULL;
modeobj = PyUnicode_FromString(mode);
if (modeobj == NULL)
goto error;
/* buffering */
{
PyObject *res = PyObject_CallMethod(raw, "isatty", NULL);
if (res == NULL)
goto error;
isatty = PyLong_AsLong(res);
Py_DECREF(res);
if (isatty == -1 && PyErr_Occurred())
goto error;
}
if (buffering == 1 || (buffering < 0 && isatty)) {
buffering = -1;
line_buffering = 1;
}
else
line_buffering = 0;
if (buffering < 0) {
buffering = DEFAULT_BUFFER_SIZE;
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
{
struct stat st;
long fileno;
PyObject *res = PyObject_CallMethod(raw, "fileno", NULL);
if (res == NULL)
goto error;
fileno = PyInt_AsLong(res);
Py_DECREF(res);
if (fileno == -1 && PyErr_Occurred())
goto error;
if (fstat(fileno, &st) >= 0 && st.st_blksize > 1)
buffering = st.st_blksize;
}
#endif
}
if (buffering < 0) {
PyErr_SetString(PyExc_ValueError,
"invalid buffering size");
goto error;
}
/* if not buffering, returns the raw file object */
if (buffering == 0) {
if (!binary) {
PyErr_SetString(PyExc_ValueError,
"can't have unbuffered text I/O");
goto error;
}
Py_DECREF(modeobj);
return raw;
}
/* wraps into a buffered file */
{
PyObject *Buffered_class;
if (updating)
Buffered_class = (PyObject *)&PyBufferedRandom_Type;
else if (writing || appending)
Buffered_class = (PyObject *)&PyBufferedWriter_Type;
else if (reading)
Buffered_class = (PyObject *)&PyBufferedReader_Type;
else {
PyErr_Format(PyExc_ValueError,
"unknown mode: '%s'", mode);
goto error;
}
buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering);
}
Py_CLEAR(raw);
if (buffer == NULL)
goto error;
/* if binary, returns the buffered file */
if (binary) {
Py_DECREF(modeobj);
return buffer;
}
/* wraps into a TextIOWrapper */
wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type,
"Osssi",
buffer,
encoding, errors, newline,
line_buffering);
Py_CLEAR(buffer);
if (wrapper == NULL)
goto error;
if (PyObject_SetAttrString(wrapper, "mode", modeobj) < 0)
goto error;
Py_DECREF(modeobj);
return wrapper;
error:
Py_XDECREF(raw);
Py_XDECREF(modeobj);
Py_XDECREF(buffer);
Py_XDECREF(wrapper);
return NULL;
}
/*
* Private helpers for the io module.
*/
Py_off_t
PyNumber_AsOff_t(PyObject *item, PyObject *err)
{
Py_off_t result;
PyObject *runerr;
PyObject *value = PyNumber_Index(item);
if (value == NULL)
return -1;
if (PyInt_Check(value)) {
/* We assume a long always fits in a Py_off_t... */
result = (Py_off_t) PyInt_AS_LONG(value);
goto finish;
}
/* We're done if PyLong_AsSsize_t() returns without error. */
result = PyLong_AsOff_t(value);
if (result != -1 || !(runerr = PyErr_Occurred()))
goto finish;
/* Error handling code -- only manage OverflowError differently */
if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
goto finish;
PyErr_Clear();
/* If no error-handling desired then the default clipping
is sufficient.
*/
if (!err) {
assert(PyLong_Check(value));
/* Whether or not it is less than or equal to
zero is determined by the sign of ob_size
*/
if (_PyLong_Sign(value) < 0)
result = PY_OFF_T_MIN;
else
result = PY_OFF_T_MAX;
}
else {
/* Otherwise replace the error with caller's error object. */
PyErr_Format(err,
"cannot fit '%.200s' into an offset-sized integer",
item->ob_type->tp_name);
}
finish:
Py_DECREF(value);
return result;
}
/* Basically the "n" format code with the ability to turn None into -1. */
int
_PyIO_ConvertSsize_t(PyObject *obj, void *result) {
Py_ssize_t limit;
if (obj == Py_None) {
limit = -1;
}
else if (PyNumber_Check(obj)) {
limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
if (limit == -1 && PyErr_Occurred())
return 0;
}
else {
PyErr_Format(PyExc_TypeError,
"integer argument expected, got '%.200s'",
Py_TYPE(obj)->tp_name);
return 0;
}
*((Py_ssize_t *)result) = limit;
return 1;
}
/*
* Module definition
*/
PyObject *_PyIO_os_module = NULL;
PyObject *_PyIO_locale_module = NULL;
PyObject *_PyIO_unsupported_operation = NULL;
static PyMethodDef module_methods[] = {
{"open", (PyCFunction)io_open, METH_VARARGS|METH_KEYWORDS, open_doc},
{NULL, NULL}
};
PyMODINIT_FUNC
init_io(void)
{
PyObject *m = Py_InitModule4("_io", module_methods,
module_doc, NULL, PYTHON_API_VERSION);
if (m == NULL)
return;
/* put os in the module state */
_PyIO_os_module = PyImport_ImportModule("os");
if (_PyIO_os_module == NULL)
goto fail;
#define ADD_TYPE(type, name) \
if (PyType_Ready(type) < 0) \
goto fail; \
Py_INCREF(type); \
if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \
Py_DECREF(type); \
goto fail; \
}
/* DEFAULT_BUFFER_SIZE */
if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0)
goto fail;
/* UnsupportedOperation inherits from ValueError and IOError */
_PyIO_unsupported_operation = PyObject_CallFunction(
(PyObject *)&PyType_Type, "s(OO){}",
"UnsupportedOperation", PyExc_ValueError, PyExc_IOError);
if (_PyIO_unsupported_operation == NULL)
goto fail;
Py_INCREF(_PyIO_unsupported_operation);
if (PyModule_AddObject(m, "UnsupportedOperation",
_PyIO_unsupported_operation) < 0)
goto fail;
/* BlockingIOError */
_PyExc_BlockingIOError.tp_base = (PyTypeObject *) PyExc_IOError;
ADD_TYPE(&_PyExc_BlockingIOError, "BlockingIOError");
/* Concrete base types of the IO ABCs.
(the ABCs themselves are declared through inheritance in io.py)
*/
ADD_TYPE(&PyIOBase_Type, "_IOBase");
ADD_TYPE(&PyRawIOBase_Type, "_RawIOBase");
ADD_TYPE(&PyBufferedIOBase_Type, "_BufferedIOBase");
ADD_TYPE(&PyTextIOBase_Type, "_TextIOBase");
/* Implementation of concrete IO objects. */
/* FileIO */
PyFileIO_Type.tp_base = &PyRawIOBase_Type;
ADD_TYPE(&PyFileIO_Type, "FileIO");
/* BytesIO */
PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type;
ADD_TYPE(&PyBytesIO_Type, "BytesIO");
/* StringIO */
PyStringIO_Type.tp_base = &PyTextIOBase_Type;
ADD_TYPE(&PyStringIO_Type, "StringIO");
/* BufferedReader */
PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type;
ADD_TYPE(&PyBufferedReader_Type, "BufferedReader");
/* BufferedWriter */
PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type;
ADD_TYPE(&PyBufferedWriter_Type, "BufferedWriter");
/* BufferedRWPair */
PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type;
ADD_TYPE(&PyBufferedRWPair_Type, "BufferedRWPair");
/* BufferedRandom */
PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type;
ADD_TYPE(&PyBufferedRandom_Type, "BufferedRandom");
/* TextIOWrapper */
PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type;
ADD_TYPE(&PyTextIOWrapper_Type, "TextIOWrapper");
/* IncrementalNewlineDecoder */
ADD_TYPE(&PyIncrementalNewlineDecoder_Type, "IncrementalNewlineDecoder");
/* Interned strings */
if (!(_PyIO_str_close = PyString_InternFromString("close")))
goto fail;
if (!(_PyIO_str_closed = PyString_InternFromString("closed")))
goto fail;
if (!(_PyIO_str_decode = PyString_InternFromString("decode")))
goto fail;
if (!(_PyIO_str_encode = PyString_InternFromString("encode")))
goto fail;
if (!(_PyIO_str_fileno = PyString_InternFromString("fileno")))
goto fail;
if (!(_PyIO_str_flush = PyString_InternFromString("flush")))
goto fail;
if (!(_PyIO_str_getstate = PyString_InternFromString("getstate")))
goto fail;
if (!(_PyIO_str_isatty = PyString_InternFromString("isatty")))
goto fail;
if (!(_PyIO_str_newlines = PyString_InternFromString("newlines")))
goto fail;
if (!(_PyIO_str_nl = PyString_InternFromString("\n")))
goto fail;
if (!(_PyIO_str_read = PyString_InternFromString("read")))
goto fail;
if (!(_PyIO_str_read1 = PyString_InternFromString("read1")))
goto fail;
if (!(_PyIO_str_readable = PyString_InternFromString("readable")))
goto fail;
if (!(_PyIO_str_readinto = PyString_InternFromString("readinto")))
goto fail;
if (!(_PyIO_str_readline = PyString_InternFromString("readline")))
goto fail;
if (!(_PyIO_str_reset = PyString_InternFromString("reset")))
goto fail;
if (!(_PyIO_str_seek = PyString_InternFromString("seek")))
goto fail;
if (!(_PyIO_str_seekable = PyString_InternFromString("seekable")))
goto fail;
if (!(_PyIO_str_setstate = PyString_InternFromString("setstate")))
goto fail;
if (!(_PyIO_str_tell = PyString_InternFromString("tell")))
goto fail;
if (!(_PyIO_str_truncate = PyString_InternFromString("truncate")))
goto fail;
if (!(_PyIO_str_write = PyString_InternFromString("write")))
goto fail;
if (!(_PyIO_str_writable = PyString_InternFromString("writable")))
goto fail;
if (!(_PyIO_empty_str = PyUnicode_FromStringAndSize(NULL, 0)))
goto fail;
if (!(_PyIO_empty_bytes = PyBytes_FromStringAndSize(NULL, 0)))
goto fail;
if (!(_PyIO_zero = PyLong_FromLong(0L)))
goto fail;
return;
fail:
Py_CLEAR(_PyIO_os_module);
Py_CLEAR(_PyIO_unsupported_operation);
Py_DECREF(m);
}

View File

@@ -0,0 +1,165 @@
/*
* Declarations shared between the different parts of the io module
*/
/* ABCs */
extern PyTypeObject PyIOBase_Type;
extern PyTypeObject PyRawIOBase_Type;
extern PyTypeObject PyBufferedIOBase_Type;
extern PyTypeObject PyTextIOBase_Type;
/* Concrete classes */
extern PyTypeObject PyFileIO_Type;
extern PyTypeObject PyBytesIO_Type;
extern PyTypeObject PyStringIO_Type;
extern PyTypeObject PyBufferedReader_Type;
extern PyTypeObject PyBufferedWriter_Type;
extern PyTypeObject PyBufferedRWPair_Type;
extern PyTypeObject PyBufferedRandom_Type;
extern PyTypeObject PyTextIOWrapper_Type;
extern PyTypeObject PyIncrementalNewlineDecoder_Type;
extern int _PyIO_ConvertSsize_t(PyObject *, void *);
/* These functions are used as METH_NOARGS methods, are normally called
* with args=NULL, and return a new reference.
* BUT when args=Py_True is passed, they return a borrowed reference.
*/
extern PyObject* _PyIOBase_check_readable(PyObject *self, PyObject *args);
extern PyObject* _PyIOBase_check_writable(PyObject *self, PyObject *args);
extern PyObject* _PyIOBase_check_seekable(PyObject *self, PyObject *args);
extern PyObject* _PyIOBase_check_closed(PyObject *self, PyObject *args);
/* Helper for finalization.
This function will revive an object ready to be deallocated and try to
close() it. It returns 0 if the object can be destroyed, or -1 if it
is alive again. */
extern int _PyIOBase_finalize(PyObject *self);
/* Returns true if the given FileIO object is closed.
Doesn't check the argument type, so be careful! */
extern int _PyFileIO_closed(PyObject *self);
/* Shortcut to the core of the IncrementalNewlineDecoder.decode method */
extern PyObject *_PyIncrementalNewlineDecoder_decode(
PyObject *self, PyObject *input, int final);
/* Finds the first line ending between `start` and `end`.
If found, returns the index after the line ending and doesn't touch
`*consumed`.
If not found, returns -1 and sets `*consumed` to the number of characters
which can be safely put aside until another search.
NOTE: for performance reasons, `end` must point to a NUL character ('\0').
Otherwise, the function will scan further and return garbage. */
extern Py_ssize_t _PyIO_find_line_ending(
int translated, int universal, PyObject *readnl,
Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed);
#define DEFAULT_BUFFER_SIZE (8 * 1024) /* bytes */
typedef struct {
/* This is the equivalent of PyException_HEAD in 3.x */
PyObject_HEAD
PyObject *dict;
PyObject *args;
PyObject *message;
PyObject *myerrno;
PyObject *strerror;
PyObject *filename; /* Not used, but part of the IOError object */
Py_ssize_t written;
} PyBlockingIOErrorObject;
PyAPI_DATA(PyObject *) PyExc_BlockingIOError;
/*
* Offset type for positioning.
*/
/* Printing a variable of type off_t (with e.g., PyString_FromFormat)
correctly and without producing compiler warnings is surprisingly painful.
We identify an integer type whose size matches off_t and then: (1) cast the
off_t to that integer type and (2) use the appropriate conversion
specification. The cast is necessary: gcc complains about formatting a
long with "%lld" even when both long and long long have the same
precision. */
#if defined(MS_WIN64) || defined(MS_WINDOWS)
/* Windows uses long long for offsets */
typedef PY_LONG_LONG Py_off_t;
# define PyLong_AsOff_t PyLong_AsLongLong
# define PyLong_FromOff_t PyLong_FromLongLong
# define PY_OFF_T_MAX PY_LLONG_MAX
# define PY_OFF_T_MIN PY_LLONG_MIN
# define PY_OFF_T_COMPAT PY_LONG_LONG /* type compatible with off_t */
# define PY_PRIdOFF "lld" /* format to use for that type */
#else
/* Other platforms use off_t */
typedef off_t Py_off_t;
#if (SIZEOF_OFF_T == SIZEOF_SIZE_T)
# define PyLong_AsOff_t PyLong_AsSsize_t
# define PyLong_FromOff_t PyLong_FromSsize_t
# define PY_OFF_T_MAX PY_SSIZE_T_MAX
# define PY_OFF_T_MIN PY_SSIZE_T_MIN
# define PY_OFF_T_COMPAT Py_ssize_t
# define PY_PRIdOFF "zd"
#elif (HAVE_LONG_LONG && SIZEOF_OFF_T == SIZEOF_LONG_LONG)
# define PyLong_AsOff_t PyLong_AsLongLong
# define PyLong_FromOff_t PyLong_FromLongLong
# define PY_OFF_T_MAX PY_LLONG_MAX
# define PY_OFF_T_MIN PY_LLONG_MIN
# define PY_OFF_T_COMPAT PY_LONG_LONG
# define PY_PRIdOFF "lld"
#elif (SIZEOF_OFF_T == SIZEOF_LONG)
# define PyLong_AsOff_t PyLong_AsLong
# define PyLong_FromOff_t PyLong_FromLong
# define PY_OFF_T_MAX LONG_MAX
# define PY_OFF_T_MIN LONG_MIN
# define PY_OFF_T_COMPAT long
# define PY_PRIdOFF "ld"
#else
# error off_t does not match either size_t, long, or long long!
#endif
#endif
extern Py_off_t PyNumber_AsOff_t(PyObject *item, PyObject *err);
/* Implementation details */
extern PyObject *_PyIO_os_module;
extern PyObject *_PyIO_locale_module;
extern PyObject *_PyIO_unsupported_operation;
extern PyObject *_PyIO_str_close;
extern PyObject *_PyIO_str_closed;
extern PyObject *_PyIO_str_decode;
extern PyObject *_PyIO_str_encode;
extern PyObject *_PyIO_str_fileno;
extern PyObject *_PyIO_str_flush;
extern PyObject *_PyIO_str_getstate;
extern PyObject *_PyIO_str_isatty;
extern PyObject *_PyIO_str_newlines;
extern PyObject *_PyIO_str_nl;
extern PyObject *_PyIO_str_read;
extern PyObject *_PyIO_str_read1;
extern PyObject *_PyIO_str_readable;
extern PyObject *_PyIO_str_readinto;
extern PyObject *_PyIO_str_readline;
extern PyObject *_PyIO_str_reset;
extern PyObject *_PyIO_str_seek;
extern PyObject *_PyIO_str_seekable;
extern PyObject *_PyIO_str_setstate;
extern PyObject *_PyIO_str_tell;
extern PyObject *_PyIO_str_truncate;
extern PyObject *_PyIO_str_writable;
extern PyObject *_PyIO_str_write;
extern PyObject *_PyIO_empty_str;
extern PyObject *_PyIO_empty_bytes;
extern PyObject *_PyIO_zero;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,887 @@
#include "Python.h"
#include "structmember.h" /* for offsetof() */
#include "_iomodule.h"
typedef struct {
PyObject_HEAD
char *buf;
Py_ssize_t pos;
Py_ssize_t string_size;
size_t buf_size;
PyObject *dict;
PyObject *weakreflist;
} bytesio;
#define CHECK_CLOSED(self) \
if ((self)->buf == NULL) { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on closed file."); \
return NULL; \
}
/* Internal routine to get a line from the buffer of a BytesIO
object. Returns the length between the current position to the
next newline character. */
static Py_ssize_t
get_line(bytesio *self, char **output)
{
char *n;
const char *str_end;
Py_ssize_t len;
assert(self->buf != NULL);
/* Move to the end of the line, up to the end of the string, s. */
str_end = self->buf + self->string_size;
for (n = self->buf + self->pos;
n < str_end && *n != '\n';
n++);
/* Skip the newline character */
if (n < str_end)
n++;
/* Get the length from the current position to the end of the line. */
len = n - (self->buf + self->pos);
*output = self->buf + self->pos;
assert(len >= 0);
assert(self->pos < PY_SSIZE_T_MAX - len);
self->pos += len;
return len;
}
/* Internal routine for changing the size of the buffer of BytesIO objects.
The caller should ensure that the 'size' argument is non-negative. Returns
0 on success, -1 otherwise. */
static int
resize_buffer(bytesio *self, size_t size)
{
/* Here, unsigned types are used to avoid dealing with signed integer
overflow, which is undefined in C. */
size_t alloc = self->buf_size;
char *new_buf = NULL;
assert(self->buf != NULL);
/* For simplicity, stay in the range of the signed type. Anyway, Python
doesn't allow strings to be longer than this. */
if (size > PY_SSIZE_T_MAX)
goto overflow;
if (size < alloc / 2) {
/* Major downsize; resize down to exact size. */
alloc = size + 1;
}
else if (size < alloc) {
/* Within allocated size; quick exit */
return 0;
}
else if (size <= alloc * 1.125) {
/* Moderate upsize; overallocate similar to list_resize() */
alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
}
else {
/* Major upsize; resize up to exact size */
alloc = size + 1;
}
if (alloc > ((size_t)-1) / sizeof(char))
goto overflow;
new_buf = (char *)PyMem_Realloc(self->buf, alloc * sizeof(char));
if (new_buf == NULL) {
PyErr_NoMemory();
return -1;
}
self->buf_size = alloc;
self->buf = new_buf;
return 0;
overflow:
PyErr_SetString(PyExc_OverflowError,
"new buffer size too large");
return -1;
}
/* Internal routine for writing a string of bytes to the buffer of a BytesIO
object. Returns the number of bytes wrote, or -1 on error. */
static Py_ssize_t
write_bytes(bytesio *self, const char *bytes, Py_ssize_t len)
{
assert(self->buf != NULL);
assert(self->pos >= 0);
assert(len >= 0);
if ((size_t)self->pos + len > self->buf_size) {
if (resize_buffer(self, (size_t)self->pos + len) < 0)
return -1;
}
if (self->pos > self->string_size) {
/* In case of overseek, pad with null bytes the buffer region between
the end of stream and the current position.
0 lo string_size hi
| |<---used--->|<----------available----------->|
| | <--to pad-->|<---to write---> |
0 buf position
*/
memset(self->buf + self->string_size, '\0',
(self->pos - self->string_size) * sizeof(char));
}
/* Copy the data to the internal buffer, overwriting some of the existing
data if self->pos < self->string_size. */
memcpy(self->buf + self->pos, bytes, len);
self->pos += len;
/* Set the new length of the internal string if it has changed. */
if (self->string_size < self->pos) {
self->string_size = self->pos;
}
return len;
}
static PyObject *
bytesio_get_closed(bytesio *self)
{
if (self->buf == NULL) {
Py_RETURN_TRUE;
}
else {
Py_RETURN_FALSE;
}
}
/* Generic getter for the writable, readable and seekable properties */
static PyObject *
return_true(bytesio *self)
{
Py_RETURN_TRUE;
}
PyDoc_STRVAR(flush_doc,
"flush() -> None. Does nothing.");
static PyObject *
bytesio_flush(bytesio *self)
{
CHECK_CLOSED(self);
Py_RETURN_NONE;
}
PyDoc_STRVAR(getval_doc,
"getvalue() -> bytes.\n"
"\n"
"Retrieve the entire contents of the BytesIO object.");
static PyObject *
bytesio_getvalue(bytesio *self)
{
CHECK_CLOSED(self);
return PyBytes_FromStringAndSize(self->buf, self->string_size);
}
PyDoc_STRVAR(isatty_doc,
"isatty() -> False.\n"
"\n"
"Always returns False since BytesIO objects are not connected\n"
"to a tty-like device.");
static PyObject *
bytesio_isatty(bytesio *self)
{
CHECK_CLOSED(self);
Py_RETURN_FALSE;
}
PyDoc_STRVAR(tell_doc,
"tell() -> current file position, an integer\n");
static PyObject *
bytesio_tell(bytesio *self)
{
CHECK_CLOSED(self);
return PyLong_FromSsize_t(self->pos);
}
PyDoc_STRVAR(read_doc,
"read([size]) -> read at most size bytes, returned as a string.\n"
"\n"
"If the size argument is negative, read until EOF is reached.\n"
"Return an empty string at EOF.");
static PyObject *
bytesio_read(bytesio *self, PyObject *args)
{
Py_ssize_t size, n;
char *output;
PyObject *arg = Py_None;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "|O:read", &arg))
return NULL;
if (PyNumber_Check(arg)) {
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* Read until EOF is reached, by default. */
size = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
/* adjust invalid sizes */
n = self->string_size - self->pos;
if (size < 0 || size > n) {
size = n;
if (size < 0)
size = 0;
}
assert(self->buf != NULL);
output = self->buf + self->pos;
self->pos += size;
return PyBytes_FromStringAndSize(output, size);
}
PyDoc_STRVAR(read1_doc,
"read1(size) -> read at most size bytes, returned as a string.\n"
"\n"
"If the size argument is negative or omitted, read until EOF is reached.\n"
"Return an empty string at EOF.");
static PyObject *
bytesio_read1(bytesio *self, PyObject *n)
{
PyObject *arg, *res;
arg = PyTuple_Pack(1, n);
if (arg == NULL)
return NULL;
res = bytesio_read(self, arg);
Py_DECREF(arg);
return res;
}
PyDoc_STRVAR(readline_doc,
"readline([size]) -> next line from the file, as a string.\n"
"\n"
"Retain newline. A non-negative size argument limits the maximum\n"
"number of bytes to return (an incomplete line may be returned then).\n"
"Return an empty string at EOF.\n");
static PyObject *
bytesio_readline(bytesio *self, PyObject *args)
{
Py_ssize_t size, n;
char *output;
PyObject *arg = Py_None;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "|O:readline", &arg))
return NULL;
if (PyNumber_Check(arg)) {
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* No size limit, by default. */
size = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
n = get_line(self, &output);
if (size >= 0 && size < n) {
size = n - size;
n -= size;
self->pos -= size;
}
return PyBytes_FromStringAndSize(output, n);
}
PyDoc_STRVAR(readlines_doc,
"readlines([size]) -> list of strings, each a line from the file.\n"
"\n"
"Call readline() repeatedly and return a list of the lines so read.\n"
"The optional size argument, if given, is an approximate bound on the\n"
"total number of bytes in the lines returned.\n");
static PyObject *
bytesio_readlines(bytesio *self, PyObject *args)
{
Py_ssize_t maxsize, size, n;
PyObject *result, *line;
char *output;
PyObject *arg = Py_None;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "|O:readlines", &arg))
return NULL;
if (PyNumber_Check(arg)) {
maxsize = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (maxsize == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* No size limit, by default. */
maxsize = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
size = 0;
result = PyList_New(0);
if (!result)
return NULL;
while ((n = get_line(self, &output)) != 0) {
line = PyBytes_FromStringAndSize(output, n);
if (!line)
goto on_error;
if (PyList_Append(result, line) == -1) {
Py_DECREF(line);
goto on_error;
}
Py_DECREF(line);
size += n;
if (maxsize > 0 && size >= maxsize)
break;
}
return result;
on_error:
Py_DECREF(result);
return NULL;
}
PyDoc_STRVAR(readinto_doc,
"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n"
"\n"
"Returns number of bytes read (0 for EOF), or None if the object\n"
"is set not to block as has no data to read.");
static PyObject *
bytesio_readinto(bytesio *self, PyObject *args)
{
Py_buffer buf;
Py_ssize_t len, n;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "w*", &buf))
return NULL;
len = buf.len;
/* adjust invalid sizes */
n = self->string_size - self->pos;
if (len > n) {
len = n;
if (len < 0)
len = 0;
}
memcpy(buf.buf, self->buf + self->pos, len);
assert(self->pos + len < PY_SSIZE_T_MAX);
assert(len >= 0);
self->pos += len;
PyBuffer_Release(&buf);
return PyLong_FromSsize_t(len);
}
PyDoc_STRVAR(truncate_doc,
"truncate([size]) -> int. Truncate the file to at most size bytes.\n"
"\n"
"Size defaults to the current file position, as returned by tell().\n"
"The current file position is unchanged. Returns the new size.\n");
static PyObject *
bytesio_truncate(bytesio *self, PyObject *args)
{
Py_ssize_t size;
PyObject *arg = Py_None;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
return NULL;
if (PyNumber_Check(arg)) {
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* Truncate to current position if no argument is passed. */
size = self->pos;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
if (size < 0) {
PyErr_Format(PyExc_ValueError,
"negative size value %zd", size);
return NULL;
}
if (size < self->string_size) {
self->string_size = size;
if (resize_buffer(self, size) < 0)
return NULL;
}
return PyLong_FromSsize_t(size);
}
static PyObject *
bytesio_iternext(bytesio *self)
{
char *next;
Py_ssize_t n;
CHECK_CLOSED(self);
n = get_line(self, &next);
if (!next || n == 0)
return NULL;
return PyBytes_FromStringAndSize(next, n);
}
PyDoc_STRVAR(seek_doc,
"seek(pos, whence=0) -> int. Change stream position.\n"
"\n"
"Seek to byte offset pos relative to position indicated by whence:\n"
" 0 Start of stream (the default). pos should be >= 0;\n"
" 1 Current position - pos may be negative;\n"
" 2 End of stream - pos usually negative.\n"
"Returns the new absolute position.");
static PyObject *
bytesio_seek(bytesio *self, PyObject *args)
{
PyObject *posobj;
Py_ssize_t pos;
int mode = 0;
CHECK_CLOSED(self);
if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
return NULL;
pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
if (pos == -1 && PyErr_Occurred())
return NULL;
if (pos < 0 && mode == 0) {
PyErr_Format(PyExc_ValueError,
"negative seek value %zd", pos);
return NULL;
}
/* mode 0: offset relative to beginning of the string.
mode 1: offset relative to current position.
mode 2: offset relative the end of the string. */
if (mode == 1) {
if (pos > PY_SSIZE_T_MAX - self->pos) {
PyErr_SetString(PyExc_OverflowError,
"new position too large");
return NULL;
}
pos += self->pos;
}
else if (mode == 2) {
if (pos > PY_SSIZE_T_MAX - self->string_size) {
PyErr_SetString(PyExc_OverflowError,
"new position too large");
return NULL;
}
pos += self->string_size;
}
else if (mode != 0) {
PyErr_Format(PyExc_ValueError,
"invalid whence (%i, should be 0, 1 or 2)", mode);
return NULL;
}
if (pos < 0)
pos = 0;
self->pos = pos;
return PyLong_FromSsize_t(self->pos);
}
PyDoc_STRVAR(write_doc,
"write(bytes) -> int. Write bytes to file.\n"
"\n"
"Return the number of bytes written.");
static PyObject *
bytesio_write(bytesio *self, PyObject *obj)
{
Py_ssize_t n = 0;
Py_buffer buf;
PyObject *result = NULL;
CHECK_CLOSED(self);
if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0)
return NULL;
if (buf.len != 0)
n = write_bytes(self, buf.buf, buf.len);
if (n >= 0)
result = PyLong_FromSsize_t(n);
PyBuffer_Release(&buf);
return result;
}
PyDoc_STRVAR(writelines_doc,
"writelines(sequence_of_strings) -> None. Write strings to the file.\n"
"\n"
"Note that newlines are not added. The sequence can be any iterable\n"
"object producing strings. This is equivalent to calling write() for\n"
"each string.");
static PyObject *
bytesio_writelines(bytesio *self, PyObject *v)
{
PyObject *it, *item;
PyObject *ret;
CHECK_CLOSED(self);
it = PyObject_GetIter(v);
if (it == NULL)
return NULL;
while ((item = PyIter_Next(it)) != NULL) {
ret = bytesio_write(self, item);
Py_DECREF(item);
if (ret == NULL) {
Py_DECREF(it);
return NULL;
}
Py_DECREF(ret);
}
Py_DECREF(it);
/* See if PyIter_Next failed */
if (PyErr_Occurred())
return NULL;
Py_RETURN_NONE;
}
PyDoc_STRVAR(close_doc,
"close() -> None. Disable all I/O operations.");
static PyObject *
bytesio_close(bytesio *self)
{
if (self->buf != NULL) {
PyMem_Free(self->buf);
self->buf = NULL;
}
Py_RETURN_NONE;
}
/* Pickling support.
Note that only pickle protocol 2 and onward are supported since we use
extended __reduce__ API of PEP 307 to make BytesIO instances picklable.
Providing support for protocol < 2 would require the __reduce_ex__ method
which is notably long-winded when defined properly.
For BytesIO, the implementation would similar to one coded for
object.__reduce_ex__, but slightly less general. To be more specific, we
could call bytesio_getstate directly and avoid checking for the presence of
a fallback __reduce__ method. However, we would still need a __newobj__
function to use the efficient instance representation of PEP 307.
*/
static PyObject *
bytesio_getstate(bytesio *self)
{
PyObject *initvalue = bytesio_getvalue(self);
PyObject *dict;
PyObject *state;
if (initvalue == NULL)
return NULL;
if (self->dict == NULL) {
Py_INCREF(Py_None);
dict = Py_None;
}
else {
dict = PyDict_Copy(self->dict);
if (dict == NULL)
return NULL;
}
state = Py_BuildValue("(OnN)", initvalue, self->pos, dict);
Py_DECREF(initvalue);
return state;
}
static PyObject *
bytesio_setstate(bytesio *self, PyObject *state)
{
PyObject *result;
PyObject *position_obj;
PyObject *dict;
Py_ssize_t pos;
assert(state != NULL);
/* We allow the state tuple to be longer than 3, because we may need
someday to extend the object's state without breaking
backward-compatibility. */
if (!PyTuple_Check(state) || Py_SIZE(state) < 3) {
PyErr_Format(PyExc_TypeError,
"%.200s.__setstate__ argument should be 3-tuple, got %.200s",
Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
return NULL;
}
/* Reset the object to its default state. This is only needed to handle
the case of repeated calls to __setstate__. */
self->string_size = 0;
self->pos = 0;
/* Set the value of the internal buffer. If state[0] does not support the
buffer protocol, bytesio_write will raise the appropriate TypeError. */
result = bytesio_write(self, PyTuple_GET_ITEM(state, 0));
if (result == NULL)
return NULL;
Py_DECREF(result);
/* Set carefully the position value. Alternatively, we could use the seek
method instead of modifying self->pos directly to better protect the
object internal state against errneous (or malicious) inputs. */
position_obj = PyTuple_GET_ITEM(state, 1);
if (!PyIndex_Check(position_obj)) {
PyErr_Format(PyExc_TypeError,
"second item of state must be an integer, not %.200s",
Py_TYPE(position_obj)->tp_name);
return NULL;
}
pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
if (pos == -1 && PyErr_Occurred())
return NULL;
if (pos < 0) {
PyErr_SetString(PyExc_ValueError,
"position value cannot be negative");
return NULL;
}
self->pos = pos;
/* Set the dictionary of the instance variables. */
dict = PyTuple_GET_ITEM(state, 2);
if (dict != Py_None) {
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError,
"third item of state should be a dict, got a %.200s",
Py_TYPE(dict)->tp_name);
return NULL;
}
if (self->dict) {
/* Alternatively, we could replace the internal dictionary
completely. However, it seems more practical to just update it. */
if (PyDict_Update(self->dict, dict) < 0)
return NULL;
}
else {
Py_INCREF(dict);
self->dict = dict;
}
}
Py_RETURN_NONE;
}
static void
bytesio_dealloc(bytesio *self)
{
_PyObject_GC_UNTRACK(self);
if (self->buf != NULL) {
PyMem_Free(self->buf);
self->buf = NULL;
}
Py_CLEAR(self->dict);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_TYPE(self)->tp_free(self);
}
static PyObject *
bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
bytesio *self;
assert(type != NULL && type->tp_alloc != NULL);
self = (bytesio *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
/* tp_alloc initializes all the fields to zero. So we don't have to
initialize them here. */
self->buf = (char *)PyMem_Malloc(0);
if (self->buf == NULL) {
Py_DECREF(self);
return PyErr_NoMemory();
}
return (PyObject *)self;
}
static int
bytesio_init(bytesio *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"initial_bytes", NULL};
PyObject *initvalue = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist,
&initvalue))
return -1;
/* In case, __init__ is called multiple times. */
self->string_size = 0;
self->pos = 0;
if (initvalue && initvalue != Py_None) {
PyObject *res;
res = bytesio_write(self, initvalue);
if (res == NULL)
return -1;
Py_DECREF(res);
self->pos = 0;
}
return 0;
}
static int
bytesio_traverse(bytesio *self, visitproc visit, void *arg)
{
Py_VISIT(self->dict);
return 0;
}
static int
bytesio_clear(bytesio *self)
{
Py_CLEAR(self->dict);
return 0;
}
static PyGetSetDef bytesio_getsetlist[] = {
{"closed", (getter)bytesio_get_closed, NULL,
"True if the file is closed."},
{NULL}, /* sentinel */
};
static struct PyMethodDef bytesio_methods[] = {
{"readable", (PyCFunction)return_true, METH_NOARGS, NULL},
{"seekable", (PyCFunction)return_true, METH_NOARGS, NULL},
{"writable", (PyCFunction)return_true, METH_NOARGS, NULL},
{"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc},
{"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc},
{"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc},
{"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc},
{"write", (PyCFunction)bytesio_write, METH_O, write_doc},
{"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc},
{"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc},
{"readinto", (PyCFunction)bytesio_readinto, METH_VARARGS, readinto_doc},
{"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc},
{"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc},
{"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc},
{"getvalue", (PyCFunction)bytesio_getvalue, METH_NOARGS, getval_doc},
{"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc},
{"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc},
{"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL},
{"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(bytesio_doc,
"BytesIO([buffer]) -> object\n"
"\n"
"Create a buffered I/O implementation using an in-memory bytes\n"
"buffer, ready for reading and writing.");
PyTypeObject PyBytesIO_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io.BytesIO", /*tp_name*/
sizeof(bytesio), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)bytesio_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_HAVE_GC, /*tp_flags*/
bytesio_doc, /*tp_doc*/
(traverseproc)bytesio_traverse, /*tp_traverse*/
(inquiry)bytesio_clear, /*tp_clear*/
0, /*tp_richcompare*/
offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/
PyObject_SelfIter, /*tp_iter*/
(iternextfunc)bytesio_iternext, /*tp_iternext*/
bytesio_methods, /*tp_methods*/
0, /*tp_members*/
bytesio_getsetlist, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
offsetof(bytesio, dict), /*tp_dictoffset*/
(initproc)bytesio_init, /*tp_init*/
0, /*tp_alloc*/
bytesio_new, /*tp_new*/
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,893 @@
/*
An implementation of the I/O abstract base classes hierarchy
as defined by PEP 3116 - "New I/O"
Classes defined here: IOBase, RawIOBase.
Written by Amaury Forgeot d'Arc and Antoine Pitrou
*/
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"
#include "_iomodule.h"
/*
* IOBase class, an abstract class
*/
typedef struct {
PyObject_HEAD
PyObject *dict;
PyObject *weakreflist;
} iobase;
PyDoc_STRVAR(iobase_doc,
"The abstract base class for all I/O classes, acting on streams of\n"
"bytes. There is no public constructor.\n"
"\n"
"This class provides dummy implementations for many methods that\n"
"derived classes can override selectively; the default implementations\n"
"represent a file that cannot be read, written or seeked.\n"
"\n"
"Even though IOBase does not declare read, readinto, or write because\n"
"their signatures will vary, implementations and clients should\n"
"consider those methods part of the interface. Also, implementations\n"
"may raise a IOError when operations they do not support are called.\n"
"\n"
"The basic type used for binary data read from or written to a file is\n"
"bytes. bytearrays are accepted too, and in some cases (such as\n"
"readinto) needed. Text I/O classes work with str data.\n"
"\n"
"Note that calling any method (even inquiries) on a closed stream is\n"
"undefined. Implementations may raise IOError in this case.\n"
"\n"
"IOBase (and its subclasses) support the iterator protocol, meaning\n"
"that an IOBase object can be iterated over yielding the lines in a\n"
"stream.\n"
"\n"
"IOBase also supports the :keyword:`with` statement. In this example,\n"
"fp is closed after the suite of the with statement is complete:\n"
"\n"
"with open('spam.txt', 'r') as fp:\n"
" fp.write('Spam and eggs!')\n");
/* Use this macro whenever you want to check the internal `closed` status
of the IOBase object rather than the virtual `closed` attribute as returned
by whatever subclass. */
#define IS_CLOSED(self) \
PyObject_HasAttrString(self, "__IOBase_closed")
/* Internal methods */
static PyObject *
iobase_unsupported(const char *message)
{
PyErr_SetString(_PyIO_unsupported_operation, message);
return NULL;
}
/* Positionning */
PyDoc_STRVAR(iobase_seek_doc,
"Change stream position.\n"
"\n"
"Change the stream position to byte offset offset. offset is\n"
"interpreted relative to the position indicated by whence. Values\n"
"for whence are:\n"
"\n"
"* 0 -- start of stream (the default); offset should be zero or positive\n"
"* 1 -- current stream position; offset may be negative\n"
"* 2 -- end of stream; offset is usually negative\n"
"\n"
"Return the new absolute position.");
static PyObject *
iobase_seek(PyObject *self, PyObject *args)
{
return iobase_unsupported("seek");
}
PyDoc_STRVAR(iobase_tell_doc,
"Return current stream position.");
static PyObject *
iobase_tell(PyObject *self, PyObject *args)
{
return PyObject_CallMethod(self, "seek", "ii", 0, 1);
}
PyDoc_STRVAR(iobase_truncate_doc,
"Truncate file to size bytes.\n"
"\n"
"File pointer is left unchanged. Size defaults to the current IO\n"
"position as reported by tell(). Returns the new size.");
static PyObject *
iobase_truncate(PyObject *self, PyObject *args)
{
return iobase_unsupported("truncate");
}
/* Flush and close methods */
PyDoc_STRVAR(iobase_flush_doc,
"Flush write buffers, if applicable.\n"
"\n"
"This is not implemented for read-only and non-blocking streams.\n");
static PyObject *
iobase_flush(PyObject *self, PyObject *args)
{
/* XXX Should this return the number of bytes written??? */
if (IS_CLOSED(self)) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
return NULL;
}
Py_RETURN_NONE;
}
PyDoc_STRVAR(iobase_close_doc,
"Flush and close the IO object.\n"
"\n"
"This method has no effect if the file is already closed.\n");
static int
iobase_closed(PyObject *self)
{
PyObject *res;
int closed;
/* This gets the derived attribute, which is *not* __IOBase_closed
in most cases! */
res = PyObject_GetAttr(self, _PyIO_str_closed);
if (res == NULL)
return 0;
closed = PyObject_IsTrue(res);
Py_DECREF(res);
return closed;
}
static PyObject *
iobase_closed_get(PyObject *self, void *context)
{
return PyBool_FromLong(IS_CLOSED(self));
}
PyObject *
_PyIOBase_check_closed(PyObject *self, PyObject *args)
{
if (iobase_closed(self)) {
PyErr_SetString(PyExc_ValueError, "I/O operation on closed file.");
return NULL;
}
if (args == Py_True)
return Py_None;
else
Py_RETURN_NONE;
}
/* XXX: IOBase thinks it has to maintain its own internal state in
`__IOBase_closed` and call flush() by itself, but it is redundant with
whatever behaviour a non-trivial derived class will implement. */
static PyObject *
iobase_close(PyObject *self, PyObject *args)
{
PyObject *res;
if (IS_CLOSED(self))
Py_RETURN_NONE;
res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL);
PyObject_SetAttrString(self, "__IOBase_closed", Py_True);
if (res == NULL) {
return NULL;
}
Py_XDECREF(res);
Py_RETURN_NONE;
}
/* Finalization and garbage collection support */
int
_PyIOBase_finalize(PyObject *self)
{
PyObject *res;
PyObject *tp, *v, *tb;
int closed = 1;
int is_zombie;
/* If _PyIOBase_finalize() is called from a destructor, we need to
resurrect the object as calling close() can invoke arbitrary code. */
is_zombie = (Py_REFCNT(self) == 0);
if (is_zombie) {
++Py_REFCNT(self);
}
PyErr_Fetch(&tp, &v, &tb);
/* If `closed` doesn't exist or can't be evaluated as bool, then the
object is probably in an unusable state, so ignore. */
res = PyObject_GetAttr(self, _PyIO_str_closed);
if (res == NULL)
PyErr_Clear();
else {
closed = PyObject_IsTrue(res);
Py_DECREF(res);
if (closed == -1)
PyErr_Clear();
}
if (closed == 0) {
res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close,
NULL);
/* Silencing I/O errors is bad, but printing spurious tracebacks is
equally as bad, and potentially more frequent (because of
shutdown issues). */
if (res == NULL)
PyErr_Clear();
else
Py_DECREF(res);
}
PyErr_Restore(tp, v, tb);
if (is_zombie) {
if (--Py_REFCNT(self) != 0) {
/* The object lives again. The following code is taken from
slot_tp_del in typeobject.c. */
Py_ssize_t refcnt = Py_REFCNT(self);
_Py_NewReference(self);
Py_REFCNT(self) = refcnt;
/* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
* we need to undo that. */
_Py_DEC_REFTOTAL;
/* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
* chain, so no more to do there.
* If COUNT_ALLOCS, the original decref bumped tp_frees, and
* _Py_NewReference bumped tp_allocs: both of those need to be
* undone.
*/
#ifdef COUNT_ALLOCS
--Py_TYPE(self)->tp_frees;
--Py_TYPE(self)->tp_allocs;
#endif
return -1;
}
}
return 0;
}
static int
iobase_traverse(iobase *self, visitproc visit, void *arg)
{
Py_VISIT(self->dict);
return 0;
}
static int
iobase_clear(iobase *self)
{
if (_PyIOBase_finalize((PyObject *) self) < 0)
return -1;
Py_CLEAR(self->dict);
return 0;
}
/* Destructor */
static void
iobase_dealloc(iobase *self)
{
/* NOTE: since IOBaseObject has its own dict, Python-defined attributes
are still available here for close() to use.
However, if the derived class declares a __slots__, those slots are
already gone.
*/
if (_PyIOBase_finalize((PyObject *) self) < 0) {
/* When called from a heap type's dealloc, the type will be
decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */
if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE))
Py_INCREF(Py_TYPE(self));
return;
}
_PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_CLEAR(self->dict);
Py_TYPE(self)->tp_free((PyObject *) self);
}
/* Inquiry methods */
PyDoc_STRVAR(iobase_seekable_doc,
"Return whether object supports random access.\n"
"\n"
"If False, seek(), tell() and truncate() will raise IOError.\n"
"This method may need to do a test seek().");
static PyObject *
iobase_seekable(PyObject *self, PyObject *args)
{
Py_RETURN_FALSE;
}
PyObject *
_PyIOBase_check_seekable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL);
if (res == NULL)
return NULL;
if (res != Py_True) {
Py_CLEAR(res);
PyErr_SetString(PyExc_IOError, "File or stream is not seekable.");
return NULL;
}
if (args == Py_True) {
Py_DECREF(res);
}
return res;
}
PyDoc_STRVAR(iobase_readable_doc,
"Return whether object was opened for reading.\n"
"\n"
"If False, read() will raise IOError.");
static PyObject *
iobase_readable(PyObject *self, PyObject *args)
{
Py_RETURN_FALSE;
}
/* May be called with any object */
PyObject *
_PyIOBase_check_readable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL);
if (res == NULL)
return NULL;
if (res != Py_True) {
Py_CLEAR(res);
PyErr_SetString(PyExc_IOError, "File or stream is not readable.");
return NULL;
}
if (args == Py_True) {
Py_DECREF(res);
}
return res;
}
PyDoc_STRVAR(iobase_writable_doc,
"Return whether object was opened for writing.\n"
"\n"
"If False, read() will raise IOError.");
static PyObject *
iobase_writable(PyObject *self, PyObject *args)
{
Py_RETURN_FALSE;
}
/* May be called with any object */
PyObject *
_PyIOBase_check_writable(PyObject *self, PyObject *args)
{
PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL);
if (res == NULL)
return NULL;
if (res != Py_True) {
Py_CLEAR(res);
PyErr_SetString(PyExc_IOError, "File or stream is not writable.");
return NULL;
}
if (args == Py_True) {
Py_DECREF(res);
}
return res;
}
/* Context manager */
static PyObject *
iobase_enter(PyObject *self, PyObject *args)
{
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
Py_INCREF(self);
return self;
}
static PyObject *
iobase_exit(PyObject *self, PyObject *args)
{
return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL);
}
/* Lower-level APIs */
/* XXX Should these be present even if unimplemented? */
PyDoc_STRVAR(iobase_fileno_doc,
"Returns underlying file descriptor if one exists.\n"
"\n"
"An IOError is raised if the IO object does not use a file descriptor.\n");
static PyObject *
iobase_fileno(PyObject *self, PyObject *args)
{
return iobase_unsupported("fileno");
}
PyDoc_STRVAR(iobase_isatty_doc,
"Return whether this is an 'interactive' stream.\n"
"\n"
"Return False if it can't be determined.\n");
static PyObject *
iobase_isatty(PyObject *self, PyObject *args)
{
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
Py_RETURN_FALSE;
}
/* Readline(s) and writelines */
PyDoc_STRVAR(iobase_readline_doc,
"Read and return a line from the stream.\n"
"\n"
"If limit is specified, at most limit bytes will be read.\n"
"\n"
"The line terminator is always b'\n' for binary files; for text\n"
"files, the newlines argument to open can be used to select the line\n"
"terminator(s) recognized.\n");
static PyObject *
iobase_readline(PyObject *self, PyObject *args)
{
/* For backwards compatibility, a (slowish) readline(). */
Py_ssize_t limit = -1;
int has_peek = 0;
PyObject *buffer, *result;
Py_ssize_t old_size = -1;
if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) {
return NULL;
}
if (PyObject_HasAttrString(self, "peek"))
has_peek = 1;
buffer = PyByteArray_FromStringAndSize(NULL, 0);
if (buffer == NULL)
return NULL;
while (limit < 0 || Py_SIZE(buffer) < limit) {
Py_ssize_t nreadahead = 1;
PyObject *b;
if (has_peek) {
PyObject *readahead = PyObject_CallMethod(self, "peek", "i", 1);
if (readahead == NULL)
goto fail;
if (!PyBytes_Check(readahead)) {
PyErr_Format(PyExc_IOError,
"peek() should have returned a bytes object, "
"not '%.200s'", Py_TYPE(readahead)->tp_name);
Py_DECREF(readahead);
goto fail;
}
if (PyBytes_GET_SIZE(readahead) > 0) {
Py_ssize_t n = 0;
const char *buf = PyBytes_AS_STRING(readahead);
if (limit >= 0) {
do {
if (n >= PyBytes_GET_SIZE(readahead) || n >= limit)
break;
if (buf[n++] == '\n')
break;
} while (1);
}
else {
do {
if (n >= PyBytes_GET_SIZE(readahead))
break;
if (buf[n++] == '\n')
break;
} while (1);
}
nreadahead = n;
}
Py_DECREF(readahead);
}
b = PyObject_CallMethod(self, "read", "n", nreadahead);
if (b == NULL)
goto fail;
if (!PyBytes_Check(b)) {
PyErr_Format(PyExc_IOError,
"read() should have returned a bytes object, "
"not '%.200s'", Py_TYPE(b)->tp_name);
Py_DECREF(b);
goto fail;
}
if (PyBytes_GET_SIZE(b) == 0) {
Py_DECREF(b);
break;
}
old_size = PyByteArray_GET_SIZE(buffer);
PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b));
memcpy(PyByteArray_AS_STRING(buffer) + old_size,
PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b));
Py_DECREF(b);
if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n')
break;
}
result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer),
PyByteArray_GET_SIZE(buffer));
Py_DECREF(buffer);
return result;
fail:
Py_DECREF(buffer);
return NULL;
}
static PyObject *
iobase_iter(PyObject *self)
{
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
Py_INCREF(self);
return self;
}
static PyObject *
iobase_iternext(PyObject *self)
{
PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL);
if (line == NULL)
return NULL;
if (PyObject_Size(line) == 0) {
Py_DECREF(line);
return NULL;
}
return line;
}
PyDoc_STRVAR(iobase_readlines_doc,
"Return a list of lines from the stream.\n"
"\n"
"hint can be specified to control the number of lines read: no more\n"
"lines will be read if the total size (in bytes/characters) of all\n"
"lines so far exceeds hint.");
static PyObject *
iobase_readlines(PyObject *self, PyObject *args)
{
Py_ssize_t hint = -1, length = 0;
PyObject *result;
if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) {
return NULL;
}
result = PyList_New(0);
if (result == NULL)
return NULL;
if (hint <= 0) {
/* XXX special-casing this made sense in the Python version in order
to remove the bytecode interpretation overhead, but it could
probably be removed here. */
PyObject *ret = PyObject_CallMethod(result, "extend", "O", self);
if (ret == NULL) {
Py_DECREF(result);
return NULL;
}
Py_DECREF(ret);
return result;
}
while (1) {
PyObject *line = PyIter_Next(self);
if (line == NULL) {
if (PyErr_Occurred()) {
Py_DECREF(result);
return NULL;
}
else
break; /* StopIteration raised */
}
if (PyList_Append(result, line) < 0) {
Py_DECREF(line);
Py_DECREF(result);
return NULL;
}
length += PyObject_Size(line);
Py_DECREF(line);
if (length > hint)
break;
}
return result;
}
static PyObject *
iobase_writelines(PyObject *self, PyObject *args)
{
PyObject *lines, *iter, *res;
if (!PyArg_ParseTuple(args, "O:writelines", &lines)) {
return NULL;
}
if (_PyIOBase_check_closed(self, Py_True) == NULL)
return NULL;
iter = PyObject_GetIter(lines);
if (iter == NULL)
return NULL;
while (1) {
PyObject *line = PyIter_Next(iter);
if (line == NULL) {
if (PyErr_Occurred()) {
Py_DECREF(iter);
return NULL;
}
else
break; /* Stop Iteration */
}
res = PyObject_CallMethodObjArgs(self, _PyIO_str_write, line, NULL);
Py_DECREF(line);
if (res == NULL) {
Py_DECREF(iter);
return NULL;
}
Py_DECREF(res);
}
Py_DECREF(iter);
Py_RETURN_NONE;
}
static PyMethodDef iobase_methods[] = {
{"seek", iobase_seek, METH_VARARGS, iobase_seek_doc},
{"tell", iobase_tell, METH_NOARGS, iobase_tell_doc},
{"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc},
{"flush", iobase_flush, METH_NOARGS, iobase_flush_doc},
{"close", iobase_close, METH_NOARGS, iobase_close_doc},
{"seekable", iobase_seekable, METH_NOARGS, iobase_seekable_doc},
{"readable", iobase_readable, METH_NOARGS, iobase_readable_doc},
{"writable", iobase_writable, METH_NOARGS, iobase_writable_doc},
{"_checkClosed", _PyIOBase_check_closed, METH_NOARGS},
{"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS},
{"_checkReadable", _PyIOBase_check_readable, METH_NOARGS},
{"_checkWritable", _PyIOBase_check_writable, METH_NOARGS},
{"fileno", iobase_fileno, METH_NOARGS, iobase_fileno_doc},
{"isatty", iobase_isatty, METH_NOARGS, iobase_isatty_doc},
{"__enter__", iobase_enter, METH_NOARGS},
{"__exit__", iobase_exit, METH_VARARGS},
{"readline", iobase_readline, METH_VARARGS, iobase_readline_doc},
{"readlines", iobase_readlines, METH_VARARGS, iobase_readlines_doc},
{"writelines", iobase_writelines, METH_VARARGS},
{NULL, NULL}
};
static PyGetSetDef iobase_getset[] = {
{"closed", (getter)iobase_closed_get, NULL, NULL},
{NULL}
};
PyTypeObject PyIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._IOBase", /*tp_name*/
sizeof(iobase), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)iobase_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare */
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
iobase_doc, /* tp_doc */
(traverseproc)iobase_traverse, /* tp_traverse */
(inquiry)iobase_clear, /* tp_clear */
0, /* tp_richcompare */
offsetof(iobase, weakreflist), /* tp_weaklistoffset */
iobase_iter, /* tp_iter */
iobase_iternext, /* tp_iternext */
iobase_methods, /* tp_methods */
0, /* tp_members */
iobase_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof(iobase, dict), /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
};
/*
* RawIOBase class, Inherits from IOBase.
*/
PyDoc_STRVAR(rawiobase_doc,
"Base class for raw binary I/O.");
/*
* The read() method is implemented by calling readinto(); derived classes
* that want to support read() only need to implement readinto() as a
* primitive operation. In general, readinto() can be more efficient than
* read().
*
* (It would be tempting to also provide an implementation of readinto() in
* terms of read(), in case the latter is a more suitable primitive operation,
* but that would lead to nasty recursion in case a subclass doesn't implement
* either.)
*/
static PyObject *
rawiobase_read(PyObject *self, PyObject *args)
{
Py_ssize_t n = -1;
PyObject *b, *res;
if (!PyArg_ParseTuple(args, "|n:read", &n)) {
return NULL;
}
if (n < 0)
return PyObject_CallMethod(self, "readall", NULL);
/* TODO: allocate a bytes object directly instead and manually construct
a writable memoryview pointing to it. */
b = PyByteArray_FromStringAndSize(NULL, n);
if (b == NULL)
return NULL;
res = PyObject_CallMethodObjArgs(self, _PyIO_str_readinto, b, NULL);
if (res == NULL || res == Py_None) {
Py_DECREF(b);
return res;
}
n = PyNumber_AsSsize_t(res, PyExc_ValueError);
Py_DECREF(res);
if (n == -1 && PyErr_Occurred()) {
Py_DECREF(b);
return NULL;
}
res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n);
Py_DECREF(b);
return res;
}
PyDoc_STRVAR(rawiobase_readall_doc,
"Read until EOF, using multiple read() call.");
static PyObject *
rawiobase_readall(PyObject *self, PyObject *args)
{
int r;
PyObject *chunks = PyList_New(0);
PyObject *result;
if (chunks == NULL)
return NULL;
while (1) {
PyObject *data = PyObject_CallMethod(self, "read",
"i", DEFAULT_BUFFER_SIZE);
if (!data) {
Py_DECREF(chunks);
return NULL;
}
if (data == Py_None) {
if (PyList_GET_SIZE(chunks) == 0) {
Py_DECREF(chunks);
return data;
}
Py_DECREF(data);
break;
}
if (!PyBytes_Check(data)) {
Py_DECREF(chunks);
Py_DECREF(data);
PyErr_SetString(PyExc_TypeError, "read() should return bytes");
return NULL;
}
if (PyBytes_GET_SIZE(data) == 0) {
/* EOF */
Py_DECREF(data);
break;
}
r = PyList_Append(chunks, data);
Py_DECREF(data);
if (r < 0) {
Py_DECREF(chunks);
return NULL;
}
}
result = _PyBytes_Join(_PyIO_empty_bytes, chunks);
Py_DECREF(chunks);
return result;
}
static PyMethodDef rawiobase_methods[] = {
{"read", rawiobase_read, METH_VARARGS},
{"readall", rawiobase_readall, METH_NOARGS, rawiobase_readall_doc},
{NULL, NULL}
};
PyTypeObject PyRawIOBase_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io._RawIOBase", /*tp_name*/
0, /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare */
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
rawiobase_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
rawiobase_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&PyIOBase_Type, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};

View File

@@ -0,0 +1,882 @@
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "structmember.h"
#include "_iomodule.h"
/* Implementation note: the buffer is always at least one character longer
than the enclosed string, for proper functioning of _PyIO_find_line_ending.
*/
typedef struct {
PyObject_HEAD
Py_UNICODE *buf;
Py_ssize_t pos;
Py_ssize_t string_size;
size_t buf_size;
char ok; /* initialized? */
char closed;
char readuniversal;
char readtranslate;
PyObject *decoder;
PyObject *readnl;
PyObject *writenl;
PyObject *dict;
PyObject *weakreflist;
} stringio;
#define CHECK_INITIALIZED(self) \
if (self->ok <= 0) { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on uninitialized object"); \
return NULL; \
}
#define CHECK_CLOSED(self) \
if (self->closed) { \
PyErr_SetString(PyExc_ValueError, \
"I/O operation on closed file"); \
return NULL; \
}
PyDoc_STRVAR(stringio_doc,
"Text I/O implementation using an in-memory buffer.\n"
"\n"
"The initial_value argument sets the value of object. The newline\n"
"argument is like the one of TextIOWrapper's constructor.");
/* Internal routine for changing the size, in terms of characters, of the
buffer of StringIO objects. The caller should ensure that the 'size'
argument is non-negative. Returns 0 on success, -1 otherwise. */
static int
resize_buffer(stringio *self, size_t size)
{
/* Here, unsigned types are used to avoid dealing with signed integer
overflow, which is undefined in C. */
size_t alloc = self->buf_size;
Py_UNICODE *new_buf = NULL;
assert(self->buf != NULL);
/* Reserve one more char for line ending detection. */
size = size + 1;
/* For simplicity, stay in the range of the signed type. Anyway, Python
doesn't allow strings to be longer than this. */
if (size > PY_SSIZE_T_MAX)
goto overflow;
if (size < alloc / 2) {
/* Major downsize; resize down to exact size. */
alloc = size + 1;
}
else if (size < alloc) {
/* Within allocated size; quick exit */
return 0;
}
else if (size <= alloc * 1.125) {
/* Moderate upsize; overallocate similar to list_resize() */
alloc = size + (size >> 3) + (size < 9 ? 3 : 6);
}
else {
/* Major upsize; resize up to exact size */
alloc = size + 1;
}
if (alloc > ((size_t)-1) / sizeof(Py_UNICODE))
goto overflow;
new_buf = (Py_UNICODE *)PyMem_Realloc(self->buf,
alloc * sizeof(Py_UNICODE));
if (new_buf == NULL) {
PyErr_NoMemory();
return -1;
}
self->buf_size = alloc;
self->buf = new_buf;
return 0;
overflow:
PyErr_SetString(PyExc_OverflowError,
"new buffer size too large");
return -1;
}
/* Internal routine for writing a whole PyUnicode object to the buffer of a
StringIO object. Returns 0 on success, or -1 on error. */
static Py_ssize_t
write_str(stringio *self, PyObject *obj)
{
Py_UNICODE *str;
Py_ssize_t len;
PyObject *decoded = NULL;
assert(self->buf != NULL);
assert(self->pos >= 0);
if (self->decoder != NULL) {
decoded = _PyIncrementalNewlineDecoder_decode(
self->decoder, obj, 1 /* always final */);
}
else {
decoded = obj;
Py_INCREF(decoded);
}
if (self->writenl) {
PyObject *translated = PyUnicode_Replace(
decoded, _PyIO_str_nl, self->writenl, -1);
Py_DECREF(decoded);
decoded = translated;
}
if (decoded == NULL)
return -1;
assert(PyUnicode_Check(decoded));
str = PyUnicode_AS_UNICODE(decoded);
len = PyUnicode_GET_SIZE(decoded);
assert(len >= 0);
/* This overflow check is not strictly necessary. However, it avoids us to
deal with funky things like comparing an unsigned and a signed
integer. */
if (self->pos > PY_SSIZE_T_MAX - len) {
PyErr_SetString(PyExc_OverflowError,
"new position too large");
goto fail;
}
if (self->pos + len > self->string_size) {
if (resize_buffer(self, self->pos + len) < 0)
goto fail;
}
if (self->pos > self->string_size) {
/* In case of overseek, pad with null bytes the buffer region between
the end of stream and the current position.
0 lo string_size hi
| |<---used--->|<----------available----------->|
| | <--to pad-->|<---to write---> |
0 buf position
*/
memset(self->buf + self->string_size, '\0',
(self->pos - self->string_size) * sizeof(Py_UNICODE));
}
/* Copy the data to the internal buffer, overwriting some of the
existing data if self->pos < self->string_size. */
memcpy(self->buf + self->pos, str, len * sizeof(Py_UNICODE));
self->pos += len;
/* Set the new length of the internal string if it has changed. */
if (self->string_size < self->pos) {
self->string_size = self->pos;
}
Py_DECREF(decoded);
return 0;
fail:
Py_XDECREF(decoded);
return -1;
}
PyDoc_STRVAR(stringio_getvalue_doc,
"Retrieve the entire contents of the object.");
static PyObject *
stringio_getvalue(stringio *self)
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
return PyUnicode_FromUnicode(self->buf, self->string_size);
}
PyDoc_STRVAR(stringio_tell_doc,
"Tell the current file position.");
static PyObject *
stringio_tell(stringio *self)
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
return PyLong_FromSsize_t(self->pos);
}
PyDoc_STRVAR(stringio_read_doc,
"Read at most n characters, returned as a string.\n"
"\n"
"If the argument is negative or omitted, read until EOF\n"
"is reached. Return an empty string at EOF.\n");
static PyObject *
stringio_read(stringio *self, PyObject *args)
{
Py_ssize_t size, n;
Py_UNICODE *output;
PyObject *arg = Py_None;
CHECK_INITIALIZED(self);
if (!PyArg_ParseTuple(args, "|O:read", &arg))
return NULL;
CHECK_CLOSED(self);
if (PyNumber_Check(arg)) {
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* Read until EOF is reached, by default. */
size = -1;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
/* adjust invalid sizes */
n = self->string_size - self->pos;
if (size < 0 || size > n) {
size = n;
if (size < 0)
size = 0;
}
output = self->buf + self->pos;
self->pos += size;
return PyUnicode_FromUnicode(output, size);
}
/* Internal helper, used by stringio_readline and stringio_iternext */
static PyObject *
_stringio_readline(stringio *self, Py_ssize_t limit)
{
Py_UNICODE *start, *end, old_char;
Py_ssize_t len, consumed;
/* In case of overseek, return the empty string */
if (self->pos >= self->string_size)
return PyUnicode_FromString("");
start = self->buf + self->pos;
if (limit < 0 || limit > self->string_size - self->pos)
limit = self->string_size - self->pos;
end = start + limit;
old_char = *end;
*end = '\0';
len = _PyIO_find_line_ending(
self->readtranslate, self->readuniversal, self->readnl,
start, end, &consumed);
*end = old_char;
/* If we haven't found any line ending, we just return everything
(`consumed` is ignored). */
if (len < 0)
len = limit;
self->pos += len;
return PyUnicode_FromUnicode(start, len);
}
PyDoc_STRVAR(stringio_readline_doc,
"Read until newline or EOF.\n"
"\n"
"Returns an empty string if EOF is hit immediately.\n");
static PyObject *
stringio_readline(stringio *self, PyObject *args)
{
PyObject *arg = Py_None;
Py_ssize_t limit = -1;
CHECK_INITIALIZED(self);
if (!PyArg_ParseTuple(args, "|O:readline", &arg))
return NULL;
CHECK_CLOSED(self);
if (PyNumber_Check(arg)) {
limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (limit == -1 && PyErr_Occurred())
return NULL;
}
else if (arg != Py_None) {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
return _stringio_readline(self, limit);
}
static PyObject *
stringio_iternext(stringio *self)
{
PyObject *line;
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
if (Py_TYPE(self) == &PyStringIO_Type) {
/* Skip method call overhead for speed */
line = _stringio_readline(self, -1);
}
else {
/* XXX is subclassing StringIO really supported? */
line = PyObject_CallMethodObjArgs((PyObject *)self,
_PyIO_str_readline, NULL);
if (line && !PyUnicode_Check(line)) {
PyErr_Format(PyExc_IOError,
"readline() should have returned an str object, "
"not '%.200s'", Py_TYPE(line)->tp_name);
Py_DECREF(line);
return NULL;
}
}
if (line == NULL)
return NULL;
if (PyUnicode_GET_SIZE(line) == 0) {
/* Reached EOF */
Py_DECREF(line);
return NULL;
}
return line;
}
PyDoc_STRVAR(stringio_truncate_doc,
"Truncate size to pos.\n"
"\n"
"The pos argument defaults to the current file position, as\n"
"returned by tell(). The current file position is unchanged.\n"
"Returns the new absolute position.\n");
static PyObject *
stringio_truncate(stringio *self, PyObject *args)
{
Py_ssize_t size;
PyObject *arg = Py_None;
CHECK_INITIALIZED(self);
if (!PyArg_ParseTuple(args, "|O:truncate", &arg))
return NULL;
CHECK_CLOSED(self);
if (PyNumber_Check(arg)) {
size = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
if (size == -1 && PyErr_Occurred())
return NULL;
}
else if (arg == Py_None) {
/* Truncate to current position if no argument is passed. */
size = self->pos;
}
else {
PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'",
Py_TYPE(arg)->tp_name);
return NULL;
}
if (size < 0) {
PyErr_Format(PyExc_ValueError,
"Negative size value %zd", size);
return NULL;
}
if (size < self->string_size) {
if (resize_buffer(self, size) < 0)
return NULL;
self->string_size = size;
}
return PyLong_FromSsize_t(size);
}
PyDoc_STRVAR(stringio_seek_doc,
"Change stream position.\n"
"\n"
"Seek to character offset pos relative to position indicated by whence:\n"
" 0 Start of stream (the default). pos should be >= 0;\n"
" 1 Current position - pos must be 0;\n"
" 2 End of stream - pos must be 0.\n"
"Returns the new absolute position.\n");
static PyObject *
stringio_seek(stringio *self, PyObject *args)
{
PyObject *posobj;
Py_ssize_t pos;
int mode = 0;
CHECK_INITIALIZED(self);
if (!PyArg_ParseTuple(args, "O|i:seek", &posobj, &mode))
return NULL;
pos = PyNumber_AsSsize_t(posobj, PyExc_OverflowError);
if (pos == -1 && PyErr_Occurred())
return NULL;
CHECK_CLOSED(self);
if (mode != 0 && mode != 1 && mode != 2) {
PyErr_Format(PyExc_ValueError,
"Invalid whence (%i, should be 0, 1 or 2)", mode);
return NULL;
}
else if (pos < 0 && mode == 0) {
PyErr_Format(PyExc_ValueError,
"Negative seek position %zd", pos);
return NULL;
}
else if (mode != 0 && pos != 0) {
PyErr_SetString(PyExc_IOError,
"Can't do nonzero cur-relative seeks");
return NULL;
}
/* mode 0: offset relative to beginning of the string.
mode 1: no change to current position.
mode 2: change position to end of file. */
if (mode == 1) {
pos = self->pos;
}
else if (mode == 2) {
pos = self->string_size;
}
self->pos = pos;
return PyLong_FromSsize_t(self->pos);
}
PyDoc_STRVAR(stringio_write_doc,
"Write string to file.\n"
"\n"
"Returns the number of characters written, which is always equal to\n"
"the length of the string.\n");
static PyObject *
stringio_write(stringio *self, PyObject *obj)
{
Py_ssize_t size;
CHECK_INITIALIZED(self);
if (!PyUnicode_Check(obj)) {
PyErr_Format(PyExc_TypeError, "string argument expected, got '%s'",
Py_TYPE(obj)->tp_name);
return NULL;
}
CHECK_CLOSED(self);
size = PyUnicode_GET_SIZE(obj);
if (size > 0 && write_str(self, obj) < 0)
return NULL;
return PyLong_FromSsize_t(size);
}
PyDoc_STRVAR(stringio_close_doc,
"Close the IO object. Attempting any further operation after the\n"
"object is closed will raise a ValueError.\n"
"\n"
"This method has no effect if the file is already closed.\n");
static PyObject *
stringio_close(stringio *self)
{
self->closed = 1;
/* Free up some memory */
if (resize_buffer(self, 0) < 0)
return NULL;
Py_CLEAR(self->readnl);
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
Py_RETURN_NONE;
}
static int
stringio_traverse(stringio *self, visitproc visit, void *arg)
{
Py_VISIT(self->dict);
return 0;
}
static int
stringio_clear(stringio *self)
{
Py_CLEAR(self->dict);
return 0;
}
static void
stringio_dealloc(stringio *self)
{
_PyObject_GC_UNTRACK(self);
self->ok = 0;
if (self->buf) {
PyMem_Free(self->buf);
self->buf = NULL;
}
Py_CLEAR(self->readnl);
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
Py_CLEAR(self->dict);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_TYPE(self)->tp_free(self);
}
static PyObject *
stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
stringio *self;
assert(type != NULL && type->tp_alloc != NULL);
self = (stringio *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
/* tp_alloc initializes all the fields to zero. So we don't have to
initialize them here. */
self->buf = (Py_UNICODE *)PyMem_Malloc(0);
if (self->buf == NULL) {
Py_DECREF(self);
return PyErr_NoMemory();
}
return (PyObject *)self;
}
static int
stringio_init(stringio *self, PyObject *args, PyObject *kwds)
{
char *kwlist[] = {"initial_value", "newline", NULL};
PyObject *value = NULL;
char *newline = "\n";
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oz:__init__", kwlist,
&value, &newline))
return -1;
if (newline && newline[0] != '\0'
&& !(newline[0] == '\n' && newline[1] == '\0')
&& !(newline[0] == '\r' && newline[1] == '\0')
&& !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
PyErr_Format(PyExc_ValueError,
"illegal newline value: %s", newline);
return -1;
}
if (value && value != Py_None && !PyUnicode_Check(value)) {
PyErr_Format(PyExc_TypeError,
"initial_value must be unicode or None, not %.200s",
Py_TYPE(value)->tp_name);
return -1;
}
self->ok = 0;
Py_CLEAR(self->readnl);
Py_CLEAR(self->writenl);
Py_CLEAR(self->decoder);
if (newline) {
self->readnl = PyString_FromString(newline);
if (self->readnl == NULL)
return -1;
}
self->readuniversal = (newline == NULL || newline[0] == '\0');
self->readtranslate = (newline == NULL);
/* If newline == "", we don't translate anything.
If newline == "\n" or newline == None, we translate to "\n", which is
a no-op.
(for newline == None, TextIOWrapper translates to os.sepline, but it
is pointless for StringIO)
*/
if (newline != NULL && newline[0] == '\r') {
self->writenl = PyUnicode_FromString(newline);
}
if (self->readuniversal) {
self->decoder = PyObject_CallFunction(
(PyObject *)&PyIncrementalNewlineDecoder_Type,
"Oi", Py_None, (int) self->readtranslate);
if (self->decoder == NULL)
return -1;
}
/* Now everything is set up, resize buffer to size of initial value,
and copy it */
self->string_size = 0;
if (value && value != Py_None) {
Py_ssize_t len = PyUnicode_GetSize(value);
/* This is a heuristic, for newline translation might change
the string length. */
if (resize_buffer(self, len) < 0)
return -1;
self->pos = 0;
if (write_str(self, value) < 0)
return -1;
}
else {
if (resize_buffer(self, 0) < 0)
return -1;
}
self->pos = 0;
self->closed = 0;
self->ok = 1;
return 0;
}
/* Properties and pseudo-properties */
static PyObject *
stringio_seekable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
Py_RETURN_TRUE;
}
static PyObject *
stringio_readable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
Py_RETURN_TRUE;
}
static PyObject *
stringio_writable(stringio *self, PyObject *args)
{
CHECK_INITIALIZED(self);
Py_RETURN_TRUE;
}
/* Pickling support.
The implementation of __getstate__ is similar to the one for BytesIO,
except that we also save the newline parameter. For __setstate__ and unlike
BytesIO, we call __init__ to restore the object's state. Doing so allows us
to avoid decoding the complex newline state while keeping the object
representation compact.
See comment in bytesio.c regarding why only pickle protocols and onward are
supported.
*/
static PyObject *
stringio_getstate(stringio *self)
{
PyObject *initvalue = stringio_getvalue(self);
PyObject *dict;
PyObject *state;
if (initvalue == NULL)
return NULL;
if (self->dict == NULL) {
Py_INCREF(Py_None);
dict = Py_None;
}
else {
dict = PyDict_Copy(self->dict);
if (dict == NULL)
return NULL;
}
state = Py_BuildValue("(OOnN)", initvalue,
self->readnl ? self->readnl : Py_None,
self->pos, dict);
Py_DECREF(initvalue);
return state;
}
static PyObject *
stringio_setstate(stringio *self, PyObject *state)
{
PyObject *initarg;
PyObject *position_obj;
PyObject *dict;
Py_ssize_t pos;
assert(state != NULL);
CHECK_CLOSED(self);
/* We allow the state tuple to be longer than 4, because we may need
someday to extend the object's state without breaking
backward-compatibility. */
if (!PyTuple_Check(state) || Py_SIZE(state) < 4) {
PyErr_Format(PyExc_TypeError,
"%.200s.__setstate__ argument should be 4-tuple, got %.200s",
Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name);
return NULL;
}
/* Initialize the object's state. */
initarg = PyTuple_GetSlice(state, 0, 2);
if (initarg == NULL)
return NULL;
if (stringio_init(self, initarg, NULL) < 0) {
Py_DECREF(initarg);
return NULL;
}
Py_DECREF(initarg);
/* Restore the buffer state. Even if __init__ did initialize the buffer,
we have to initialize it again since __init__ may translates the
newlines in the inital_value string. We clearly do not want that
because the string value in the state tuple has already been translated
once by __init__. So we do not take any chance and replace object's
buffer completely. */
{
Py_UNICODE *buf = PyUnicode_AS_UNICODE(PyTuple_GET_ITEM(state, 0));
Py_ssize_t bufsize = PyUnicode_GET_SIZE(PyTuple_GET_ITEM(state, 0));
if (resize_buffer(self, bufsize) < 0)
return NULL;
memcpy(self->buf, buf, bufsize * sizeof(Py_UNICODE));
self->string_size = bufsize;
}
/* Set carefully the position value. Alternatively, we could use the seek
method instead of modifying self->pos directly to better protect the
object internal state against errneous (or malicious) inputs. */
position_obj = PyTuple_GET_ITEM(state, 2);
if (!PyIndex_Check(position_obj)) {
PyErr_Format(PyExc_TypeError,
"third item of state must be an integer, got %.200s",
Py_TYPE(position_obj)->tp_name);
return NULL;
}
pos = PyNumber_AsSsize_t(position_obj, PyExc_OverflowError);
if (pos == -1 && PyErr_Occurred())
return NULL;
if (pos < 0) {
PyErr_SetString(PyExc_ValueError,
"position value cannot be negative");
return NULL;
}
self->pos = pos;
/* Set the dictionary of the instance variables. */
dict = PyTuple_GET_ITEM(state, 3);
if (dict != Py_None) {
if (!PyDict_Check(dict)) {
PyErr_Format(PyExc_TypeError,
"fourth item of state should be a dict, got a %.200s",
Py_TYPE(dict)->tp_name);
return NULL;
}
if (self->dict) {
/* Alternatively, we could replace the internal dictionary
completely. However, it seems more practical to just update it. */
if (PyDict_Update(self->dict, dict) < 0)
return NULL;
}
else {
Py_INCREF(dict);
self->dict = dict;
}
}
Py_RETURN_NONE;
}
static PyObject *
stringio_closed(stringio *self, void *context)
{
CHECK_INITIALIZED(self);
return PyBool_FromLong(self->closed);
}
static PyObject *
stringio_line_buffering(stringio *self, void *context)
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
Py_RETURN_FALSE;
}
static PyObject *
stringio_newlines(stringio *self, void *context)
{
CHECK_INITIALIZED(self);
CHECK_CLOSED(self);
if (self->decoder == NULL)
Py_RETURN_NONE;
return PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
}
static struct PyMethodDef stringio_methods[] = {
{"close", (PyCFunction)stringio_close, METH_NOARGS, stringio_close_doc},
{"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS, stringio_getvalue_doc},
{"read", (PyCFunction)stringio_read, METH_VARARGS, stringio_read_doc},
{"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc},
{"tell", (PyCFunction)stringio_tell, METH_NOARGS, stringio_tell_doc},
{"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc},
{"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc},
{"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc},
{"seekable", (PyCFunction)stringio_seekable, METH_NOARGS},
{"readable", (PyCFunction)stringio_readable, METH_NOARGS},
{"writable", (PyCFunction)stringio_writable, METH_NOARGS},
{"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS},
{"__setstate__", (PyCFunction)stringio_setstate, METH_O},
{NULL, NULL} /* sentinel */
};
static PyGetSetDef stringio_getset[] = {
{"closed", (getter)stringio_closed, NULL, NULL},
{"newlines", (getter)stringio_newlines, NULL, NULL},
/* (following comments straight off of the original Python wrapper:)
XXX Cruft to support the TextIOWrapper API. This would only
be meaningful if StringIO supported the buffer attribute.
Hopefully, a better solution, than adding these pseudo-attributes,
will be found.
*/
{"line_buffering", (getter)stringio_line_buffering, NULL, NULL},
{NULL}
};
PyTypeObject PyStringIO_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io.StringIO", /*tp_name*/
sizeof(stringio), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)stringio_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_reserved*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_GC, /*tp_flags*/
stringio_doc, /*tp_doc*/
(traverseproc)stringio_traverse, /*tp_traverse*/
(inquiry)stringio_clear, /*tp_clear*/
0, /*tp_richcompare*/
offsetof(stringio, weakreflist), /*tp_weaklistoffset*/
0, /*tp_iter*/
(iternextfunc)stringio_iternext, /*tp_iternext*/
stringio_methods, /*tp_methods*/
0, /*tp_members*/
stringio_getset, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
offsetof(stringio, dict), /*tp_dictoffset*/
(initproc)stringio_init, /*tp_init*/
0, /*tp_alloc*/
stringio_new, /*tp_new*/
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,758 @@
/***********************************************************
Copyright (C) 1997, 2002, 2003 Martin von Loewis
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies.
This software comes with no warranty. Use at your own risk.
******************************************************************/
#include "Python.h"
#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif
#ifdef HAVE_LIBINTL_H
#include <libintl.h>
#endif
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif
#if defined(MS_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#ifdef RISCOS
char *strdup(const char *);
#endif
PyDoc_STRVAR(locale__doc__, "Support for POSIX locales.");
static PyObject *Error;
/* support functions for formatting floating point numbers */
PyDoc_STRVAR(setlocale__doc__,
"(integer,string=None) -> string. Activates/queries locale processing.");
/* the grouping is terminated by either 0 or CHAR_MAX */
static PyObject*
copy_grouping(char* s)
{
int i;
PyObject *result, *val = NULL;
if (s[0] == '\0')
/* empty string: no grouping at all */
return PyList_New(0);
for (i = 0; s[i] != '\0' && s[i] != CHAR_MAX; i++)
; /* nothing */
result = PyList_New(i+1);
if (!result)
return NULL;
i = -1;
do {
i++;
val = PyInt_FromLong(s[i]);
if (!val)
break;
if (PyList_SetItem(result, i, val)) {
Py_DECREF(val);
val = NULL;
break;
}
} while (s[i] != '\0' && s[i] != CHAR_MAX);
if (!val) {
Py_DECREF(result);
return NULL;
}
return result;
}
static void
fixup_ulcase(void)
{
PyObject *mods, *strop, *string, *ulo;
unsigned char ul[256];
int n, c;
/* find the string and strop modules */
mods = PyImport_GetModuleDict();
if (!mods)
return;
string = PyDict_GetItemString(mods, "string");
if (string)
string = PyModule_GetDict(string);
strop=PyDict_GetItemString(mods, "strop");
if (strop)
strop = PyModule_GetDict(strop);
if (!string && !strop)
return;
/* create uppercase map string */
n = 0;
for (c = 0; c < 256; c++) {
if (isupper(c))
ul[n++] = c;
}
ulo = PyString_FromStringAndSize((const char *)ul, n);
if (!ulo)
return;
if (string)
PyDict_SetItemString(string, "uppercase", ulo);
if (strop)
PyDict_SetItemString(strop, "uppercase", ulo);
Py_DECREF(ulo);
/* create lowercase string */
n = 0;
for (c = 0; c < 256; c++) {
if (islower(c))
ul[n++] = c;
}
ulo = PyString_FromStringAndSize((const char *)ul, n);
if (!ulo)
return;
if (string)
PyDict_SetItemString(string, "lowercase", ulo);
if (strop)
PyDict_SetItemString(strop, "lowercase", ulo);
Py_DECREF(ulo);
/* create letters string */
n = 0;
for (c = 0; c < 256; c++) {
if (isalpha(c))
ul[n++] = c;
}
ulo = PyString_FromStringAndSize((const char *)ul, n);
if (!ulo)
return;
if (string)
PyDict_SetItemString(string, "letters", ulo);
Py_DECREF(ulo);
}
static PyObject*
PyLocale_setlocale(PyObject* self, PyObject* args)
{
int category;
char *locale = NULL, *result;
PyObject *result_object;
if (!PyArg_ParseTuple(args, "i|z:setlocale", &category, &locale))
return NULL;
#if defined(MS_WINDOWS)
if (category < LC_MIN || category > LC_MAX)
{
PyErr_SetString(Error, "invalid locale category");
return NULL;
}
#endif
if (locale) {
/* set locale */
result = setlocale(category, locale);
if (!result) {
/* operation failed, no setting was changed */
PyErr_SetString(Error, "unsupported locale setting");
return NULL;
}
result_object = PyString_FromString(result);
if (!result_object)
return NULL;
/* record changes to LC_CTYPE */
if (category == LC_CTYPE || category == LC_ALL)
fixup_ulcase();
/* things that got wrong up to here are ignored */
PyErr_Clear();
} else {
/* get locale */
result = setlocale(category, NULL);
if (!result) {
PyErr_SetString(Error, "locale query failed");
return NULL;
}
result_object = PyString_FromString(result);
}
return result_object;
}
PyDoc_STRVAR(localeconv__doc__,
"() -> dict. Returns numeric and monetary locale-specific parameters.");
static PyObject*
PyLocale_localeconv(PyObject* self)
{
PyObject* result;
struct lconv *l;
PyObject *x;
result = PyDict_New();
if (!result)
return NULL;
/* if LC_NUMERIC is different in the C library, use saved value */
l = localeconv();
/* hopefully, the localeconv result survives the C library calls
involved herein */
#define RESULT_STRING(s)\
x = PyString_FromString(l->s);\
if (!x) goto failed;\
PyDict_SetItemString(result, #s, x);\
Py_XDECREF(x)
#define RESULT_INT(i)\
x = PyInt_FromLong(l->i);\
if (!x) goto failed;\
PyDict_SetItemString(result, #i, x);\
Py_XDECREF(x)
/* Numeric information */
RESULT_STRING(decimal_point);
RESULT_STRING(thousands_sep);
x = copy_grouping(l->grouping);
if (!x)
goto failed;
PyDict_SetItemString(result, "grouping", x);
Py_XDECREF(x);
/* Monetary information */
RESULT_STRING(int_curr_symbol);
RESULT_STRING(currency_symbol);
RESULT_STRING(mon_decimal_point);
RESULT_STRING(mon_thousands_sep);
x = copy_grouping(l->mon_grouping);
if (!x)
goto failed;
PyDict_SetItemString(result, "mon_grouping", x);
Py_XDECREF(x);
RESULT_STRING(positive_sign);
RESULT_STRING(negative_sign);
RESULT_INT(int_frac_digits);
RESULT_INT(frac_digits);
RESULT_INT(p_cs_precedes);
RESULT_INT(p_sep_by_space);
RESULT_INT(n_cs_precedes);
RESULT_INT(n_sep_by_space);
RESULT_INT(p_sign_posn);
RESULT_INT(n_sign_posn);
return result;
failed:
Py_XDECREF(result);
Py_XDECREF(x);
return NULL;
}
PyDoc_STRVAR(strcoll__doc__,
"string,string -> int. Compares two strings according to the locale.");
static PyObject*
PyLocale_strcoll(PyObject* self, PyObject* args)
{
#if !defined(HAVE_WCSCOLL) || !defined(Py_USING_UNICODE)
char *s1,*s2;
if (!PyArg_ParseTuple(args, "ss:strcoll", &s1, &s2))
return NULL;
return PyInt_FromLong(strcoll(s1, s2));
#else
PyObject *os1, *os2, *result = NULL;
wchar_t *ws1 = NULL, *ws2 = NULL;
int rel1 = 0, rel2 = 0, len1, len2;
if (!PyArg_UnpackTuple(args, "strcoll", 2, 2, &os1, &os2))
return NULL;
/* If both arguments are byte strings, use strcoll. */
if (PyString_Check(os1) && PyString_Check(os2))
return PyInt_FromLong(strcoll(PyString_AS_STRING(os1),
PyString_AS_STRING(os2)));
/* If neither argument is unicode, it's an error. */
if (!PyUnicode_Check(os1) && !PyUnicode_Check(os2)) {
PyErr_SetString(PyExc_ValueError, "strcoll arguments must be strings");
}
/* Convert the non-unicode argument to unicode. */
if (!PyUnicode_Check(os1)) {
os1 = PyUnicode_FromObject(os1);
if (!os1)
return NULL;
rel1 = 1;
}
if (!PyUnicode_Check(os2)) {
os2 = PyUnicode_FromObject(os2);
if (!os2) {
if (rel1) {
Py_DECREF(os1);
}
return NULL;
}
rel2 = 1;
}
/* Convert the unicode strings to wchar[]. */
len1 = PyUnicode_GET_SIZE(os1) + 1;
ws1 = PyMem_MALLOC(len1 * sizeof(wchar_t));
if (!ws1) {
PyErr_NoMemory();
goto done;
}
if (PyUnicode_AsWideChar((PyUnicodeObject*)os1, ws1, len1) == -1)
goto done;
ws1[len1 - 1] = 0;
len2 = PyUnicode_GET_SIZE(os2) + 1;
ws2 = PyMem_MALLOC(len2 * sizeof(wchar_t));
if (!ws2) {
PyErr_NoMemory();
goto done;
}
if (PyUnicode_AsWideChar((PyUnicodeObject*)os2, ws2, len2) == -1)
goto done;
ws2[len2 - 1] = 0;
/* Collate the strings. */
result = PyInt_FromLong(wcscoll(ws1, ws2));
done:
/* Deallocate everything. */
if (ws1) PyMem_FREE(ws1);
if (ws2) PyMem_FREE(ws2);
if (rel1) {
Py_DECREF(os1);
}
if (rel2) {
Py_DECREF(os2);
}
return result;
#endif
}
PyDoc_STRVAR(strxfrm__doc__,
"string -> string. Returns a string that behaves for cmp locale-aware.");
static PyObject*
PyLocale_strxfrm(PyObject* self, PyObject* args)
{
char *s, *buf;
size_t n1, n2;
PyObject *result;
if (!PyArg_ParseTuple(args, "s:strxfrm", &s))
return NULL;
/* assume no change in size, first */
n1 = strlen(s) + 1;
buf = PyMem_Malloc(n1);
if (!buf)
return PyErr_NoMemory();
n2 = strxfrm(buf, s, n1) + 1;
if (n2 > n1) {
/* more space needed */
buf = PyMem_Realloc(buf, n2);
if (!buf)
return PyErr_NoMemory();
strxfrm(buf, s, n2);
}
result = PyString_FromString(buf);
PyMem_Free(buf);
return result;
}
#if defined(MS_WINDOWS)
static PyObject*
PyLocale_getdefaultlocale(PyObject* self)
{
char encoding[100];
char locale[100];
PyOS_snprintf(encoding, sizeof(encoding), "cp%d", GetACP());
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SISO639LANGNAME,
locale, sizeof(locale))) {
Py_ssize_t i = strlen(locale);
locale[i++] = '_';
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SISO3166CTRYNAME,
locale+i, (int)(sizeof(locale)-i)))
return Py_BuildValue("ss", locale, encoding);
}
/* If we end up here, this windows version didn't know about
ISO639/ISO3166 names (it's probably Windows 95). Return the
Windows language identifier instead (a hexadecimal number) */
locale[0] = '0';
locale[1] = 'x';
if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTLANGUAGE,
locale+2, sizeof(locale)-2)) {
return Py_BuildValue("ss", locale, encoding);
}
/* cannot determine the language code (very unlikely) */
Py_INCREF(Py_None);
return Py_BuildValue("Os", Py_None, encoding);
}
#endif
#ifdef HAVE_LANGINFO_H
#define LANGINFO(X) {#X, X}
static struct langinfo_constant{
char* name;
int value;
} langinfo_constants[] =
{
/* These constants should exist on any langinfo implementation */
LANGINFO(DAY_1),
LANGINFO(DAY_2),
LANGINFO(DAY_3),
LANGINFO(DAY_4),
LANGINFO(DAY_5),
LANGINFO(DAY_6),
LANGINFO(DAY_7),
LANGINFO(ABDAY_1),
LANGINFO(ABDAY_2),
LANGINFO(ABDAY_3),
LANGINFO(ABDAY_4),
LANGINFO(ABDAY_5),
LANGINFO(ABDAY_6),
LANGINFO(ABDAY_7),
LANGINFO(MON_1),
LANGINFO(MON_2),
LANGINFO(MON_3),
LANGINFO(MON_4),
LANGINFO(MON_5),
LANGINFO(MON_6),
LANGINFO(MON_7),
LANGINFO(MON_8),
LANGINFO(MON_9),
LANGINFO(MON_10),
LANGINFO(MON_11),
LANGINFO(MON_12),
LANGINFO(ABMON_1),
LANGINFO(ABMON_2),
LANGINFO(ABMON_3),
LANGINFO(ABMON_4),
LANGINFO(ABMON_5),
LANGINFO(ABMON_6),
LANGINFO(ABMON_7),
LANGINFO(ABMON_8),
LANGINFO(ABMON_9),
LANGINFO(ABMON_10),
LANGINFO(ABMON_11),
LANGINFO(ABMON_12),
#ifdef RADIXCHAR
/* The following are not available with glibc 2.0 */
LANGINFO(RADIXCHAR),
LANGINFO(THOUSEP),
/* YESSTR and NOSTR are deprecated in glibc, since they are
a special case of message translation, which should be rather
done using gettext. So we don't expose it to Python in the
first place.
LANGINFO(YESSTR),
LANGINFO(NOSTR),
*/
LANGINFO(CRNCYSTR),
#endif
LANGINFO(D_T_FMT),
LANGINFO(D_FMT),
LANGINFO(T_FMT),
LANGINFO(AM_STR),
LANGINFO(PM_STR),
/* The following constants are available only with XPG4, but...
AIX 3.2. only has CODESET.
OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have
a few of the others.
Solution: ifdef-test them all. */
#ifdef CODESET
LANGINFO(CODESET),
#endif
#ifdef T_FMT_AMPM
LANGINFO(T_FMT_AMPM),
#endif
#ifdef ERA
LANGINFO(ERA),
#endif
#ifdef ERA_D_FMT
LANGINFO(ERA_D_FMT),
#endif
#ifdef ERA_D_T_FMT
LANGINFO(ERA_D_T_FMT),
#endif
#ifdef ERA_T_FMT
LANGINFO(ERA_T_FMT),
#endif
#ifdef ALT_DIGITS
LANGINFO(ALT_DIGITS),
#endif
#ifdef YESEXPR
LANGINFO(YESEXPR),
#endif
#ifdef NOEXPR
LANGINFO(NOEXPR),
#endif
#ifdef _DATE_FMT
/* This is not available in all glibc versions that have CODESET. */
LANGINFO(_DATE_FMT),
#endif
{0, 0}
};
PyDoc_STRVAR(nl_langinfo__doc__,
"nl_langinfo(key) -> string\n"
"Return the value for the locale information associated with key.");
static PyObject*
PyLocale_nl_langinfo(PyObject* self, PyObject* args)
{
int item, i;
if (!PyArg_ParseTuple(args, "i:nl_langinfo", &item))
return NULL;
/* Check whether this is a supported constant. GNU libc sometimes
returns numeric values in the char* return value, which would
crash PyString_FromString. */
for (i = 0; langinfo_constants[i].name; i++)
if (langinfo_constants[i].value == item) {
/* Check NULL as a workaround for GNU libc's returning NULL
instead of an empty string for nl_langinfo(ERA). */
const char *result = nl_langinfo(item);
return PyString_FromString(result != NULL ? result : "");
}
PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant");
return NULL;
}
#endif /* HAVE_LANGINFO_H */
#ifdef HAVE_LIBINTL_H
PyDoc_STRVAR(gettext__doc__,
"gettext(msg) -> string\n"
"Return translation of msg.");
static PyObject*
PyIntl_gettext(PyObject* self, PyObject *args)
{
char *in;
if (!PyArg_ParseTuple(args, "s", &in))
return 0;
return PyString_FromString(gettext(in));
}
PyDoc_STRVAR(dgettext__doc__,
"dgettext(domain, msg) -> string\n"
"Return translation of msg in domain.");
static PyObject*
PyIntl_dgettext(PyObject* self, PyObject *args)
{
char *domain, *in;
if (!PyArg_ParseTuple(args, "zs", &domain, &in))
return 0;
return PyString_FromString(dgettext(domain, in));
}
PyDoc_STRVAR(dcgettext__doc__,
"dcgettext(domain, msg, category) -> string\n"
"Return translation of msg in domain and category.");
static PyObject*
PyIntl_dcgettext(PyObject *self, PyObject *args)
{
char *domain, *msgid;
int category;
if (!PyArg_ParseTuple(args, "zsi", &domain, &msgid, &category))
return 0;
return PyString_FromString(dcgettext(domain,msgid,category));
}
PyDoc_STRVAR(textdomain__doc__,
"textdomain(domain) -> string\n"
"Set the C library's textdmain to domain, returning the new domain.");
static PyObject*
PyIntl_textdomain(PyObject* self, PyObject* args)
{
char *domain;
if (!PyArg_ParseTuple(args, "z", &domain))
return 0;
domain = textdomain(domain);
if (!domain) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyString_FromString(domain);
}
PyDoc_STRVAR(bindtextdomain__doc__,
"bindtextdomain(domain, dir) -> string\n"
"Bind the C library's domain to dir.");
static PyObject*
PyIntl_bindtextdomain(PyObject* self,PyObject*args)
{
char *domain, *dirname;
if (!PyArg_ParseTuple(args, "sz", &domain, &dirname))
return 0;
if (!strlen(domain)) {
PyErr_SetString(Error, "domain must be a non-empty string");
return 0;
}
dirname = bindtextdomain(domain, dirname);
if (!dirname) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyString_FromString(dirname);
}
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
PyDoc_STRVAR(bind_textdomain_codeset__doc__,
"bind_textdomain_codeset(domain, codeset) -> string\n"
"Bind the C library's domain to codeset.");
static PyObject*
PyIntl_bind_textdomain_codeset(PyObject* self,PyObject*args)
{
char *domain,*codeset;
if (!PyArg_ParseTuple(args, "sz", &domain, &codeset))
return NULL;
codeset = bind_textdomain_codeset(domain, codeset);
if (codeset)
return PyString_FromString(codeset);
Py_RETURN_NONE;
}
#endif
#endif
static struct PyMethodDef PyLocale_Methods[] = {
{"setlocale", (PyCFunction) PyLocale_setlocale,
METH_VARARGS, setlocale__doc__},
{"localeconv", (PyCFunction) PyLocale_localeconv,
METH_NOARGS, localeconv__doc__},
{"strcoll", (PyCFunction) PyLocale_strcoll,
METH_VARARGS, strcoll__doc__},
{"strxfrm", (PyCFunction) PyLocale_strxfrm,
METH_VARARGS, strxfrm__doc__},
#if defined(MS_WINDOWS)
{"_getdefaultlocale", (PyCFunction) PyLocale_getdefaultlocale, METH_NOARGS},
#endif
#ifdef HAVE_LANGINFO_H
{"nl_langinfo", (PyCFunction) PyLocale_nl_langinfo,
METH_VARARGS, nl_langinfo__doc__},
#endif
#ifdef HAVE_LIBINTL_H
{"gettext",(PyCFunction)PyIntl_gettext,METH_VARARGS,
gettext__doc__},
{"dgettext",(PyCFunction)PyIntl_dgettext,METH_VARARGS,
dgettext__doc__},
{"dcgettext",(PyCFunction)PyIntl_dcgettext,METH_VARARGS,
dcgettext__doc__},
{"textdomain",(PyCFunction)PyIntl_textdomain,METH_VARARGS,
textdomain__doc__},
{"bindtextdomain",(PyCFunction)PyIntl_bindtextdomain,METH_VARARGS,
bindtextdomain__doc__},
#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
{"bind_textdomain_codeset",(PyCFunction)PyIntl_bind_textdomain_codeset,
METH_VARARGS, bind_textdomain_codeset__doc__},
#endif
#endif
{NULL, NULL}
};
PyMODINIT_FUNC
init_locale(void)
{
PyObject *m, *d, *x;
#ifdef HAVE_LANGINFO_H
int i;
#endif
m = Py_InitModule("_locale", PyLocale_Methods);
if (m == NULL)
return;
d = PyModule_GetDict(m);
x = PyInt_FromLong(LC_CTYPE);
PyDict_SetItemString(d, "LC_CTYPE", x);
Py_XDECREF(x);
x = PyInt_FromLong(LC_TIME);
PyDict_SetItemString(d, "LC_TIME", x);
Py_XDECREF(x);
x = PyInt_FromLong(LC_COLLATE);
PyDict_SetItemString(d, "LC_COLLATE", x);
Py_XDECREF(x);
x = PyInt_FromLong(LC_MONETARY);
PyDict_SetItemString(d, "LC_MONETARY", x);
Py_XDECREF(x);
#ifdef LC_MESSAGES
x = PyInt_FromLong(LC_MESSAGES);
PyDict_SetItemString(d, "LC_MESSAGES", x);
Py_XDECREF(x);
#endif /* LC_MESSAGES */
x = PyInt_FromLong(LC_NUMERIC);
PyDict_SetItemString(d, "LC_NUMERIC", x);
Py_XDECREF(x);
x = PyInt_FromLong(LC_ALL);
PyDict_SetItemString(d, "LC_ALL", x);
Py_XDECREF(x);
x = PyInt_FromLong(CHAR_MAX);
PyDict_SetItemString(d, "CHAR_MAX", x);
Py_XDECREF(x);
Error = PyErr_NewException("locale.Error", NULL, NULL);
PyDict_SetItemString(d, "Error", Error);
x = PyString_FromString(locale__doc__);
PyDict_SetItemString(d, "__doc__", x);
Py_XDECREF(x);
#ifdef HAVE_LANGINFO_H
for (i = 0; langinfo_constants[i].name; i++) {
PyModule_AddIntConstant(m, langinfo_constants[i].name,
langinfo_constants[i].value);
}
#endif
}
/*
Local variables:
c-basic-offset: 4
indent-tabs-mode: nil
End:
*/

View File

@@ -0,0 +1,892 @@
#include "Python.h"
#include "compile.h"
#include "frameobject.h"
#include "structseq.h"
#include "rotatingtree.h"
#if !defined(HAVE_LONG_LONG)
#error "This module requires long longs!"
#endif
/*** Selection of a high-precision timer ***/
#ifdef MS_WINDOWS
#include <windows.h>
static PY_LONG_LONG
hpTimer(void)
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return li.QuadPart;
}
static double
hpTimerUnit(void)
{
LARGE_INTEGER li;
if (QueryPerformanceFrequency(&li))
return 1.0 / li.QuadPart;
else
return 0.000001; /* unlikely */
}
#else /* !MS_WINDOWS */
#ifndef HAVE_GETTIMEOFDAY
#error "This module requires gettimeofday() on non-Windows platforms!"
#endif
#if (defined(PYOS_OS2) && defined(PYCC_GCC))
#include <sys/time.h>
#else
#include <sys/resource.h>
#include <sys/times.h>
#endif
static PY_LONG_LONG
hpTimer(void)
{
struct timeval tv;
PY_LONG_LONG ret;
#ifdef GETTIMEOFDAY_NO_TZ
gettimeofday(&tv);
#else
gettimeofday(&tv, (struct timezone *)NULL);
#endif
ret = tv.tv_sec;
ret = ret * 1000000 + tv.tv_usec;
return ret;
}
static double
hpTimerUnit(void)
{
return 0.000001;
}
#endif /* MS_WINDOWS */
/************************************************************/
/* Written by Brett Rosen and Ted Czotter */
struct _ProfilerEntry;
/* represents a function called from another function */
typedef struct _ProfilerSubEntry {
rotating_node_t header;
PY_LONG_LONG tt;
PY_LONG_LONG it;
long callcount;
long recursivecallcount;
long recursionLevel;
} ProfilerSubEntry;
/* represents a function or user defined block */
typedef struct _ProfilerEntry {
rotating_node_t header;
PyObject *userObj; /* PyCodeObject, or a descriptive str for builtins */
PY_LONG_LONG tt; /* total time in this entry */
PY_LONG_LONG it; /* inline time in this entry (not in subcalls) */
long callcount; /* how many times this was called */
long recursivecallcount; /* how many times called recursively */
long recursionLevel;
rotating_node_t *calls;
} ProfilerEntry;
typedef struct _ProfilerContext {
PY_LONG_LONG t0;
PY_LONG_LONG subt;
struct _ProfilerContext *previous;
ProfilerEntry *ctxEntry;
} ProfilerContext;
typedef struct {
PyObject_HEAD
rotating_node_t *profilerEntries;
ProfilerContext *currentProfilerContext;
ProfilerContext *freelistProfilerContext;
int flags;
PyObject *externalTimer;
double externalTimerUnit;
} ProfilerObject;
#define POF_ENABLED 0x001
#define POF_SUBCALLS 0x002
#define POF_BUILTINS 0x004
#define POF_NOMEMORY 0x100
staticforward PyTypeObject PyProfiler_Type;
#define PyProfiler_Check(op) PyObject_TypeCheck(op, &PyProfiler_Type)
#define PyProfiler_CheckExact(op) (Py_TYPE(op) == &PyProfiler_Type)
/*** External Timers ***/
#define DOUBLE_TIMER_PRECISION 4294967296.0
static PyObject *empty_tuple;
static PY_LONG_LONG CallExternalTimer(ProfilerObject *pObj)
{
PY_LONG_LONG result;
PyObject *o = PyObject_Call(pObj->externalTimer, empty_tuple, NULL);
if (o == NULL) {
PyErr_WriteUnraisable(pObj->externalTimer);
return 0;
}
if (pObj->externalTimerUnit > 0.0) {
/* interpret the result as an integer that will be scaled
in profiler_getstats() */
result = PyLong_AsLongLong(o);
}
else {
/* interpret the result as a double measured in seconds.
As the profiler works with PY_LONG_LONG internally
we convert it to a large integer */
double val = PyFloat_AsDouble(o);
/* error handling delayed to the code below */
result = (PY_LONG_LONG) (val * DOUBLE_TIMER_PRECISION);
}
Py_DECREF(o);
if (PyErr_Occurred()) {
PyErr_WriteUnraisable(pObj->externalTimer);
return 0;
}
return result;
}
#define CALL_TIMER(pObj) ((pObj)->externalTimer ? \
CallExternalTimer(pObj) : \
hpTimer())
/*** ProfilerObject ***/
static PyObject *
normalizeUserObj(PyObject *obj)
{
PyCFunctionObject *fn;
if (!PyCFunction_Check(obj)) {
Py_INCREF(obj);
return obj;
}
/* Replace built-in function objects with a descriptive string
because of built-in methods -- keeping a reference to
__self__ is probably not a good idea. */
fn = (PyCFunctionObject *)obj;
if (fn->m_self == NULL) {
/* built-in function: look up the module name */
PyObject *mod = fn->m_module;
char *modname;
if (mod && PyString_Check(mod)) {
modname = PyString_AS_STRING(mod);
}
else if (mod && PyModule_Check(mod)) {
modname = PyModule_GetName(mod);
if (modname == NULL) {
PyErr_Clear();
modname = "__builtin__";
}
}
else {
modname = "__builtin__";
}
if (strcmp(modname, "__builtin__") != 0)
return PyString_FromFormat("<%s.%s>",
modname,
fn->m_ml->ml_name);
else
return PyString_FromFormat("<%s>",
fn->m_ml->ml_name);
}
else {
/* built-in method: try to return
repr(getattr(type(__self__), __name__))
*/
PyObject *self = fn->m_self;
PyObject *name = PyString_FromString(fn->m_ml->ml_name);
if (name != NULL) {
PyObject *mo = _PyType_Lookup(Py_TYPE(self), name);
Py_XINCREF(mo);
Py_DECREF(name);
if (mo != NULL) {
PyObject *res = PyObject_Repr(mo);
Py_DECREF(mo);
if (res != NULL)
return res;
}
}
PyErr_Clear();
return PyString_FromFormat("<built-in method %s>",
fn->m_ml->ml_name);
}
}
static ProfilerEntry*
newProfilerEntry(ProfilerObject *pObj, void *key, PyObject *userObj)
{
ProfilerEntry *self;
self = (ProfilerEntry*) malloc(sizeof(ProfilerEntry));
if (self == NULL) {
pObj->flags |= POF_NOMEMORY;
return NULL;
}
userObj = normalizeUserObj(userObj);
if (userObj == NULL) {
PyErr_Clear();
free(self);
pObj->flags |= POF_NOMEMORY;
return NULL;
}
self->header.key = key;
self->userObj = userObj;
self->tt = 0;
self->it = 0;
self->callcount = 0;
self->recursivecallcount = 0;
self->recursionLevel = 0;
self->calls = EMPTY_ROTATING_TREE;
RotatingTree_Add(&pObj->profilerEntries, &self->header);
return self;
}
static ProfilerEntry*
getEntry(ProfilerObject *pObj, void *key)
{
return (ProfilerEntry*) RotatingTree_Get(&pObj->profilerEntries, key);
}
static ProfilerSubEntry *
getSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry)
{
return (ProfilerSubEntry*) RotatingTree_Get(&caller->calls,
(void *)entry);
}
static ProfilerSubEntry *
newSubEntry(ProfilerObject *pObj, ProfilerEntry *caller, ProfilerEntry* entry)
{
ProfilerSubEntry *self;
self = (ProfilerSubEntry*) malloc(sizeof(ProfilerSubEntry));
if (self == NULL) {
pObj->flags |= POF_NOMEMORY;
return NULL;
}
self->header.key = (void *)entry;
self->tt = 0;
self->it = 0;
self->callcount = 0;
self->recursivecallcount = 0;
self->recursionLevel = 0;
RotatingTree_Add(&caller->calls, &self->header);
return self;
}
static int freeSubEntry(rotating_node_t *header, void *arg)
{
ProfilerSubEntry *subentry = (ProfilerSubEntry*) header;
free(subentry);
return 0;
}
static int freeEntry(rotating_node_t *header, void *arg)
{
ProfilerEntry *entry = (ProfilerEntry*) header;
RotatingTree_Enum(entry->calls, freeSubEntry, NULL);
Py_DECREF(entry->userObj);
free(entry);
return 0;
}
static void clearEntries(ProfilerObject *pObj)
{
RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL);
pObj->profilerEntries = EMPTY_ROTATING_TREE;
/* release the memory hold by the ProfilerContexts */
if (pObj->currentProfilerContext) {
free(pObj->currentProfilerContext);
pObj->currentProfilerContext = NULL;
}
while (pObj->freelistProfilerContext) {
ProfilerContext *c = pObj->freelistProfilerContext;
pObj->freelistProfilerContext = c->previous;
free(c);
}
pObj->freelistProfilerContext = NULL;
}
static void
initContext(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
{
self->ctxEntry = entry;
self->subt = 0;
self->previous = pObj->currentProfilerContext;
pObj->currentProfilerContext = self;
++entry->recursionLevel;
if ((pObj->flags & POF_SUBCALLS) && self->previous) {
/* find or create an entry for me in my caller's entry */
ProfilerEntry *caller = self->previous->ctxEntry;
ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
if (subentry == NULL)
subentry = newSubEntry(pObj, caller, entry);
if (subentry)
++subentry->recursionLevel;
}
self->t0 = CALL_TIMER(pObj);
}
static void
Stop(ProfilerObject *pObj, ProfilerContext *self, ProfilerEntry *entry)
{
PY_LONG_LONG tt = CALL_TIMER(pObj) - self->t0;
PY_LONG_LONG it = tt - self->subt;
if (self->previous)
self->previous->subt += tt;
pObj->currentProfilerContext = self->previous;
if (--entry->recursionLevel == 0)
entry->tt += tt;
else
++entry->recursivecallcount;
entry->it += it;
entry->callcount++;
if ((pObj->flags & POF_SUBCALLS) && self->previous) {
/* find or create an entry for me in my caller's entry */
ProfilerEntry *caller = self->previous->ctxEntry;
ProfilerSubEntry *subentry = getSubEntry(pObj, caller, entry);
if (subentry) {
if (--subentry->recursionLevel == 0)
subentry->tt += tt;
else
++subentry->recursivecallcount;
subentry->it += it;
++subentry->callcount;
}
}
}
static void
ptrace_enter_call(PyObject *self, void *key, PyObject *userObj)
{
/* entering a call to the function identified by 'key'
(which can be a PyCodeObject or a PyMethodDef pointer) */
ProfilerObject *pObj = (ProfilerObject*)self;
ProfilerEntry *profEntry;
ProfilerContext *pContext;
/* In the case of entering a generator expression frame via a
* throw (gen_send_ex(.., 1)), we may already have an
* Exception set here. We must not mess around with this
* exception, and some of the code under here assumes that
* PyErr_* is its own to mess around with, so we have to
* save and restore any current exception. */
PyObject *last_type, *last_value, *last_tb;
PyErr_Fetch(&last_type, &last_value, &last_tb);
profEntry = getEntry(pObj, key);
if (profEntry == NULL) {
profEntry = newProfilerEntry(pObj, key, userObj);
if (profEntry == NULL)
goto restorePyerr;
}
/* grab a ProfilerContext out of the free list */
pContext = pObj->freelistProfilerContext;
if (pContext) {
pObj->freelistProfilerContext = pContext->previous;
}
else {
/* free list exhausted, allocate a new one */
pContext = (ProfilerContext*)
malloc(sizeof(ProfilerContext));
if (pContext == NULL) {
pObj->flags |= POF_NOMEMORY;
goto restorePyerr;
}
}
initContext(pObj, pContext, profEntry);
restorePyerr:
PyErr_Restore(last_type, last_value, last_tb);
}
static void
ptrace_leave_call(PyObject *self, void *key)
{
/* leaving a call to the function identified by 'key' */
ProfilerObject *pObj = (ProfilerObject*)self;
ProfilerEntry *profEntry;
ProfilerContext *pContext;
pContext = pObj->currentProfilerContext;
if (pContext == NULL)
return;
profEntry = getEntry(pObj, key);
if (profEntry) {
Stop(pObj, pContext, profEntry);
}
else {
pObj->currentProfilerContext = pContext->previous;
}
/* put pContext into the free list */
pContext->previous = pObj->freelistProfilerContext;
pObj->freelistProfilerContext = pContext;
}
static int
profiler_callback(PyObject *self, PyFrameObject *frame, int what,
PyObject *arg)
{
switch (what) {
/* the 'frame' of a called function is about to start its execution */
case PyTrace_CALL:
ptrace_enter_call(self, (void *)frame->f_code,
(PyObject *)frame->f_code);
break;
/* the 'frame' of a called function is about to finish
(either normally or with an exception) */
case PyTrace_RETURN:
ptrace_leave_call(self, (void *)frame->f_code);
break;
/* case PyTrace_EXCEPTION:
If the exception results in the function exiting, a
PyTrace_RETURN event will be generated, so we don't need to
handle it. */
#ifdef PyTrace_C_CALL /* not defined in Python <= 2.3 */
/* the Python function 'frame' is issuing a call to the built-in
function 'arg' */
case PyTrace_C_CALL:
if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
&& PyCFunction_Check(arg)) {
ptrace_enter_call(self,
((PyCFunctionObject *)arg)->m_ml,
arg);
}
break;
/* the call to the built-in function 'arg' is returning into its
caller 'frame' */
case PyTrace_C_RETURN: /* ...normally */
case PyTrace_C_EXCEPTION: /* ...with an exception set */
if ((((ProfilerObject *)self)->flags & POF_BUILTINS)
&& PyCFunction_Check(arg)) {
ptrace_leave_call(self,
((PyCFunctionObject *)arg)->m_ml);
}
break;
#endif
default:
break;
}
return 0;
}
static int
pending_exception(ProfilerObject *pObj)
{
if (pObj->flags & POF_NOMEMORY) {
pObj->flags -= POF_NOMEMORY;
PyErr_SetString(PyExc_MemoryError,
"memory was exhausted while profiling");
return -1;
}
return 0;
}
/************************************************************/
static PyStructSequence_Field profiler_entry_fields[] = {
{"code", "code object or built-in function name"},
{"callcount", "how many times this was called"},
{"reccallcount", "how many times called recursively"},
{"totaltime", "total time in this entry"},
{"inlinetime", "inline time in this entry (not in subcalls)"},
{"calls", "details of the calls"},
{0}
};
static PyStructSequence_Field profiler_subentry_fields[] = {
{"code", "called code object or built-in function name"},
{"callcount", "how many times this is called"},
{"reccallcount", "how many times this is called recursively"},
{"totaltime", "total time spent in this call"},
{"inlinetime", "inline time (not in further subcalls)"},
{0}
};
static PyStructSequence_Desc profiler_entry_desc = {
"_lsprof.profiler_entry", /* name */
NULL, /* doc */
profiler_entry_fields,
6
};
static PyStructSequence_Desc profiler_subentry_desc = {
"_lsprof.profiler_subentry", /* name */
NULL, /* doc */
profiler_subentry_fields,
5
};
static int initialized;
static PyTypeObject StatsEntryType;
static PyTypeObject StatsSubEntryType;
typedef struct {
PyObject *list;
PyObject *sublist;
double factor;
} statscollector_t;
static int statsForSubEntry(rotating_node_t *node, void *arg)
{
ProfilerSubEntry *sentry = (ProfilerSubEntry*) node;
statscollector_t *collect = (statscollector_t*) arg;
ProfilerEntry *entry = (ProfilerEntry*) sentry->header.key;
int err;
PyObject *sinfo;
sinfo = PyObject_CallFunction((PyObject*) &StatsSubEntryType,
"((Olldd))",
entry->userObj,
sentry->callcount,
sentry->recursivecallcount,
collect->factor * sentry->tt,
collect->factor * sentry->it);
if (sinfo == NULL)
return -1;
err = PyList_Append(collect->sublist, sinfo);
Py_DECREF(sinfo);
return err;
}
static int statsForEntry(rotating_node_t *node, void *arg)
{
ProfilerEntry *entry = (ProfilerEntry*) node;
statscollector_t *collect = (statscollector_t*) arg;
PyObject *info;
int err;
if (entry->callcount == 0)
return 0; /* skip */
if (entry->calls != EMPTY_ROTATING_TREE) {
collect->sublist = PyList_New(0);
if (collect->sublist == NULL)
return -1;
if (RotatingTree_Enum(entry->calls,
statsForSubEntry, collect) != 0) {
Py_DECREF(collect->sublist);
return -1;
}
}
else {
Py_INCREF(Py_None);
collect->sublist = Py_None;
}
info = PyObject_CallFunction((PyObject*) &StatsEntryType,
"((OllddO))",
entry->userObj,
entry->callcount,
entry->recursivecallcount,
collect->factor * entry->tt,
collect->factor * entry->it,
collect->sublist);
Py_DECREF(collect->sublist);
if (info == NULL)
return -1;
err = PyList_Append(collect->list, info);
Py_DECREF(info);
return err;
}
PyDoc_STRVAR(getstats_doc, "\
getstats() -> list of profiler_entry objects\n\
\n\
Return all information collected by the profiler.\n\
Each profiler_entry is a tuple-like object with the\n\
following attributes:\n\
\n\
code code object\n\
callcount how many times this was called\n\
reccallcount how many times called recursively\n\
totaltime total time in this entry\n\
inlinetime inline time in this entry (not in subcalls)\n\
calls details of the calls\n\
\n\
The calls attribute is either None or a list of\n\
profiler_subentry objects:\n\
\n\
code called code object\n\
callcount how many times this is called\n\
reccallcount how many times this is called recursively\n\
totaltime total time spent in this call\n\
inlinetime inline time (not in further subcalls)\n\
");
static PyObject*
profiler_getstats(ProfilerObject *pObj, PyObject* noarg)
{
statscollector_t collect;
if (pending_exception(pObj))
return NULL;
if (!pObj->externalTimer)
collect.factor = hpTimerUnit();
else if (pObj->externalTimerUnit > 0.0)
collect.factor = pObj->externalTimerUnit;
else
collect.factor = 1.0 / DOUBLE_TIMER_PRECISION;
collect.list = PyList_New(0);
if (collect.list == NULL)
return NULL;
if (RotatingTree_Enum(pObj->profilerEntries, statsForEntry, &collect)
!= 0) {
Py_DECREF(collect.list);
return NULL;
}
return collect.list;
}
static int
setSubcalls(ProfilerObject *pObj, int nvalue)
{
if (nvalue == 0)
pObj->flags &= ~POF_SUBCALLS;
else if (nvalue > 0)
pObj->flags |= POF_SUBCALLS;
return 0;
}
static int
setBuiltins(ProfilerObject *pObj, int nvalue)
{
if (nvalue == 0)
pObj->flags &= ~POF_BUILTINS;
else if (nvalue > 0) {
#ifndef PyTrace_C_CALL
PyErr_SetString(PyExc_ValueError,
"builtins=True requires Python >= 2.4");
return -1;
#else
pObj->flags |= POF_BUILTINS;
#endif
}
return 0;
}
PyDoc_STRVAR(enable_doc, "\
enable(subcalls=True, builtins=True)\n\
\n\
Start collecting profiling information.\n\
If 'subcalls' is True, also records for each function\n\
statistics separated according to its current caller.\n\
If 'builtins' is True, records the time spent in\n\
built-in functions separately from their caller.\n\
");
static PyObject*
profiler_enable(ProfilerObject *self, PyObject *args, PyObject *kwds)
{
int subcalls = -1;
int builtins = -1;
static char *kwlist[] = {"subcalls", "builtins", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii:enable",
kwlist, &subcalls, &builtins))
return NULL;
if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0)
return NULL;
PyEval_SetProfile(profiler_callback, (PyObject*)self);
self->flags |= POF_ENABLED;
Py_INCREF(Py_None);
return Py_None;
}
static void
flush_unmatched(ProfilerObject *pObj)
{
while (pObj->currentProfilerContext) {
ProfilerContext *pContext = pObj->currentProfilerContext;
ProfilerEntry *profEntry= pContext->ctxEntry;
if (profEntry)
Stop(pObj, pContext, profEntry);
else
pObj->currentProfilerContext = pContext->previous;
if (pContext)
free(pContext);
}
}
PyDoc_STRVAR(disable_doc, "\
disable()\n\
\n\
Stop collecting profiling information.\n\
");
static PyObject*
profiler_disable(ProfilerObject *self, PyObject* noarg)
{
self->flags &= ~POF_ENABLED;
PyEval_SetProfile(NULL, NULL);
flush_unmatched(self);
if (pending_exception(self))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(clear_doc, "\
clear()\n\
\n\
Clear all profiling information collected so far.\n\
");
static PyObject*
profiler_clear(ProfilerObject *pObj, PyObject* noarg)
{
clearEntries(pObj);
Py_INCREF(Py_None);
return Py_None;
}
static void
profiler_dealloc(ProfilerObject *op)
{
if (op->flags & POF_ENABLED)
PyEval_SetProfile(NULL, NULL);
flush_unmatched(op);
clearEntries(op);
Py_XDECREF(op->externalTimer);
Py_TYPE(op)->tp_free(op);
}
static int
profiler_init(ProfilerObject *pObj, PyObject *args, PyObject *kw)
{
PyObject *o;
PyObject *timer = NULL;
double timeunit = 0.0;
int subcalls = 1;
#ifdef PyTrace_C_CALL
int builtins = 1;
#else
int builtins = 0;
#endif
static char *kwlist[] = {"timer", "timeunit",
"subcalls", "builtins", 0};
if (!PyArg_ParseTupleAndKeywords(args, kw, "|Odii:Profiler", kwlist,
&timer, &timeunit,
&subcalls, &builtins))
return -1;
if (setSubcalls(pObj, subcalls) < 0 || setBuiltins(pObj, builtins) < 0)
return -1;
o = pObj->externalTimer;
pObj->externalTimer = timer;
Py_XINCREF(timer);
Py_XDECREF(o);
pObj->externalTimerUnit = timeunit;
return 0;
}
static PyMethodDef profiler_methods[] = {
{"getstats", (PyCFunction)profiler_getstats,
METH_NOARGS, getstats_doc},
{"enable", (PyCFunction)profiler_enable,
METH_VARARGS | METH_KEYWORDS, enable_doc},
{"disable", (PyCFunction)profiler_disable,
METH_NOARGS, disable_doc},
{"clear", (PyCFunction)profiler_clear,
METH_NOARGS, clear_doc},
{NULL, NULL}
};
PyDoc_STRVAR(profiler_doc, "\
Profiler(custom_timer=None, time_unit=None, subcalls=True, builtins=True)\n\
\n\
Builds a profiler object using the specified timer function.\n\
The default timer is a fast built-in one based on real time.\n\
For custom timer functions returning integers, time_unit can\n\
be a float specifying a scale (i.e. how long each integer unit\n\
is, in seconds).\n\
");
statichere PyTypeObject PyProfiler_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"_lsprof.Profiler", /* tp_name */
sizeof(ProfilerObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)profiler_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
profiler_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
profiler_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)profiler_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_Del, /* tp_free */
};
static PyMethodDef moduleMethods[] = {
{NULL, NULL}
};
PyMODINIT_FUNC
init_lsprof(void)
{
PyObject *module, *d;
module = Py_InitModule3("_lsprof", moduleMethods, "Fast profiler");
if (module == NULL)
return;
d = PyModule_GetDict(module);
if (PyType_Ready(&PyProfiler_Type) < 0)
return;
PyDict_SetItemString(d, "Profiler", (PyObject *)&PyProfiler_Type);
if (!initialized) {
PyStructSequence_InitType(&StatsEntryType,
&profiler_entry_desc);
PyStructSequence_InitType(&StatsSubEntryType,
&profiler_subentry_desc);
}
Py_INCREF((PyObject*) &StatsEntryType);
Py_INCREF((PyObject*) &StatsSubEntryType);
PyModule_AddObject(module, "profiler_entry",
(PyObject*) &StatsEntryType);
PyModule_AddObject(module, "profiler_subentry",
(PyObject*) &StatsSubEntryType);
empty_tuple = PyTuple_New(0);
initialized = 1;
}

View File

@@ -0,0 +1,232 @@
/* Definitions of some C99 math library functions, for those platforms
that don't implement these functions already. */
#include "Python.h"
#include <float.h>
#include "_math.h"
/* The following copyright notice applies to the original
implementations of acosh, asinh and atanh. */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
static const double ln2 = 6.93147180559945286227E-01;
static const double two_pow_m28 = 3.7252902984619141E-09; /* 2**-28 */
static const double two_pow_p28 = 268435456.0; /* 2**28 */
static const double zero = 0.0;
/* acosh(x)
* Method :
* Based on
* acosh(x) = log [ x + sqrt(x*x-1) ]
* we have
* acosh(x) := log(x)+ln2, if x is large; else
* acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
* acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
*
* Special cases:
* acosh(x) is NaN with signal if x<1.
* acosh(NaN) is NaN without signal.
*/
double
_Py_acosh(double x)
{
if (Py_IS_NAN(x)) {
return x+x;
}
if (x < 1.) { /* x < 1; return a signaling NaN */
errno = EDOM;
#ifdef Py_NAN
return Py_NAN;
#else
return (x-x)/(x-x);
#endif
}
else if (x >= two_pow_p28) { /* x > 2**28 */
if (Py_IS_INFINITY(x)) {
return x+x;
}
else {
return log(x)+ln2; /* acosh(huge)=log(2x) */
}
}
else if (x == 1.) {
return 0.0; /* acosh(1) = 0 */
}
else if (x > 2.) { /* 2 < x < 2**28 */
double t = x*x;
return log(2.0*x - 1.0 / (x + sqrt(t - 1.0)));
}
else { /* 1 < x <= 2 */
double t = x - 1.0;
return m_log1p(t + sqrt(2.0*t + t*t));
}
}
/* asinh(x)
* Method :
* Based on
* asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
* we have
* asinh(x) := x if 1+x*x=1,
* := sign(x)*(log(x)+ln2)) for large |x|, else
* := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
* := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
*/
double
_Py_asinh(double x)
{
double w;
double absx = fabs(x);
if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
return x+x;
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x; /* return x inexact except 0 */
}
if (absx > two_pow_p28) { /* |x| > 2**28 */
w = log(absx)+ln2;
}
else if (absx > 2.0) { /* 2 < |x| < 2**28 */
w = log(2.0*absx + 1.0 / (sqrt(x*x + 1.0) + absx));
}
else { /* 2**-28 <= |x| < 2= */
double t = x*x;
w = m_log1p(absx + t / (1.0 + sqrt(1.0 + t)));
}
return copysign(w, x);
}
/* atanh(x)
* Method :
* 1.Reduced x to positive by atanh(-x) = -atanh(x)
* 2.For x>=0.5
* 1 2x x
* atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * -------)
* 2 1 - x 1 - x
*
* For x<0.5
* atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
*
* Special cases:
* atanh(x) is NaN if |x| >= 1 with signal;
* atanh(NaN) is that NaN with no signal;
*
*/
double
_Py_atanh(double x)
{
double absx;
double t;
if (Py_IS_NAN(x)) {
return x+x;
}
absx = fabs(x);
if (absx >= 1.) { /* |x| >= 1 */
errno = EDOM;
#ifdef Py_NAN
return Py_NAN;
#else
return x/zero;
#endif
}
if (absx < two_pow_m28) { /* |x| < 2**-28 */
return x;
}
if (absx < 0.5) { /* |x| < 0.5 */
t = absx+absx;
t = 0.5 * m_log1p(t + t*absx / (1.0 - absx));
}
else { /* 0.5 <= |x| <= 1.0 */
t = 0.5 * m_log1p((absx + absx) / (1.0 - absx));
}
return copysign(t, x);
}
/* Mathematically, expm1(x) = exp(x) - 1. The expm1 function is designed
to avoid the significant loss of precision that arises from direct
evaluation of the expression exp(x) - 1, for x near 0. */
double
_Py_expm1(double x)
{
/* For abs(x) >= log(2), it's safe to evaluate exp(x) - 1 directly; this
also works fine for infinities and nans.
For smaller x, we can use a method due to Kahan that achieves close to
full accuracy.
*/
if (fabs(x) < 0.7) {
double u;
u = exp(x);
if (u == 1.0)
return x;
else
return (u - 1.0) * x / log(u);
}
else
return exp(x) - 1.0;
}
/* log1p(x) = log(1+x). The log1p function is designed to avoid the
significant loss of precision that arises from direct evaluation when x is
small. */
double
_Py_log1p(double x)
{
/* For x small, we use the following approach. Let y be the nearest float
to 1+x, then
1+x = y * (1 - (y-1-x)/y)
so log(1+x) = log(y) + log(1-(y-1-x)/y). Since (y-1-x)/y is tiny, the
second term is well approximated by (y-1-x)/y. If abs(x) >=
DBL_EPSILON/2 or the rounding-mode is some form of round-to-nearest
then y-1-x will be exactly representable, and is computed exactly by
(y-1)-x.
If abs(x) < DBL_EPSILON/2 and the rounding mode is not known to be
round-to-nearest then this method is slightly dangerous: 1+x could be
rounded up to 1+DBL_EPSILON instead of down to 1, and in that case
y-1-x will not be exactly representable any more and the result can be
off by many ulps. But this is easily fixed: for a floating-point
number |x| < DBL_EPSILON/2., the closest floating-point number to
log(1+x) is exactly x.
*/
double y;
if (fabs(x) < DBL_EPSILON/2.) {
return x;
}
else if (-0.5 <= x && x <= 1.) {
/* WARNING: it's possible than an overeager compiler
will incorrectly optimize the following two lines
to the equivalent of "return log(1.+x)". If this
happens, then results from log1p will be inaccurate
for small x. */
y = 1.+x;
return log(y)-((y-1.)-x)/y;
}
else {
/* NaNs and infinities should end up here */
return log(1.+x);
}
}

View File

@@ -0,0 +1,45 @@
double _Py_acosh(double x);
double _Py_asinh(double x);
double _Py_atanh(double x);
double _Py_expm1(double x);
double _Py_log1p(double x);
#ifdef HAVE_ACOSH
#define m_acosh acosh
#else
/* if the system doesn't have acosh, use the substitute
function defined in Modules/_math.c. */
#define m_acosh _Py_acosh
#endif
#ifdef HAVE_ASINH
#define m_asinh asinh
#else
/* if the system doesn't have asinh, use the substitute
function defined in Modules/_math.c. */
#define m_asinh _Py_asinh
#endif
#ifdef HAVE_ATANH
#define m_atanh atanh
#else
/* if the system doesn't have atanh, use the substitute
function defined in Modules/_math.c. */
#define m_atanh _Py_atanh
#endif
#ifdef HAVE_EXPM1
#define m_expm1 expm1
#else
/* if the system doesn't have expm1, use the substitute
function defined in Modules/_math.c. */
#define m_expm1 _Py_expm1
#endif
#ifdef HAVE_LOG1P
#define m_log1p log1p
#else
/* if the system doesn't have log1p, use the substitute
function defined in Modules/_math.c. */
#define m_log1p _Py_log1p
#endif

View File

@@ -0,0 +1,580 @@
/* Random objects */
/* ------------------------------------------------------------------
The code in this module was based on a download from:
http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html
It was modified in 2002 by Raymond Hettinger as follows:
* the principal computational lines untouched.
* renamed genrand_res53() to random_random() and wrapped
in python calling/return code.
* genrand_int32() and the helper functions, init_genrand()
and init_by_array(), were declared static, wrapped in
Python calling/return code. also, their global data
references were replaced with structure references.
* unused functions from the original were deleted.
new, original C python code was added to implement the
Random() interface.
The following are the verbatim comments from the original code:
A C-program for MT19937, with initialization improved 2002/1/26.
Coded by Takuji Nishimura and Makoto Matsumoto.
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The names of its contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Any feedback is very welcome.
http://www.math.keio.ac.jp/matumoto/emt.html
email: matumoto@math.keio.ac.jp
*/
/* ---------------------------------------------------------------*/
#include "Python.h"
#include <time.h> /* for seeding to current time */
/* Period parameters -- These are all magic. Don't change. */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL /* constant vector a */
#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
typedef struct {
PyObject_HEAD
unsigned long state[N];
int index;
} RandomObject;
static PyTypeObject Random_Type;
#define RandomObject_Check(v) (Py_TYPE(v) == &Random_Type)
/* Random methods */
/* generates a random number on [0,0xffffffff]-interval */
static unsigned long
genrand_int32(RandomObject *self)
{
unsigned long y;
static unsigned long mag01[2]={0x0UL, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
unsigned long *mt;
mt = self->state;
if (self->index >= N) { /* generate N words at one time */
int kk;
for (kk=0;kk<N-M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (;kk<N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
self->index = 0;
}
y = mt[self->index++];
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
/* random_random is the function named genrand_res53 in the original code;
* generates a random number on [0,1) with 53-bit resolution; note that
* 9007199254740992 == 2**53; I assume they're spelling "/2**53" as
* multiply-by-reciprocal in the (likely vain) hope that the compiler will
* optimize the division away at compile-time. 67108864 is 2**26. In
* effect, a contains 27 random bits shifted left 26, and b fills in the
* lower 26 bits of the 53-bit numerator.
* The orginal code credited Isaku Wada for this algorithm, 2002/01/09.
*/
static PyObject *
random_random(RandomObject *self)
{
unsigned long a=genrand_int32(self)>>5, b=genrand_int32(self)>>6;
return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
}
/* initializes mt[N] with a seed */
static void
init_genrand(RandomObject *self, unsigned long s)
{
int mti;
unsigned long *mt;
mt = self->state;
mt[0]= s & 0xffffffffUL;
for (mti=1; mti<N; mti++) {
mt[mti] =
(1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= 0xffffffffUL;
/* for >32 bit machines */
}
self->index = mti;
return;
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
static PyObject *
init_by_array(RandomObject *self, unsigned long init_key[], unsigned long key_length)
{
unsigned int i, j, k; /* was signed in the original code. RDH 12/16/2002 */
unsigned long *mt;
mt = self->state;
init_genrand(self, 19650218UL);
i=1; j=0;
k = (N>key_length ? N : key_length);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++; j++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
if (j>=key_length) j=0;
}
for (k=N-1; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
- i; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
if (i>=N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
Py_INCREF(Py_None);
return Py_None;
}
/*
* The rest is Python-specific code, neither part of, nor derived from, the
* Twister download.
*/
static PyObject *
random_seed(RandomObject *self, PyObject *args)
{
PyObject *result = NULL; /* guilty until proved innocent */
PyObject *masklower = NULL;
PyObject *thirtytwo = NULL;
PyObject *n = NULL;
unsigned long *key = NULL;
unsigned long keymax; /* # of allocated slots in key */
unsigned long keyused; /* # of used slots in key */
int err;
PyObject *arg = NULL;
if (!PyArg_UnpackTuple(args, "seed", 0, 1, &arg))
return NULL;
if (arg == NULL || arg == Py_None) {
time_t now;
time(&now);
init_genrand(self, (unsigned long)now);
Py_INCREF(Py_None);
return Py_None;
}
/* If the arg is an int or long, use its absolute value; else use
* the absolute value of its hash code.
*/
if (PyInt_Check(arg) || PyLong_Check(arg))
n = PyNumber_Absolute(arg);
else {
long hash = PyObject_Hash(arg);
if (hash == -1)
goto Done;
n = PyLong_FromUnsignedLong((unsigned long)hash);
}
if (n == NULL)
goto Done;
/* Now split n into 32-bit chunks, from the right. Each piece is
* stored into key, which has a capacity of keymax chunks, of which
* keyused are filled. Alas, the repeated shifting makes this a
* quadratic-time algorithm; we'd really like to use
* _PyLong_AsByteArray here, but then we'd have to break into the
* long representation to figure out how big an array was needed
* in advance.
*/
keymax = 8; /* arbitrary; grows later if needed */
keyused = 0;
key = (unsigned long *)PyMem_Malloc(keymax * sizeof(*key));
if (key == NULL)
goto Done;
masklower = PyLong_FromUnsignedLong(0xffffffffU);
if (masklower == NULL)
goto Done;
thirtytwo = PyInt_FromLong(32L);
if (thirtytwo == NULL)
goto Done;
while ((err=PyObject_IsTrue(n))) {
PyObject *newn;
PyObject *pychunk;
unsigned long chunk;
if (err == -1)
goto Done;
pychunk = PyNumber_And(n, masklower);
if (pychunk == NULL)
goto Done;
chunk = PyLong_AsUnsignedLong(pychunk);
Py_DECREF(pychunk);
if (chunk == (unsigned long)-1 && PyErr_Occurred())
goto Done;
newn = PyNumber_Rshift(n, thirtytwo);
if (newn == NULL)
goto Done;
Py_DECREF(n);
n = newn;
if (keyused >= keymax) {
unsigned long bigger = keymax << 1;
if ((bigger >> 1) != keymax) {
PyErr_NoMemory();
goto Done;
}
key = (unsigned long *)PyMem_Realloc(key,
bigger * sizeof(*key));
if (key == NULL)
goto Done;
keymax = bigger;
}
assert(keyused < keymax);
key[keyused++] = chunk;
}
if (keyused == 0)
key[keyused++] = 0UL;
result = init_by_array(self, key, keyused);
Done:
Py_XDECREF(masklower);
Py_XDECREF(thirtytwo);
Py_XDECREF(n);
PyMem_Free(key);
return result;
}
static PyObject *
random_getstate(RandomObject *self)
{
PyObject *state;
PyObject *element;
int i;
state = PyTuple_New(N+1);
if (state == NULL)
return NULL;
for (i=0; i<N ; i++) {
element = PyLong_FromUnsignedLong(self->state[i]);
if (element == NULL)
goto Fail;
PyTuple_SET_ITEM(state, i, element);
}
element = PyLong_FromLong((long)(self->index));
if (element == NULL)
goto Fail;
PyTuple_SET_ITEM(state, i, element);
return state;
Fail:
Py_DECREF(state);
return NULL;
}
static PyObject *
random_setstate(RandomObject *self, PyObject *state)
{
int i;
unsigned long element;
long index;
if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError,
"state vector must be a tuple");
return NULL;
}
if (PyTuple_Size(state) != N+1) {
PyErr_SetString(PyExc_ValueError,
"state vector is the wrong size");
return NULL;
}
for (i=0; i<N ; i++) {
element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
if (element == (unsigned long)-1 && PyErr_Occurred())
return NULL;
self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
}
index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
if (index == -1 && PyErr_Occurred())
return NULL;
self->index = (int)index;
Py_INCREF(Py_None);
return Py_None;
}
/*
Jumpahead should be a fast way advance the generator n-steps ahead, but
lacking a formula for that, the next best is to use n and the existing
state to create a new state far away from the original.
The generator uses constant spaced additive feedback, so shuffling the
state elements ought to produce a state which would not be encountered
(in the near term) by calls to random(). Shuffling is normally
implemented by swapping the ith element with another element ranging
from 0 to i inclusive. That allows the element to have the possibility
of not being moved. Since the goal is to produce a new, different
state, the swap element is ranged from 0 to i-1 inclusive. This assures
that each element gets moved at least once.
To make sure that consecutive calls to jumpahead(n) produce different
states (even in the rare case of involutory shuffles), i+1 is added to
each element at position i. Successive calls are then guaranteed to
have changing (growing) values as well as shuffled positions.
Finally, the self->index value is set to N so that the generator itself
kicks in on the next call to random(). This assures that all results
have been through the generator and do not just reflect alterations to
the underlying state.
*/
static PyObject *
random_jumpahead(RandomObject *self, PyObject *n)
{
long i, j;
PyObject *iobj;
PyObject *remobj;
unsigned long *mt, tmp;
if (!PyInt_Check(n) && !PyLong_Check(n)) {
PyErr_Format(PyExc_TypeError, "jumpahead requires an "
"integer, not '%s'",
Py_TYPE(n)->tp_name);
return NULL;
}
mt = self->state;
for (i = N-1; i > 1; i--) {
iobj = PyInt_FromLong(i);
if (iobj == NULL)
return NULL;
remobj = PyNumber_Remainder(n, iobj);
Py_DECREF(iobj);
if (remobj == NULL)
return NULL;
j = PyInt_AsLong(remobj);
Py_DECREF(remobj);
if (j == -1L && PyErr_Occurred())
return NULL;
tmp = mt[i];
mt[i] = mt[j];
mt[j] = tmp;
}
for (i = 0; i < N; i++)
mt[i] += i+1;
self->index = N;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
random_getrandbits(RandomObject *self, PyObject *args)
{
int k, i, bytes;
unsigned long r;
unsigned char *bytearray;
PyObject *result;
if (!PyArg_ParseTuple(args, "i:getrandbits", &k))
return NULL;
if (k <= 0) {
PyErr_SetString(PyExc_ValueError,
"number of bits must be greater than zero");
return NULL;
}
bytes = ((k - 1) / 32 + 1) * 4;
bytearray = (unsigned char *)PyMem_Malloc(bytes);
if (bytearray == NULL) {
PyErr_NoMemory();
return NULL;
}
/* Fill-out whole words, byte-by-byte to avoid endianness issues */
for (i=0 ; i<bytes ; i+=4, k-=32) {
r = genrand_int32(self);
if (k < 32)
r >>= (32 - k);
bytearray[i+0] = (unsigned char)r;
bytearray[i+1] = (unsigned char)(r >> 8);
bytearray[i+2] = (unsigned char)(r >> 16);
bytearray[i+3] = (unsigned char)(r >> 24);
}
/* little endian order to match bytearray assignment order */
result = _PyLong_FromByteArray(bytearray, bytes, 1, 0);
PyMem_Free(bytearray);
return result;
}
static PyObject *
random_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
RandomObject *self;
PyObject *tmp;
if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds))
return NULL;
self = (RandomObject *)type->tp_alloc(type, 0);
if (self == NULL)
return NULL;
tmp = random_seed(self, args);
if (tmp == NULL) {
Py_DECREF(self);
return NULL;
}
Py_DECREF(tmp);
return (PyObject *)self;
}
static PyMethodDef random_methods[] = {
{"random", (PyCFunction)random_random, METH_NOARGS,
PyDoc_STR("random() -> x in the interval [0, 1).")},
{"seed", (PyCFunction)random_seed, METH_VARARGS,
PyDoc_STR("seed([n]) -> None. Defaults to current time.")},
{"getstate", (PyCFunction)random_getstate, METH_NOARGS,
PyDoc_STR("getstate() -> tuple containing the current state.")},
{"setstate", (PyCFunction)random_setstate, METH_O,
PyDoc_STR("setstate(state) -> None. Restores generator state.")},
{"jumpahead", (PyCFunction)random_jumpahead, METH_O,
PyDoc_STR("jumpahead(int) -> None. Create new state from "
"existing state and integer.")},
{"getrandbits", (PyCFunction)random_getrandbits, METH_VARARGS,
PyDoc_STR("getrandbits(k) -> x. Generates a long int with "
"k random bits.")},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(random_doc,
"Random() -> create a random number generator with its own internal state.");
static PyTypeObject Random_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_random.Random", /*tp_name*/
sizeof(RandomObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
PyObject_GenericGetAttr, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
random_doc, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
random_methods, /*tp_methods*/
0, /*tp_members*/
0, /*tp_getset*/
0, /*tp_base*/
0, /*tp_dict*/
0, /*tp_descr_get*/
0, /*tp_descr_set*/
0, /*tp_dictoffset*/
0, /*tp_init*/
0, /*tp_alloc*/
random_new, /*tp_new*/
_PyObject_Del, /*tp_free*/
0, /*tp_is_gc*/
};
PyDoc_STRVAR(module_doc,
"Module implements the Mersenne Twister random number generator.");
PyMODINIT_FUNC
init_random(void)
{
PyObject *m;
if (PyType_Ready(&Random_Type) < 0)
return;
m = Py_InitModule3("_random", NULL, module_doc);
if (m == NULL)
return;
Py_INCREF(&Random_Type);
PyModule_AddObject(m, "Random", (PyObject *)&Random_Type);
}

View File

@@ -0,0 +1,375 @@
/* cache .c - a LRU cache
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "sqlitecompat.h"
#include "cache.h"
#include <limits.h>
/* only used internally */
pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data)
{
pysqlite_Node* node;
node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0));
if (!node) {
return NULL;
}
Py_INCREF(key);
node->key = key;
Py_INCREF(data);
node->data = data;
node->prev = NULL;
node->next = NULL;
return node;
}
void pysqlite_node_dealloc(pysqlite_Node* self)
{
Py_DECREF(self->key);
Py_DECREF(self->data);
Py_TYPE(self)->tp_free((PyObject*)self);
}
int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs)
{
PyObject* factory;
int size = 10;
self->factory = NULL;
if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) {
return -1;
}
/* minimum cache size is 5 entries */
if (size < 5) {
size = 5;
}
self->size = size;
self->first = NULL;
self->last = NULL;
self->mapping = PyDict_New();
if (!self->mapping) {
return -1;
}
Py_INCREF(factory);
self->factory = factory;
self->decref_factory = 1;
return 0;
}
void pysqlite_cache_dealloc(pysqlite_Cache* self)
{
pysqlite_Node* node;
pysqlite_Node* delete_node;
if (!self->factory) {
/* constructor failed, just get out of here */
return;
}
/* iterate over all nodes and deallocate them */
node = self->first;
while (node) {
delete_node = node;
node = node->next;
Py_DECREF(delete_node);
}
if (self->decref_factory) {
Py_DECREF(self->factory);
}
Py_DECREF(self->mapping);
Py_TYPE(self)->tp_free((PyObject*)self);
}
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args)
{
PyObject* key = args;
pysqlite_Node* node;
pysqlite_Node* ptr;
PyObject* data;
node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key);
if (node) {
/* an entry for this key already exists in the cache */
/* increase usage counter of the node found */
if (node->count < LONG_MAX) {
node->count++;
}
/* if necessary, reorder entries in the cache by swapping positions */
if (node->prev && node->count > node->prev->count) {
ptr = node->prev;
while (ptr->prev && node->count > ptr->prev->count) {
ptr = ptr->prev;
}
if (node->next) {
node->next->prev = node->prev;
} else {
self->last = node->prev;
}
if (node->prev) {
node->prev->next = node->next;
}
if (ptr->prev) {
ptr->prev->next = node;
} else {
self->first = node;
}
node->next = ptr;
node->prev = ptr->prev;
if (!node->prev) {
self->first = node;
}
ptr->prev = node;
}
} else {
/* There is no entry for this key in the cache, yet. We'll insert a new
* entry in the cache, and make space if necessary by throwing the
* least used item out of the cache. */
if (PyDict_Size(self->mapping) == self->size) {
if (self->last) {
node = self->last;
if (PyDict_DelItem(self->mapping, self->last->key) != 0) {
return NULL;
}
if (node->prev) {
node->prev->next = NULL;
}
self->last = node->prev;
node->prev = NULL;
Py_DECREF(node);
}
}
data = PyObject_CallFunction(self->factory, "O", key);
if (!data) {
return NULL;
}
node = pysqlite_new_node(key, data);
if (!node) {
return NULL;
}
node->prev = self->last;
Py_DECREF(data);
if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) {
Py_DECREF(node);
return NULL;
}
if (self->last) {
self->last->next = node;
} else {
self->first = node;
}
self->last = node;
}
Py_INCREF(node->data);
return node->data;
}
PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args)
{
pysqlite_Node* ptr;
PyObject* prevkey;
PyObject* nextkey;
PyObject* fmt_args;
PyObject* template;
PyObject* display_str;
ptr = self->first;
while (ptr) {
if (ptr->prev) {
prevkey = ptr->prev->key;
} else {
prevkey = Py_None;
}
Py_INCREF(prevkey);
if (ptr->next) {
nextkey = ptr->next->key;
} else {
nextkey = Py_None;
}
Py_INCREF(nextkey);
fmt_args = Py_BuildValue("OOO", prevkey, ptr->key, nextkey);
if (!fmt_args) {
return NULL;
}
template = PyString_FromString("%s <- %s ->%s\n");
if (!template) {
Py_DECREF(fmt_args);
return NULL;
}
display_str = PyString_Format(template, fmt_args);
Py_DECREF(template);
Py_DECREF(fmt_args);
if (!display_str) {
return NULL;
}
PyObject_Print(display_str, stdout, Py_PRINT_RAW);
Py_DECREF(display_str);
Py_DECREF(prevkey);
Py_DECREF(nextkey);
ptr = ptr->next;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef cache_methods[] = {
{"get", (PyCFunction)pysqlite_cache_get, METH_O,
PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")},
{"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS,
PyDoc_STR("For debugging only.")},
{NULL, NULL}
};
PyTypeObject pysqlite_NodeType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME "Node", /* tp_name */
sizeof(pysqlite_Node), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_node_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
PyTypeObject pysqlite_CacheType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".Cache", /* tp_name */
sizeof(pysqlite_Cache), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_cache_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
cache_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pysqlite_cache_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
extern int pysqlite_cache_setup_types(void)
{
int rc;
pysqlite_NodeType.tp_new = PyType_GenericNew;
pysqlite_CacheType.tp_new = PyType_GenericNew;
rc = PyType_Ready(&pysqlite_NodeType);
if (rc < 0) {
return rc;
}
rc = PyType_Ready(&pysqlite_CacheType);
return rc;
}

View File

@@ -0,0 +1,73 @@
/* cache.h - definitions for the LRU cache
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_CACHE_H
#define PYSQLITE_CACHE_H
#include "Python.h"
/* The LRU cache is implemented as a combination of a doubly-linked with a
* dictionary. The list items are of type 'Node' and the dictionary has the
* nodes as values. */
typedef struct _pysqlite_Node
{
PyObject_HEAD
PyObject* key;
PyObject* data;
long count;
struct _pysqlite_Node* prev;
struct _pysqlite_Node* next;
} pysqlite_Node;
typedef struct
{
PyObject_HEAD
int size;
/* a dictionary mapping keys to Node entries */
PyObject* mapping;
/* the factory callable */
PyObject* factory;
pysqlite_Node* first;
pysqlite_Node* last;
/* if set, decrement the factory function when the Cache is deallocated.
* this is almost always desirable, but not in the pysqlite context */
int decref_factory;
} pysqlite_Cache;
extern PyTypeObject pysqlite_NodeType;
extern PyTypeObject pysqlite_CacheType;
int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs);
void pysqlite_node_dealloc(pysqlite_Node* self);
int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs);
void pysqlite_cache_dealloc(pysqlite_Cache* self);
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args);
int pysqlite_cache_setup_types(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/* connection.h - definitions for the connection type
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_CONNECTION_H
#define PYSQLITE_CONNECTION_H
#include "Python.h"
#include "pythread.h"
#include "structmember.h"
#include "cache.h"
#include "module.h"
#include "sqlite3.h"
typedef struct
{
PyObject_HEAD
sqlite3* db;
/* 1 if we are currently within a transaction, i. e. if a BEGIN has been
* issued */
int inTransaction;
/* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a
* bitwise combination thereof makes sense */
int detect_types;
/* the timeout value in seconds for database locks */
double timeout;
/* for internal use in the timeout handler: when did the timeout handler
* first get called with count=0? */
double timeout_started;
/* None for autocommit, otherwise a PyString with the isolation level */
PyObject* isolation_level;
/* NULL for autocommit, otherwise a string with the BEGIN statement; will be
* freed in connection destructor */
char* begin_statement;
/* 1 if a check should be performed for each API call if the connection is
* used from the same thread it was created in */
int check_same_thread;
int initialized;
/* thread identification of the thread the connection was created in */
long thread_ident;
pysqlite_Cache* statement_cache;
/* Lists of weak references to statements and cursors used within this connection */
PyObject* statements;
PyObject* cursors;
/* Counters for how many statements/cursors were created in the connection. May be
* reset to 0 at certain intervals */
int created_statements;
int created_cursors;
PyObject* row_factory;
/* Determines how bytestrings from SQLite are converted to Python objects:
* - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings
* - OptimizedUnicode: Like before, but for ASCII data, only PyStrings are created.
* - PyString_Type: PyStrings are created as-is.
* - Any custom callable: Any object returned from the callable called with the bytestring
* as single parameter.
*/
PyObject* text_factory;
/* remember references to functions/classes used in
* create_function/create/aggregate, use these as dictionary keys, so we
* can keep the total system refcount constant by clearing that dictionary
* in connection_dealloc */
PyObject* function_pinboard;
/* a dictionary of registered collation name => collation callable mappings */
PyObject* collations;
/* if our connection was created from a APSW connection, we keep a
* reference to the APSW connection around and get rid of it in our
* destructor */
PyObject* apsw_connection;
/* Exception objects */
PyObject* Warning;
PyObject* Error;
PyObject* InterfaceError;
PyObject* DatabaseError;
PyObject* DataError;
PyObject* OperationalError;
PyObject* IntegrityError;
PyObject* InternalError;
PyObject* ProgrammingError;
PyObject* NotSupportedError;
} pysqlite_Connection;
extern PyTypeObject pysqlite_ConnectionType;
PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware);
void pysqlite_connection_dealloc(pysqlite_Connection* self);
PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);
PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args);
PyObject* _pysqlite_connection_begin(pysqlite_Connection* self);
PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args);
PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args);
PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw);
int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs);
int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor);
int pysqlite_check_thread(pysqlite_Connection* self);
int pysqlite_check_connection(pysqlite_Connection* con);
int pysqlite_connection_setup_types(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
/* cursor.h - definitions for the cursor type
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_CURSOR_H
#define PYSQLITE_CURSOR_H
#include "Python.h"
#include "statement.h"
#include "connection.h"
#include "module.h"
typedef struct
{
PyObject_HEAD
pysqlite_Connection* connection;
PyObject* description;
PyObject* row_cast_map;
int arraysize;
PyObject* lastrowid;
long rowcount;
PyObject* row_factory;
pysqlite_Statement* statement;
int closed;
int reset;
int initialized;
/* the next row to be returned, NULL if no next row available */
PyObject* next_row;
PyObject* in_weakreflist; /* List of weak references */
} pysqlite_Cursor;
typedef enum {
STATEMENT_INVALID, STATEMENT_INSERT, STATEMENT_DELETE,
STATEMENT_UPDATE, STATEMENT_REPLACE, STATEMENT_SELECT,
STATEMENT_OTHER
} pysqlite_StatementKind;
extern PyTypeObject pysqlite_CursorType;
PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self);
PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self);
PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs);
PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args);
PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args);
PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args);
int pysqlite_cursor_setup_types(void);
#define UNKNOWN (-1)
#endif

View File

@@ -0,0 +1,142 @@
/* microprotocols.c - minimalist and non-validating protocols implementation
*
* Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
*
* This file is part of psycopg and was adapted for pysqlite. Federico Di
* Gregorio gave the permission to use it within pysqlite under the following
* license:
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include <Python.h>
#include <structmember.h>
#include "cursor.h"
#include "microprotocols.h"
#include "prepare_protocol.h"
/** the adapters registry **/
PyObject *psyco_adapters;
/* pysqlite_microprotocols_init - initialize the adapters dictionary */
int
pysqlite_microprotocols_init(PyObject *dict)
{
/* create adapters dictionary and put it in module namespace */
if ((psyco_adapters = PyDict_New()) == NULL) {
return -1;
}
return PyDict_SetItemString(dict, "adapters", psyco_adapters);
}
/* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */
int
pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
{
PyObject* key;
int rc;
if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType;
key = Py_BuildValue("(OO)", (PyObject*)type, proto);
if (!key) {
return -1;
}
rc = PyDict_SetItem(psyco_adapters, key, cast);
Py_DECREF(key);
return rc;
}
/* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */
PyObject *
pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
{
PyObject *adapter, *key;
/* we don't check for exact type conformance as specified in PEP 246
because the pysqlite_PrepareProtocolType type is abstract and there is no
way to get a quotable object to be its instance */
/* look for an adapter in the registry */
key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto);
if (!key) {
return NULL;
}
adapter = PyDict_GetItem(psyco_adapters, key);
Py_DECREF(key);
if (adapter) {
PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL);
return adapted;
}
/* try to have the protocol adapt this object*/
if (PyObject_HasAttrString(proto, "__adapt__")) {
PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj);
if (adapted) {
if (adapted != Py_None) {
return adapted;
} else {
Py_DECREF(adapted);
}
}
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
return NULL;
}
/* and finally try to have the object adapt itself */
if (PyObject_HasAttrString(obj, "__conform__")) {
PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
if (adapted) {
if (adapted != Py_None) {
return adapted;
} else {
Py_DECREF(adapted);
}
}
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) {
return NULL;
}
}
/* else set the right exception and return NULL */
PyErr_SetString(pysqlite_ProgrammingError, "can't adapt");
return NULL;
}
/** module-level functions **/
PyObject *
pysqlite_adapt(pysqlite_Cursor *self, PyObject *args)
{
PyObject *obj, *alt = NULL;
PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType;
if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL;
return pysqlite_microprotocols_adapt(obj, proto, alt);
}

View File

@@ -0,0 +1,55 @@
/* microprotocols.c - definitions for minimalist and non-validating protocols
*
* Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
*
* This file is part of psycopg and was adapted for pysqlite. Federico Di
* Gregorio gave the permission to use it within pysqlite under the following
* license:
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PSYCOPG_MICROPROTOCOLS_H
#define PSYCOPG_MICROPROTOCOLS_H 1
#include <Python.h>
/** adapters registry **/
extern PyObject *psyco_adapters;
/** the names of the three mandatory methods **/
#define MICROPROTOCOLS_GETQUOTED_NAME "getquoted"
#define MICROPROTOCOLS_GETSTRING_NAME "getstring"
#define MICROPROTOCOLS_GETBINARY_NAME "getbinary"
/** exported functions **/
/* used by module.c to init the microprotocols system */
extern int pysqlite_microprotocols_init(PyObject *dict);
extern int pysqlite_microprotocols_add(
PyTypeObject *type, PyObject *proto, PyObject *cast);
extern PyObject *pysqlite_microprotocols_adapt(
PyObject *obj, PyObject *proto, PyObject *alt);
extern PyObject *
pysqlite_adapt(pysqlite_Cursor* self, PyObject *args);
#define pysqlite_adapt_doc \
"adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard."
#endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */

View File

@@ -0,0 +1,457 @@
/* module.c - the module itself
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "connection.h"
#include "statement.h"
#include "cursor.h"
#include "cache.h"
#include "prepare_protocol.h"
#include "microprotocols.h"
#include "row.h"
#if SQLITE_VERSION_NUMBER >= 3003003
#define HAVE_SHARED_CACHE
#endif
/* static objects at module-level */
PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError,
*pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError,
*pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError, *pysqlite_OptimizedUnicode;
PyObject* converters;
int _enable_callback_tracebacks;
int pysqlite_BaseTypeAdapted;
static PyObject* module_connect(PyObject* self, PyObject* args, PyObject*
kwargs)
{
/* Python seems to have no way of extracting a single keyword-arg at
* C-level, so this code is redundant with the one in connection_init in
* connection.c and must always be copied from there ... */
static char *kwlist[] = {"database", "timeout", "detect_types", "isolation_level", "check_same_thread", "factory", "cached_statements", NULL, NULL};
PyObject* database;
int detect_types = 0;
PyObject* isolation_level;
PyObject* factory = NULL;
int check_same_thread = 1;
int cached_statements;
double timeout = 5.0;
PyObject* result;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|diOiOi", kwlist,
&database, &timeout, &detect_types, &isolation_level, &check_same_thread, &factory, &cached_statements))
{
return NULL;
}
if (factory == NULL) {
factory = (PyObject*)&pysqlite_ConnectionType;
}
result = PyObject_Call(factory, args, kwargs);
return result;
}
PyDoc_STRVAR(module_connect_doc,
"connect(database[, timeout, isolation_level, detect_types, factory])\n\
\n\
Opens a connection to the SQLite database file *database*. You can use\n\
\":memory:\" to open a database connection to a database that resides in\n\
RAM instead of on disk.");
static PyObject* module_complete(PyObject* self, PyObject* args, PyObject*
kwargs)
{
static char *kwlist[] = {"statement", NULL, NULL};
char* statement;
PyObject* result;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement))
{
return NULL;
}
if (sqlite3_complete(statement)) {
result = Py_True;
} else {
result = Py_False;
}
Py_INCREF(result);
return result;
}
PyDoc_STRVAR(module_complete_doc,
"complete_statement(sql)\n\
\n\
Checks if a string contains a complete SQL statement. Non-standard.");
#ifdef HAVE_SHARED_CACHE
static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject*
kwargs)
{
static char *kwlist[] = {"do_enable", NULL, NULL};
int do_enable;
int rc;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable))
{
return NULL;
}
rc = sqlite3_enable_shared_cache(do_enable);
if (rc != SQLITE_OK) {
PyErr_SetString(pysqlite_OperationalError, "Changing the shared_cache flag failed");
return NULL;
} else {
Py_INCREF(Py_None);
return Py_None;
}
}
PyDoc_STRVAR(module_enable_shared_cache_doc,
"enable_shared_cache(do_enable)\n\
\n\
Enable or disable shared cache mode for the calling thread.\n\
Experimental/Non-standard.");
#endif /* HAVE_SHARED_CACHE */
static PyObject* module_register_adapter(PyObject* self, PyObject* args)
{
PyTypeObject* type;
PyObject* caster;
int rc;
if (!PyArg_ParseTuple(args, "OO", &type, &caster)) {
return NULL;
}
/* a basic type is adapted; there's a performance optimization if that's not the case
* (99 % of all usages) */
if (type == &PyInt_Type || type == &PyLong_Type || type == &PyFloat_Type
|| type == &PyString_Type || type == &PyUnicode_Type || type == &PyBuffer_Type) {
pysqlite_BaseTypeAdapted = 1;
}
rc = pysqlite_microprotocols_add(type, (PyObject*)&pysqlite_PrepareProtocolType, caster);
if (rc == -1)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(module_register_adapter_doc,
"register_adapter(type, callable)\n\
\n\
Registers an adapter with pysqlite's adapter registry. Non-standard.");
static PyObject* module_register_converter(PyObject* self, PyObject* args)
{
PyObject* orig_name;
PyObject* name = NULL;
PyObject* callable;
PyObject* retval = NULL;
if (!PyArg_ParseTuple(args, "SO", &orig_name, &callable)) {
return NULL;
}
/* convert the name to upper case */
name = PyObject_CallMethod(orig_name, "upper", "");
if (!name) {
goto error;
}
if (PyDict_SetItem(converters, name, callable) != 0) {
goto error;
}
Py_INCREF(Py_None);
retval = Py_None;
error:
Py_XDECREF(name);
return retval;
}
PyDoc_STRVAR(module_register_converter_doc,
"register_converter(typename, callable)\n\
\n\
Registers a converter with pysqlite. Non-standard.");
static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, "i", &_enable_callback_tracebacks)) {
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(enable_callback_tracebacks_doc,
"enable_callback_tracebacks(flag)\n\
\n\
Enable or disable callback functions throwing errors to stderr.");
static void converters_init(PyObject* dict)
{
converters = PyDict_New();
if (!converters) {
return;
}
PyDict_SetItemString(dict, "converters", converters);
}
static PyMethodDef module_methods[] = {
{"connect", (PyCFunction)module_connect,
METH_VARARGS | METH_KEYWORDS, module_connect_doc},
{"complete_statement", (PyCFunction)module_complete,
METH_VARARGS | METH_KEYWORDS, module_complete_doc},
#ifdef HAVE_SHARED_CACHE
{"enable_shared_cache", (PyCFunction)module_enable_shared_cache,
METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc},
#endif
{"register_adapter", (PyCFunction)module_register_adapter,
METH_VARARGS, module_register_adapter_doc},
{"register_converter", (PyCFunction)module_register_converter,
METH_VARARGS, module_register_converter_doc},
{"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS,
pysqlite_adapt_doc},
{"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks,
METH_VARARGS, enable_callback_tracebacks_doc},
{NULL, NULL}
};
struct _IntConstantPair {
char* constant_name;
int constant_value;
};
typedef struct _IntConstantPair IntConstantPair;
static IntConstantPair _int_constants[] = {
{"PARSE_DECLTYPES", PARSE_DECLTYPES},
{"PARSE_COLNAMES", PARSE_COLNAMES},
{"SQLITE_OK", SQLITE_OK},
{"SQLITE_DENY", SQLITE_DENY},
{"SQLITE_IGNORE", SQLITE_IGNORE},
{"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX},
{"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE},
{"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX},
{"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE},
{"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER},
{"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW},
{"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER},
{"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW},
{"SQLITE_DELETE", SQLITE_DELETE},
{"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX},
{"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE},
{"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX},
{"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE},
{"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER},
{"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW},
{"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER},
{"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW},
{"SQLITE_INSERT", SQLITE_INSERT},
{"SQLITE_PRAGMA", SQLITE_PRAGMA},
{"SQLITE_READ", SQLITE_READ},
{"SQLITE_SELECT", SQLITE_SELECT},
{"SQLITE_TRANSACTION", SQLITE_TRANSACTION},
{"SQLITE_UPDATE", SQLITE_UPDATE},
{"SQLITE_ATTACH", SQLITE_ATTACH},
{"SQLITE_DETACH", SQLITE_DETACH},
#if SQLITE_VERSION_NUMBER >= 3002001
{"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE},
{"SQLITE_REINDEX", SQLITE_REINDEX},
#endif
#if SQLITE_VERSION_NUMBER >= 3003000
{"SQLITE_ANALYZE", SQLITE_ANALYZE},
#endif
{(char*)NULL, 0}
};
PyMODINIT_FUNC init_sqlite3(void)
{
PyObject *module, *dict;
PyObject *tmp_obj;
int i;
module = Py_InitModule("_sqlite3", module_methods);
if (!module ||
(pysqlite_row_setup_types() < 0) ||
(pysqlite_cursor_setup_types() < 0) ||
(pysqlite_connection_setup_types() < 0) ||
(pysqlite_cache_setup_types() < 0) ||
(pysqlite_statement_setup_types() < 0) ||
(pysqlite_prepare_protocol_setup_types() < 0)
) {
return;
}
Py_INCREF(&pysqlite_ConnectionType);
PyModule_AddObject(module, "Connection", (PyObject*) &pysqlite_ConnectionType);
Py_INCREF(&pysqlite_CursorType);
PyModule_AddObject(module, "Cursor", (PyObject*) &pysqlite_CursorType);
Py_INCREF(&pysqlite_CacheType);
PyModule_AddObject(module, "Statement", (PyObject*)&pysqlite_StatementType);
Py_INCREF(&pysqlite_StatementType);
PyModule_AddObject(module, "Cache", (PyObject*) &pysqlite_CacheType);
Py_INCREF(&pysqlite_PrepareProtocolType);
PyModule_AddObject(module, "PrepareProtocol", (PyObject*) &pysqlite_PrepareProtocolType);
Py_INCREF(&pysqlite_RowType);
PyModule_AddObject(module, "Row", (PyObject*) &pysqlite_RowType);
if (!(dict = PyModule_GetDict(module))) {
goto error;
}
/*** Create DB-API Exception hierarchy */
if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_StandardError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "Error", pysqlite_Error);
if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_StandardError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "Warning", pysqlite_Warning);
/* Error subclasses */
if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError);
if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError);
/* pysqlite_DatabaseError subclasses */
if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError);
if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError);
if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError);
if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) {
goto error;
}
PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError);
if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "DataError", pysqlite_DataError);
if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) {
goto error;
}
PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError);
/* We just need "something" unique for pysqlite_OptimizedUnicode. It does not really
* need to be a string subclass. Just anything that can act as a special
* marker for us. So I pulled PyCell_Type out of my magic hat.
*/
Py_INCREF((PyObject*)&PyCell_Type);
pysqlite_OptimizedUnicode = (PyObject*)&PyCell_Type;
PyDict_SetItemString(dict, "OptimizedUnicode", pysqlite_OptimizedUnicode);
/* Set integer constants */
for (i = 0; _int_constants[i].constant_name != 0; i++) {
tmp_obj = PyInt_FromLong(_int_constants[i].constant_value);
if (!tmp_obj) {
goto error;
}
PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj);
Py_DECREF(tmp_obj);
}
if (!(tmp_obj = PyString_FromString(PYSQLITE_VERSION))) {
goto error;
}
PyDict_SetItemString(dict, "version", tmp_obj);
Py_DECREF(tmp_obj);
if (!(tmp_obj = PyString_FromString(sqlite3_libversion()))) {
goto error;
}
PyDict_SetItemString(dict, "sqlite_version", tmp_obj);
Py_DECREF(tmp_obj);
/* initialize microprotocols layer */
pysqlite_microprotocols_init(dict);
/* initialize the default converters */
converters_init(dict);
_enable_callback_tracebacks = 0;
pysqlite_BaseTypeAdapted = 0;
/* Original comment from _bsddb.c in the Python core. This is also still
* needed nowadays for Python 2.3/2.4.
*
* PyEval_InitThreads is called here due to a quirk in python 1.5
* - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
* The global interpreter lock is not initialized until the first
* thread is created using thread.start_new_thread() or fork() is
* called. that would cause the ALLOW_THREADS here to segfault due
* to a null pointer reference if no threads or child processes
* have been created. This works around that and is a no-op if
* threads have already been initialized.
* (see pybsddb-users mailing list post on 2002-08-07)
*/
#ifdef WITH_THREAD
PyEval_InitThreads();
#endif
error:
if (PyErr_Occurred())
{
PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed");
}
}

View File

@@ -0,0 +1,58 @@
/* module.h - definitions for the module
*
* Copyright (C) 2004-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_MODULE_H
#define PYSQLITE_MODULE_H
#include "Python.h"
#define PYSQLITE_VERSION "2.6.0"
extern PyObject* pysqlite_Error;
extern PyObject* pysqlite_Warning;
extern PyObject* pysqlite_InterfaceError;
extern PyObject* pysqlite_DatabaseError;
extern PyObject* pysqlite_InternalError;
extern PyObject* pysqlite_OperationalError;
extern PyObject* pysqlite_ProgrammingError;
extern PyObject* pysqlite_IntegrityError;
extern PyObject* pysqlite_DataError;
extern PyObject* pysqlite_NotSupportedError;
extern PyObject* pysqlite_OptimizedUnicode;
/* the functions time.time() and time.sleep() */
extern PyObject* time_time;
extern PyObject* time_sleep;
/* A dictionary, mapping colum types (INTEGER, VARCHAR, etc.) to converter
* functions, that convert the SQL value to the appropriate Python value.
* The key is uppercase.
*/
extern PyObject* converters;
extern int _enable_callback_tracebacks;
extern int pysqlite_BaseTypeAdapted;
#define PARSE_DECLTYPES 1
#define PARSE_COLNAMES 2
#endif

View File

@@ -0,0 +1,84 @@
/* prepare_protocol.c - the protocol for preparing values for SQLite
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "sqlitecompat.h"
#include "prepare_protocol.h"
int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs)
{
return 0;
}
void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self)
{
Py_TYPE(self)->tp_free((PyObject*)self);
}
PyTypeObject pysqlite_PrepareProtocolType= {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".PrepareProtocol", /* tp_name */
sizeof(pysqlite_PrepareProtocol), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_prepare_protocol_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pysqlite_prepare_protocol_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
extern int pysqlite_prepare_protocol_setup_types(void)
{
pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew;
Py_TYPE(&pysqlite_PrepareProtocolType)= &PyType_Type;
return PyType_Ready(&pysqlite_PrepareProtocolType);
}

View File

@@ -0,0 +1,41 @@
/* prepare_protocol.h - the protocol for preparing values for SQLite
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_PREPARE_PROTOCOL_H
#define PYSQLITE_PREPARE_PROTOCOL_H
#include "Python.h"
typedef struct
{
PyObject_HEAD
} pysqlite_PrepareProtocol;
extern PyTypeObject pysqlite_PrepareProtocolType;
int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs);
void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self);
int pysqlite_prepare_protocol_setup_types(void);
#define UNKNOWN (-1)
#endif

View File

@@ -0,0 +1,256 @@
/* row.c - an enhanced tuple for database rows
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "row.h"
#include "cursor.h"
#include "sqlitecompat.h"
void pysqlite_row_dealloc(pysqlite_Row* self)
{
Py_XDECREF(self->data);
Py_XDECREF(self->description);
Py_TYPE(self)->tp_free((PyObject*)self);
}
int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
{
PyObject* data;
pysqlite_Cursor* cursor;
self->data = 0;
self->description = 0;
if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) {
return -1;
}
if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) {
PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument");
return -1;
}
if (!PyTuple_Check(data)) {
PyErr_SetString(PyExc_TypeError, "tuple required for second argument");
return -1;
}
Py_INCREF(data);
self->data = data;
Py_INCREF(cursor->description);
self->description = cursor->description;
return 0;
}
PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx)
{
long _idx;
char* key;
int nitems, i;
char* compare_key;
char* p1;
char* p2;
PyObject* item;
if (PyInt_Check(idx)) {
_idx = PyInt_AsLong(idx);
item = PyTuple_GetItem(self->data, _idx);
Py_XINCREF(item);
return item;
} else if (PyLong_Check(idx)) {
_idx = PyLong_AsLong(idx);
item = PyTuple_GetItem(self->data, _idx);
Py_XINCREF(item);
return item;
} else if (PyString_Check(idx)) {
key = PyString_AsString(idx);
nitems = PyTuple_Size(self->description);
for (i = 0; i < nitems; i++) {
compare_key = PyString_AsString(PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0));
if (!compare_key) {
return NULL;
}
p1 = key;
p2 = compare_key;
while (1) {
if ((*p1 == (char)0) || (*p2 == (char)0)) {
break;
}
if ((*p1 | 0x20) != (*p2 | 0x20)) {
break;
}
p1++;
p2++;
}
if ((*p1 == (char)0) && (*p2 == (char)0)) {
/* found item */
item = PyTuple_GetItem(self->data, i);
Py_INCREF(item);
return item;
}
}
PyErr_SetString(PyExc_IndexError, "No item with that key");
return NULL;
} else if (PySlice_Check(idx)) {
PyErr_SetString(PyExc_ValueError, "slices not implemented, yet");
return NULL;
} else {
PyErr_SetString(PyExc_IndexError, "Index must be int or string");
return NULL;
}
}
Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
{
return PyTuple_GET_SIZE(self->data);
}
PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs)
{
PyObject* list;
int nitems, i;
list = PyList_New(0);
if (!list) {
return NULL;
}
nitems = PyTuple_Size(self->description);
for (i = 0; i < nitems; i++) {
if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) {
Py_DECREF(list);
return NULL;
}
}
return list;
}
static int pysqlite_row_print(pysqlite_Row* self, FILE *fp, int flags)
{
return (&PyTuple_Type)->tp_print(self->data, fp, flags);
}
static PyObject* pysqlite_iter(pysqlite_Row* self)
{
return PyObject_GetIter(self->data);
}
static long pysqlite_row_hash(pysqlite_Row *self)
{
return PyObject_Hash(self->description) ^ PyObject_Hash(self->data);
}
static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid)
{
if (opid != Py_EQ && opid != Py_NE) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) {
pysqlite_Row *other = (pysqlite_Row *)_other;
PyObject *res = PyObject_RichCompare(self->description, other->description, opid);
if ((opid == Py_EQ && res == Py_True)
|| (opid == Py_NE && res == Py_False)) {
Py_DECREF(res);
return PyObject_RichCompare(self->data, other->data, opid);
}
}
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
PyMappingMethods pysqlite_row_as_mapping = {
/* mp_length */ (lenfunc)pysqlite_row_length,
/* mp_subscript */ (binaryfunc)pysqlite_row_subscript,
/* mp_ass_subscript */ (objobjargproc)0,
};
static PyMethodDef pysqlite_row_methods[] = {
{"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS,
PyDoc_STR("Returns the keys of the row.")},
{NULL, NULL}
};
PyTypeObject pysqlite_RowType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".Row", /* tp_name */
sizeof(pysqlite_Row), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_row_dealloc, /* tp_dealloc */
(printfunc)pysqlite_row_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)pysqlite_row_hash, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)0, /* tp_traverse */
0, /* tp_clear */
(richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)pysqlite_iter, /* tp_iter */
0, /* tp_iternext */
pysqlite_row_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)pysqlite_row_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
extern int pysqlite_row_setup_types(void)
{
pysqlite_RowType.tp_new = PyType_GenericNew;
pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping;
return PyType_Ready(&pysqlite_RowType);
}

View File

@@ -0,0 +1,39 @@
/* row.h - an enhanced tuple for database rows
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_ROW_H
#define PYSQLITE_ROW_H
#include "Python.h"
typedef struct _Row
{
PyObject_HEAD
PyObject* data;
PyObject* description;
} pysqlite_Row;
extern PyTypeObject pysqlite_RowType;
int pysqlite_row_setup_types(void);
#endif

View File

@@ -0,0 +1,63 @@
/* sqlitecompat.h - compatibility macros
*
* Copyright (C) 2006-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "Python.h"
#ifndef PYSQLITE_COMPAT_H
#define PYSQLITE_COMPAT_H
/* define Py_ssize_t for pre-2.5 versions of Python */
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
typedef int (*lenfunc)(PyObject*);
#endif
/* define PyDict_CheckExact for pre-2.4 versions of Python */
#ifndef PyDict_CheckExact
#define PyDict_CheckExact(op) ((op)->ob_type == &PyDict_Type)
#endif
/* define Py_CLEAR for pre-2.4 versions of Python */
#ifndef Py_CLEAR
#define Py_CLEAR(op) \
do { \
if (op) { \
PyObject *tmp = (PyObject *)(op); \
(op) = NULL; \
Py_DECREF(tmp); \
} \
} while (0)
#endif
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#endif
#ifndef Py_TYPE
#define Py_TYPE(ob) ((ob)->ob_type)
#endif
#endif

View File

@@ -0,0 +1,543 @@
/* statement.c - the statement type
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "statement.h"
#include "cursor.h"
#include "connection.h"
#include "microprotocols.h"
#include "prepare_protocol.h"
#include "sqlitecompat.h"
/* prototypes */
static int pysqlite_check_remaining_sql(const char* tail);
typedef enum {
LINECOMMENT_1,
IN_LINECOMMENT,
COMMENTSTART_1,
IN_COMMENT,
COMMENTEND_1,
NORMAL
} parse_remaining_sql_state;
typedef enum {
TYPE_INT,
TYPE_LONG,
TYPE_FLOAT,
TYPE_STRING,
TYPE_UNICODE,
TYPE_BUFFER,
TYPE_UNKNOWN
} parameter_type;
int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql)
{
const char* tail;
int rc;
PyObject* sql_str;
char* sql_cstr;
self->st = NULL;
self->in_use = 0;
if (PyString_Check(sql)) {
sql_str = sql;
Py_INCREF(sql_str);
} else if (PyUnicode_Check(sql)) {
sql_str = PyUnicode_AsUTF8String(sql);
if (!sql_str) {
rc = PYSQLITE_SQL_WRONG_TYPE;
return rc;
}
} else {
rc = PYSQLITE_SQL_WRONG_TYPE;
return rc;
}
self->in_weakreflist = NULL;
self->sql = sql_str;
sql_cstr = PyString_AsString(sql_str);
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(connection->db,
sql_cstr,
-1,
&self->st,
&tail);
Py_END_ALLOW_THREADS
self->db = connection->db;
if (rc == SQLITE_OK && pysqlite_check_remaining_sql(tail)) {
(void)sqlite3_finalize(self->st);
self->st = NULL;
rc = PYSQLITE_TOO_MUCH_SQL;
}
return rc;
}
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars)
{
int rc = SQLITE_OK;
long longval;
PY_LONG_LONG longlongval;
const char* buffer;
char* string;
Py_ssize_t buflen;
PyObject* stringval;
parameter_type paramtype;
char* c;
if (parameter == Py_None) {
rc = sqlite3_bind_null(self->st, pos);
goto final;
}
if (PyInt_CheckExact(parameter)) {
paramtype = TYPE_INT;
} else if (PyLong_CheckExact(parameter)) {
paramtype = TYPE_LONG;
} else if (PyFloat_CheckExact(parameter)) {
paramtype = TYPE_FLOAT;
} else if (PyString_CheckExact(parameter)) {
paramtype = TYPE_STRING;
} else if (PyUnicode_CheckExact(parameter)) {
paramtype = TYPE_UNICODE;
} else if (PyBuffer_Check(parameter)) {
paramtype = TYPE_BUFFER;
} else if (PyInt_Check(parameter)) {
paramtype = TYPE_INT;
} else if (PyLong_Check(parameter)) {
paramtype = TYPE_LONG;
} else if (PyFloat_Check(parameter)) {
paramtype = TYPE_FLOAT;
} else if (PyString_Check(parameter)) {
paramtype = TYPE_STRING;
} else if (PyUnicode_Check(parameter)) {
paramtype = TYPE_UNICODE;
} else {
paramtype = TYPE_UNKNOWN;
}
if (paramtype == TYPE_STRING && !allow_8bit_chars) {
string = PyString_AS_STRING(parameter);
for (c = string; *c != 0; c++) {
if (*c & 0x80) {
PyErr_SetString(pysqlite_ProgrammingError, "You must not use 8-bit bytestrings unless you use a text_factory that can interpret 8-bit bytestrings (like text_factory = str). It is highly recommended that you instead just switch your application to Unicode strings.");
rc = -1;
goto final;
}
}
}
switch (paramtype) {
case TYPE_INT:
longval = PyInt_AsLong(parameter);
rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longval);
break;
case TYPE_LONG:
longlongval = PyLong_AsLongLong(parameter);
/* in the overflow error case, longlongval is -1, and an exception is set */
rc = sqlite3_bind_int64(self->st, pos, (sqlite_int64)longlongval);
break;
case TYPE_FLOAT:
rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter));
break;
case TYPE_STRING:
string = PyString_AS_STRING(parameter);
rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
break;
case TYPE_UNICODE:
stringval = PyUnicode_AsUTF8String(parameter);
string = PyString_AsString(stringval);
rc = sqlite3_bind_text(self->st, pos, string, -1, SQLITE_TRANSIENT);
Py_DECREF(stringval);
break;
case TYPE_BUFFER:
if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) == 0) {
rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT);
} else {
PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer");
rc = -1;
}
break;
case TYPE_UNKNOWN:
rc = -1;
}
final:
return rc;
}
/* returns 0 if the object is one of Python's internal ones that don't need to be adapted */
static int _need_adapt(PyObject* obj)
{
if (pysqlite_BaseTypeAdapted) {
return 1;
}
if (PyInt_CheckExact(obj) || PyLong_CheckExact(obj)
|| PyFloat_CheckExact(obj) || PyString_CheckExact(obj)
|| PyUnicode_CheckExact(obj) || PyBuffer_Check(obj)) {
return 0;
} else {
return 1;
}
}
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars)
{
PyObject* current_param;
PyObject* adapted;
const char* binding_name;
int i;
int rc;
int num_params_needed;
int num_params;
Py_BEGIN_ALLOW_THREADS
num_params_needed = sqlite3_bind_parameter_count(self->st);
Py_END_ALLOW_THREADS
if (PyTuple_CheckExact(parameters) || PyList_CheckExact(parameters) || (!PyDict_Check(parameters) && PySequence_Check(parameters))) {
/* parameters passed as sequence */
if (PyTuple_CheckExact(parameters)) {
num_params = PyTuple_GET_SIZE(parameters);
} else if (PyList_CheckExact(parameters)) {
num_params = PyList_GET_SIZE(parameters);
} else {
num_params = PySequence_Size(parameters);
}
if (num_params != num_params_needed) {
PyErr_Format(pysqlite_ProgrammingError, "Incorrect number of bindings supplied. The current statement uses %d, and there are %d supplied.",
num_params_needed, num_params);
return;
}
for (i = 0; i < num_params; i++) {
if (PyTuple_CheckExact(parameters)) {
current_param = PyTuple_GET_ITEM(parameters, i);
Py_XINCREF(current_param);
} else if (PyList_CheckExact(parameters)) {
current_param = PyList_GET_ITEM(parameters, i);
Py_XINCREF(current_param);
} else {
current_param = PySequence_GetItem(parameters, i);
}
if (!current_param) {
return;
}
if (!_need_adapt(current_param)) {
adapted = current_param;
} else {
adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL);
if (adapted) {
Py_DECREF(current_param);
} else {
PyErr_Clear();
adapted = current_param;
}
}
rc = pysqlite_statement_bind_parameter(self, i + 1, adapted, allow_8bit_chars);
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
if (!PyErr_Occurred()) {
PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i);
}
return;
}
}
} else if (PyDict_Check(parameters)) {
/* parameters passed as dictionary */
for (i = 1; i <= num_params_needed; i++) {
Py_BEGIN_ALLOW_THREADS
binding_name = sqlite3_bind_parameter_name(self->st, i);
Py_END_ALLOW_THREADS
if (!binding_name) {
PyErr_Format(pysqlite_ProgrammingError, "Binding %d has no name, but you supplied a dictionary (which has only names).", i);
return;
}
binding_name++; /* skip first char (the colon) */
if (PyDict_CheckExact(parameters)) {
current_param = PyDict_GetItemString(parameters, binding_name);
Py_XINCREF(current_param);
} else {
current_param = PyMapping_GetItemString(parameters, (char*)binding_name);
}
if (!current_param) {
PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i);
return;
}
if (!_need_adapt(current_param)) {
adapted = current_param;
} else {
adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL);
if (adapted) {
Py_DECREF(current_param);
} else {
PyErr_Clear();
adapted = current_param;
}
}
rc = pysqlite_statement_bind_parameter(self, i, adapted, allow_8bit_chars);
Py_DECREF(adapted);
if (rc != SQLITE_OK) {
if (!PyErr_Occurred()) {
PyErr_Format(pysqlite_InterfaceError, "Error binding parameter :%s - probably unsupported type.", binding_name);
}
return;
}
}
} else {
PyErr_SetString(PyExc_ValueError, "parameters are of unsupported type");
}
}
int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params)
{
const char* tail;
int rc;
char* sql_cstr;
sqlite3_stmt* new_st;
sql_cstr = PyString_AsString(self->sql);
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_prepare(self->db,
sql_cstr,
-1,
&new_st,
&tail);
Py_END_ALLOW_THREADS
if (rc == SQLITE_OK) {
/* The efficient sqlite3_transfer_bindings is only available in SQLite
* version 3.2.2 or later. For older SQLite releases, that might not
* even define SQLITE_VERSION_NUMBER, we do it the manual way.
*/
#ifdef SQLITE_VERSION_NUMBER
#if SQLITE_VERSION_NUMBER >= 3002002
/* The check for the number of parameters is necessary to not trigger a
* bug in certain SQLite versions (experienced in 3.2.8 and 3.3.4). */
if (sqlite3_bind_parameter_count(self->st) > 0) {
(void)sqlite3_transfer_bindings(self->st, new_st);
}
#endif
#else
statement_bind_parameters(self, params);
#endif
(void)sqlite3_finalize(self->st);
self->st = new_st;
}
return rc;
}
int pysqlite_statement_finalize(pysqlite_Statement* self)
{
int rc;
rc = SQLITE_OK;
if (self->st) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize(self->st);
Py_END_ALLOW_THREADS
self->st = NULL;
}
self->in_use = 0;
return rc;
}
int pysqlite_statement_reset(pysqlite_Statement* self)
{
int rc;
rc = SQLITE_OK;
if (self->in_use && self->st) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_reset(self->st);
Py_END_ALLOW_THREADS
if (rc == SQLITE_OK) {
self->in_use = 0;
}
}
return rc;
}
void pysqlite_statement_mark_dirty(pysqlite_Statement* self)
{
self->in_use = 1;
}
void pysqlite_statement_dealloc(pysqlite_Statement* self)
{
int rc;
if (self->st) {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_finalize(self->st);
Py_END_ALLOW_THREADS
}
self->st = NULL;
Py_XDECREF(self->sql);
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject*)self);
}
Py_TYPE(self)->tp_free((PyObject*)self);
}
/*
* Checks if there is anything left in an SQL string after SQLite compiled it.
* This is used to check if somebody tried to execute more than one SQL command
* with one execute()/executemany() command, which the DB-API and we don't
* allow.
*
* Returns 1 if there is more left than should be. 0 if ok.
*/
static int pysqlite_check_remaining_sql(const char* tail)
{
const char* pos = tail;
parse_remaining_sql_state state = NORMAL;
for (;;) {
switch (*pos) {
case 0:
return 0;
case '-':
if (state == NORMAL) {
state = LINECOMMENT_1;
} else if (state == LINECOMMENT_1) {
state = IN_LINECOMMENT;
}
break;
case ' ':
case '\t':
break;
case '\n':
case 13:
if (state == IN_LINECOMMENT) {
state = NORMAL;
}
break;
case '/':
if (state == NORMAL) {
state = COMMENTSTART_1;
} else if (state == COMMENTEND_1) {
state = NORMAL;
} else if (state == COMMENTSTART_1) {
return 1;
}
break;
case '*':
if (state == NORMAL) {
return 1;
} else if (state == LINECOMMENT_1) {
return 1;
} else if (state == COMMENTSTART_1) {
state = IN_COMMENT;
} else if (state == IN_COMMENT) {
state = COMMENTEND_1;
}
break;
default:
if (state == COMMENTEND_1) {
state = IN_COMMENT;
} else if (state == IN_LINECOMMENT) {
} else if (state == IN_COMMENT) {
} else {
return 1;
}
}
pos++;
}
return 0;
}
PyTypeObject pysqlite_StatementType = {
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME ".Statement", /* tp_name */
sizeof(pysqlite_Statement), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)pysqlite_statement_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(pysqlite_Statement, in_weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0 /* tp_free */
};
extern int pysqlite_statement_setup_types(void)
{
pysqlite_StatementType.tp_new = PyType_GenericNew;
return PyType_Ready(&pysqlite_StatementType);
}

View File

@@ -0,0 +1,59 @@
/* statement.h - definitions for the statement type
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_STATEMENT_H
#define PYSQLITE_STATEMENT_H
#include "Python.h"
#include "connection.h"
#include "sqlite3.h"
#define PYSQLITE_TOO_MUCH_SQL (-100)
#define PYSQLITE_SQL_WRONG_TYPE (-101)
typedef struct
{
PyObject_HEAD
sqlite3* db;
sqlite3_stmt* st;
PyObject* sql;
int in_use;
PyObject* in_weakreflist; /* List of weak references */
} pysqlite_Statement;
extern PyTypeObject pysqlite_StatementType;
int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql);
void pysqlite_statement_dealloc(pysqlite_Statement* self);
int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter, int allow_8bit_chars);
void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters, int allow_8bit_chars);
int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters);
int pysqlite_statement_finalize(pysqlite_Statement* self);
int pysqlite_statement_reset(pysqlite_Statement* self);
void pysqlite_statement_mark_dirty(pysqlite_Statement* self);
int pysqlite_statement_setup_types(void);
#endif

View File

@@ -0,0 +1,106 @@
/* util.c - various utility functions
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include "module.h"
#include "connection.h"
int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection)
{
int rc;
if (statement == NULL) {
/* this is a workaround for SQLite 3.5 and later. it now apparently
* returns NULL for "no-operation" statements */
rc = SQLITE_OK;
} else {
Py_BEGIN_ALLOW_THREADS
rc = sqlite3_step(statement);
Py_END_ALLOW_THREADS
}
return rc;
}
/**
* Checks the SQLite error code and sets the appropriate DB-API exception.
* Returns the error code (0 means no error occurred).
*/
int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st)
{
int errorcode;
/* SQLite often doesn't report anything useful, unless you reset the statement first */
if (st != NULL) {
(void)sqlite3_reset(st);
}
errorcode = sqlite3_errcode(db);
switch (errorcode)
{
case SQLITE_OK:
PyErr_Clear();
break;
case SQLITE_INTERNAL:
case SQLITE_NOTFOUND:
PyErr_SetString(pysqlite_InternalError, sqlite3_errmsg(db));
break;
case SQLITE_NOMEM:
(void)PyErr_NoMemory();
break;
case SQLITE_ERROR:
case SQLITE_PERM:
case SQLITE_ABORT:
case SQLITE_BUSY:
case SQLITE_LOCKED:
case SQLITE_READONLY:
case SQLITE_INTERRUPT:
case SQLITE_IOERR:
case SQLITE_FULL:
case SQLITE_CANTOPEN:
case SQLITE_PROTOCOL:
case SQLITE_EMPTY:
case SQLITE_SCHEMA:
PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db));
break;
case SQLITE_CORRUPT:
PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
break;
case SQLITE_TOOBIG:
PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db));
break;
case SQLITE_CONSTRAINT:
case SQLITE_MISMATCH:
PyErr_SetString(pysqlite_IntegrityError, sqlite3_errmsg(db));
break;
case SQLITE_MISUSE:
PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db));
break;
default:
PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db));
break;
}
return errorcode;
}

View File

@@ -0,0 +1,38 @@
/* util.h - various utility functions
*
* Copyright (C) 2005-2010 Gerhard H<>ring <gh@ghaering.de>
*
* This file is part of pysqlite.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef PYSQLITE_UTIL_H
#define PYSQLITE_UTIL_H
#include "Python.h"
#include "pythread.h"
#include "sqlite3.h"
#include "connection.h"
int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection);
/**
* Checks the SQLite error code and sets the appropriate DB-API exception.
* Returns the error code (0 means no error occurred).
*/
int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,112 @@
#include "Python.h"
#define GET_WEAKREFS_LISTPTR(o) \
((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
PyDoc_STRVAR(weakref_getweakrefcount__doc__,
"getweakrefcount(object) -- return the number of weak references\n"
"to 'object'.");
static PyObject *
weakref_getweakrefcount(PyObject *self, PyObject *object)
{
PyObject *result = NULL;
if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
result = PyInt_FromSsize_t(_PyWeakref_GetWeakrefCount(*list));
}
else
result = PyInt_FromLong(0);
return result;
}
PyDoc_STRVAR(weakref_getweakrefs__doc__,
"getweakrefs(object) -- return a list of all weak reference objects\n"
"that point to 'object'.");
static PyObject *
weakref_getweakrefs(PyObject *self, PyObject *object)
{
PyObject *result = NULL;
if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
result = PyList_New(count);
if (result != NULL) {
PyWeakReference *current = *list;
Py_ssize_t i;
for (i = 0; i < count; ++i) {
PyList_SET_ITEM(result, i, (PyObject *) current);
Py_INCREF(current);
current = current->wr_next;
}
}
}
else {
result = PyList_New(0);
}
return result;
}
PyDoc_STRVAR(weakref_proxy__doc__,
"proxy(object[, callback]) -- create a proxy object that weakly\n"
"references 'object'. 'callback', if given, is called with a\n"
"reference to the proxy when 'object' is about to be finalized.");
static PyObject *
weakref_proxy(PyObject *self, PyObject *args)
{
PyObject *object;
PyObject *callback = NULL;
PyObject *result = NULL;
if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) {
result = PyWeakref_NewProxy(object, callback);
}
return result;
}
static PyMethodDef
weakref_functions[] = {
{"getweakrefcount", weakref_getweakrefcount, METH_O,
weakref_getweakrefcount__doc__},
{"getweakrefs", weakref_getweakrefs, METH_O,
weakref_getweakrefs__doc__},
{"proxy", weakref_proxy, METH_VARARGS,
weakref_proxy__doc__},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC
init_weakref(void)
{
PyObject *m;
m = Py_InitModule3("_weakref", weakref_functions,
"Weak-reference support module.");
if (m != NULL) {
Py_INCREF(&_PyWeakref_RefType);
PyModule_AddObject(m, "ref",
(PyObject *) &_PyWeakref_RefType);
Py_INCREF(&_PyWeakref_RefType);
PyModule_AddObject(m, "ReferenceType",
(PyObject *) &_PyWeakref_RefType);
Py_INCREF(&_PyWeakref_ProxyType);
PyModule_AddObject(m, "ProxyType",
(PyObject *) &_PyWeakref_ProxyType);
Py_INCREF(&_PyWeakref_CallableProxyType);
PyModule_AddObject(m, "CallableProxyType",
(PyObject *) &_PyWeakref_CallableProxyType);
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef HAVE_GETADDRINFO
/*
* Error return codes from getaddrinfo()
*/
#ifdef EAI_ADDRFAMILY
/* If this is defined, there is a conflicting implementation
in the C library, which can't be used for some reason.
Make sure it won't interfere with this emulation. */
#undef EAI_ADDRFAMILY
#undef EAI_AGAIN
#undef EAI_BADFLAGS
#undef EAI_FAIL
#undef EAI_FAMILY
#undef EAI_MEMORY
#undef EAI_NODATA
#undef EAI_NONAME
#undef EAI_SERVICE
#undef EAI_SOCKTYPE
#undef EAI_SYSTEM
#undef EAI_BADHINTS
#undef EAI_PROTOCOL
#undef EAI_MAX
#undef getaddrinfo
#define getaddrinfo fake_getaddrinfo
#endif /* EAI_ADDRFAMILY */
#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
#define EAI_AGAIN 2 /* temporary failure in name resolution */
#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
#define EAI_FAMILY 5 /* ai_family not supported */
#define EAI_MEMORY 6 /* memory allocation failure */
#define EAI_NODATA 7 /* no address associated with hostname */
#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
#define EAI_SYSTEM 11 /* system error returned in errno */
#define EAI_BADHINTS 12
#define EAI_PROTOCOL 13
#define EAI_MAX 14
/*
* Flag values for getaddrinfo()
*/
#ifdef AI_PASSIVE
#undef AI_PASSIVE
#undef AI_CANONNAME
#undef AI_NUMERICHOST
#undef AI_MASK
#undef AI_ALL
#undef AI_V4MAPPED_CFG
#undef AI_ADDRCONFIG
#undef AI_V4MAPPED
#undef AI_DEFAULT
#endif /* AI_PASSIVE */
#define AI_PASSIVE 0x00000001 /* get address to use bind() */
#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
/* valid flags for addrinfo */
#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
/* special recommended flags for getipnodebyname */
#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
#endif /* !HAVE_GETADDRINFO */
#ifndef HAVE_GETNAMEINFO
/*
* Constants for getnameinfo()
*/
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#define NI_MAXSERV 32
#endif /* !NI_MAXHOST */
/*
* Flag values for getnameinfo()
*/
#ifndef NI_NOFQDN
#define NI_NOFQDN 0x00000001
#define NI_NUMERICHOST 0x00000002
#define NI_NAMEREQD 0x00000004
#define NI_NUMERICSERV 0x00000008
#define NI_DGRAM 0x00000010
#endif /* !NI_NOFQDN */
#endif /* !HAVE_GETNAMEINFO */
#ifndef _SYS_SOCKET_H_
#ifndef HAVE_ADDRINFO
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
#endif /* !HAVE_ADDRINFO */
#ifndef HAVE_SOCKADDR_STORAGE
/*
* RFC 2553: protocol-independent placeholder for socket addresses
*/
#define _SS_MAXSIZE 128
#ifdef HAVE_LONG_LONG
#define _SS_ALIGNSIZE (sizeof(PY_LONG_LONG))
#else
#define _SS_ALIGNSIZE (sizeof(double))
#endif /* HAVE_LONG_LONG */
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_char) * 2)
#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(u_char) * 2 - \
_SS_PAD1SIZE - _SS_ALIGNSIZE)
struct sockaddr_storage {
#ifdef HAVE_SOCKADDR_SA_LEN
unsigned char ss_len; /* address length */
unsigned char ss_family; /* address family */
#else
unsigned short ss_family; /* address family */
#endif /* HAVE_SOCKADDR_SA_LEN */
char __ss_pad1[_SS_PAD1SIZE];
#ifdef HAVE_LONG_LONG
PY_LONG_LONG __ss_align; /* force desired structure storage alignment */
#else
double __ss_align; /* force desired structure storage alignment */
#endif /* HAVE_LONG_LONG */
char __ss_pad2[_SS_PAD2SIZE];
};
#endif /* !HAVE_SOCKADDR_STORAGE */
#endif /* _SYS_SOCKET_H_ */
#ifdef __cplusplus
extern "C" {
#endif
extern void freehostent Py_PROTO((struct hostent *));
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,752 @@
#include "Python.h"
#include "import.h"
#include "cStringIO.h"
#include "structmember.h"
PyDoc_STRVAR(cStringIO_module_documentation,
"A simple fast partial StringIO replacement.\n"
"\n"
"This module provides a simple useful replacement for\n"
"the StringIO module that is written in C. It does not provide the\n"
"full generality of StringIO, but it provides enough for most\n"
"applications and is especially useful in conjunction with the\n"
"pickle module.\n"
"\n"
"Usage:\n"
"\n"
" from cStringIO import StringIO\n"
"\n"
" an_output_stream=StringIO()\n"
" an_output_stream.write(some_stuff)\n"
" ...\n"
" value=an_output_stream.getvalue()\n"
"\n"
" an_input_stream=StringIO(a_string)\n"
" spam=an_input_stream.readline()\n"
" spam=an_input_stream.read(5)\n"
" an_input_stream.seek(0) # OK, start over\n"
" spam=an_input_stream.read() # and read it all\n"
" \n"
"If someone else wants to provide a more complete implementation,\n"
"go for it. :-) \n"
"\n"
"cStringIO.c,v 1.29 1999/06/15 14:10:27 jim Exp\n");
/* Declaration for file-like objects that manage data as strings
The IOobject type should be though of as a common base type for
Iobjects, which provide input (read-only) StringIO objects and
Oobjects, which provide read-write objects. Most of the methods
depend only on common data.
*/
typedef struct {
PyObject_HEAD
char *buf;
Py_ssize_t pos, string_size;
} IOobject;
#define IOOOBJECT(O) ((IOobject*)(O))
/* Declarations for objects of type StringO */
typedef struct { /* Subtype of IOobject */
PyObject_HEAD
char *buf;
Py_ssize_t pos, string_size;
Py_ssize_t buf_size;
int softspace;
} Oobject;
/* Declarations for objects of type StringI */
typedef struct { /* Subtype of IOobject */
PyObject_HEAD
char *buf;
Py_ssize_t pos, string_size;
/* We store a reference to the object here in order to keep
the buffer alive during the lifetime of the Iobject. */
PyObject *pbuf;
} Iobject;
/* IOobject (common) methods */
PyDoc_STRVAR(IO_flush__doc__, "flush(): does nothing.");
static int
IO__opencheck(IOobject *self) {
if (!self->buf) {
PyErr_SetString(PyExc_ValueError,
"I/O operation on closed file");
return 0;
}
return 1;
}
static PyObject *
IO_get_closed(IOobject *self, void *closure)
{
PyObject *result = Py_False;
if (self->buf == NULL)
result = Py_True;
Py_INCREF(result);
return result;
}
static PyGetSetDef file_getsetlist[] = {
{"closed", (getter)IO_get_closed, NULL, "True if the file is closed"},
{0},
};
static PyObject *
IO_flush(IOobject *self, PyObject *unused) {
if (!IO__opencheck(self)) return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(IO_getval__doc__,
"getvalue([use_pos]) -- Get the string value."
"\n"
"If use_pos is specified and is a true value, then the string returned\n"
"will include only the text up to the current file position.\n");
static PyObject *
IO_cgetval(PyObject *self) {
if (!IO__opencheck(IOOOBJECT(self))) return NULL;
assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(((IOobject*)self)->buf,
((IOobject*)self)->pos);
}
static PyObject *
IO_getval(IOobject *self, PyObject *args) {
PyObject *use_pos=Py_None;
Py_ssize_t s;
if (!IO__opencheck(self)) return NULL;
if (!PyArg_UnpackTuple(args,"getval", 0, 1,&use_pos)) return NULL;
if (PyObject_IsTrue(use_pos)) {
s=self->pos;
if (s > self->string_size) s=self->string_size;
}
else
s=self->string_size;
assert(self->pos >= 0);
return PyString_FromStringAndSize(self->buf, s);
}
PyDoc_STRVAR(IO_isatty__doc__, "isatty(): always returns 0");
static PyObject *
IO_isatty(IOobject *self, PyObject *unused) {
if (!IO__opencheck(self)) return NULL;
Py_INCREF(Py_False);
return Py_False;
}
PyDoc_STRVAR(IO_read__doc__,
"read([s]) -- Read s characters, or the rest of the string");
static int
IO_cread(PyObject *self, char **output, Py_ssize_t n) {
Py_ssize_t l;
if (!IO__opencheck(IOOOBJECT(self))) return -1;
assert(IOOOBJECT(self)->pos >= 0);
assert(IOOOBJECT(self)->string_size >= 0);
l = ((IOobject*)self)->string_size - ((IOobject*)self)->pos;
if (n < 0 || n > l) {
n = l;
if (n < 0) n=0;
}
*output=((IOobject*)self)->buf + ((IOobject*)self)->pos;
((IOobject*)self)->pos += n;
return n;
}
static PyObject *
IO_read(IOobject *self, PyObject *args) {
Py_ssize_t n = -1;
char *output = NULL;
if (!PyArg_ParseTuple(args, "|n:read", &n)) return NULL;
if ( (n=IO_cread((PyObject*)self,&output,n)) < 0) return NULL;
return PyString_FromStringAndSize(output, n);
}
PyDoc_STRVAR(IO_readline__doc__, "readline() -- Read one line");
static int
IO_creadline(PyObject *self, char **output) {
char *n, *s;
Py_ssize_t l;
if (!IO__opencheck(IOOOBJECT(self))) return -1;
for (n = ((IOobject*)self)->buf + ((IOobject*)self)->pos,
s = ((IOobject*)self)->buf + ((IOobject*)self)->string_size;
n < s && *n != '\n'; n++);
if (n < s) n++;
*output=((IOobject*)self)->buf + ((IOobject*)self)->pos;
l = n - ((IOobject*)self)->buf - ((IOobject*)self)->pos;
assert(IOOOBJECT(self)->pos <= PY_SSIZE_T_MAX - l);
assert(IOOOBJECT(self)->pos >= 0);
assert(IOOOBJECT(self)->string_size >= 0);
((IOobject*)self)->pos += l;
return (int)l;
}
static PyObject *
IO_readline(IOobject *self, PyObject *args) {
int n, m=-1;
char *output;
if (args)
if (!PyArg_ParseTuple(args, "|i:readline", &m)) return NULL;
if( (n=IO_creadline((PyObject*)self,&output)) < 0) return NULL;
if (m >= 0 && m < n) {
m = n - m;
n -= m;
self->pos -= m;
}
assert(IOOOBJECT(self)->pos >= 0);
return PyString_FromStringAndSize(output, n);
}
PyDoc_STRVAR(IO_readlines__doc__, "readlines() -- Read all lines");
static PyObject *
IO_readlines(IOobject *self, PyObject *args) {
int n;
char *output;
PyObject *result, *line;
int hint = 0, length = 0;
if (!PyArg_ParseTuple(args, "|i:readlines", &hint)) return NULL;
result = PyList_New(0);
if (!result)
return NULL;
while (1){
if ( (n = IO_creadline((PyObject*)self,&output)) < 0)
goto err;
if (n == 0)
break;
line = PyString_FromStringAndSize (output, n);
if (!line)
goto err;
if (PyList_Append (result, line) == -1) {
Py_DECREF (line);
goto err;
}
Py_DECREF (line);
length += n;
if (hint > 0 && length >= hint)
break;
}
return result;
err:
Py_DECREF(result);
return NULL;
}
PyDoc_STRVAR(IO_reset__doc__,
"reset() -- Reset the file position to the beginning");
static PyObject *
IO_reset(IOobject *self, PyObject *unused) {
if (!IO__opencheck(self)) return NULL;
self->pos = 0;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(IO_tell__doc__, "tell() -- get the current position.");
static PyObject *
IO_tell(IOobject *self, PyObject *unused) {
if (!IO__opencheck(self)) return NULL;
assert(self->pos >= 0);
return PyInt_FromSsize_t(self->pos);
}
PyDoc_STRVAR(IO_truncate__doc__,
"truncate(): truncate the file at the current position.");
static PyObject *
IO_truncate(IOobject *self, PyObject *args) {
Py_ssize_t pos = -1;
if (!IO__opencheck(self)) return NULL;
if (!PyArg_ParseTuple(args, "|n:truncate", &pos)) return NULL;
if (PyTuple_Size(args) == 0) {
/* No argument passed, truncate to current position */
pos = self->pos;
}
if (pos < 0) {
errno = EINVAL;
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
if (self->string_size > pos) self->string_size = pos;
self->pos = self->string_size;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
IO_iternext(Iobject *self)
{
PyObject *next;
next = IO_readline((IOobject *)self, NULL);
if (!next)
return NULL;
if (!PyString_GET_SIZE(next)) {
Py_DECREF(next);
PyErr_SetNone(PyExc_StopIteration);
return NULL;
}
return next;
}
/* Read-write object methods */
PyDoc_STRVAR(IO_seek__doc__,
"seek(position) -- set the current position\n"
"seek(position, mode) -- mode 0: absolute; 1: relative; 2: relative to EOF");
static PyObject *
IO_seek(Iobject *self, PyObject *args) {
Py_ssize_t position;
int mode = 0;
if (!IO__opencheck(IOOOBJECT(self))) return NULL;
if (!PyArg_ParseTuple(args, "n|i:seek", &position, &mode))
return NULL;
if (mode == 2) {
position += self->string_size;
}
else if (mode == 1) {
position += self->pos;
}
if (position < 0) position=0;
self->pos=position;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(O_write__doc__,
"write(s) -- Write a string to the file"
"\n\nNote (hack:) writing None resets the buffer");
static int
O_cwrite(PyObject *self, const char *c, Py_ssize_t l) {
Py_ssize_t newl;
Oobject *oself;
char *newbuf;
if (!IO__opencheck(IOOOBJECT(self))) return -1;
oself = (Oobject *)self;
newl = oself->pos+l;
if (newl >= oself->buf_size) {
oself->buf_size *= 2;
if (oself->buf_size <= newl) {
assert(newl + 1 < INT_MAX);
oself->buf_size = (int)(newl+1);
}
newbuf = (char*)realloc(oself->buf, oself->buf_size);
if (!newbuf) {
PyErr_SetString(PyExc_MemoryError,"out of memory");
free(oself->buf);
oself->buf = 0;
oself->buf_size = oself->pos = 0;
return -1;
}
oself->buf = newbuf;
}
if (oself->string_size < oself->pos) {
/* In case of overseek, pad with null bytes the buffer region between
the end of stream and the current position.
0 lo string_size hi
| |<---used--->|<----------available----------->|
| | <--to pad-->|<---to write---> |
0 buf position
*/
memset(oself->buf + oself->string_size, '\0',
(oself->pos - oself->string_size) * sizeof(char));
}
memcpy(oself->buf+oself->pos,c,l);
assert(oself->pos + l < INT_MAX);
oself->pos += (int)l;
if (oself->string_size < oself->pos) {
oself->string_size = oself->pos;
}
return (int)l;
}
static PyObject *
O_write(Oobject *self, PyObject *args) {
char *c;
int l;
if (!PyArg_ParseTuple(args, "t#:write", &c, &l)) return NULL;
if (O_cwrite((PyObject*)self,c,l) < 0) return NULL;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(O_close__doc__, "close(): explicitly release resources held.");
static PyObject *
O_close(Oobject *self, PyObject *unused) {
if (self->buf != NULL) free(self->buf);
self->buf = NULL;
self->pos = self->string_size = self->buf_size = 0;
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(O_writelines__doc__,
"writelines(sequence_of_strings) -> None. Write the strings to the file.\n"
"\n"
"Note that newlines are not added. The sequence can be any iterable object\n"
"producing strings. This is equivalent to calling write() for each string.");
static PyObject *
O_writelines(Oobject *self, PyObject *args) {
PyObject *it, *s;
it = PyObject_GetIter(args);
if (it == NULL)
return NULL;
while ((s = PyIter_Next(it)) != NULL) {
Py_ssize_t n;
char *c;
if (PyString_AsStringAndSize(s, &c, &n) == -1) {
Py_DECREF(it);
Py_DECREF(s);
return NULL;
}
if (O_cwrite((PyObject *)self, c, n) == -1) {
Py_DECREF(it);
Py_DECREF(s);
return NULL;
}
Py_DECREF(s);
}
Py_DECREF(it);
/* See if PyIter_Next failed */
if (PyErr_Occurred())
return NULL;
Py_RETURN_NONE;
}
static struct PyMethodDef O_methods[] = {
/* Common methods: */
{"flush", (PyCFunction)IO_flush, METH_NOARGS, IO_flush__doc__},
{"getvalue", (PyCFunction)IO_getval, METH_VARARGS, IO_getval__doc__},
{"isatty", (PyCFunction)IO_isatty, METH_NOARGS, IO_isatty__doc__},
{"read", (PyCFunction)IO_read, METH_VARARGS, IO_read__doc__},
{"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__},
{"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__},
{"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__},
{"seek", (PyCFunction)IO_seek, METH_VARARGS, IO_seek__doc__},
{"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__},
{"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__},
/* Read-write StringIO specific methods: */
{"close", (PyCFunction)O_close, METH_NOARGS, O_close__doc__},
{"write", (PyCFunction)O_write, METH_VARARGS, O_write__doc__},
{"writelines", (PyCFunction)O_writelines, METH_O, O_writelines__doc__},
{NULL, NULL} /* sentinel */
};
static PyMemberDef O_memberlist[] = {
{"softspace", T_INT, offsetof(Oobject, softspace), 0,
"flag indicating that a space needs to be printed; used by print"},
/* getattr(f, "closed") is implemented without this table */
{NULL} /* Sentinel */
};
static void
O_dealloc(Oobject *self) {
if (self->buf != NULL)
free(self->buf);
PyObject_Del(self);
}
PyDoc_STRVAR(Otype__doc__, "Simple type for output to strings.");
static PyTypeObject Otype = {
PyVarObject_HEAD_INIT(NULL, 0)
"cStringIO.StringO", /*tp_name*/
sizeof(Oobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)O_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr */
0, /*tp_setattr */
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0 , /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro */
0, /*tp_setattro */
0, /*tp_as_buffer */
Py_TPFLAGS_DEFAULT, /*tp_flags*/
Otype__doc__, /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
PyObject_SelfIter, /*tp_iter */
(iternextfunc)IO_iternext, /*tp_iternext */
O_methods, /*tp_methods */
O_memberlist, /*tp_members */
file_getsetlist, /*tp_getset */
};
static PyObject *
newOobject(int size) {
Oobject *self;
self = PyObject_New(Oobject, &Otype);
if (self == NULL)
return NULL;
self->pos=0;
self->string_size = 0;
self->softspace = 0;
self->buf = (char *)malloc(size);
if (!self->buf) {
PyErr_SetString(PyExc_MemoryError,"out of memory");
self->buf_size = 0;
Py_DECREF(self);
return NULL;
}
self->buf_size=size;
return (PyObject*)self;
}
/* End of code for StringO objects */
/* -------------------------------------------------------- */
static PyObject *
I_close(Iobject *self, PyObject *unused) {
Py_CLEAR(self->pbuf);
self->buf = NULL;
self->pos = self->string_size = 0;
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef I_methods[] = {
/* Common methods: */
{"flush", (PyCFunction)IO_flush, METH_NOARGS, IO_flush__doc__},
{"getvalue", (PyCFunction)IO_getval, METH_VARARGS, IO_getval__doc__},
{"isatty", (PyCFunction)IO_isatty, METH_NOARGS, IO_isatty__doc__},
{"read", (PyCFunction)IO_read, METH_VARARGS, IO_read__doc__},
{"readline", (PyCFunction)IO_readline, METH_VARARGS, IO_readline__doc__},
{"readlines", (PyCFunction)IO_readlines,METH_VARARGS, IO_readlines__doc__},
{"reset", (PyCFunction)IO_reset, METH_NOARGS, IO_reset__doc__},
{"seek", (PyCFunction)IO_seek, METH_VARARGS, IO_seek__doc__},
{"tell", (PyCFunction)IO_tell, METH_NOARGS, IO_tell__doc__},
{"truncate", (PyCFunction)IO_truncate, METH_VARARGS, IO_truncate__doc__},
/* Read-only StringIO specific methods: */
{"close", (PyCFunction)I_close, METH_NOARGS, O_close__doc__},
{NULL, NULL}
};
static void
I_dealloc(Iobject *self) {
Py_XDECREF(self->pbuf);
PyObject_Del(self);
}
PyDoc_STRVAR(Itype__doc__,
"Simple type for treating strings as input file streams");
static PyTypeObject Itype = {
PyVarObject_HEAD_INIT(NULL, 0)
"cStringIO.StringI", /*tp_name*/
sizeof(Iobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)I_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /* tp_getattr */
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
Itype__doc__, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
(iternextfunc)IO_iternext, /* tp_iternext */
I_methods, /* tp_methods */
0, /* tp_members */
file_getsetlist, /* tp_getset */
};
static PyObject *
newIobject(PyObject *s) {
Iobject *self;
char *buf;
Py_ssize_t size;
if (PyObject_AsReadBuffer(s, (const void **)&buf, &size)) {
PyErr_Format(PyExc_TypeError, "expected read buffer, %.200s found",
s->ob_type->tp_name);
return NULL;
}
self = PyObject_New(Iobject, &Itype);
if (!self) return NULL;
Py_INCREF(s);
self->buf=buf;
self->string_size=size;
self->pbuf=s;
self->pos=0;
return (PyObject*)self;
}
/* End of code for StringI objects */
/* -------------------------------------------------------- */
PyDoc_STRVAR(IO_StringIO__doc__,
"StringIO([s]) -- Return a StringIO-like stream for reading or writing");
static PyObject *
IO_StringIO(PyObject *self, PyObject *args) {
PyObject *s=0;
if (!PyArg_UnpackTuple(args, "StringIO", 0, 1, &s)) return NULL;
if (s) return newIobject(s);
return newOobject(128);
}
/* List of methods defined in the module */
static struct PyMethodDef IO_methods[] = {
{"StringIO", (PyCFunction)IO_StringIO,
METH_VARARGS, IO_StringIO__doc__},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initcStringIO) */
static struct PycStringIO_CAPI CAPI = {
IO_cread,
IO_creadline,
O_cwrite,
IO_cgetval,
newOobject,
newIobject,
&Itype,
&Otype,
};
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initcStringIO(void) {
PyObject *m, *d, *v;
/* Create the module and add the functions */
m = Py_InitModule4("cStringIO", IO_methods,
cStringIO_module_documentation,
(PyObject*)NULL,PYTHON_API_VERSION);
if (m == NULL) return;
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
/* Export C API */
Py_TYPE(&Itype)=&PyType_Type;
Py_TYPE(&Otype)=&PyType_Type;
if (PyType_Ready(&Otype) < 0) return;
if (PyType_Ready(&Itype) < 0) return;
v = PyCapsule_New(&CAPI, PycStringIO_CAPSULE_NAME, NULL);
PyDict_SetItemString(d,"cStringIO_CAPI", v);
Py_XDECREF(v);
/* Export Types */
PyDict_SetItemString(d,"InputType", (PyObject*)&Itype);
PyDict_SetItemString(d,"OutputType", (PyObject*)&Otype);
/* Maybe make certain warnings go away */
if (0) PycString_IMPORT;
}

View File

@@ -0,0 +1,79 @@
To generate or modify mapping headers
-------------------------------------
Mapping headers are imported from CJKCodecs as pre-generated form.
If you need to tweak or add something on it, please look at tools/
subdirectory of CJKCodecs' distribution.
Notes on implmentation characteristics of each codecs
-----------------------------------------------------
1) Big5 codec
The big5 codec maps the following characters as cp950 does rather
than conforming Unicode.org's that maps to 0xFFFD.
BIG5 Unicode Description
0xA15A 0x2574 SPACING UNDERSCORE
0xA1C3 0xFFE3 SPACING HEAVY OVERSCORE
0xA1C5 0x02CD SPACING HEAVY UNDERSCORE
0xA1FE 0xFF0F LT DIAG UP RIGHT TO LOW LEFT
0xA240 0xFF3C LT DIAG UP LEFT TO LOW RIGHT
0xA2CC 0x5341 HANGZHOU NUMERAL TEN
0xA2CE 0x5345 HANGZHOU NUMERAL THIRTY
Because unicode 0x5341, 0x5345, 0xFF0F, 0xFF3C is mapped to another
big5 codes already, a roundtrip compatibility is not guaranteed for
them.
2) cp932 codec
To conform to Windows's real mapping, cp932 codec maps the following
codepoints in addition of the official cp932 mapping.
CP932 Unicode Description
0x80 0x80 UNDEFINED
0xA0 0xF8F0 UNDEFINED
0xFD 0xF8F1 UNDEFINED
0xFE 0xF8F2 UNDEFINED
0xFF 0xF8F3 UNDEFINED
3) euc-jisx0213 codec
The euc-jisx0213 codec maps JIS X 0213 Plane 1 code 0x2140 into
unicode U+FF3C instead of U+005C as on unicode.org's mapping.
Because euc-jisx0213 has REVERSE SOLIDUS on 0x5c already and A140
is shown as a full width character, mapping to U+FF3C can make
more sense.
The euc-jisx0213 codec is enabled to decode JIS X 0212 codes on
codeset 2. Because JIS X 0212 and JIS X 0213 Plane 2 don't have
overlapped by each other, it doesn't bother standard conformations
(and JIS X 0213 Plane 2 is intended to use so.) On encoding
sessions, the codec will try to encode kanji characters in this
order:
JIS X 0213 Plane 1 -> JIS X 0213 Plane 2 -> JIS X 0212
4) euc-jp codec
The euc-jp codec is a compatibility instance on these points:
- U+FF3C FULLWIDTH REVERSE SOLIDUS is mapped to EUC-JP A1C0 (vice versa)
- U+00A5 YEN SIGN is mapped to EUC-JP 0x5c. (one way)
- U+203E OVERLINE is mapped to EUC-JP 0x7e. (one way)
5) shift-jis codec
The shift-jis codec is mapping 0x20-0x7e area to U+20-U+7E directly
instead of using JIS X 0201 for compatibility. The differences are:
- U+005C REVERSE SOLIDUS is mapped to SHIFT-JIS 0x5c.
- U+007E TILDE is mapped to SHIFT-JIS 0x7e.
- U+FF3C FULL-WIDTH REVERSE SOLIDUS is mapped to SHIFT-JIS 815f.

View File

@@ -0,0 +1,444 @@
/*
* _codecs_cn.c: Codecs collection for Mainland Chinese encodings
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#include "cjkcodecs.h"
#include "mappings_cn.h"
/**
* hz is predefined as 100 on AIX. So we undefine it to avoid
* conflict against hz codec's.
*/
#ifdef _AIX
#undef hz
#endif
/* GBK and GB2312 map differently in few codepoints that are listed below:
*
* gb2312 gbk
* A1A4 U+30FB KATAKANA MIDDLE DOT U+00B7 MIDDLE DOT
* A1AA U+2015 HORIZONTAL BAR U+2014 EM DASH
* A844 undefined U+2015 HORIZONTAL BAR
*/
#define GBK_DECODE(dc1, dc2, assi) \
if ((dc1) == 0xa1 && (dc2) == 0xaa) (assi) = 0x2014; \
else if ((dc1) == 0xa8 && (dc2) == 0x44) (assi) = 0x2015; \
else if ((dc1) == 0xa1 && (dc2) == 0xa4) (assi) = 0x00b7; \
else TRYMAP_DEC(gb2312, assi, dc1 ^ 0x80, dc2 ^ 0x80); \
else TRYMAP_DEC(gbkext, assi, dc1, dc2);
#define GBK_ENCODE(code, assi) \
if ((code) == 0x2014) (assi) = 0xa1aa; \
else if ((code) == 0x2015) (assi) = 0xa844; \
else if ((code) == 0x00b7) (assi) = 0xa1a4; \
else if ((code) != 0x30fb && TRYMAP_ENC_COND(gbcommon, assi, code));
/*
* GB2312 codec
*/
ENCODER(gb2312)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(gbcommon, code, c);
else return 1;
if (code & 0x8000) /* MSB set: GBK */
return 1;
OUT1((code >> 8) | 0x80)
OUT2((code & 0xFF) | 0x80)
NEXT(1, 2)
}
return 0;
}
DECODER(gb2312)
{
while (inleft > 0) {
unsigned char c = **inbuf;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
TRYMAP_DEC(gb2312, **outbuf, c ^ 0x80, IN2 ^ 0x80) {
NEXT(2, 1)
}
else return 2;
}
return 0;
}
/*
* GBK codec
*/
ENCODER(gbk)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
GBK_ENCODE(c, code)
else return 1;
OUT1((code >> 8) | 0x80)
if (code & 0x8000)
OUT2((code & 0xFF)) /* MSB set: GBK */
else
OUT2((code & 0xFF) | 0x80) /* MSB unset: GB2312 */
NEXT(1, 2)
}
return 0;
}
DECODER(gbk)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
GBK_DECODE(c, IN2, **outbuf)
else return 2;
NEXT(2, 1)
}
return 0;
}
/*
* GB18030 codec
*/
ENCODER(gb18030)
{
while (inleft > 0) {
ucs4_t c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1(c)
NEXT(1, 1)
continue;
}
DECODE_SURROGATE(c)
if (c > 0x10FFFF)
#if Py_UNICODE_SIZE == 2
return 2; /* surrogates pair */
#else
return 1;
#endif
else if (c >= 0x10000) {
ucs4_t tc = c - 0x10000;
REQUIRE_OUTBUF(4)
OUT4((unsigned char)(tc % 10) + 0x30)
tc /= 10;
OUT3((unsigned char)(tc % 126) + 0x81)
tc /= 126;
OUT2((unsigned char)(tc % 10) + 0x30)
tc /= 10;
OUT1((unsigned char)(tc + 0x90))
#if Py_UNICODE_SIZE == 2
NEXT(2, 4) /* surrogates pair */
#else
NEXT(1, 4)
#endif
continue;
}
REQUIRE_OUTBUF(2)
GBK_ENCODE(c, code)
else TRYMAP_ENC(gb18030ext, code, c);
else {
const struct _gb18030_to_unibmp_ranges *utrrange;
REQUIRE_OUTBUF(4)
for (utrrange = gb18030_to_unibmp_ranges;
utrrange->first != 0;
utrrange++)
if (utrrange->first <= c &&
c <= utrrange->last) {
Py_UNICODE tc;
tc = c - utrrange->first +
utrrange->base;
OUT4((unsigned char)(tc % 10) + 0x30)
tc /= 10;
OUT3((unsigned char)(tc % 126) + 0x81)
tc /= 126;
OUT2((unsigned char)(tc % 10) + 0x30)
tc /= 10;
OUT1((unsigned char)tc + 0x81)
NEXT(1, 4)
break;
}
if (utrrange->first == 0)
return 1;
continue;
}
OUT1((code >> 8) | 0x80)
if (code & 0x8000)
OUT2((code & 0xFF)) /* MSB set: GBK or GB18030ext */
else
OUT2((code & 0xFF) | 0x80) /* MSB unset: GB2312 */
NEXT(1, 2)
}
return 0;
}
DECODER(gb18030)
{
while (inleft > 0) {
unsigned char c = IN1, c2;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
c2 = IN2;
if (c2 >= 0x30 && c2 <= 0x39) { /* 4 bytes seq */
const struct _gb18030_to_unibmp_ranges *utr;
unsigned char c3, c4;
ucs4_t lseq;
REQUIRE_INBUF(4)
c3 = IN3;
c4 = IN4;
if (c < 0x81 || c3 < 0x81 || c4 < 0x30 || c4 > 0x39)
return 4;
c -= 0x81; c2 -= 0x30;
c3 -= 0x81; c4 -= 0x30;
if (c < 4) { /* U+0080 - U+FFFF */
lseq = ((ucs4_t)c * 10 + c2) * 1260 +
(ucs4_t)c3 * 10 + c4;
if (lseq < 39420) {
for (utr = gb18030_to_unibmp_ranges;
lseq >= (utr + 1)->base;
utr++) ;
OUT1(utr->first - utr->base + lseq)
NEXT(4, 1)
continue;
}
}
else if (c >= 15) { /* U+10000 - U+10FFFF */
lseq = 0x10000 + (((ucs4_t)c-15) * 10 + c2)
* 1260 + (ucs4_t)c3 * 10 + c4;
if (lseq <= 0x10FFFF) {
WRITEUCS4(lseq);
NEXT_IN(4)
continue;
}
}
return 4;
}
GBK_DECODE(c, c2, **outbuf)
else TRYMAP_DEC(gb18030ext, **outbuf, c, c2);
else return 2;
NEXT(2, 1)
}
return 0;
}
/*
* HZ codec
*/
ENCODER_INIT(hz)
{
state->i = 0;
return 0;
}
ENCODER_RESET(hz)
{
if (state->i != 0) {
WRITE2('~', '}')
state->i = 0;
NEXT_OUT(2)
}
return 0;
}
ENCODER(hz)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
if (state->i == 0) {
WRITE1((unsigned char)c)
NEXT(1, 1)
}
else {
WRITE3('~', '}', (unsigned char)c)
NEXT(1, 3)
state->i = 0;
}
continue;
}
UCS4INVALID(c)
TRYMAP_ENC(gbcommon, code, c);
else return 1;
if (code & 0x8000) /* MSB set: GBK */
return 1;
if (state->i == 0) {
WRITE4('~', '{', code >> 8, code & 0xff)
NEXT(1, 4)
state->i = 1;
}
else {
WRITE2(code >> 8, code & 0xff)
NEXT(1, 2)
}
}
return 0;
}
DECODER_INIT(hz)
{
state->i = 0;
return 0;
}
DECODER_RESET(hz)
{
state->i = 0;
return 0;
}
DECODER(hz)
{
while (inleft > 0) {
unsigned char c = IN1;
if (c == '~') {
unsigned char c2 = IN2;
REQUIRE_INBUF(2)
if (c2 == '~') {
WRITE1('~')
NEXT(2, 1)
continue;
}
else if (c2 == '{' && state->i == 0)
state->i = 1; /* set GB */
else if (c2 == '}' && state->i == 1)
state->i = 0; /* set ASCII */
else if (c2 == '\n')
; /* line-continuation */
else
return 2;
NEXT(2, 0);
continue;
}
if (c & 0x80)
return 1;
if (state->i == 0) { /* ASCII mode */
WRITE1(c)
NEXT(1, 1)
}
else { /* GB mode */
REQUIRE_INBUF(2)
REQUIRE_OUTBUF(1)
TRYMAP_DEC(gb2312, **outbuf, c, IN2) {
NEXT(2, 1)
}
else
return 2;
}
}
return 0;
}
BEGIN_MAPPINGS_LIST
MAPPING_DECONLY(gb2312)
MAPPING_DECONLY(gbkext)
MAPPING_ENCONLY(gbcommon)
MAPPING_ENCDEC(gb18030ext)
END_MAPPINGS_LIST
BEGIN_CODECS_LIST
CODEC_STATELESS(gb2312)
CODEC_STATELESS(gbk)
CODEC_STATELESS(gb18030)
CODEC_STATEFUL(hz)
END_CODECS_LIST
I_AM_A_MODULE_FOR(cn)

View File

@@ -0,0 +1,183 @@
/*
* _codecs_hk.c: Codecs collection for encodings from Hong Kong
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#define USING_IMPORTED_MAPS
#include "cjkcodecs.h"
#include "mappings_hk.h"
/*
* BIG5HKSCS codec
*/
static const encode_map *big5_encmap = NULL;
static const decode_map *big5_decmap = NULL;
CODEC_INIT(big5hkscs)
{
static int initialized = 0;
if (!initialized && IMPORT_MAP(tw, big5, &big5_encmap, &big5_decmap))
return -1;
initialized = 1;
return 0;
}
/*
* There are four possible pair unicode -> big5hkscs maps as in HKSCS 2004:
* U+00CA U+0304 -> 8862 (U+00CA alone is mapped to 8866)
* U+00CA U+030C -> 8864
* U+00EA U+0304 -> 88a3 (U+00EA alone is mapped to 88a7)
* U+00EA U+030C -> 88a5
* These are handled by not mapping tables but a hand-written code.
*/
static const DBCHAR big5hkscs_pairenc_table[4] = {0x8862, 0x8864, 0x88a3, 0x88a5};
ENCODER(big5hkscs)
{
while (inleft > 0) {
ucs4_t c = **inbuf;
DBCHAR code;
Py_ssize_t insize;
if (c < 0x80) {
REQUIRE_OUTBUF(1)
**outbuf = (unsigned char)c;
NEXT(1, 1)
continue;
}
DECODE_SURROGATE(c)
insize = GET_INSIZE(c);
REQUIRE_OUTBUF(2)
if (c < 0x10000) {
TRYMAP_ENC(big5hkscs_bmp, code, c) {
if (code == MULTIC) {
if (inleft >= 2 &&
((c & 0xffdf) == 0x00ca) &&
(((*inbuf)[1] & 0xfff7) == 0x0304)) {
code = big5hkscs_pairenc_table[
((c >> 4) |
((*inbuf)[1] >> 3)) & 3];
insize = 2;
}
else if (inleft < 2 &&
!(flags & MBENC_FLUSH))
return MBERR_TOOFEW;
else {
if (c == 0xca)
code = 0x8866;
else /* c == 0xea */
code = 0x88a7;
}
}
}
else TRYMAP_ENC(big5, code, c);
else return 1;
}
else if (c < 0x20000)
return insize;
else if (c < 0x30000) {
TRYMAP_ENC(big5hkscs_nonbmp, code, c & 0xffff);
else return insize;
}
else
return insize;
OUT1(code >> 8)
OUT2(code & 0xFF)
NEXT(insize, 2)
}
return 0;
}
#define BH2S(c1, c2) (((c1) - 0x87) * (0xfe - 0x40 + 1) + ((c2) - 0x40))
DECODER(big5hkscs)
{
while (inleft > 0) {
unsigned char c = IN1;
ucs4_t decoded;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
if (0xc6 <= c && c <= 0xc8 && (c >= 0xc7 || IN2 >= 0xa1))
goto hkscsdec;
TRYMAP_DEC(big5, **outbuf, c, IN2) {
NEXT(2, 1)
}
else
hkscsdec: TRYMAP_DEC(big5hkscs, decoded, c, IN2) {
int s = BH2S(c, IN2);
const unsigned char *hintbase;
assert(0x87 <= c && c <= 0xfe);
assert(0x40 <= IN2 && IN2 <= 0xfe);
if (BH2S(0x87, 0x40) <= s && s <= BH2S(0xa0, 0xfe)) {
hintbase = big5hkscs_phint_0;
s -= BH2S(0x87, 0x40);
}
else if (BH2S(0xc6,0xa1) <= s && s <= BH2S(0xc8,0xfe)){
hintbase = big5hkscs_phint_12130;
s -= BH2S(0xc6, 0xa1);
}
else if (BH2S(0xf9,0xd6) <= s && s <= BH2S(0xfe,0xfe)){
hintbase = big5hkscs_phint_21924;
s -= BH2S(0xf9, 0xd6);
}
else
return MBERR_INTERNAL;
if (hintbase[s >> 3] & (1 << (s & 7))) {
WRITEUCS4(decoded | 0x20000)
NEXT_IN(2)
}
else {
OUT1(decoded)
NEXT(2, 1)
}
}
else {
switch ((c << 8) | IN2) {
case 0x8862: WRITE2(0x00ca, 0x0304); break;
case 0x8864: WRITE2(0x00ca, 0x030c); break;
case 0x88a3: WRITE2(0x00ea, 0x0304); break;
case 0x88a5: WRITE2(0x00ea, 0x030c); break;
default: return 2;
}
NEXT(2, 2) /* all decoded codepoints are pairs, above. */
}
}
return 0;
}
BEGIN_MAPPINGS_LIST
MAPPING_DECONLY(big5hkscs)
MAPPING_ENCONLY(big5hkscs_bmp)
MAPPING_ENCONLY(big5hkscs_nonbmp)
END_MAPPINGS_LIST
BEGIN_CODECS_LIST
CODEC_STATELESS_WINIT(big5hkscs)
END_CODECS_LIST
I_AM_A_MODULE_FOR(hk)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,731 @@
/*
* _codecs_jp.c: Codecs collection for Japanese encodings
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#define USING_BINARY_PAIR_SEARCH
#define EMPBASE 0x20000
#include "cjkcodecs.h"
#include "mappings_jp.h"
#include "mappings_jisx0213_pair.h"
#include "alg_jisx0201.h"
#include "emu_jisx0213_2000.h"
/*
* CP932 codec
*/
ENCODER(cp932)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
unsigned char c1, c2;
if (c <= 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
else if (c >= 0xff61 && c <= 0xff9f) {
WRITE1(c - 0xfec0)
NEXT(1, 1)
continue;
}
else if (c >= 0xf8f0 && c <= 0xf8f3) {
/* Windows compatibility */
REQUIRE_OUTBUF(1)
if (c == 0xf8f0)
OUT1(0xa0)
else
OUT1(c - 0xfef1 + 0xfd)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(cp932ext, code, c) {
OUT1(code >> 8)
OUT2(code & 0xff)
}
else TRYMAP_ENC(jisxcommon, code, c) {
if (code & 0x8000) /* MSB set: JIS X 0212 */
return 1;
/* JIS X 0208 */
c1 = code >> 8;
c2 = code & 0xff;
c2 = (((c1 - 0x21) & 1) ? 0x5e : 0) + (c2 - 0x21);
c1 = (c1 - 0x21) >> 1;
OUT1(c1 < 0x1f ? c1 + 0x81 : c1 + 0xc1)
OUT2(c2 < 0x3f ? c2 + 0x40 : c2 + 0x41)
}
else if (c >= 0xe000 && c < 0xe758) {
/* User-defined area */
c1 = (Py_UNICODE)(c - 0xe000) / 188;
c2 = (Py_UNICODE)(c - 0xe000) % 188;
OUT1(c1 + 0xf0)
OUT2(c2 < 0x3f ? c2 + 0x40 : c2 + 0x41)
}
else
return 1;
NEXT(1, 2)
}
return 0;
}
DECODER(cp932)
{
while (inleft > 0) {
unsigned char c = IN1, c2;
REQUIRE_OUTBUF(1)
if (c <= 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
else if (c >= 0xa0 && c <= 0xdf) {
if (c == 0xa0)
OUT1(0xf8f0) /* half-width katakana */
else
OUT1(0xfec0 + c)
NEXT(1, 1)
continue;
}
else if (c >= 0xfd/* && c <= 0xff*/) {
/* Windows compatibility */
OUT1(0xf8f1 - 0xfd + c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
c2 = IN2;
TRYMAP_DEC(cp932ext, **outbuf, c, c2);
else if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)){
if (c2 < 0x40 || (c2 > 0x7e && c2 < 0x80) || c2 > 0xfc)
return 2;
c = (c < 0xe0 ? c - 0x81 : c - 0xc1);
c2 = (c2 < 0x80 ? c2 - 0x40 : c2 - 0x41);
c = (2 * c + (c2 < 0x5e ? 0 : 1) + 0x21);
c2 = (c2 < 0x5e ? c2 : c2 - 0x5e) + 0x21;
TRYMAP_DEC(jisx0208, **outbuf, c, c2);
else return 2;
}
else if (c >= 0xf0 && c <= 0xf9) {
if ((c2 >= 0x40 && c2 <= 0x7e) ||
(c2 >= 0x80 && c2 <= 0xfc))
OUT1(0xe000 + 188 * (c - 0xf0) +
(c2 < 0x80 ? c2 - 0x40 : c2 - 0x41))
else
return 2;
}
else
return 2;
NEXT(2, 1)
}
return 0;
}
/*
* EUC-JIS-2004 codec
*/
ENCODER(euc_jis_2004)
{
while (inleft > 0) {
ucs4_t c = IN1;
DBCHAR code;
Py_ssize_t insize;
if (c < 0x80) {
WRITE1(c)
NEXT(1, 1)
continue;
}
DECODE_SURROGATE(c)
insize = GET_INSIZE(c);
if (c <= 0xFFFF) {
EMULATE_JISX0213_2000_ENCODE_BMP(code, c)
else TRYMAP_ENC(jisx0213_bmp, code, c) {
if (code == MULTIC) {
if (inleft < 2) {
if (flags & MBENC_FLUSH) {
code = find_pairencmap(
(ucs2_t)c, 0,
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV)
return 1;
}
else
return MBERR_TOOFEW;
}
else {
code = find_pairencmap(
(ucs2_t)c, (*inbuf)[1],
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV) {
code = find_pairencmap(
(ucs2_t)c, 0,
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV)
return 1;
} else
insize = 2;
}
}
}
else TRYMAP_ENC(jisxcommon, code, c);
else if (c >= 0xff61 && c <= 0xff9f) {
/* JIS X 0201 half-width katakana */
WRITE2(0x8e, c - 0xfec0)
NEXT(1, 2)
continue;
}
else if (c == 0xff3c)
/* F/W REVERSE SOLIDUS (see NOTES) */
code = 0x2140;
else if (c == 0xff5e)
/* F/W TILDE (see NOTES) */
code = 0x2232;
else
return 1;
}
else if (c >> 16 == EMPBASE >> 16) {
EMULATE_JISX0213_2000_ENCODE_EMP(code, c)
else TRYMAP_ENC(jisx0213_emp, code, c & 0xffff);
else return insize;
}
else
return insize;
if (code & 0x8000) {
/* Codeset 2 */
WRITE3(0x8f, code >> 8, (code & 0xFF) | 0x80)
NEXT(insize, 3)
} else {
/* Codeset 1 */
WRITE2((code >> 8) | 0x80, (code & 0xFF) | 0x80)
NEXT(insize, 2)
}
}
return 0;
}
DECODER(euc_jis_2004)
{
while (inleft > 0) {
unsigned char c = IN1;
ucs4_t code;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
if (c == 0x8e) {
/* JIS X 0201 half-width katakana */
unsigned char c2;
REQUIRE_INBUF(2)
c2 = IN2;
if (c2 >= 0xa1 && c2 <= 0xdf) {
OUT1(0xfec0 + c2)
NEXT(2, 1)
}
else
return 2;
}
else if (c == 0x8f) {
unsigned char c2, c3;
REQUIRE_INBUF(3)
c2 = IN2 ^ 0x80;
c3 = IN3 ^ 0x80;
/* JIS X 0213 Plane 2 or JIS X 0212 (see NOTES) */
EMULATE_JISX0213_2000_DECODE_PLANE2(**outbuf, c2, c3)
else TRYMAP_DEC(jisx0213_2_bmp, **outbuf, c2, c3) ;
else TRYMAP_DEC(jisx0213_2_emp, code, c2, c3) {
WRITEUCS4(EMPBASE | code)
NEXT_IN(3)
continue;
}
else TRYMAP_DEC(jisx0212, **outbuf, c2, c3) ;
else return 3;
NEXT(3, 1)
}
else {
unsigned char c2;
REQUIRE_INBUF(2)
c ^= 0x80;
c2 = IN2 ^ 0x80;
/* JIS X 0213 Plane 1 */
EMULATE_JISX0213_2000_DECODE_PLANE1(**outbuf, c, c2)
else if (c == 0x21 && c2 == 0x40) **outbuf = 0xff3c;
else if (c == 0x22 && c2 == 0x32) **outbuf = 0xff5e;
else TRYMAP_DEC(jisx0208, **outbuf, c, c2);
else TRYMAP_DEC(jisx0213_1_bmp, **outbuf, c, c2);
else TRYMAP_DEC(jisx0213_1_emp, code, c, c2) {
WRITEUCS4(EMPBASE | code)
NEXT_IN(2)
continue;
}
else TRYMAP_DEC(jisx0213_pair, code, c, c2) {
WRITE2(code >> 16, code & 0xffff)
NEXT(2, 2)
continue;
}
else return 2;
NEXT(2, 1)
}
}
return 0;
}
/*
* EUC-JP codec
*/
ENCODER(euc_jp)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
TRYMAP_ENC(jisxcommon, code, c);
else if (c >= 0xff61 && c <= 0xff9f) {
/* JIS X 0201 half-width katakana */
WRITE2(0x8e, c - 0xfec0)
NEXT(1, 2)
continue;
}
#ifndef STRICT_BUILD
else if (c == 0xff3c) /* FULL-WIDTH REVERSE SOLIDUS */
code = 0x2140;
else if (c == 0xa5) { /* YEN SIGN */
WRITE1(0x5c);
NEXT(1, 1)
continue;
} else if (c == 0x203e) { /* OVERLINE */
WRITE1(0x7e);
NEXT(1, 1)
continue;
}
#endif
else
return 1;
if (code & 0x8000) {
/* JIS X 0212 */
WRITE3(0x8f, code >> 8, (code & 0xFF) | 0x80)
NEXT(1, 3)
} else {
/* JIS X 0208 */
WRITE2((code >> 8) | 0x80, (code & 0xFF) | 0x80)
NEXT(1, 2)
}
}
return 0;
}
DECODER(euc_jp)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
if (c == 0x8e) {
/* JIS X 0201 half-width katakana */
unsigned char c2;
REQUIRE_INBUF(2)
c2 = IN2;
if (c2 >= 0xa1 && c2 <= 0xdf) {
OUT1(0xfec0 + c2)
NEXT(2, 1)
}
else
return 2;
}
else if (c == 0x8f) {
unsigned char c2, c3;
REQUIRE_INBUF(3)
c2 = IN2;
c3 = IN3;
/* JIS X 0212 */
TRYMAP_DEC(jisx0212, **outbuf, c2 ^ 0x80, c3 ^ 0x80) {
NEXT(3, 1)
}
else
return 3;
}
else {
unsigned char c2;
REQUIRE_INBUF(2)
c2 = IN2;
/* JIS X 0208 */
#ifndef STRICT_BUILD
if (c == 0xa1 && c2 == 0xc0)
/* FULL-WIDTH REVERSE SOLIDUS */
**outbuf = 0xff3c;
else
#endif
TRYMAP_DEC(jisx0208, **outbuf,
c ^ 0x80, c2 ^ 0x80) ;
else return 2;
NEXT(2, 1)
}
}
return 0;
}
/*
* SHIFT_JIS codec
*/
ENCODER(shift_jis)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
unsigned char c1, c2;
#ifdef STRICT_BUILD
JISX0201_R_ENCODE(c, code)
#else
if (c < 0x80) code = c;
else if (c == 0x00a5) code = 0x5c; /* YEN SIGN */
else if (c == 0x203e) code = 0x7e; /* OVERLINE */
#endif
else JISX0201_K_ENCODE(c, code)
else UCS4INVALID(c)
else code = NOCHAR;
if (code < 0x80 || (code >= 0xa1 && code <= 0xdf)) {
REQUIRE_OUTBUF(1)
OUT1((unsigned char)code)
NEXT(1, 1)
continue;
}
REQUIRE_OUTBUF(2)
if (code == NOCHAR) {
TRYMAP_ENC(jisxcommon, code, c);
#ifndef STRICT_BUILD
else if (c == 0xff3c)
code = 0x2140; /* FULL-WIDTH REVERSE SOLIDUS */
#endif
else
return 1;
if (code & 0x8000) /* MSB set: JIS X 0212 */
return 1;
}
c1 = code >> 8;
c2 = code & 0xff;
c2 = (((c1 - 0x21) & 1) ? 0x5e : 0) + (c2 - 0x21);
c1 = (c1 - 0x21) >> 1;
OUT1(c1 < 0x1f ? c1 + 0x81 : c1 + 0xc1)
OUT2(c2 < 0x3f ? c2 + 0x40 : c2 + 0x41)
NEXT(1, 2)
}
return 0;
}
DECODER(shift_jis)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
#ifdef STRICT_BUILD
JISX0201_R_DECODE(c, **outbuf)
#else
if (c < 0x80) **outbuf = c;
#endif
else JISX0201_K_DECODE(c, **outbuf)
else if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)){
unsigned char c1, c2;
REQUIRE_INBUF(2)
c2 = IN2;
if (c2 < 0x40 || (c2 > 0x7e && c2 < 0x80) || c2 > 0xfc)
return 2;
c1 = (c < 0xe0 ? c - 0x81 : c - 0xc1);
c2 = (c2 < 0x80 ? c2 - 0x40 : c2 - 0x41);
c1 = (2 * c1 + (c2 < 0x5e ? 0 : 1) + 0x21);
c2 = (c2 < 0x5e ? c2 : c2 - 0x5e) + 0x21;
#ifndef STRICT_BUILD
if (c1 == 0x21 && c2 == 0x40) {
/* FULL-WIDTH REVERSE SOLIDUS */
OUT1(0xff3c)
NEXT(2, 1)
continue;
}
#endif
TRYMAP_DEC(jisx0208, **outbuf, c1, c2) {
NEXT(2, 1)
continue;
}
else
return 2;
}
else
return 2;
NEXT(1, 1) /* JIS X 0201 */
}
return 0;
}
/*
* SHIFT_JIS-2004 codec
*/
ENCODER(shift_jis_2004)
{
while (inleft > 0) {
ucs4_t c = IN1;
DBCHAR code = NOCHAR;
int c1, c2;
Py_ssize_t insize;
JISX0201_ENCODE(c, code)
else DECODE_SURROGATE(c)
if (code < 0x80 || (code >= 0xa1 && code <= 0xdf)) {
WRITE1((unsigned char)code)
NEXT(1, 1)
continue;
}
REQUIRE_OUTBUF(2)
insize = GET_INSIZE(c);
if (code == NOCHAR) {
if (c <= 0xffff) {
EMULATE_JISX0213_2000_ENCODE_BMP(code, c)
else TRYMAP_ENC(jisx0213_bmp, code, c) {
if (code == MULTIC) {
if (inleft < 2) {
if (flags & MBENC_FLUSH) {
code = find_pairencmap
((ucs2_t)c, 0,
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV)
return 1;
}
else
return MBERR_TOOFEW;
}
else {
code = find_pairencmap(
(ucs2_t)c, IN2,
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV) {
code = find_pairencmap(
(ucs2_t)c, 0,
jisx0213_pair_encmap,
JISX0213_ENCPAIRS);
if (code == DBCINV)
return 1;
}
else
insize = 2;
}
}
}
else TRYMAP_ENC(jisxcommon, code, c) {
/* abandon JIS X 0212 codes */
if (code & 0x8000)
return 1;
}
else return 1;
}
else if (c >> 16 == EMPBASE >> 16) {
EMULATE_JISX0213_2000_ENCODE_EMP(code, c)
else TRYMAP_ENC(jisx0213_emp, code, c&0xffff);
else return insize;
}
else
return insize;
}
c1 = code >> 8;
c2 = (code & 0xff) - 0x21;
if (c1 & 0x80) { /* Plane 2 */
if (c1 >= 0xee) c1 -= 0x87;
else if (c1 >= 0xac || c1 == 0xa8) c1 -= 0x49;
else c1 -= 0x43;
}
else /* Plane 1 */
c1 -= 0x21;
if (c1 & 1) c2 += 0x5e;
c1 >>= 1;
OUT1(c1 + (c1 < 0x1f ? 0x81 : 0xc1))
OUT2(c2 + (c2 < 0x3f ? 0x40 : 0x41))
NEXT(insize, 2)
}
return 0;
}
DECODER(shift_jis_2004)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
JISX0201_DECODE(c, **outbuf)
else if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc)){
unsigned char c1, c2;
ucs4_t code;
REQUIRE_INBUF(2)
c2 = IN2;
if (c2 < 0x40 || (c2 > 0x7e && c2 < 0x80) || c2 > 0xfc)
return 2;
c1 = (c < 0xe0 ? c - 0x81 : c - 0xc1);
c2 = (c2 < 0x80 ? c2 - 0x40 : c2 - 0x41);
c1 = (2 * c1 + (c2 < 0x5e ? 0 : 1));
c2 = (c2 < 0x5e ? c2 : c2 - 0x5e) + 0x21;
if (c1 < 0x5e) { /* Plane 1 */
c1 += 0x21;
EMULATE_JISX0213_2000_DECODE_PLANE1(**outbuf,
c1, c2)
else TRYMAP_DEC(jisx0208, **outbuf, c1, c2) {
NEXT_OUT(1)
}
else TRYMAP_DEC(jisx0213_1_bmp, **outbuf,
c1, c2) {
NEXT_OUT(1)
}
else TRYMAP_DEC(jisx0213_1_emp, code, c1, c2) {
WRITEUCS4(EMPBASE | code)
}
else TRYMAP_DEC(jisx0213_pair, code, c1, c2) {
WRITE2(code >> 16, code & 0xffff)
NEXT_OUT(2)
}
else
return 2;
NEXT_IN(2)
}
else { /* Plane 2 */
if (c1 >= 0x67) c1 += 0x07;
else if (c1 >= 0x63 || c1 == 0x5f) c1 -= 0x37;
else c1 -= 0x3d;
EMULATE_JISX0213_2000_DECODE_PLANE2(**outbuf,
c1, c2)
else TRYMAP_DEC(jisx0213_2_bmp, **outbuf,
c1, c2) ;
else TRYMAP_DEC(jisx0213_2_emp, code, c1, c2) {
WRITEUCS4(EMPBASE | code)
NEXT_IN(2)
continue;
}
else
return 2;
NEXT(2, 1)
}
continue;
}
else
return 2;
NEXT(1, 1) /* JIS X 0201 */
}
return 0;
}
BEGIN_MAPPINGS_LIST
MAPPING_DECONLY(jisx0208)
MAPPING_DECONLY(jisx0212)
MAPPING_ENCONLY(jisxcommon)
MAPPING_DECONLY(jisx0213_1_bmp)
MAPPING_DECONLY(jisx0213_2_bmp)
MAPPING_ENCONLY(jisx0213_bmp)
MAPPING_DECONLY(jisx0213_1_emp)
MAPPING_DECONLY(jisx0213_2_emp)
MAPPING_ENCONLY(jisx0213_emp)
MAPPING_ENCDEC(jisx0213_pair)
MAPPING_ENCDEC(cp932ext)
END_MAPPINGS_LIST
BEGIN_CODECS_LIST
CODEC_STATELESS(shift_jis)
CODEC_STATELESS(cp932)
CODEC_STATELESS(euc_jp)
CODEC_STATELESS(shift_jis_2004)
CODEC_STATELESS(euc_jis_2004)
{ "euc_jisx0213", (void *)2000, NULL, _STATELESS_METHODS(euc_jis_2004) },
{ "shift_jisx0213", (void *)2000, NULL, _STATELESS_METHODS(shift_jis_2004) },
END_CODECS_LIST
I_AM_A_MODULE_FOR(jp)

View File

@@ -0,0 +1,452 @@
/*
* _codecs_kr.c: Codecs collection for Korean encodings
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#include "cjkcodecs.h"
#include "mappings_kr.h"
/*
* EUC-KR codec
*/
#define EUCKR_JAMO_FIRSTBYTE 0xA4
#define EUCKR_JAMO_FILLER 0xD4
static const unsigned char u2cgk_choseong[19] = {
0xa1, 0xa2, 0xa4, 0xa7, 0xa8, 0xa9, 0xb1, 0xb2,
0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
0xbc, 0xbd, 0xbe
};
static const unsigned char u2cgk_jungseong[21] = {
0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
0xcf, 0xd0, 0xd1, 0xd2, 0xd3
};
static const unsigned char u2cgk_jongseong[28] = {
0xd4, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0,
0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xba,
0xbb, 0xbc, 0xbd, 0xbe
};
ENCODER(euc_kr)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(cp949, code, c);
else return 1;
if ((code & 0x8000) == 0) {
/* KS X 1001 coded character */
OUT1((code >> 8) | 0x80)
OUT2((code & 0xFF) | 0x80)
NEXT(1, 2)
}
else { /* Mapping is found in CP949 extension,
* but we encode it in KS X 1001:1998 Annex 3,
* make-up sequence for EUC-KR. */
REQUIRE_OUTBUF(8)
/* syllable composition precedence */
OUT1(EUCKR_JAMO_FIRSTBYTE)
OUT2(EUCKR_JAMO_FILLER)
/* All codepoints in CP949 extension are in unicode
* Hangul Syllable area. */
assert(0xac00 <= c && c <= 0xd7a3);
c -= 0xac00;
OUT3(EUCKR_JAMO_FIRSTBYTE)
OUT4(u2cgk_choseong[c / 588])
NEXT_OUT(4)
OUT1(EUCKR_JAMO_FIRSTBYTE)
OUT2(u2cgk_jungseong[(c / 28) % 21])
OUT3(EUCKR_JAMO_FIRSTBYTE)
OUT4(u2cgk_jongseong[c % 28])
NEXT(1, 4)
}
}
return 0;
}
#define NONE 127
static const unsigned char cgk2u_choseong[] = { /* [A1, BE] */
0, 1, NONE, 2, NONE, NONE, 3, 4,
5, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
6, 7, 8, NONE, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18
};
static const unsigned char cgk2u_jongseong[] = { /* [A1, BE] */
1, 2, 3, 4, 5, 6, 7, NONE,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, NONE, 18, 19, 20, 21, 22,
NONE, 23, 24, 25, 26, 27
};
DECODER(euc_kr)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
if (c == EUCKR_JAMO_FIRSTBYTE &&
IN2 == EUCKR_JAMO_FILLER) {
/* KS X 1001:1998 Annex 3 make-up sequence */
DBCHAR cho, jung, jong;
REQUIRE_INBUF(8)
if ((*inbuf)[2] != EUCKR_JAMO_FIRSTBYTE ||
(*inbuf)[4] != EUCKR_JAMO_FIRSTBYTE ||
(*inbuf)[6] != EUCKR_JAMO_FIRSTBYTE)
return 8;
c = (*inbuf)[3];
if (0xa1 <= c && c <= 0xbe)
cho = cgk2u_choseong[c - 0xa1];
else
cho = NONE;
c = (*inbuf)[5];
jung = (0xbf <= c && c <= 0xd3) ? c - 0xbf : NONE;
c = (*inbuf)[7];
if (c == EUCKR_JAMO_FILLER)
jong = 0;
else if (0xa1 <= c && c <= 0xbe)
jong = cgk2u_jongseong[c - 0xa1];
else
jong = NONE;
if (cho == NONE || jung == NONE || jong == NONE)
return 8;
OUT1(0xac00 + cho*588 + jung*28 + jong);
NEXT(8, 1)
}
else TRYMAP_DEC(ksx1001, **outbuf, c ^ 0x80, IN2 ^ 0x80) {
NEXT(2, 1)
}
else
return 2;
}
return 0;
}
#undef NONE
/*
* CP949 codec
*/
ENCODER(cp949)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(cp949, code, c);
else return 1;
OUT1((code >> 8) | 0x80)
if (code & 0x8000)
OUT2(code & 0xFF) /* MSB set: CP949 */
else
OUT2((code & 0xFF) | 0x80) /* MSB unset: ks x 1001 */
NEXT(1, 2)
}
return 0;
}
DECODER(cp949)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
TRYMAP_DEC(ksx1001, **outbuf, c ^ 0x80, IN2 ^ 0x80);
else TRYMAP_DEC(cp949ext, **outbuf, c, IN2);
else return 2;
NEXT(2, 1)
}
return 0;
}
/*
* JOHAB codec
*/
static const unsigned char u2johabidx_choseong[32] = {
0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14,
};
static const unsigned char u2johabidx_jungseong[32] = {
0x03, 0x04, 0x05, 0x06, 0x07,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x1a, 0x1b, 0x1c, 0x1d,
};
static const unsigned char u2johabidx_jongseong[32] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
};
static const DBCHAR u2johabjamo[] = {
0x8841, 0x8c41, 0x8444, 0x9041, 0x8446, 0x8447, 0x9441,
0x9841, 0x9c41, 0x844a, 0x844b, 0x844c, 0x844d, 0x844e, 0x844f,
0x8450, 0xa041, 0xa441, 0xa841, 0x8454, 0xac41, 0xb041, 0xb441,
0xb841, 0xbc41, 0xc041, 0xc441, 0xc841, 0xcc41, 0xd041, 0x8461,
0x8481, 0x84a1, 0x84c1, 0x84e1, 0x8541, 0x8561, 0x8581, 0x85a1,
0x85c1, 0x85e1, 0x8641, 0x8661, 0x8681, 0x86a1, 0x86c1, 0x86e1,
0x8741, 0x8761, 0x8781, 0x87a1,
};
ENCODER(johab)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
if (c >= 0xac00 && c <= 0xd7a3) {
c -= 0xac00;
code = 0x8000 |
(u2johabidx_choseong[c / 588] << 10) |
(u2johabidx_jungseong[(c / 28) % 21] << 5) |
u2johabidx_jongseong[c % 28];
}
else if (c >= 0x3131 && c <= 0x3163)
code = u2johabjamo[c - 0x3131];
else TRYMAP_ENC(cp949, code, c) {
unsigned char c1, c2, t2;
unsigned short t1;
assert((code & 0x8000) == 0);
c1 = code >> 8;
c2 = code & 0xff;
if (((c1 >= 0x21 && c1 <= 0x2c) ||
(c1 >= 0x4a && c1 <= 0x7d)) &&
(c2 >= 0x21 && c2 <= 0x7e)) {
t1 = (c1 < 0x4a ? (c1 - 0x21 + 0x1b2) :
(c1 - 0x21 + 0x197));
t2 = ((t1 & 1) ? 0x5e : 0) + (c2 - 0x21);
OUT1(t1 >> 1)
OUT2(t2 < 0x4e ? t2 + 0x31 : t2 + 0x43)
NEXT(1, 2)
continue;
}
else
return 1;
}
else
return 1;
OUT1(code >> 8)
OUT2(code & 0xff)
NEXT(1, 2)
}
return 0;
}
#define FILL 0xfd
#define NONE 0xff
static const unsigned char johabidx_choseong[32] = {
NONE, FILL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
};
static const unsigned char johabidx_jungseong[32] = {
NONE, NONE, FILL, 0x00, 0x01, 0x02, 0x03, 0x04,
NONE, NONE, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
NONE, NONE, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
NONE, NONE, 0x11, 0x12, 0x13, 0x14, NONE, NONE,
};
static const unsigned char johabidx_jongseong[32] = {
NONE, FILL, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, NONE, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, NONE, NONE,
};
static const unsigned char johabjamo_choseong[32] = {
NONE, FILL, 0x31, 0x32, 0x34, 0x37, 0x38, 0x39,
0x41, 0x42, 0x43, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, NONE, NONE, NONE,
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE,
};
static const unsigned char johabjamo_jungseong[32] = {
NONE, NONE, FILL, 0x4f, 0x50, 0x51, 0x52, 0x53,
NONE, NONE, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
NONE, NONE, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
NONE, NONE, 0x60, 0x61, 0x62, 0x63, NONE, NONE,
};
static const unsigned char johabjamo_jongseong[32] = {
NONE, FILL, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
0x37, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, NONE, 0x42, 0x44, 0x45, 0x46, 0x47,
0x48, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, NONE, NONE,
};
DECODER(johab)
{
while (inleft > 0) {
unsigned char c = IN1, c2;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
c2 = IN2;
if (c < 0xd8) {
/* johab hangul */
unsigned char c_cho, c_jung, c_jong;
unsigned char i_cho, i_jung, i_jong;
c_cho = (c >> 2) & 0x1f;
c_jung = ((c << 3) | c2 >> 5) & 0x1f;
c_jong = c2 & 0x1f;
i_cho = johabidx_choseong[c_cho];
i_jung = johabidx_jungseong[c_jung];
i_jong = johabidx_jongseong[c_jong];
if (i_cho == NONE || i_jung == NONE || i_jong == NONE)
return 2;
/* we don't use U+1100 hangul jamo yet. */
if (i_cho == FILL) {
if (i_jung == FILL) {
if (i_jong == FILL)
OUT1(0x3000)
else
OUT1(0x3100 |
johabjamo_jongseong[c_jong])
}
else {
if (i_jong == FILL)
OUT1(0x3100 |
johabjamo_jungseong[c_jung])
else
return 2;
}
} else {
if (i_jung == FILL) {
if (i_jong == FILL)
OUT1(0x3100 |
johabjamo_choseong[c_cho])
else
return 2;
}
else
OUT1(0xac00 +
i_cho * 588 +
i_jung * 28 +
(i_jong == FILL ? 0 : i_jong))
}
NEXT(2, 1)
} else {
/* KS X 1001 except hangul jamos and syllables */
if (c == 0xdf || c > 0xf9 ||
c2 < 0x31 || (c2 >= 0x80 && c2 < 0x91) ||
(c2 & 0x7f) == 0x7f ||
(c == 0xda && (c2 >= 0xa1 && c2 <= 0xd3)))
return 2;
else {
unsigned char t1, t2;
t1 = (c < 0xe0 ? 2 * (c - 0xd9) :
2 * c - 0x197);
t2 = (c2 < 0x91 ? c2 - 0x31 : c2 - 0x43);
t1 = t1 + (t2 < 0x5e ? 0 : 1) + 0x21;
t2 = (t2 < 0x5e ? t2 : t2 - 0x5e) + 0x21;
TRYMAP_DEC(ksx1001, **outbuf, t1, t2);
else return 2;
NEXT(2, 1)
}
}
}
return 0;
}
#undef NONE
#undef FILL
BEGIN_MAPPINGS_LIST
MAPPING_DECONLY(ksx1001)
MAPPING_ENCONLY(cp949)
MAPPING_DECONLY(cp949ext)
END_MAPPINGS_LIST
BEGIN_CODECS_LIST
CODEC_STATELESS(euc_kr)
CODEC_STATELESS(cp949)
CODEC_STATELESS(johab)
END_CODECS_LIST
I_AM_A_MODULE_FOR(kr)

View File

@@ -0,0 +1,132 @@
/*
* _codecs_tw.c: Codecs collection for Taiwan's encodings
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#include "cjkcodecs.h"
#include "mappings_tw.h"
/*
* BIG5 codec
*/
ENCODER(big5)
{
while (inleft > 0) {
Py_UNICODE c = **inbuf;
DBCHAR code;
if (c < 0x80) {
REQUIRE_OUTBUF(1)
**outbuf = (unsigned char)c;
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(big5, code, c);
else return 1;
OUT1(code >> 8)
OUT2(code & 0xFF)
NEXT(1, 2)
}
return 0;
}
DECODER(big5)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
TRYMAP_DEC(big5, **outbuf, c, IN2) {
NEXT(2, 1)
}
else return 2;
}
return 0;
}
/*
* CP950 codec
*/
ENCODER(cp950)
{
while (inleft > 0) {
Py_UNICODE c = IN1;
DBCHAR code;
if (c < 0x80) {
WRITE1((unsigned char)c)
NEXT(1, 1)
continue;
}
UCS4INVALID(c)
REQUIRE_OUTBUF(2)
TRYMAP_ENC(cp950ext, code, c);
else TRYMAP_ENC(big5, code, c);
else return 1;
OUT1(code >> 8)
OUT2(code & 0xFF)
NEXT(1, 2)
}
return 0;
}
DECODER(cp950)
{
while (inleft > 0) {
unsigned char c = IN1;
REQUIRE_OUTBUF(1)
if (c < 0x80) {
OUT1(c)
NEXT(1, 1)
continue;
}
REQUIRE_INBUF(2)
TRYMAP_DEC(cp950ext, **outbuf, c, IN2);
else TRYMAP_DEC(big5, **outbuf, c, IN2);
else return 2;
NEXT(2, 1)
}
return 0;
}
BEGIN_MAPPINGS_LIST
MAPPING_ENCDEC(big5)
MAPPING_ENCDEC(cp950ext)
END_MAPPINGS_LIST
BEGIN_CODECS_LIST
CODEC_STATELESS(big5)
CODEC_STATELESS(cp950)
END_CODECS_LIST
I_AM_A_MODULE_FOR(tw)

View File

@@ -0,0 +1,24 @@
#define JISX0201_R_ENCODE(c, assi) \
if ((c) < 0x80 && (c) != 0x5c && (c) != 0x7e) \
(assi) = (c); \
else if ((c) == 0x00a5) (assi) = 0x5c; \
else if ((c) == 0x203e) (assi) = 0x7e;
#define JISX0201_K_ENCODE(c, assi) \
if ((c) >= 0xff61 && (c) <= 0xff9f) \
(assi) = (c) - 0xfec0;
#define JISX0201_ENCODE(c, assi) \
JISX0201_R_ENCODE(c, assi) \
else JISX0201_K_ENCODE(c, assi)
#define JISX0201_R_DECODE(c, assi) \
if ((c) < 0x5c) (assi) = (c); \
else if ((c) == 0x5c) (assi) = 0x00a5; \
else if ((c) < 0x7e) (assi) = (c); \
else if ((c) == 0x7e) (assi) = 0x203e; \
else if ((c) == 0x7f) (assi) = 0x7f;
#define JISX0201_K_DECODE(c, assi) \
if ((c) >= 0xa1 && (c) <= 0xdf) \
(assi) = 0xfec0 + (c);
#define JISX0201_DECODE(c, assi) \
JISX0201_R_DECODE(c, assi) \
else JISX0201_K_DECODE(c, assi)

View File

@@ -0,0 +1,398 @@
/*
* cjkcodecs.h: common header for cjkcodecs
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#ifndef _CJKCODECS_H_
#define _CJKCODECS_H_
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#include "multibytecodec.h"
/* a unicode "undefined" codepoint */
#define UNIINV 0xFFFE
/* internal-use DBCS codepoints which aren't used by any charsets */
#define NOCHAR 0xFFFF
#define MULTIC 0xFFFE
#define DBCINV 0xFFFD
/* shorter macros to save source size of mapping tables */
#define U UNIINV
#define N NOCHAR
#define M MULTIC
#define D DBCINV
struct dbcs_index {
const ucs2_t *map;
unsigned char bottom, top;
};
typedef struct dbcs_index decode_map;
struct widedbcs_index {
const ucs4_t *map;
unsigned char bottom, top;
};
typedef struct widedbcs_index widedecode_map;
struct unim_index {
const DBCHAR *map;
unsigned char bottom, top;
};
typedef struct unim_index encode_map;
struct unim_index_bytebased {
const unsigned char *map;
unsigned char bottom, top;
};
struct dbcs_map {
const char *charset;
const struct unim_index *encmap;
const struct dbcs_index *decmap;
};
struct pair_encodemap {
ucs4_t uniseq;
DBCHAR code;
};
static const MultibyteCodec *codec_list;
static const struct dbcs_map *mapping_list;
#define CODEC_INIT(encoding) \
static int encoding##_codec_init(const void *config)
#define ENCODER_INIT(encoding) \
static int encoding##_encode_init( \
MultibyteCodec_State *state, const void *config)
#define ENCODER(encoding) \
static Py_ssize_t encoding##_encode( \
MultibyteCodec_State *state, const void *config, \
const Py_UNICODE **inbuf, Py_ssize_t inleft, \
unsigned char **outbuf, Py_ssize_t outleft, int flags)
#define ENCODER_RESET(encoding) \
static Py_ssize_t encoding##_encode_reset( \
MultibyteCodec_State *state, const void *config, \
unsigned char **outbuf, Py_ssize_t outleft)
#define DECODER_INIT(encoding) \
static int encoding##_decode_init( \
MultibyteCodec_State *state, const void *config)
#define DECODER(encoding) \
static Py_ssize_t encoding##_decode( \
MultibyteCodec_State *state, const void *config, \
const unsigned char **inbuf, Py_ssize_t inleft, \
Py_UNICODE **outbuf, Py_ssize_t outleft)
#define DECODER_RESET(encoding) \
static Py_ssize_t encoding##_decode_reset( \
MultibyteCodec_State *state, const void *config)
#if Py_UNICODE_SIZE == 4
#define UCS4INVALID(code) \
if ((code) > 0xFFFF) \
return 1;
#else
#define UCS4INVALID(code) \
if (0) ;
#endif
#define NEXT_IN(i) \
(*inbuf) += (i); \
(inleft) -= (i);
#define NEXT_OUT(o) \
(*outbuf) += (o); \
(outleft) -= (o);
#define NEXT(i, o) \
NEXT_IN(i) NEXT_OUT(o)
#define REQUIRE_INBUF(n) \
if (inleft < (n)) \
return MBERR_TOOFEW;
#define REQUIRE_OUTBUF(n) \
if (outleft < (n)) \
return MBERR_TOOSMALL;
#define IN1 ((*inbuf)[0])
#define IN2 ((*inbuf)[1])
#define IN3 ((*inbuf)[2])
#define IN4 ((*inbuf)[3])
#define OUT1(c) ((*outbuf)[0]) = (c);
#define OUT2(c) ((*outbuf)[1]) = (c);
#define OUT3(c) ((*outbuf)[2]) = (c);
#define OUT4(c) ((*outbuf)[3]) = (c);
#define WRITE1(c1) \
REQUIRE_OUTBUF(1) \
(*outbuf)[0] = (c1);
#define WRITE2(c1, c2) \
REQUIRE_OUTBUF(2) \
(*outbuf)[0] = (c1); \
(*outbuf)[1] = (c2);
#define WRITE3(c1, c2, c3) \
REQUIRE_OUTBUF(3) \
(*outbuf)[0] = (c1); \
(*outbuf)[1] = (c2); \
(*outbuf)[2] = (c3);
#define WRITE4(c1, c2, c3, c4) \
REQUIRE_OUTBUF(4) \
(*outbuf)[0] = (c1); \
(*outbuf)[1] = (c2); \
(*outbuf)[2] = (c3); \
(*outbuf)[3] = (c4);
#if Py_UNICODE_SIZE == 2
# define WRITEUCS4(c) \
REQUIRE_OUTBUF(2) \
(*outbuf)[0] = 0xd800 + (((c) - 0x10000) >> 10); \
(*outbuf)[1] = 0xdc00 + (((c) - 0x10000) & 0x3ff); \
NEXT_OUT(2)
#else
# define WRITEUCS4(c) \
REQUIRE_OUTBUF(1) \
**outbuf = (Py_UNICODE)(c); \
NEXT_OUT(1)
#endif
#define _TRYMAP_ENC(m, assi, val) \
((m)->map != NULL && (val) >= (m)->bottom && \
(val)<= (m)->top && ((assi) = (m)->map[(val) - \
(m)->bottom]) != NOCHAR)
#define TRYMAP_ENC_COND(charset, assi, uni) \
_TRYMAP_ENC(&charset##_encmap[(uni) >> 8], assi, (uni) & 0xff)
#define TRYMAP_ENC(charset, assi, uni) \
if TRYMAP_ENC_COND(charset, assi, uni)
#define _TRYMAP_DEC(m, assi, val) \
((m)->map != NULL && (val) >= (m)->bottom && \
(val)<= (m)->top && ((assi) = (m)->map[(val) - \
(m)->bottom]) != UNIINV)
#define TRYMAP_DEC(charset, assi, c1, c2) \
if _TRYMAP_DEC(&charset##_decmap[c1], assi, c2)
#define _TRYMAP_ENC_MPLANE(m, assplane, asshi, asslo, val) \
((m)->map != NULL && (val) >= (m)->bottom && \
(val)<= (m)->top && \
((assplane) = (m)->map[((val) - (m)->bottom)*3]) != 0 && \
(((asshi) = (m)->map[((val) - (m)->bottom)*3 + 1]), 1) && \
(((asslo) = (m)->map[((val) - (m)->bottom)*3 + 2]), 1))
#define TRYMAP_ENC_MPLANE(charset, assplane, asshi, asslo, uni) \
if _TRYMAP_ENC_MPLANE(&charset##_encmap[(uni) >> 8], \
assplane, asshi, asslo, (uni) & 0xff)
#define TRYMAP_DEC_MPLANE(charset, assi, plane, c1, c2) \
if _TRYMAP_DEC(&charset##_decmap[plane][c1], assi, c2)
#if Py_UNICODE_SIZE == 2
#define DECODE_SURROGATE(c) \
if (c >> 10 == 0xd800 >> 10) { /* high surrogate */ \
REQUIRE_INBUF(2) \
if (IN2 >> 10 == 0xdc00 >> 10) { /* low surrogate */ \
c = 0x10000 + ((ucs4_t)(c - 0xd800) << 10) + \
((ucs4_t)(IN2) - 0xdc00); \
} \
}
#define GET_INSIZE(c) ((c) > 0xffff ? 2 : 1)
#else
#define DECODE_SURROGATE(c) {;}
#define GET_INSIZE(c) 1
#endif
#define BEGIN_MAPPINGS_LIST static const struct dbcs_map _mapping_list[] = {
#define MAPPING_ENCONLY(enc) {#enc, (void*)enc##_encmap, NULL},
#define MAPPING_DECONLY(enc) {#enc, NULL, (void*)enc##_decmap},
#define MAPPING_ENCDEC(enc) {#enc, (void*)enc##_encmap, (void*)enc##_decmap},
#define END_MAPPINGS_LIST \
{"", NULL, NULL} }; \
static const struct dbcs_map *mapping_list = \
(const struct dbcs_map *)_mapping_list;
#define BEGIN_CODECS_LIST static const MultibyteCodec _codec_list[] = {
#define _STATEFUL_METHODS(enc) \
enc##_encode, \
enc##_encode_init, \
enc##_encode_reset, \
enc##_decode, \
enc##_decode_init, \
enc##_decode_reset,
#define _STATELESS_METHODS(enc) \
enc##_encode, NULL, NULL, \
enc##_decode, NULL, NULL,
#define CODEC_STATEFUL(enc) { \
#enc, NULL, NULL, \
_STATEFUL_METHODS(enc) \
},
#define CODEC_STATELESS(enc) { \
#enc, NULL, NULL, \
_STATELESS_METHODS(enc) \
},
#define CODEC_STATELESS_WINIT(enc) { \
#enc, NULL, \
enc##_codec_init, \
_STATELESS_METHODS(enc) \
},
#define END_CODECS_LIST \
{"", NULL,} }; \
static const MultibyteCodec *codec_list = \
(const MultibyteCodec *)_codec_list;
static PyObject *
getmultibytecodec(void)
{
static PyObject *cofunc = NULL;
if (cofunc == NULL) {
PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec");
if (mod == NULL)
return NULL;
cofunc = PyObject_GetAttrString(mod, "__create_codec");
Py_DECREF(mod);
}
return cofunc;
}
static PyObject *
getcodec(PyObject *self, PyObject *encoding)
{
PyObject *codecobj, *r, *cofunc;
const MultibyteCodec *codec;
const char *enc;
if (!PyString_Check(encoding)) {
PyErr_SetString(PyExc_TypeError,
"encoding name must be a string.");
return NULL;
}
cofunc = getmultibytecodec();
if (cofunc == NULL)
return NULL;
enc = PyString_AS_STRING(encoding);
for (codec = codec_list; codec->encoding[0]; codec++)
if (strcmp(codec->encoding, enc) == 0)
break;
if (codec->encoding[0] == '\0') {
PyErr_SetString(PyExc_LookupError,
"no such codec is supported.");
return NULL;
}
codecobj = PyCapsule_New((void *)codec, PyMultibyteCodec_CAPSULE_NAME, NULL);
if (codecobj == NULL)
return NULL;
r = PyObject_CallFunctionObjArgs(cofunc, codecobj, NULL);
Py_DECREF(codecobj);
return r;
}
static struct PyMethodDef __methods[] = {
{"getcodec", (PyCFunction)getcodec, METH_O, ""},
{NULL, NULL},
};
static int
register_maps(PyObject *module)
{
const struct dbcs_map *h;
for (h = mapping_list; h->charset[0] != '\0'; h++) {
char mhname[256] = "__map_";
int r;
strcpy(mhname + sizeof("__map_") - 1, h->charset);
r = PyModule_AddObject(module, mhname,
PyCapsule_New((void *)h, PyMultibyteCodec_CAPSULE_NAME, NULL));
if (r == -1)
return -1;
}
return 0;
}
#ifdef USING_BINARY_PAIR_SEARCH
static DBCHAR
find_pairencmap(ucs2_t body, ucs2_t modifier,
const struct pair_encodemap *haystack, int haystacksize)
{
int pos, min, max;
ucs4_t value = body << 16 | modifier;
min = 0;
max = haystacksize;
for (pos = haystacksize >> 1; min != max; pos = (min + max) >> 1)
if (value < haystack[pos].uniseq) {
if (max == pos) break;
else max = pos;
}
else if (value > haystack[pos].uniseq) {
if (min == pos) break;
else min = pos;
}
else
break;
if (value == haystack[pos].uniseq)
return haystack[pos].code;
else
return DBCINV;
}
#endif
#ifdef USING_IMPORTED_MAPS
#define IMPORT_MAP(locale, charset, encmap, decmap) \
importmap("_codecs_" #locale, "__map_" #charset, \
(const void**)encmap, (const void**)decmap)
static int
importmap(const char *modname, const char *symbol,
const void **encmap, const void **decmap)
{
PyObject *o, *mod;
mod = PyImport_ImportModule((char *)modname);
if (mod == NULL)
return -1;
o = PyObject_GetAttrString(mod, (char*)symbol);
if (o == NULL)
goto errorexit;
else if (!PyCapsule_IsValid(o, PyMultibyteCodec_CAPSULE_NAME)) {
PyErr_SetString(PyExc_ValueError,
"map data must be a Capsule.");
goto errorexit;
}
else {
struct dbcs_map *map;
map = PyCapsule_GetPointer(o, PyMultibyteCodec_CAPSULE_NAME);
if (encmap != NULL)
*encmap = map->encmap;
if (decmap != NULL)
*decmap = map->decmap;
Py_DECREF(o);
}
Py_DECREF(mod);
return 0;
errorexit:
Py_DECREF(mod);
return -1;
}
#endif
#define I_AM_A_MODULE_FOR(loc) \
void \
init_codecs_##loc(void) \
{ \
PyObject *m = Py_InitModule("_codecs_" #loc, __methods);\
if (m != NULL) \
(void)register_maps(m); \
}
#endif

View File

@@ -0,0 +1,43 @@
/* These routines may be quite inefficient, but it's used only to emulate old
* standards. */
#ifndef EMULATE_JISX0213_2000_ENCODE_INVALID
#define EMULATE_JISX0213_2000_ENCODE_INVALID 1
#endif
#define EMULATE_JISX0213_2000_ENCODE_BMP(assi, c) \
if (config == (void *)2000 && ( \
(c) == 0x9B1C || (c) == 0x4FF1 || \
(c) == 0x525D || (c) == 0x541E || \
(c) == 0x5653 || (c) == 0x59F8 || \
(c) == 0x5C5B || (c) == 0x5E77 || \
(c) == 0x7626 || (c) == 0x7E6B)) \
return EMULATE_JISX0213_2000_ENCODE_INVALID; \
else if (config == (void *)2000 && (c) == 0x9B1D) \
(assi) = 0x8000 | 0x7d3b; \
#define EMULATE_JISX0213_2000_ENCODE_EMP(assi, c) \
if (config == (void *)2000 && (c) == 0x20B9F) \
return EMULATE_JISX0213_2000_ENCODE_INVALID;
#ifndef EMULATE_JISX0213_2000_DECODE_INVALID
#define EMULATE_JISX0213_2000_DECODE_INVALID 2
#endif
#define EMULATE_JISX0213_2000_DECODE_PLANE1(assi, c1, c2) \
if (config == (void *)2000 && \
(((c1) == 0x2E && (c2) == 0x21) || \
((c1) == 0x2F && (c2) == 0x7E) || \
((c1) == 0x4F && (c2) == 0x54) || \
((c1) == 0x4F && (c2) == 0x7E) || \
((c1) == 0x74 && (c2) == 0x27) || \
((c1) == 0x7E && (c2) == 0x7A) || \
((c1) == 0x7E && (c2) == 0x7B) || \
((c1) == 0x7E && (c2) == 0x7C) || \
((c1) == 0x7E && (c2) == 0x7D) || \
((c1) == 0x7E && (c2) == 0x7E))) \
return EMULATE_JISX0213_2000_DECODE_INVALID;
#define EMULATE_JISX0213_2000_DECODE_PLANE2(assi, c1, c2) \
if (config == (void *)2000 && (c1) == 0x7D && (c2) == 0x3B) \
(assi) = 0x9B1D;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
#define JISX0213_ENCPAIRS 46
#ifdef EXTERN_JISX0213_PAIR
static const struct widedbcs_index *jisx0213_pair_decmap;
static const struct pair_encodemap *jisx0213_pair_encmap;
#else
static const ucs4_t __jisx0213_pair_decmap[49] = {
810234010,810365082,810496154,810627226,810758298,816525466,816656538,
816787610,816918682,817049754,817574042,818163866,818426010,838283418,
15074048,U,U,U,39060224,39060225,42730240,42730241,39387904,39387905,39453440,
39453441,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,48825061,48562921,
};
static const struct widedbcs_index jisx0213_pair_decmap[256] = {
{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{__jisx0213_pair_decmap
+0,119,123},{__jisx0213_pair_decmap+5,119,126},{__jisx0213_pair_decmap+13,120,
120},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{__jisx0213_pair_decmap+14,68,102},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,
0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{
0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0
},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},
};
static const struct pair_encodemap jisx0213_pair_encmap[JISX0213_ENCPAIRS] = {
{0x00e60000,0x295c},{0x00e60300,0x2b44},{0x02540000,0x2b38},{0x02540300,0x2b48
},{0x02540301,0x2b49},{0x02590000,0x2b30},{0x02590300,0x2b4c},{0x02590301,
0x2b4d},{0x025a0000,0x2b43},{0x025a0300,0x2b4e},{0x025a0301,0x2b4f},{
0x028c0000,0x2b37},{0x028c0300,0x2b4a},{0x028c0301,0x2b4b},{0x02e50000,0x2b60
},{0x02e502e9,0x2b66},{0x02e90000,0x2b64},{0x02e902e5,0x2b65},{0x304b0000,
0x242b},{0x304b309a,0x2477},{0x304d0000,0x242d},{0x304d309a,0x2478},{
0x304f0000,0x242f},{0x304f309a,0x2479},{0x30510000,0x2431},{0x3051309a,0x247a
},{0x30530000,0x2433},{0x3053309a,0x247b},{0x30ab0000,0x252b},{0x30ab309a,
0x2577},{0x30ad0000,0x252d},{0x30ad309a,0x2578},{0x30af0000,0x252f},{
0x30af309a,0x2579},{0x30b10000,0x2531},{0x30b1309a,0x257a},{0x30b30000,0x2533
},{0x30b3309a,0x257b},{0x30bb0000,0x253b},{0x30bb309a,0x257c},{0x30c40000,
0x2544},{0x30c4309a,0x257d},{0x30c80000,0x2548},{0x30c8309a,0x257e},{
0x31f70000,0x2675},{0x31f7309a,0x2678},
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
/*
* multibytecodec.h: Common Multibyte Codec Implementation
*
* Written by Hye-Shik Chang <perky@FreeBSD.org>
*/
#ifndef _PYTHON_MULTIBYTECODEC_H_
#define _PYTHON_MULTIBYTECODEC_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef uint32_t
typedef uint32_t ucs4_t;
#else
typedef unsigned int ucs4_t;
#endif
#ifdef uint16_t
typedef uint16_t ucs2_t, DBCHAR;
#else
typedef unsigned short ucs2_t, DBCHAR;
#endif
typedef union {
void *p;
int i;
unsigned char c[8];
ucs2_t u2[4];
ucs4_t u4[2];
} MultibyteCodec_State;
typedef int (*mbcodec_init)(const void *config);
typedef Py_ssize_t (*mbencode_func)(MultibyteCodec_State *state,
const void *config,
const Py_UNICODE **inbuf, Py_ssize_t inleft,
unsigned char **outbuf, Py_ssize_t outleft,
int flags);
typedef int (*mbencodeinit_func)(MultibyteCodec_State *state,
const void *config);
typedef Py_ssize_t (*mbencodereset_func)(MultibyteCodec_State *state,
const void *config,
unsigned char **outbuf, Py_ssize_t outleft);
typedef Py_ssize_t (*mbdecode_func)(MultibyteCodec_State *state,
const void *config,
const unsigned char **inbuf, Py_ssize_t inleft,
Py_UNICODE **outbuf, Py_ssize_t outleft);
typedef int (*mbdecodeinit_func)(MultibyteCodec_State *state,
const void *config);
typedef Py_ssize_t (*mbdecodereset_func)(MultibyteCodec_State *state,
const void *config);
typedef struct {
const char *encoding;
const void *config;
mbcodec_init codecinit;
mbencode_func encode;
mbencodeinit_func encinit;
mbencodereset_func encreset;
mbdecode_func decode;
mbdecodeinit_func decinit;
mbdecodereset_func decreset;
} MultibyteCodec;
typedef struct {
PyObject_HEAD
MultibyteCodec *codec;
} MultibyteCodecObject;
#define MultibyteCodec_Check(op) ((op)->ob_type == &MultibyteCodec_Type)
#define _MultibyteStatefulCodec_HEAD \
PyObject_HEAD \
MultibyteCodec *codec; \
MultibyteCodec_State state; \
PyObject *errors;
typedef struct {
_MultibyteStatefulCodec_HEAD
} MultibyteStatefulCodecContext;
#define MAXENCPENDING 2
#define _MultibyteStatefulEncoder_HEAD \
_MultibyteStatefulCodec_HEAD \
Py_UNICODE pending[MAXENCPENDING]; \
Py_ssize_t pendingsize;
typedef struct {
_MultibyteStatefulEncoder_HEAD
} MultibyteStatefulEncoderContext;
#define MAXDECPENDING 8
#define _MultibyteStatefulDecoder_HEAD \
_MultibyteStatefulCodec_HEAD \
unsigned char pending[MAXDECPENDING]; \
Py_ssize_t pendingsize;
typedef struct {
_MultibyteStatefulDecoder_HEAD
} MultibyteStatefulDecoderContext;
typedef struct {
_MultibyteStatefulEncoder_HEAD
} MultibyteIncrementalEncoderObject;
typedef struct {
_MultibyteStatefulDecoder_HEAD
} MultibyteIncrementalDecoderObject;
typedef struct {
_MultibyteStatefulDecoder_HEAD
PyObject *stream;
} MultibyteStreamReaderObject;
typedef struct {
_MultibyteStatefulEncoder_HEAD
PyObject *stream;
} MultibyteStreamWriterObject;
/* positive values for illegal sequences */
#define MBERR_TOOSMALL (-1) /* insufficient output buffer space */
#define MBERR_TOOFEW (-2) /* incomplete input buffer */
#define MBERR_INTERNAL (-3) /* internal runtime error */
#define ERROR_STRICT (PyObject *)(1)
#define ERROR_IGNORE (PyObject *)(2)
#define ERROR_REPLACE (PyObject *)(3)
#define ERROR_ISCUSTOM(p) ((p) < ERROR_STRICT || ERROR_REPLACE < (p))
#define ERROR_DECREF(p) do { \
if (p != NULL && ERROR_ISCUSTOM(p)) { \
Py_DECREF(p); \
} \
} while (0);
#define MBENC_FLUSH 0x0001 /* encode all characters encodable */
#define MBENC_MAX MBENC_FLUSH
#define PyMultibyteCodec_CAPSULE_NAME "multibytecodec.__map_*"
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
/* cryptmodule.c - by Steve Majewski
*/
#include "Python.h"
#include <sys/types.h>
#ifdef __VMS
#include <openssl/des.h>
#endif
/* Module crypt */
static PyObject *crypt_crypt(PyObject *self, PyObject *args)
{
char *word, *salt;
#ifndef __VMS
extern char * crypt(const char *, const char *);
#endif
if (!PyArg_ParseTuple(args, "ss:crypt", &word, &salt)) {
return NULL;
}
/* On some platforms (AtheOS) crypt returns NULL for an invalid
salt. Return None in that case. XXX Maybe raise an exception? */
return Py_BuildValue("s", crypt(word, salt));
}
PyDoc_STRVAR(crypt_crypt__doc__,
"crypt(word, salt) -> string\n\
word will usually be a user's password. salt is a 2-character string\n\
which will be used to select one of 4096 variations of DES. The characters\n\
in salt must be either \".\", \"/\", or an alphanumeric character. Returns\n\
the hashed password as a string, which will be composed of characters from\n\
the same alphabet as the salt.");
static PyMethodDef crypt_methods[] = {
{"crypt", crypt_crypt, METH_VARARGS, crypt_crypt__doc__},
{NULL, NULL} /* sentinel */
};
PyMODINIT_FUNC
initcrypt(void)
{
Py_InitModule("crypt", crypt_methods);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,845 @@
/* Errno module
Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*/
#include "Python.h"
/* Windows socket errors (WSA*) */
#ifdef MS_WINDOWS
#include <windows.h>
#endif
/*
* Pull in the system error definitions
*/
static PyMethodDef errno_methods[] = {
{NULL, NULL}
};
/* Helper function doing the dictionary inserting */
static void
_inscode(PyObject *d, PyObject *de, char *name, int code)
{
PyObject *u = PyString_FromString(name);
PyObject *v = PyInt_FromLong((long) code);
/* Don't bother checking for errors; they'll be caught at the end
* of the module initialization function by the caller of
* initerrno().
*/
if (u && v) {
/* insert in modules dict */
PyDict_SetItem(d, u, v);
/* insert in errorcode dict */
PyDict_SetItem(de, v, u);
}
Py_XDECREF(u);
Py_XDECREF(v);
}
PyDoc_STRVAR(errno__doc__,
"This module makes available standard errno system symbols.\n\
\n\
The value of each symbol is the corresponding integer value,\n\
e.g., on most systems, errno.ENOENT equals the integer 2.\n\
\n\
The dictionary errno.errorcode maps numeric codes to symbol names,\n\
e.g., errno.errorcode[2] could be the string 'ENOENT'.\n\
\n\
Symbols that are not relevant to the underlying system are not defined.\n\
\n\
To map error codes to error messages, use the function os.strerror(),\n\
e.g. os.strerror(2) could return 'No such file or directory'.");
PyMODINIT_FUNC
initerrno(void)
{
PyObject *m, *d, *de;
m = Py_InitModule3("errno", errno_methods, errno__doc__);
if (m == NULL)
return;
d = PyModule_GetDict(m);
de = PyDict_New();
if (!d || !de || PyDict_SetItemString(d, "errorcode", de) < 0)
return;
/* Macro so I don't have to edit each and every line below... */
#define inscode(d, ds, de, name, code, comment) _inscode(d, de, name, code)
/*
* The names and comments are borrowed from linux/include/errno.h,
* which should be pretty all-inclusive
*/
#ifdef ENODEV
inscode(d, ds, de, "ENODEV", ENODEV, "No such device");
#endif
#ifdef ENOCSI
inscode(d, ds, de, "ENOCSI", ENOCSI, "No CSI structure available");
#endif
#ifdef EHOSTUNREACH
inscode(d, ds, de, "EHOSTUNREACH", EHOSTUNREACH, "No route to host");
#else
#ifdef WSAEHOSTUNREACH
inscode(d, ds, de, "EHOSTUNREACH", WSAEHOSTUNREACH, "No route to host");
#endif
#endif
#ifdef ENOMSG
inscode(d, ds, de, "ENOMSG", ENOMSG, "No message of desired type");
#endif
#ifdef EUCLEAN
inscode(d, ds, de, "EUCLEAN", EUCLEAN, "Structure needs cleaning");
#endif
#ifdef EL2NSYNC
inscode(d, ds, de, "EL2NSYNC", EL2NSYNC, "Level 2 not synchronized");
#endif
#ifdef EL2HLT
inscode(d, ds, de, "EL2HLT", EL2HLT, "Level 2 halted");
#endif
#ifdef ENODATA
inscode(d, ds, de, "ENODATA", ENODATA, "No data available");
#endif
#ifdef ENOTBLK
inscode(d, ds, de, "ENOTBLK", ENOTBLK, "Block device required");
#endif
#ifdef ENOSYS
inscode(d, ds, de, "ENOSYS", ENOSYS, "Function not implemented");
#endif
#ifdef EPIPE
inscode(d, ds, de, "EPIPE", EPIPE, "Broken pipe");
#endif
#ifdef EINVAL
inscode(d, ds, de, "EINVAL", EINVAL, "Invalid argument");
#else
#ifdef WSAEINVAL
inscode(d, ds, de, "EINVAL", WSAEINVAL, "Invalid argument");
#endif
#endif
#ifdef EOVERFLOW
inscode(d, ds, de, "EOVERFLOW", EOVERFLOW, "Value too large for defined data type");
#endif
#ifdef EADV
inscode(d, ds, de, "EADV", EADV, "Advertise error");
#endif
#ifdef EINTR
inscode(d, ds, de, "EINTR", EINTR, "Interrupted system call");
#else
#ifdef WSAEINTR
inscode(d, ds, de, "EINTR", WSAEINTR, "Interrupted system call");
#endif
#endif
#ifdef EUSERS
inscode(d, ds, de, "EUSERS", EUSERS, "Too many users");
#else
#ifdef WSAEUSERS
inscode(d, ds, de, "EUSERS", WSAEUSERS, "Too many users");
#endif
#endif
#ifdef ENOTEMPTY
inscode(d, ds, de, "ENOTEMPTY", ENOTEMPTY, "Directory not empty");
#else
#ifdef WSAENOTEMPTY
inscode(d, ds, de, "ENOTEMPTY", WSAENOTEMPTY, "Directory not empty");
#endif
#endif
#ifdef ENOBUFS
inscode(d, ds, de, "ENOBUFS", ENOBUFS, "No buffer space available");
#else
#ifdef WSAENOBUFS
inscode(d, ds, de, "ENOBUFS", WSAENOBUFS, "No buffer space available");
#endif
#endif
#ifdef EPROTO
inscode(d, ds, de, "EPROTO", EPROTO, "Protocol error");
#endif
#ifdef EREMOTE
inscode(d, ds, de, "EREMOTE", EREMOTE, "Object is remote");
#else
#ifdef WSAEREMOTE
inscode(d, ds, de, "EREMOTE", WSAEREMOTE, "Object is remote");
#endif
#endif
#ifdef ENAVAIL
inscode(d, ds, de, "ENAVAIL", ENAVAIL, "No XENIX semaphores available");
#endif
#ifdef ECHILD
inscode(d, ds, de, "ECHILD", ECHILD, "No child processes");
#endif
#ifdef ELOOP
inscode(d, ds, de, "ELOOP", ELOOP, "Too many symbolic links encountered");
#else
#ifdef WSAELOOP
inscode(d, ds, de, "ELOOP", WSAELOOP, "Too many symbolic links encountered");
#endif
#endif
#ifdef EXDEV
inscode(d, ds, de, "EXDEV", EXDEV, "Cross-device link");
#endif
#ifdef E2BIG
inscode(d, ds, de, "E2BIG", E2BIG, "Arg list too long");
#endif
#ifdef ESRCH
inscode(d, ds, de, "ESRCH", ESRCH, "No such process");
#endif
#ifdef EMSGSIZE
inscode(d, ds, de, "EMSGSIZE", EMSGSIZE, "Message too long");
#else
#ifdef WSAEMSGSIZE
inscode(d, ds, de, "EMSGSIZE", WSAEMSGSIZE, "Message too long");
#endif
#endif
#ifdef EAFNOSUPPORT
inscode(d, ds, de, "EAFNOSUPPORT", EAFNOSUPPORT, "Address family not supported by protocol");
#else
#ifdef WSAEAFNOSUPPORT
inscode(d, ds, de, "EAFNOSUPPORT", WSAEAFNOSUPPORT, "Address family not supported by protocol");
#endif
#endif
#ifdef EBADR
inscode(d, ds, de, "EBADR", EBADR, "Invalid request descriptor");
#endif
#ifdef EHOSTDOWN
inscode(d, ds, de, "EHOSTDOWN", EHOSTDOWN, "Host is down");
#else
#ifdef WSAEHOSTDOWN
inscode(d, ds, de, "EHOSTDOWN", WSAEHOSTDOWN, "Host is down");
#endif
#endif
#ifdef EPFNOSUPPORT
inscode(d, ds, de, "EPFNOSUPPORT", EPFNOSUPPORT, "Protocol family not supported");
#else
#ifdef WSAEPFNOSUPPORT
inscode(d, ds, de, "EPFNOSUPPORT", WSAEPFNOSUPPORT, "Protocol family not supported");
#endif
#endif
#ifdef ENOPROTOOPT
inscode(d, ds, de, "ENOPROTOOPT", ENOPROTOOPT, "Protocol not available");
#else
#ifdef WSAENOPROTOOPT
inscode(d, ds, de, "ENOPROTOOPT", WSAENOPROTOOPT, "Protocol not available");
#endif
#endif
#ifdef EBUSY
inscode(d, ds, de, "EBUSY", EBUSY, "Device or resource busy");
#endif
#ifdef EWOULDBLOCK
inscode(d, ds, de, "EWOULDBLOCK", EWOULDBLOCK, "Operation would block");
#else
#ifdef WSAEWOULDBLOCK
inscode(d, ds, de, "EWOULDBLOCK", WSAEWOULDBLOCK, "Operation would block");
#endif
#endif
#ifdef EBADFD
inscode(d, ds, de, "EBADFD", EBADFD, "File descriptor in bad state");
#endif
#ifdef EDOTDOT
inscode(d, ds, de, "EDOTDOT", EDOTDOT, "RFS specific error");
#endif
#ifdef EISCONN
inscode(d, ds, de, "EISCONN", EISCONN, "Transport endpoint is already connected");
#else
#ifdef WSAEISCONN
inscode(d, ds, de, "EISCONN", WSAEISCONN, "Transport endpoint is already connected");
#endif
#endif
#ifdef ENOANO
inscode(d, ds, de, "ENOANO", ENOANO, "No anode");
#endif
#ifdef ESHUTDOWN
inscode(d, ds, de, "ESHUTDOWN", ESHUTDOWN, "Cannot send after transport endpoint shutdown");
#else
#ifdef WSAESHUTDOWN
inscode(d, ds, de, "ESHUTDOWN", WSAESHUTDOWN, "Cannot send after transport endpoint shutdown");
#endif
#endif
#ifdef ECHRNG
inscode(d, ds, de, "ECHRNG", ECHRNG, "Channel number out of range");
#endif
#ifdef ELIBBAD
inscode(d, ds, de, "ELIBBAD", ELIBBAD, "Accessing a corrupted shared library");
#endif
#ifdef ENONET
inscode(d, ds, de, "ENONET", ENONET, "Machine is not on the network");
#endif
#ifdef EBADE
inscode(d, ds, de, "EBADE", EBADE, "Invalid exchange");
#endif
#ifdef EBADF
inscode(d, ds, de, "EBADF", EBADF, "Bad file number");
#else
#ifdef WSAEBADF
inscode(d, ds, de, "EBADF", WSAEBADF, "Bad file number");
#endif
#endif
#ifdef EMULTIHOP
inscode(d, ds, de, "EMULTIHOP", EMULTIHOP, "Multihop attempted");
#endif
#ifdef EIO
inscode(d, ds, de, "EIO", EIO, "I/O error");
#endif
#ifdef EUNATCH
inscode(d, ds, de, "EUNATCH", EUNATCH, "Protocol driver not attached");
#endif
#ifdef EPROTOTYPE
inscode(d, ds, de, "EPROTOTYPE", EPROTOTYPE, "Protocol wrong type for socket");
#else
#ifdef WSAEPROTOTYPE
inscode(d, ds, de, "EPROTOTYPE", WSAEPROTOTYPE, "Protocol wrong type for socket");
#endif
#endif
#ifdef ENOSPC
inscode(d, ds, de, "ENOSPC", ENOSPC, "No space left on device");
#endif
#ifdef ENOEXEC
inscode(d, ds, de, "ENOEXEC", ENOEXEC, "Exec format error");
#endif
#ifdef EALREADY
inscode(d, ds, de, "EALREADY", EALREADY, "Operation already in progress");
#else
#ifdef WSAEALREADY
inscode(d, ds, de, "EALREADY", WSAEALREADY, "Operation already in progress");
#endif
#endif
#ifdef ENETDOWN
inscode(d, ds, de, "ENETDOWN", ENETDOWN, "Network is down");
#else
#ifdef WSAENETDOWN
inscode(d, ds, de, "ENETDOWN", WSAENETDOWN, "Network is down");
#endif
#endif
#ifdef ENOTNAM
inscode(d, ds, de, "ENOTNAM", ENOTNAM, "Not a XENIX named type file");
#endif
#ifdef EACCES
inscode(d, ds, de, "EACCES", EACCES, "Permission denied");
#else
#ifdef WSAEACCES
inscode(d, ds, de, "EACCES", WSAEACCES, "Permission denied");
#endif
#endif
#ifdef ELNRNG
inscode(d, ds, de, "ELNRNG", ELNRNG, "Link number out of range");
#endif
#ifdef EILSEQ
inscode(d, ds, de, "EILSEQ", EILSEQ, "Illegal byte sequence");
#endif
#ifdef ENOTDIR
inscode(d, ds, de, "ENOTDIR", ENOTDIR, "Not a directory");
#endif
#ifdef ENOTUNIQ
inscode(d, ds, de, "ENOTUNIQ", ENOTUNIQ, "Name not unique on network");
#endif
#ifdef EPERM
inscode(d, ds, de, "EPERM", EPERM, "Operation not permitted");
#endif
#ifdef EDOM
inscode(d, ds, de, "EDOM", EDOM, "Math argument out of domain of func");
#endif
#ifdef EXFULL
inscode(d, ds, de, "EXFULL", EXFULL, "Exchange full");
#endif
#ifdef ECONNREFUSED
inscode(d, ds, de, "ECONNREFUSED", ECONNREFUSED, "Connection refused");
#else
#ifdef WSAECONNREFUSED
inscode(d, ds, de, "ECONNREFUSED", WSAECONNREFUSED, "Connection refused");
#endif
#endif
#ifdef EISDIR
inscode(d, ds, de, "EISDIR", EISDIR, "Is a directory");
#endif
#ifdef EPROTONOSUPPORT
inscode(d, ds, de, "EPROTONOSUPPORT", EPROTONOSUPPORT, "Protocol not supported");
#else
#ifdef WSAEPROTONOSUPPORT
inscode(d, ds, de, "EPROTONOSUPPORT", WSAEPROTONOSUPPORT, "Protocol not supported");
#endif
#endif
#ifdef EROFS
inscode(d, ds, de, "EROFS", EROFS, "Read-only file system");
#endif
#ifdef EADDRNOTAVAIL
inscode(d, ds, de, "EADDRNOTAVAIL", EADDRNOTAVAIL, "Cannot assign requested address");
#else
#ifdef WSAEADDRNOTAVAIL
inscode(d, ds, de, "EADDRNOTAVAIL", WSAEADDRNOTAVAIL, "Cannot assign requested address");
#endif
#endif
#ifdef EIDRM
inscode(d, ds, de, "EIDRM", EIDRM, "Identifier removed");
#endif
#ifdef ECOMM
inscode(d, ds, de, "ECOMM", ECOMM, "Communication error on send");
#endif
#ifdef ESRMNT
inscode(d, ds, de, "ESRMNT", ESRMNT, "Srmount error");
#endif
#ifdef EREMOTEIO
inscode(d, ds, de, "EREMOTEIO", EREMOTEIO, "Remote I/O error");
#endif
#ifdef EL3RST
inscode(d, ds, de, "EL3RST", EL3RST, "Level 3 reset");
#endif
#ifdef EBADMSG
inscode(d, ds, de, "EBADMSG", EBADMSG, "Not a data message");
#endif
#ifdef ENFILE
inscode(d, ds, de, "ENFILE", ENFILE, "File table overflow");
#endif
#ifdef ELIBMAX
inscode(d, ds, de, "ELIBMAX", ELIBMAX, "Attempting to link in too many shared libraries");
#endif
#ifdef ESPIPE
inscode(d, ds, de, "ESPIPE", ESPIPE, "Illegal seek");
#endif
#ifdef ENOLINK
inscode(d, ds, de, "ENOLINK", ENOLINK, "Link has been severed");
#endif
#ifdef ENETRESET
inscode(d, ds, de, "ENETRESET", ENETRESET, "Network dropped connection because of reset");
#else
#ifdef WSAENETRESET
inscode(d, ds, de, "ENETRESET", WSAENETRESET, "Network dropped connection because of reset");
#endif
#endif
#ifdef ETIMEDOUT
inscode(d, ds, de, "ETIMEDOUT", ETIMEDOUT, "Connection timed out");
#else
#ifdef WSAETIMEDOUT
inscode(d, ds, de, "ETIMEDOUT", WSAETIMEDOUT, "Connection timed out");
#endif
#endif
#ifdef ENOENT
inscode(d, ds, de, "ENOENT", ENOENT, "No such file or directory");
#endif
#ifdef EEXIST
inscode(d, ds, de, "EEXIST", EEXIST, "File exists");
#endif
#ifdef EDQUOT
inscode(d, ds, de, "EDQUOT", EDQUOT, "Quota exceeded");
#else
#ifdef WSAEDQUOT
inscode(d, ds, de, "EDQUOT", WSAEDQUOT, "Quota exceeded");
#endif
#endif
#ifdef ENOSTR
inscode(d, ds, de, "ENOSTR", ENOSTR, "Device not a stream");
#endif
#ifdef EBADSLT
inscode(d, ds, de, "EBADSLT", EBADSLT, "Invalid slot");
#endif
#ifdef EBADRQC
inscode(d, ds, de, "EBADRQC", EBADRQC, "Invalid request code");
#endif
#ifdef ELIBACC
inscode(d, ds, de, "ELIBACC", ELIBACC, "Can not access a needed shared library");
#endif
#ifdef EFAULT
inscode(d, ds, de, "EFAULT", EFAULT, "Bad address");
#else
#ifdef WSAEFAULT
inscode(d, ds, de, "EFAULT", WSAEFAULT, "Bad address");
#endif
#endif
#ifdef EFBIG
inscode(d, ds, de, "EFBIG", EFBIG, "File too large");
#endif
#ifdef EDEADLK
inscode(d, ds, de, "EDEADLK", EDEADLK, "Resource deadlock would occur");
#endif
#ifdef ENOTCONN
inscode(d, ds, de, "ENOTCONN", ENOTCONN, "Transport endpoint is not connected");
#else
#ifdef WSAENOTCONN
inscode(d, ds, de, "ENOTCONN", WSAENOTCONN, "Transport endpoint is not connected");
#endif
#endif
#ifdef EDESTADDRREQ
inscode(d, ds, de, "EDESTADDRREQ", EDESTADDRREQ, "Destination address required");
#else
#ifdef WSAEDESTADDRREQ
inscode(d, ds, de, "EDESTADDRREQ", WSAEDESTADDRREQ, "Destination address required");
#endif
#endif
#ifdef ELIBSCN
inscode(d, ds, de, "ELIBSCN", ELIBSCN, ".lib section in a.out corrupted");
#endif
#ifdef ENOLCK
inscode(d, ds, de, "ENOLCK", ENOLCK, "No record locks available");
#endif
#ifdef EISNAM
inscode(d, ds, de, "EISNAM", EISNAM, "Is a named type file");
#endif
#ifdef ECONNABORTED
inscode(d, ds, de, "ECONNABORTED", ECONNABORTED, "Software caused connection abort");
#else
#ifdef WSAECONNABORTED
inscode(d, ds, de, "ECONNABORTED", WSAECONNABORTED, "Software caused connection abort");
#endif
#endif
#ifdef ENETUNREACH
inscode(d, ds, de, "ENETUNREACH", ENETUNREACH, "Network is unreachable");
#else
#ifdef WSAENETUNREACH
inscode(d, ds, de, "ENETUNREACH", WSAENETUNREACH, "Network is unreachable");
#endif
#endif
#ifdef ESTALE
inscode(d, ds, de, "ESTALE", ESTALE, "Stale NFS file handle");
#else
#ifdef WSAESTALE
inscode(d, ds, de, "ESTALE", WSAESTALE, "Stale NFS file handle");
#endif
#endif
#ifdef ENOSR
inscode(d, ds, de, "ENOSR", ENOSR, "Out of streams resources");
#endif
#ifdef ENOMEM
inscode(d, ds, de, "ENOMEM", ENOMEM, "Out of memory");
#endif
#ifdef ENOTSOCK
inscode(d, ds, de, "ENOTSOCK", ENOTSOCK, "Socket operation on non-socket");
#else
#ifdef WSAENOTSOCK
inscode(d, ds, de, "ENOTSOCK", WSAENOTSOCK, "Socket operation on non-socket");
#endif
#endif
#ifdef ESTRPIPE
inscode(d, ds, de, "ESTRPIPE", ESTRPIPE, "Streams pipe error");
#endif
#ifdef EMLINK
inscode(d, ds, de, "EMLINK", EMLINK, "Too many links");
#endif
#ifdef ERANGE
inscode(d, ds, de, "ERANGE", ERANGE, "Math result not representable");
#endif
#ifdef ELIBEXEC
inscode(d, ds, de, "ELIBEXEC", ELIBEXEC, "Cannot exec a shared library directly");
#endif
#ifdef EL3HLT
inscode(d, ds, de, "EL3HLT", EL3HLT, "Level 3 halted");
#endif
#ifdef ECONNRESET
inscode(d, ds, de, "ECONNRESET", ECONNRESET, "Connection reset by peer");
#else
#ifdef WSAECONNRESET
inscode(d, ds, de, "ECONNRESET", WSAECONNRESET, "Connection reset by peer");
#endif
#endif
#ifdef EADDRINUSE
inscode(d, ds, de, "EADDRINUSE", EADDRINUSE, "Address already in use");
#else
#ifdef WSAEADDRINUSE
inscode(d, ds, de, "EADDRINUSE", WSAEADDRINUSE, "Address already in use");
#endif
#endif
#ifdef EOPNOTSUPP
inscode(d, ds, de, "EOPNOTSUPP", EOPNOTSUPP, "Operation not supported on transport endpoint");
#else
#ifdef WSAEOPNOTSUPP
inscode(d, ds, de, "EOPNOTSUPP", WSAEOPNOTSUPP, "Operation not supported on transport endpoint");
#endif
#endif
#ifdef EREMCHG
inscode(d, ds, de, "EREMCHG", EREMCHG, "Remote address changed");
#endif
#ifdef EAGAIN
inscode(d, ds, de, "EAGAIN", EAGAIN, "Try again");
#endif
#ifdef ENAMETOOLONG
inscode(d, ds, de, "ENAMETOOLONG", ENAMETOOLONG, "File name too long");
#else
#ifdef WSAENAMETOOLONG
inscode(d, ds, de, "ENAMETOOLONG", WSAENAMETOOLONG, "File name too long");
#endif
#endif
#ifdef ENOTTY
inscode(d, ds, de, "ENOTTY", ENOTTY, "Not a typewriter");
#endif
#ifdef ERESTART
inscode(d, ds, de, "ERESTART", ERESTART, "Interrupted system call should be restarted");
#endif
#ifdef ESOCKTNOSUPPORT
inscode(d, ds, de, "ESOCKTNOSUPPORT", ESOCKTNOSUPPORT, "Socket type not supported");
#else
#ifdef WSAESOCKTNOSUPPORT
inscode(d, ds, de, "ESOCKTNOSUPPORT", WSAESOCKTNOSUPPORT, "Socket type not supported");
#endif
#endif
#ifdef ETIME
inscode(d, ds, de, "ETIME", ETIME, "Timer expired");
#endif
#ifdef EBFONT
inscode(d, ds, de, "EBFONT", EBFONT, "Bad font file format");
#endif
#ifdef EDEADLOCK
inscode(d, ds, de, "EDEADLOCK", EDEADLOCK, "Error EDEADLOCK");
#endif
#ifdef ETOOMANYREFS
inscode(d, ds, de, "ETOOMANYREFS", ETOOMANYREFS, "Too many references: cannot splice");
#else
#ifdef WSAETOOMANYREFS
inscode(d, ds, de, "ETOOMANYREFS", WSAETOOMANYREFS, "Too many references: cannot splice");
#endif
#endif
#ifdef EMFILE
inscode(d, ds, de, "EMFILE", EMFILE, "Too many open files");
#else
#ifdef WSAEMFILE
inscode(d, ds, de, "EMFILE", WSAEMFILE, "Too many open files");
#endif
#endif
#ifdef ETXTBSY
inscode(d, ds, de, "ETXTBSY", ETXTBSY, "Text file busy");
#endif
#ifdef EINPROGRESS
inscode(d, ds, de, "EINPROGRESS", EINPROGRESS, "Operation now in progress");
#else
#ifdef WSAEINPROGRESS
inscode(d, ds, de, "EINPROGRESS", WSAEINPROGRESS, "Operation now in progress");
#endif
#endif
#ifdef ENXIO
inscode(d, ds, de, "ENXIO", ENXIO, "No such device or address");
#endif
#ifdef ENOPKG
inscode(d, ds, de, "ENOPKG", ENOPKG, "Package not installed");
#endif
#ifdef WSASY
inscode(d, ds, de, "WSASY", WSASY, "Error WSASY");
#endif
#ifdef WSAEHOSTDOWN
inscode(d, ds, de, "WSAEHOSTDOWN", WSAEHOSTDOWN, "Host is down");
#endif
#ifdef WSAENETDOWN
inscode(d, ds, de, "WSAENETDOWN", WSAENETDOWN, "Network is down");
#endif
#ifdef WSAENOTSOCK
inscode(d, ds, de, "WSAENOTSOCK", WSAENOTSOCK, "Socket operation on non-socket");
#endif
#ifdef WSAEHOSTUNREACH
inscode(d, ds, de, "WSAEHOSTUNREACH", WSAEHOSTUNREACH, "No route to host");
#endif
#ifdef WSAELOOP
inscode(d, ds, de, "WSAELOOP", WSAELOOP, "Too many symbolic links encountered");
#endif
#ifdef WSAEMFILE
inscode(d, ds, de, "WSAEMFILE", WSAEMFILE, "Too many open files");
#endif
#ifdef WSAESTALE
inscode(d, ds, de, "WSAESTALE", WSAESTALE, "Stale NFS file handle");
#endif
#ifdef WSAVERNOTSUPPORTED
inscode(d, ds, de, "WSAVERNOTSUPPORTED", WSAVERNOTSUPPORTED, "Error WSAVERNOTSUPPORTED");
#endif
#ifdef WSAENETUNREACH
inscode(d, ds, de, "WSAENETUNREACH", WSAENETUNREACH, "Network is unreachable");
#endif
#ifdef WSAEPROCLIM
inscode(d, ds, de, "WSAEPROCLIM", WSAEPROCLIM, "Error WSAEPROCLIM");
#endif
#ifdef WSAEFAULT
inscode(d, ds, de, "WSAEFAULT", WSAEFAULT, "Bad address");
#endif
#ifdef WSANOTINITIALISED
inscode(d, ds, de, "WSANOTINITIALISED", WSANOTINITIALISED, "Error WSANOTINITIALISED");
#endif
#ifdef WSAEUSERS
inscode(d, ds, de, "WSAEUSERS", WSAEUSERS, "Too many users");
#endif
#ifdef WSAMAKEASYNCREPL
inscode(d, ds, de, "WSAMAKEASYNCREPL", WSAMAKEASYNCREPL, "Error WSAMAKEASYNCREPL");
#endif
#ifdef WSAENOPROTOOPT
inscode(d, ds, de, "WSAENOPROTOOPT", WSAENOPROTOOPT, "Protocol not available");
#endif
#ifdef WSAECONNABORTED
inscode(d, ds, de, "WSAECONNABORTED", WSAECONNABORTED, "Software caused connection abort");
#endif
#ifdef WSAENAMETOOLONG
inscode(d, ds, de, "WSAENAMETOOLONG", WSAENAMETOOLONG, "File name too long");
#endif
#ifdef WSAENOTEMPTY
inscode(d, ds, de, "WSAENOTEMPTY", WSAENOTEMPTY, "Directory not empty");
#endif
#ifdef WSAESHUTDOWN
inscode(d, ds, de, "WSAESHUTDOWN", WSAESHUTDOWN, "Cannot send after transport endpoint shutdown");
#endif
#ifdef WSAEAFNOSUPPORT
inscode(d, ds, de, "WSAEAFNOSUPPORT", WSAEAFNOSUPPORT, "Address family not supported by protocol");
#endif
#ifdef WSAETOOMANYREFS
inscode(d, ds, de, "WSAETOOMANYREFS", WSAETOOMANYREFS, "Too many references: cannot splice");
#endif
#ifdef WSAEACCES
inscode(d, ds, de, "WSAEACCES", WSAEACCES, "Permission denied");
#endif
#ifdef WSATR
inscode(d, ds, de, "WSATR", WSATR, "Error WSATR");
#endif
#ifdef WSABASEERR
inscode(d, ds, de, "WSABASEERR", WSABASEERR, "Error WSABASEERR");
#endif
#ifdef WSADESCRIPTIO
inscode(d, ds, de, "WSADESCRIPTIO", WSADESCRIPTIO, "Error WSADESCRIPTIO");
#endif
#ifdef WSAEMSGSIZE
inscode(d, ds, de, "WSAEMSGSIZE", WSAEMSGSIZE, "Message too long");
#endif
#ifdef WSAEBADF
inscode(d, ds, de, "WSAEBADF", WSAEBADF, "Bad file number");
#endif
#ifdef WSAECONNRESET
inscode(d, ds, de, "WSAECONNRESET", WSAECONNRESET, "Connection reset by peer");
#endif
#ifdef WSAGETSELECTERRO
inscode(d, ds, de, "WSAGETSELECTERRO", WSAGETSELECTERRO, "Error WSAGETSELECTERRO");
#endif
#ifdef WSAETIMEDOUT
inscode(d, ds, de, "WSAETIMEDOUT", WSAETIMEDOUT, "Connection timed out");
#endif
#ifdef WSAENOBUFS
inscode(d, ds, de, "WSAENOBUFS", WSAENOBUFS, "No buffer space available");
#endif
#ifdef WSAEDISCON
inscode(d, ds, de, "WSAEDISCON", WSAEDISCON, "Error WSAEDISCON");
#endif
#ifdef WSAEINTR
inscode(d, ds, de, "WSAEINTR", WSAEINTR, "Interrupted system call");
#endif
#ifdef WSAEPROTOTYPE
inscode(d, ds, de, "WSAEPROTOTYPE", WSAEPROTOTYPE, "Protocol wrong type for socket");
#endif
#ifdef WSAHOS
inscode(d, ds, de, "WSAHOS", WSAHOS, "Error WSAHOS");
#endif
#ifdef WSAEADDRINUSE
inscode(d, ds, de, "WSAEADDRINUSE", WSAEADDRINUSE, "Address already in use");
#endif
#ifdef WSAEADDRNOTAVAIL
inscode(d, ds, de, "WSAEADDRNOTAVAIL", WSAEADDRNOTAVAIL, "Cannot assign requested address");
#endif
#ifdef WSAEALREADY
inscode(d, ds, de, "WSAEALREADY", WSAEALREADY, "Operation already in progress");
#endif
#ifdef WSAEPROTONOSUPPORT
inscode(d, ds, de, "WSAEPROTONOSUPPORT", WSAEPROTONOSUPPORT, "Protocol not supported");
#endif
#ifdef WSASYSNOTREADY
inscode(d, ds, de, "WSASYSNOTREADY", WSASYSNOTREADY, "Error WSASYSNOTREADY");
#endif
#ifdef WSAEWOULDBLOCK
inscode(d, ds, de, "WSAEWOULDBLOCK", WSAEWOULDBLOCK, "Operation would block");
#endif
#ifdef WSAEPFNOSUPPORT
inscode(d, ds, de, "WSAEPFNOSUPPORT", WSAEPFNOSUPPORT, "Protocol family not supported");
#endif
#ifdef WSAEOPNOTSUPP
inscode(d, ds, de, "WSAEOPNOTSUPP", WSAEOPNOTSUPP, "Operation not supported on transport endpoint");
#endif
#ifdef WSAEISCONN
inscode(d, ds, de, "WSAEISCONN", WSAEISCONN, "Transport endpoint is already connected");
#endif
#ifdef WSAEDQUOT
inscode(d, ds, de, "WSAEDQUOT", WSAEDQUOT, "Quota exceeded");
#endif
#ifdef WSAENOTCONN
inscode(d, ds, de, "WSAENOTCONN", WSAENOTCONN, "Transport endpoint is not connected");
#endif
#ifdef WSAEREMOTE
inscode(d, ds, de, "WSAEREMOTE", WSAEREMOTE, "Object is remote");
#endif
#ifdef WSAEINVAL
inscode(d, ds, de, "WSAEINVAL", WSAEINVAL, "Invalid argument");
#endif
#ifdef WSAEINPROGRESS
inscode(d, ds, de, "WSAEINPROGRESS", WSAEINPROGRESS, "Operation now in progress");
#endif
#ifdef WSAGETSELECTEVEN
inscode(d, ds, de, "WSAGETSELECTEVEN", WSAGETSELECTEVEN, "Error WSAGETSELECTEVEN");
#endif
#ifdef WSAESOCKTNOSUPPORT
inscode(d, ds, de, "WSAESOCKTNOSUPPORT", WSAESOCKTNOSUPPORT, "Socket type not supported");
#endif
#ifdef WSAGETASYNCERRO
inscode(d, ds, de, "WSAGETASYNCERRO", WSAGETASYNCERRO, "Error WSAGETASYNCERRO");
#endif
#ifdef WSAMAKESELECTREPL
inscode(d, ds, de, "WSAMAKESELECTREPL", WSAMAKESELECTREPL, "Error WSAMAKESELECTREPL");
#endif
#ifdef WSAGETASYNCBUFLE
inscode(d, ds, de, "WSAGETASYNCBUFLE", WSAGETASYNCBUFLE, "Error WSAGETASYNCBUFLE");
#endif
#ifdef WSAEDESTADDRREQ
inscode(d, ds, de, "WSAEDESTADDRREQ", WSAEDESTADDRREQ, "Destination address required");
#endif
#ifdef WSAECONNREFUSED
inscode(d, ds, de, "WSAECONNREFUSED", WSAECONNREFUSED, "Connection refused");
#endif
#ifdef WSAENETRESET
inscode(d, ds, de, "WSAENETRESET", WSAENETRESET, "Network dropped connection because of reset");
#endif
#ifdef WSAN
inscode(d, ds, de, "WSAN", WSAN, "Error WSAN");
#endif
/* These symbols are added for EDK II support. */
#ifdef EMINERRORVAL
inscode(d, ds, de, "EMINERRORVAL", EMINERRORVAL, "Lowest valid error value");
#endif
#ifdef ENOTSUP
inscode(d, ds, de, "ENOTSUP", ENOTSUP, "Operation not supported");
#endif
#ifdef EBADRPC
inscode(d, ds, de, "EBADRPC", EBADRPC, "RPC struct is bad");
#endif
#ifdef ERPCMISMATCH
inscode(d, ds, de, "ERPCMISMATCH", ERPCMISMATCH, "RPC version wrong");
#endif
#ifdef EPROGUNAVAIL
inscode(d, ds, de, "EPROGUNAVAIL", EPROGUNAVAIL, "RPC prog. not avail");
#endif
#ifdef EPROGMISMATCH
inscode(d, ds, de, "EPROGMISMATCH", EPROGMISMATCH, "Program version wrong");
#endif
#ifdef EPROCUNAVAIL
inscode(d, ds, de, "EPROCUNAVAIL", EPROCUNAVAIL, "Bad procedure for program");
#endif
#ifdef EFTYPE
inscode(d, ds, de, "EFTYPE", EFTYPE, "Inappropriate file type or format");
#endif
#ifdef EAUTH
inscode(d, ds, de, "EAUTH", EAUTH, "Authentication error");
#endif
#ifdef ENEEDAUTH
inscode(d, ds, de, "ENEEDAUTH", ENEEDAUTH, "Need authenticator");
#endif
#ifdef ECANCELED
inscode(d, ds, de, "ECANCELED", ECANCELED, "Operation canceled");
#endif
#ifdef ENOATTR
inscode(d, ds, de, "ENOATTR", ENOATTR, "Attribute not found");
#endif
#ifdef EDOOFUS
inscode(d, ds, de, "EDOOFUS", EDOOFUS, "Programming Error");
#endif
#ifdef EBUFSIZE
inscode(d, ds, de, "EBUFSIZE", EBUFSIZE, "Buffer too small to hold result");
#endif
#ifdef EMAXERRORVAL
inscode(d, ds, de, "EMAXERRORVAL", EMAXERRORVAL, "One more than the highest defined error value");
#endif
Py_DECREF(de);
}

View File

@@ -0,0 +1,21 @@
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
and Clark Cooper
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,96 @@
#ifndef AMIGACONFIG_H
#define AMIGACONFIG_H
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
#define BYTEORDER 4321
/* Define to 1 if you have the `bcopy' function. */
#define HAVE_BCOPY 1
/* Define to 1 if you have the <check.h> header file. */
#undef HAVE_CHECK_H
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "expat-bugs@mail.libexpat.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "expat"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "expat 1.95.8"
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.95.8"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* whether byteorder is bigendian */
#define WORDS_BIGENDIAN
/* Define to specify how much context to retain around the current parse
point. */
#define XML_CONTEXT_BYTES 1024
/* Define to make parameter entity parsing functionality available. */
#define XML_DTD
/* Define to make XML Namespaces functionality available. */
#define XML_NS
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `long' if <sys/types.h> does not define. */
#undef off_t
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
#endif /* AMIGACONFIG_H */

View File

@@ -0,0 +1,85 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
#define ASCII_A 0x41
#define ASCII_B 0x42
#define ASCII_C 0x43
#define ASCII_D 0x44
#define ASCII_E 0x45
#define ASCII_F 0x46
#define ASCII_G 0x47
#define ASCII_H 0x48
#define ASCII_I 0x49
#define ASCII_J 0x4A
#define ASCII_K 0x4B
#define ASCII_L 0x4C
#define ASCII_M 0x4D
#define ASCII_N 0x4E
#define ASCII_O 0x4F
#define ASCII_P 0x50
#define ASCII_Q 0x51
#define ASCII_R 0x52
#define ASCII_S 0x53
#define ASCII_T 0x54
#define ASCII_U 0x55
#define ASCII_V 0x56
#define ASCII_W 0x57
#define ASCII_X 0x58
#define ASCII_Y 0x59
#define ASCII_Z 0x5A
#define ASCII_a 0x61
#define ASCII_b 0x62
#define ASCII_c 0x63
#define ASCII_d 0x64
#define ASCII_e 0x65
#define ASCII_f 0x66
#define ASCII_g 0x67
#define ASCII_h 0x68
#define ASCII_i 0x69
#define ASCII_j 0x6A
#define ASCII_k 0x6B
#define ASCII_l 0x6C
#define ASCII_m 0x6D
#define ASCII_n 0x6E
#define ASCII_o 0x6F
#define ASCII_p 0x70
#define ASCII_q 0x71
#define ASCII_r 0x72
#define ASCII_s 0x73
#define ASCII_t 0x74
#define ASCII_u 0x75
#define ASCII_v 0x76
#define ASCII_w 0x77
#define ASCII_x 0x78
#define ASCII_y 0x79
#define ASCII_z 0x7A
#define ASCII_0 0x30
#define ASCII_1 0x31
#define ASCII_2 0x32
#define ASCII_3 0x33
#define ASCII_4 0x34
#define ASCII_5 0x35
#define ASCII_6 0x36
#define ASCII_7 0x37
#define ASCII_8 0x38
#define ASCII_9 0x39
#define ASCII_TAB 0x09
#define ASCII_SPACE 0x20
#define ASCII_EXCL 0x21
#define ASCII_QUOT 0x22
#define ASCII_AMP 0x26
#define ASCII_APOS 0x27
#define ASCII_MINUS 0x2D
#define ASCII_PERIOD 0x2E
#define ASCII_COLON 0x3A
#define ASCII_SEMI 0x3B
#define ASCII_LT 0x3C
#define ASCII_EQUALS 0x3D
#define ASCII_GT 0x3E
#define ASCII_LSQB 0x5B
#define ASCII_RSQB 0x5D
#define ASCII_UNDERSCORE 0x5F

View File

@@ -0,0 +1,36 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
/*
* Expat configuration for python. This file is not part of the expat
* distribution.
*/
#ifndef EXPAT_CONFIG_H
#define EXPAT_CONFIG_H
#include <pyconfig.h>
#ifdef WORDS_BIGENDIAN
#define BYTEORDER 4321
#else
#define BYTEORDER 1234
#endif
#define XML_NS 1
#define XML_DTD 1
#define XML_CONTEXT_BYTES 1024
#endif /* EXPAT_CONFIG_H */

View File

@@ -0,0 +1,119 @@
/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
#ifndef Expat_External_INCLUDED
#define Expat_External_INCLUDED 1
/* External API definitions */
/* Namespace external symbols to allow multiple libexpat version to
co-exist. */
#include "pyexpatns.h"
#if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__)
#define XML_USE_MSC_EXTENSIONS 1
#endif
/* Expat tries very hard to make the API boundary very specifically
defined. There are two macros defined to control this boundary;
each of these can be defined before including this header to
achieve some different behavior, but doing so it not recommended or
tested frequently.
XMLCALL - The calling convention to use for all calls across the
"library boundary." This will default to cdecl, and
try really hard to tell the compiler that's what we
want.
XMLIMPORT - Whatever magic is needed to note that a function is
to be imported from a dynamically loaded library
(.dll, .so, or .sl, depending on your platform).
The XMLCALL macro was added in Expat 1.95.7. The only one which is
expected to be directly useful in client code is XMLCALL.
Note that on at least some Unix versions, the Expat library must be
compiled with the cdecl calling convention as the default since
system headers may assume the cdecl convention.
*/
#ifndef XMLCALL
#if defined(XML_USE_MSC_EXTENSIONS)
#define XMLCALL __cdecl
#elif defined(__GNUC__) && defined(__i386)
#define XMLCALL __attribute__((cdecl))
#else
/* For any platform which uses this definition and supports more than
one calling convention, we need to extend this definition to
declare the convention used on that platform, if it's possible to
do so.
If this is the case for your platform, please file a bug report
with information on how to identify your platform via the C
pre-processor and how to specify the same calling convention as the
platform's malloc() implementation.
*/
#define XMLCALL
#endif
#endif /* not defined XMLCALL */
#if !defined(XML_STATIC) && !defined(XMLIMPORT)
#ifndef XML_BUILDING_EXPAT
/* using Expat from an application */
#ifdef XML_USE_MSC_EXTENSIONS
#define XMLIMPORT __declspec(dllimport)
#endif
#endif
#endif /* not defined XML_STATIC */
/* If we didn't define it above, define it away: */
#ifndef XMLIMPORT
#define XMLIMPORT
#endif
#define XMLPARSEAPI(type) XMLIMPORT type XMLCALL
#ifdef __cplusplus
extern "C" {
#endif
#ifdef XML_UNICODE_WCHAR_T
#define XML_UNICODE
#endif
#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
#ifdef XML_UNICODE_WCHAR_T
typedef wchar_t XML_Char;
typedef wchar_t XML_LChar;
#else
typedef unsigned short XML_Char;
typedef char XML_LChar;
#endif /* XML_UNICODE_WCHAR_T */
#else /* Information is UTF-8 encoded. */
typedef char XML_Char;
typedef char XML_LChar;
#endif /* XML_UNICODE */
#ifdef XML_LARGE_SIZE /* Use large integers for file/stream positions. */
#if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400
typedef __int64 XML_Index;
typedef unsigned __int64 XML_Size;
#else
typedef long long XML_Index;
typedef unsigned long long XML_Size;
#endif
#else
typedef long XML_Index;
typedef unsigned long XML_Size;
#endif /* XML_LARGE_SIZE */
#ifdef __cplusplus
}
#endif
#endif /* not Expat_External_INCLUDED */

View File

@@ -0,0 +1,37 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,

View File

@@ -0,0 +1,73 @@
/* internal.h
Internal definitions used by Expat. This is not needed to compile
client code.
The following calling convention macros are defined for frequently
called functions:
FASTCALL - Used for those internal functions that have a simple
body and a low number of arguments and local variables.
PTRCALL - Used for functions called though function pointers.
PTRFASTCALL - Like PTRCALL, but for low number of arguments.
inline - Used for selected internal functions for which inlining
may improve performance on some platforms.
Note: Use of these macros is based on judgement, not hard rules,
and therefore subject to change.
*/
#if defined(__GNUC__) && defined(__i386__)
/* We'll use this version by default only where we know it helps.
regparm() generates warnings on Solaris boxes. See SF bug #692878.
Instability reported with egcs on a RedHat Linux 7.3.
Let's comment out:
#define FASTCALL __attribute__((stdcall, regparm(3)))
and let's try this:
*/
#define FASTCALL __attribute__((regparm(3)))
#define PTRFASTCALL __attribute__((regparm(3)))
#endif
/* Using __fastcall seems to have an unexpected negative effect under
MS VC++, especially for function pointers, so we won't use it for
now on that platform. It may be reconsidered for a future release
if it can be made more effective.
Likely reason: __fastcall on Windows is like stdcall, therefore
the compiler cannot perform stack optimizations for call clusters.
*/
/* Make sure all of these are defined if they aren't already. */
#ifndef FASTCALL
#define FASTCALL
#endif
#ifndef PTRCALL
#define PTRCALL
#endif
#ifndef PTRFASTCALL
#define PTRFASTCALL
#endif
#ifndef XML_MIN_SIZE
#if !defined(__cplusplus) && !defined(inline)
#ifdef __GNUC__
#define inline __inline
#endif /* __GNUC__ */
#endif
#endif /* XML_MIN_SIZE */
#ifdef __cplusplus
#define inline inline
#else
#ifndef inline
#define inline
#endif
#endif

View File

@@ -0,0 +1,36 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,

View File

@@ -0,0 +1,53 @@
/*================================================================
** Copyright 2000, Clark Cooper
** All rights reserved.
**
** This is free software. You are permitted to copy, distribute, or modify
** it under the terms of the MIT/X license (contained in the COPYING file
** with this distribution.)
**
*/
#ifndef MACCONFIG_H
#define MACCONFIG_H
/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
#define BYTEORDER 4321
/* Define to 1 if you have the `bcopy' function. */
#undef HAVE_BCOPY
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* whether byteorder is bigendian */
#define WORDS_BIGENDIAN
/* Define to specify how much context to retain around the current parse
point. */
#undef XML_CONTEXT_BYTES
/* Define to make parameter entity parsing functionality available. */
#define XML_DTD
/* Define to make XML Namespaces functionality available. */
#define XML_NS
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `long' if <sys/types.h> does not define. */
#define off_t long
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
#endif /* ifndef MACCONFIG_H */

View File

@@ -0,0 +1,150 @@
static const unsigned namingBitmap[] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
0x40000000, 0xF580C900, 0x00000007, 0x02010800,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
0x00000000, 0x00004C40, 0x00000000, 0x00000000,
0x00000007, 0x00000000, 0x00000000, 0x00000000,
0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
};
static const unsigned char nmstrtPages[] = {
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char namePages[] = {
0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

View File

@@ -0,0 +1,124 @@
/* Copyright (c) 2005-2006 ActiveState Software Inc.
*
* Namespace all expat exported symbols to avoid dynamic loading symbol
* collisions when embedding Python.
*
* The Problem:
* - you embed Python in some app
* - the app dynamically loads libexpat of version X
* - the embedded Python imports pyexpat (which was built against
* libexpat version X+n)
* --> pyexpat gets the expat symbols from the already loaded and *older*
* libexpat: crash (Specifically the crash we observed was in
* getting an old XML_ErrorString (from xmlparse.c) and then calling
* it with newer values in the XML_Error enum:
*
* // pyexpat.c, line 1970
* ...
* // Added in Expat 1.95.7.
* MYCONST(XML_ERROR_UNBOUND_PREFIX);
* ...
*
*
* The Solution:
* Prefix all a exported symbols with "PyExpat_". This is similar to
* what Mozilla does for some common libs:
* http://lxr.mozilla.org/seamonkey/source/modules/libimg/png/mozpngconf.h#115
*
* The list of relevant exported symbols can be had with this command:
*
nm pyexpat.so \
| grep -v " [a-zBUA] " \
| grep -v "_fini\|_init\|initpyexpat"
*
* If any of those symbols are NOT prefixed with "PyExpat_" then
* a #define should be added for it here.
*/
#ifndef PYEXPATNS_H
#define PYEXPATNS_H
#define XML_DefaultCurrent PyExpat_XML_DefaultCurrent
#define XML_ErrorString PyExpat_XML_ErrorString
#define XML_ExpatVersion PyExpat_XML_ExpatVersion
#define XML_ExpatVersionInfo PyExpat_XML_ExpatVersionInfo
#define XML_ExternalEntityParserCreate PyExpat_XML_ExternalEntityParserCreate
#define XML_FreeContentModel PyExpat_XML_FreeContentModel
#define XML_GetBase PyExpat_XML_GetBase
#define XML_GetBuffer PyExpat_XML_GetBuffer
#define XML_GetCurrentByteCount PyExpat_XML_GetCurrentByteCount
#define XML_GetCurrentByteIndex PyExpat_XML_GetCurrentByteIndex
#define XML_GetCurrentColumnNumber PyExpat_XML_GetCurrentColumnNumber
#define XML_GetCurrentLineNumber PyExpat_XML_GetCurrentLineNumber
#define XML_GetErrorCode PyExpat_XML_GetErrorCode
#define XML_GetFeatureList PyExpat_XML_GetFeatureList
#define XML_GetIdAttributeIndex PyExpat_XML_GetIdAttributeIndex
#define XML_GetInputContext PyExpat_XML_GetInputContext
#define XML_GetParsingStatus PyExpat_XML_GetParsingStatus
#define XML_GetSpecifiedAttributeCount PyExpat_XML_GetSpecifiedAttributeCount
#define XmlGetUtf16InternalEncoding PyExpat_XmlGetUtf16InternalEncoding
#define XmlGetUtf16InternalEncodingNS PyExpat_XmlGetUtf16InternalEncodingNS
#define XmlGetUtf8InternalEncoding PyExpat_XmlGetUtf8InternalEncoding
#define XmlGetUtf8InternalEncodingNS PyExpat_XmlGetUtf8InternalEncodingNS
#define XmlInitEncoding PyExpat_XmlInitEncoding
#define XmlInitEncodingNS PyExpat_XmlInitEncodingNS
#define XmlInitUnknownEncoding PyExpat_XmlInitUnknownEncoding
#define XmlInitUnknownEncodingNS PyExpat_XmlInitUnknownEncodingNS
#define XML_MemFree PyExpat_XML_MemFree
#define XML_MemMalloc PyExpat_XML_MemMalloc
#define XML_MemRealloc PyExpat_XML_MemRealloc
#define XML_Parse PyExpat_XML_Parse
#define XML_ParseBuffer PyExpat_XML_ParseBuffer
#define XML_ParserCreate PyExpat_XML_ParserCreate
#define XML_ParserCreate_MM PyExpat_XML_ParserCreate_MM
#define XML_ParserCreateNS PyExpat_XML_ParserCreateNS
#define XML_ParserFree PyExpat_XML_ParserFree
#define XML_ParserReset PyExpat_XML_ParserReset
#define XmlParseXmlDecl PyExpat_XmlParseXmlDecl
#define XmlParseXmlDeclNS PyExpat_XmlParseXmlDeclNS
#define XmlPrologStateInit PyExpat_XmlPrologStateInit
#define XmlPrologStateInitExternalEntity PyExpat_XmlPrologStateInitExternalEntity
#define XML_ResumeParser PyExpat_XML_ResumeParser
#define XML_SetAttlistDeclHandler PyExpat_XML_SetAttlistDeclHandler
#define XML_SetBase PyExpat_XML_SetBase
#define XML_SetCdataSectionHandler PyExpat_XML_SetCdataSectionHandler
#define XML_SetCharacterDataHandler PyExpat_XML_SetCharacterDataHandler
#define XML_SetCommentHandler PyExpat_XML_SetCommentHandler
#define XML_SetDefaultHandler PyExpat_XML_SetDefaultHandler
#define XML_SetDefaultHandlerExpand PyExpat_XML_SetDefaultHandlerExpand
#define XML_SetDoctypeDeclHandler PyExpat_XML_SetDoctypeDeclHandler
#define XML_SetElementDeclHandler PyExpat_XML_SetElementDeclHandler
#define XML_SetElementHandler PyExpat_XML_SetElementHandler
#define XML_SetEncoding PyExpat_XML_SetEncoding
#define XML_SetEndCdataSectionHandler PyExpat_XML_SetEndCdataSectionHandler
#define XML_SetEndDoctypeDeclHandler PyExpat_XML_SetEndDoctypeDeclHandler
#define XML_SetEndElementHandler PyExpat_XML_SetEndElementHandler
#define XML_SetEndNamespaceDeclHandler PyExpat_XML_SetEndNamespaceDeclHandler
#define XML_SetEntityDeclHandler PyExpat_XML_SetEntityDeclHandler
#define XML_SetExternalEntityRefHandler PyExpat_XML_SetExternalEntityRefHandler
#define XML_SetExternalEntityRefHandlerArg PyExpat_XML_SetExternalEntityRefHandlerArg
#define XML_SetNamespaceDeclHandler PyExpat_XML_SetNamespaceDeclHandler
#define XML_SetNotationDeclHandler PyExpat_XML_SetNotationDeclHandler
#define XML_SetNotStandaloneHandler PyExpat_XML_SetNotStandaloneHandler
#define XML_SetParamEntityParsing PyExpat_XML_SetParamEntityParsing
#define XML_SetProcessingInstructionHandler PyExpat_XML_SetProcessingInstructionHandler
#define XML_SetReturnNSTriplet PyExpat_XML_SetReturnNSTriplet
#define XML_SetSkippedEntityHandler PyExpat_XML_SetSkippedEntityHandler
#define XML_SetStartCdataSectionHandler PyExpat_XML_SetStartCdataSectionHandler
#define XML_SetStartDoctypeDeclHandler PyExpat_XML_SetStartDoctypeDeclHandler
#define XML_SetStartElementHandler PyExpat_XML_SetStartElementHandler
#define XML_SetStartNamespaceDeclHandler PyExpat_XML_SetStartNamespaceDeclHandler
#define XML_SetUnknownEncodingHandler PyExpat_XML_SetUnknownEncodingHandler
#define XML_SetUnparsedEntityDeclHandler PyExpat_XML_SetUnparsedEntityDeclHandler
#define XML_SetUserData PyExpat_XML_SetUserData
#define XML_SetXmlDeclHandler PyExpat_XML_SetXmlDeclHandler
#define XmlSizeOfUnknownEncoding PyExpat_XmlSizeOfUnknownEncoding
#define XML_StopParser PyExpat_XML_StopParser
#define XML_UseForeignDTD PyExpat_XML_UseForeignDTD
#define XML_UseParserAsHandlerArg PyExpat_XML_UseParserAsHandlerArg
#define XmlUtf16Encode PyExpat_XmlUtf16Encode
#define XmlUtf8Encode PyExpat_XmlUtf8Encode
#endif /* !PYEXPATNS_H */

View File

@@ -0,0 +1,37 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,

View File

@@ -0,0 +1,30 @@
/*================================================================
** Copyright 2000, Clark Cooper
** All rights reserved.
**
** This is free software. You are permitted to copy, distribute, or modify
** it under the terms of the MIT/X license (contained in the COPYING file
** with this distribution.)
*/
#ifndef WINCONFIG_H
#define WINCONFIG_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <memory.h>
#include <string.h>
#define XML_NS 1
#define XML_DTD 1
#define XML_CONTEXT_BYTES 1024
/* we will assume all Windows platforms are little endian */
#define BYTEORDER 1234
/* Windows has memmove() available. */
#define HAVE_MEMMOVE
#endif /* ndef WINCONFIG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
#ifndef XmlRole_INCLUDED
#define XmlRole_INCLUDED 1
#ifdef __VMS
/* 0 1 2 3 0 1 2 3
1234567890123456789012345678901 1234567890123456789012345678901 */
#define XmlPrologStateInitExternalEntity XmlPrologStateInitExternalEnt
#endif
#include "xmltok.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
XML_ROLE_ERROR = -1,
XML_ROLE_NONE = 0,
XML_ROLE_XML_DECL,
XML_ROLE_INSTANCE_START,
XML_ROLE_DOCTYPE_NONE,
XML_ROLE_DOCTYPE_NAME,
XML_ROLE_DOCTYPE_SYSTEM_ID,
XML_ROLE_DOCTYPE_PUBLIC_ID,
XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
XML_ROLE_DOCTYPE_CLOSE,
XML_ROLE_GENERAL_ENTITY_NAME,
XML_ROLE_PARAM_ENTITY_NAME,
XML_ROLE_ENTITY_NONE,
XML_ROLE_ENTITY_VALUE,
XML_ROLE_ENTITY_SYSTEM_ID,
XML_ROLE_ENTITY_PUBLIC_ID,
XML_ROLE_ENTITY_COMPLETE,
XML_ROLE_ENTITY_NOTATION_NAME,
XML_ROLE_NOTATION_NONE,
XML_ROLE_NOTATION_NAME,
XML_ROLE_NOTATION_SYSTEM_ID,
XML_ROLE_NOTATION_NO_SYSTEM_ID,
XML_ROLE_NOTATION_PUBLIC_ID,
XML_ROLE_ATTRIBUTE_NAME,
XML_ROLE_ATTRIBUTE_TYPE_CDATA,
XML_ROLE_ATTRIBUTE_TYPE_ID,
XML_ROLE_ATTRIBUTE_TYPE_IDREF,
XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
XML_ROLE_ATTRIBUTE_ENUM_VALUE,
XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
XML_ROLE_ATTLIST_NONE,
XML_ROLE_ATTLIST_ELEMENT_NAME,
XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
XML_ROLE_FIXED_ATTRIBUTE_VALUE,
XML_ROLE_ELEMENT_NONE,
XML_ROLE_ELEMENT_NAME,
XML_ROLE_CONTENT_ANY,
XML_ROLE_CONTENT_EMPTY,
XML_ROLE_CONTENT_PCDATA,
XML_ROLE_GROUP_OPEN,
XML_ROLE_GROUP_CLOSE,
XML_ROLE_GROUP_CLOSE_REP,
XML_ROLE_GROUP_CLOSE_OPT,
XML_ROLE_GROUP_CLOSE_PLUS,
XML_ROLE_GROUP_CHOICE,
XML_ROLE_GROUP_SEQUENCE,
XML_ROLE_CONTENT_ELEMENT,
XML_ROLE_CONTENT_ELEMENT_REP,
XML_ROLE_CONTENT_ELEMENT_OPT,
XML_ROLE_CONTENT_ELEMENT_PLUS,
XML_ROLE_PI,
XML_ROLE_COMMENT,
#ifdef XML_DTD
XML_ROLE_TEXT_DECL,
XML_ROLE_IGNORE_SECT,
XML_ROLE_INNER_PARAM_ENTITY_REF,
#endif /* XML_DTD */
XML_ROLE_PARAM_ENTITY_REF
};
typedef struct prolog_state {
int (PTRCALL *handler) (struct prolog_state *state,
int tok,
const char *ptr,
const char *end,
const ENCODING *enc);
unsigned level;
int role_none;
#ifdef XML_DTD
unsigned includeLevel;
int documentEntity;
int inEntityValue;
#endif /* XML_DTD */
} PROLOG_STATE;
void XmlPrologStateInit(PROLOG_STATE *);
#ifdef XML_DTD
void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
#endif /* XML_DTD */
#define XmlTokenRole(state, tok, ptr, end, enc) \
(((state)->handler)(state, tok, ptr, end, enc))
#ifdef __cplusplus
}
#endif
#endif /* not XmlRole_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
/* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
#ifndef XmlTok_INCLUDED
#define XmlTok_INCLUDED 1
#ifdef __cplusplus
extern "C" {
#endif
/* The following token may be returned by XmlContentTok */
#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be
start of illegal ]]> sequence */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
#define XML_TOK_NONE -4 /* The string to be scanned is empty */
#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
might be part of CRLF sequence */
#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
#define XML_TOK_PARTIAL -1 /* only part of a token */
#define XML_TOK_INVALID 0
/* The following tokens are returned by XmlContentTok; some are also
returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok.
*/
#define XML_TOK_START_TAG_WITH_ATTS 1
#define XML_TOK_START_TAG_NO_ATTS 2
#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
#define XML_TOK_END_TAG 5
#define XML_TOK_DATA_CHARS 6
#define XML_TOK_DATA_NEWLINE 7
#define XML_TOK_CDATA_SECT_OPEN 8
#define XML_TOK_ENTITY_REF 9
#define XML_TOK_CHAR_REF 10 /* numeric character reference */
/* The following tokens may be returned by both XmlPrologTok and
XmlContentTok.
*/
#define XML_TOK_PI 11 /* processing instruction */
#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
#define XML_TOK_COMMENT 13
#define XML_TOK_BOM 14 /* Byte order mark */
/* The following tokens are returned only by XmlPrologTok */
#define XML_TOK_PROLOG_S 15
#define XML_TOK_DECL_OPEN 16 /* <!foo */
#define XML_TOK_DECL_CLOSE 17 /* > */
#define XML_TOK_NAME 18
#define XML_TOK_NMTOKEN 19
#define XML_TOK_POUND_NAME 20 /* #name */
#define XML_TOK_OR 21 /* | */
#define XML_TOK_PERCENT 22
#define XML_TOK_OPEN_PAREN 23
#define XML_TOK_CLOSE_PAREN 24
#define XML_TOK_OPEN_BRACKET 25
#define XML_TOK_CLOSE_BRACKET 26
#define XML_TOK_LITERAL 27
#define XML_TOK_PARAM_ENTITY_REF 28
#define XML_TOK_INSTANCE_START 29
/* The following occur only in element type declarations */
#define XML_TOK_NAME_QUESTION 30 /* name? */
#define XML_TOK_NAME_ASTERISK 31 /* name* */
#define XML_TOK_NAME_PLUS 32 /* name+ */
#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
#define XML_TOK_COMMA 38
/* The following token is returned only by XmlAttributeValueTok */
#define XML_TOK_ATTRIBUTE_VALUE_S 39
/* The following token is returned only by XmlCdataSectionTok */
#define XML_TOK_CDATA_SECT_CLOSE 40
/* With namespace processing this is returned by XmlPrologTok for a
name with a colon.
*/
#define XML_TOK_PREFIXED_NAME 41
#ifdef XML_DTD
#define XML_TOK_IGNORE_SECT 42
#endif /* XML_DTD */
#ifdef XML_DTD
#define XML_N_STATES 4
#else /* not XML_DTD */
#define XML_N_STATES 3
#endif /* not XML_DTD */
#define XML_PROLOG_STATE 0
#define XML_CONTENT_STATE 1
#define XML_CDATA_SECTION_STATE 2
#ifdef XML_DTD
#define XML_IGNORE_SECTION_STATE 3
#endif /* XML_DTD */
#define XML_N_LITERAL_TYPES 2
#define XML_ATTRIBUTE_VALUE_LITERAL 0
#define XML_ENTITY_VALUE_LITERAL 1
/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
#define XML_UTF8_ENCODE_MAX 4
/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
#define XML_UTF16_ENCODE_MAX 2
typedef struct position {
/* first line and first column are 0 not 1 */
XML_Size lineNumber;
XML_Size columnNumber;
} POSITION;
typedef struct {
const char *name;
const char *valuePtr;
const char *valueEnd;
char normalized;
} ATTRIBUTE;
struct encoding;
typedef struct encoding ENCODING;
typedef int (PTRCALL *SCANNER)(const ENCODING *,
const char *,
const char *,
const char **);
struct encoding {
SCANNER scanners[XML_N_STATES];
SCANNER literalScanners[XML_N_LITERAL_TYPES];
int (PTRCALL *sameName)(const ENCODING *,
const char *,
const char *);
int (PTRCALL *nameMatchesAscii)(const ENCODING *,
const char *,
const char *,
const char *);
int (PTRFASTCALL *nameLength)(const ENCODING *, const char *);
const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *);
int (PTRCALL *getAtts)(const ENCODING *enc,
const char *ptr,
int attsMax,
ATTRIBUTE *atts);
int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr);
int (PTRCALL *predefinedEntityName)(const ENCODING *,
const char *,
const char *);
void (PTRCALL *updatePosition)(const ENCODING *,
const char *ptr,
const char *end,
POSITION *);
int (PTRCALL *isPublicId)(const ENCODING *enc,
const char *ptr,
const char *end,
const char **badPtr);
void (PTRCALL *utf8Convert)(const ENCODING *enc,
const char **fromP,
const char *fromLim,
char **toP,
const char *toLim);
void (PTRCALL *utf16Convert)(const ENCODING *enc,
const char **fromP,
const char *fromLim,
unsigned short **toP,
const unsigned short *toLim);
int minBytesPerChar;
char isUtf8;
char isUtf16;
};
/* Scan the string starting at ptr until the end of the next complete
token, but do not scan past eptr. Return an integer giving the
type of token.
Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
Return XML_TOK_PARTIAL when the string does not contain a complete
token; nextTokPtr will not be set.
Return XML_TOK_INVALID when the string does not start a valid
token; nextTokPtr will be set to point to the character which made
the token invalid.
Otherwise the string starts with a valid token; nextTokPtr will be
set to point to the character following the end of that token.
Each data character counts as a single token, but adjacent data
characters may be returned together. Similarly for characters in
the prolog outside literals, comments and processing instructions.
*/
#define XmlTok(enc, state, ptr, end, nextTokPtr) \
(((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
#define XmlContentTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
#ifdef XML_DTD
#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
#endif /* XML_DTD */
/* This is used for performing a 2nd-level tokenization on the content
of a literal that has already been returned by XmlTok.
*/
#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
(((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
(((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
#define XmlNameLength(enc, ptr) \
(((enc)->nameLength)(enc, ptr))
#define XmlSkipS(enc, ptr) \
(((enc)->skipS)(enc, ptr))
#define XmlGetAttributes(enc, ptr, attsMax, atts) \
(((enc)->getAtts)(enc, ptr, attsMax, atts))
#define XmlCharRefNumber(enc, ptr) \
(((enc)->charRefNumber)(enc, ptr))
#define XmlPredefinedEntityName(enc, ptr, end) \
(((enc)->predefinedEntityName)(enc, ptr, end))
#define XmlUpdatePosition(enc, ptr, end, pos) \
(((enc)->updatePosition)(enc, ptr, end, pos))
#define XmlIsPublicId(enc, ptr, end, badPtr) \
(((enc)->isPublicId)(enc, ptr, end, badPtr))
#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
(((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
(((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
typedef struct {
ENCODING initEnc;
const ENCODING **encPtr;
} INIT_ENCODING;
int XmlParseXmlDecl(int isGeneralTextEntity,
const ENCODING *enc,
const char *ptr,
const char *end,
const char **badPtr,
const char **versionPtr,
const char **versionEndPtr,
const char **encodingNamePtr,
const ENCODING **namedEncodingPtr,
int *standalonePtr);
int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
const ENCODING *XmlGetUtf8InternalEncoding(void);
const ENCODING *XmlGetUtf16InternalEncoding(void);
int FASTCALL XmlUtf8Encode(int charNumber, char *buf);
int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf);
int XmlSizeOfUnknownEncoding(void);
typedef int (XMLCALL *CONVERTER) (void *userData, const char *p);
ENCODING *
XmlInitUnknownEncoding(void *mem,
int *table,
CONVERTER convert,
void *userData);
int XmlParseXmlDeclNS(int isGeneralTextEntity,
const ENCODING *enc,
const char *ptr,
const char *end,
const char **badPtr,
const char **versionPtr,
const char **versionEndPtr,
const char **encodingNamePtr,
const ENCODING **namedEncodingPtr,
int *standalonePtr);
int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
const ENCODING *XmlGetUtf8InternalEncodingNS(void);
const ENCODING *XmlGetUtf16InternalEncodingNS(void);
ENCODING *
XmlInitUnknownEncodingNS(void *mem,
int *table,
CONVERTER convert,
void *userData);
#ifdef __cplusplus
}
#endif
#endif /* not XmlTok_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
*/
enum {
BT_NONXML,
BT_MALFORM,
BT_LT,
BT_AMP,
BT_RSQB,
BT_LEAD2,
BT_LEAD3,
BT_LEAD4,
BT_TRAIL,
BT_CR,
BT_LF,
BT_GT,
BT_QUOT,
BT_APOS,
BT_EQUALS,
BT_QUEST,
BT_EXCL,
BT_SOL,
BT_SEMI,
BT_NUM,
BT_LSQB,
BT_S,
BT_NMSTRT,
BT_COLON,
BT_HEX,
BT_DIGIT,
BT_NAME,
BT_MINUS,
BT_OTHER, /* known not to be a name or name start character */
BT_NONASCII, /* might be a name or name start character */
BT_PERCNT,
BT_LPAR,
BT_RPAR,
BT_AST,
BT_PLUS,
BT_COMMA,
BT_VERBAR
};
#include <stddef.h>

View File

@@ -0,0 +1,106 @@
const ENCODING *
NS(XmlGetUtf8InternalEncoding)(void)
{
return &ns(internal_utf8_encoding).enc;
}
const ENCODING *
NS(XmlGetUtf16InternalEncoding)(void)
{
#if BYTEORDER == 1234
return &ns(internal_little2_encoding).enc;
#elif BYTEORDER == 4321
return &ns(internal_big2_encoding).enc;
#else
const short n = 1;
return (*(const char *)&n
? &ns(internal_little2_encoding).enc
: &ns(internal_big2_encoding).enc);
#endif
}
static const ENCODING * const NS(encodings)[] = {
&ns(latin1_encoding).enc,
&ns(ascii_encoding).enc,
&ns(utf8_encoding).enc,
&ns(big2_encoding).enc,
&ns(big2_encoding).enc,
&ns(little2_encoding).enc,
&ns(utf8_encoding).enc /* NO_ENC */
};
static int PTRCALL
NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr)
{
return initScan(NS(encodings), (const INIT_ENCODING *)enc,
XML_PROLOG_STATE, ptr, end, nextTokPtr);
}
static int PTRCALL
NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
const char **nextTokPtr)
{
return initScan(NS(encodings), (const INIT_ENCODING *)enc,
XML_CONTENT_STATE, ptr, end, nextTokPtr);
}
int
NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr,
const char *name)
{
int i = getEncodingIndex(name);
if (i == UNKNOWN_ENC)
return 0;
SET_INIT_ENC_INDEX(p, i);
p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
p->initEnc.updatePosition = initUpdatePosition;
p->encPtr = encPtr;
*encPtr = &(p->initEnc);
return 1;
}
static const ENCODING *
NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
{
#define ENCODING_MAX 128
char buf[ENCODING_MAX];
char *p = buf;
int i;
XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
if (ptr != end)
return 0;
*p = 0;
if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
return enc;
i = getEncodingIndex(buf);
if (i == UNKNOWN_ENC)
return 0;
return NS(encodings)[i];
}
int
NS(XmlParseXmlDecl)(int isGeneralTextEntity,
const ENCODING *enc,
const char *ptr,
const char *end,
const char **badPtr,
const char **versionPtr,
const char **versionEndPtr,
const char **encodingName,
const ENCODING **encoding,
int *standalone)
{
return doParseXmlDecl(NS(findEncoding),
isGeneralTextEntity,
enc,
ptr,
end,
badPtr,
versionPtr,
versionEndPtr,
encodingName,
encoding,
standalone);
}

View File

@@ -0,0 +1,620 @@
/* fcntl module */
#define PY_SSIZE_T_CLEAN
#include "Python.h"
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif
static int
conv_descriptor(PyObject *object, int *target)
{
int fd = PyObject_AsFileDescriptor(object);
if (fd < 0)
return 0;
*target = fd;
return 1;
}
/* fcntl(fd, opt, [arg]) */
static PyObject *
fcntl_fcntl(PyObject *self, PyObject *args)
{
int fd;
int code;
long arg;
int ret;
char *str;
Py_ssize_t len;
char buf[1024];
if (PyArg_ParseTuple(args, "O&is#:fcntl",
conv_descriptor, &fd, &code, &str, &len)) {
if (len > sizeof buf) {
PyErr_SetString(PyExc_ValueError,
"fcntl string arg too long");
return NULL;
}
memcpy(buf, str, len);
Py_BEGIN_ALLOW_THREADS
ret = fcntl(fd, code, buf);
Py_END_ALLOW_THREADS
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyString_FromStringAndSize(buf, len);
}
PyErr_Clear();
arg = 0;
if (!PyArg_ParseTuple(args,
"O&i|l;fcntl requires a file or file descriptor,"
" an integer and optionally a third integer or a string",
conv_descriptor, &fd, &code, &arg)) {
return NULL;
}
Py_BEGIN_ALLOW_THREADS
ret = fcntl(fd, code, arg);
Py_END_ALLOW_THREADS
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyInt_FromLong((long)ret);
}
PyDoc_STRVAR(fcntl_doc,
"fcntl(fd, opt, [arg])\n\
\n\
Perform the requested operation on file descriptor fd. The operation\n\
is defined by op and is operating system dependent. These constants are\n\
available from the fcntl module. The argument arg is optional, and\n\
defaults to 0; it may be an int or a string. If arg is given as a string,\n\
the return value of fcntl is a string of that length, containing the\n\
resulting value put in the arg buffer by the operating system. The length\n\
of the arg string is not allowed to exceed 1024 bytes. If the arg given\n\
is an integer or if none is specified, the result value is an integer\n\
corresponding to the return value of the fcntl call in the C code.");
/* ioctl(fd, opt, [arg]) */
static PyObject *
fcntl_ioctl(PyObject *self, PyObject *args)
{
#define IOCTL_BUFSZ 1024
int fd;
/* In PyArg_ParseTuple below, we use the unsigned non-checked 'I'
format for the 'code' parameter because Python turns 0x8000000
into either a large positive number (PyLong or PyInt on 64-bit
platforms) or a negative number on others (32-bit PyInt)
whereas the system expects it to be a 32bit bit field value
regardless of it being passed as an int or unsigned long on
various platforms. See the termios.TIOCSWINSZ constant across
platforms for an example of thise.
If any of the 64bit platforms ever decide to use more than 32bits
in their unsigned long ioctl codes this will break and need
special casing based on the platform being built on.
*/
unsigned int code;
int arg;
int ret;
char *str;
Py_ssize_t len;
int mutate_arg = 1;
char buf[IOCTL_BUFSZ+1]; /* argument plus NUL byte */
if (PyArg_ParseTuple(args, "O&Iw#|i:ioctl",
conv_descriptor, &fd, &code,
&str, &len, &mutate_arg)) {
char *arg;
if (mutate_arg) {
if (len <= IOCTL_BUFSZ) {
memcpy(buf, str, len);
buf[len] = '\0';
arg = buf;
}
else {
arg = str;
}
}
else {
if (len > IOCTL_BUFSZ) {
PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long");
return NULL;
}
else {
memcpy(buf, str, len);
buf[len] = '\0';
arg = buf;
}
}
if (buf == arg) {
Py_BEGIN_ALLOW_THREADS /* think array.resize() */
ret = ioctl(fd, code, arg);
Py_END_ALLOW_THREADS
}
else {
ret = ioctl(fd, code, arg);
}
if (mutate_arg && (len <= IOCTL_BUFSZ)) {
memcpy(str, buf, len);
}
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
if (mutate_arg) {
return PyInt_FromLong(ret);
}
else {
return PyString_FromStringAndSize(buf, len);
}
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "O&Is#:ioctl",
conv_descriptor, &fd, &code, &str, &len)) {
if (len > IOCTL_BUFSZ) {
PyErr_SetString(PyExc_ValueError,
"ioctl string arg too long");
return NULL;
}
memcpy(buf, str, len);
buf[len] = '\0';
Py_BEGIN_ALLOW_THREADS
ret = ioctl(fd, code, buf);
Py_END_ALLOW_THREADS
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyString_FromStringAndSize(buf, len);
}
PyErr_Clear();
arg = 0;
if (!PyArg_ParseTuple(args,
"O&I|i;ioctl requires a file or file descriptor,"
" an integer and optionally an integer or buffer argument",
conv_descriptor, &fd, &code, &arg)) {
return NULL;
}
Py_BEGIN_ALLOW_THREADS
#ifdef __VMS
ret = ioctl(fd, code, (void *)arg);
#else
ret = ioctl(fd, code, arg);
#endif
Py_END_ALLOW_THREADS
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyInt_FromLong((long)ret);
#undef IOCTL_BUFSZ
}
PyDoc_STRVAR(ioctl_doc,
"ioctl(fd, opt[, arg[, mutate_flag]])\n\
\n\
Perform the requested operation on file descriptor fd. The operation is\n\
defined by opt and is operating system dependent. Typically these codes are\n\
retrieved from the fcntl or termios library modules.\n\
\n\
The argument arg is optional, and defaults to 0; it may be an int or a\n\
buffer containing character data (most likely a string or an array). \n\
\n\
If the argument is a mutable buffer (such as an array) and if the\n\
mutate_flag argument (which is only allowed in this case) is true then the\n\
buffer is (in effect) passed to the operating system and changes made by\n\
the OS will be reflected in the contents of the buffer after the call has\n\
returned. The return value is the integer returned by the ioctl system\n\
call.\n\
\n\
If the argument is a mutable buffer and the mutable_flag argument is not\n\
passed or is false, the behavior is as if a string had been passed. This\n\
behavior will change in future releases of Python.\n\
\n\
If the argument is an immutable buffer (most likely a string) then a copy\n\
of the buffer is passed to the operating system and the return value is a\n\
string of the same length containing whatever the operating system put in\n\
the buffer. The length of the arg buffer in this case is not allowed to\n\
exceed 1024 bytes.\n\
\n\
If the arg given is an integer or if none is specified, the result value is\n\
an integer corresponding to the return value of the ioctl call in the C\n\
code.");
/* flock(fd, operation) */
static PyObject *
fcntl_flock(PyObject *self, PyObject *args)
{
int fd;
int code;
int ret;
if (!PyArg_ParseTuple(args, "O&i:flock",
conv_descriptor, &fd, &code))
return NULL;
#ifdef HAVE_FLOCK
Py_BEGIN_ALLOW_THREADS
ret = flock(fd, code);
Py_END_ALLOW_THREADS
#else
#ifndef LOCK_SH
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* don't block when locking */
#define LOCK_UN 8 /* unlock */
#endif
{
struct flock l;
if (code == LOCK_UN)
l.l_type = F_UNLCK;
else if (code & LOCK_SH)
l.l_type = F_RDLCK;
else if (code & LOCK_EX)
l.l_type = F_WRLCK;
else {
PyErr_SetString(PyExc_ValueError,
"unrecognized flock argument");
return NULL;
}
l.l_whence = l.l_start = l.l_len = 0;
Py_BEGIN_ALLOW_THREADS
ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
Py_END_ALLOW_THREADS
}
#endif /* HAVE_FLOCK */
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
PyDoc_STRVAR(flock_doc,
"flock(fd, operation)\n\
\n\
Perform the lock operation op on file descriptor fd. See the Unix \n\
manual page for flock(3) for details. (On some systems, this function is\n\
emulated using fcntl().)");
/* lockf(fd, operation) */
static PyObject *
fcntl_lockf(PyObject *self, PyObject *args)
{
int fd, code, ret, whence = 0;
PyObject *lenobj = NULL, *startobj = NULL;
if (!PyArg_ParseTuple(args, "O&i|OOi:lockf",
conv_descriptor, &fd, &code,
&lenobj, &startobj, &whence))
return NULL;
#if defined(PYOS_OS2) && defined(PYCC_GCC)
PyErr_SetString(PyExc_NotImplementedError,
"lockf not supported on OS/2 (EMX)");
return NULL;
#else
#ifndef LOCK_SH
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_NB 4 /* don't block when locking */
#define LOCK_UN 8 /* unlock */
#endif /* LOCK_SH */
{
struct flock l;
if (code == LOCK_UN)
l.l_type = F_UNLCK;
else if (code & LOCK_SH)
l.l_type = F_RDLCK;
else if (code & LOCK_EX)
l.l_type = F_WRLCK;
else {
PyErr_SetString(PyExc_ValueError,
"unrecognized lockf argument");
return NULL;
}
l.l_start = l.l_len = 0;
if (startobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
l.l_start = PyInt_AsLong(startobj);
#else
l.l_start = PyLong_Check(startobj) ?
PyLong_AsLongLong(startobj) :
PyInt_AsLong(startobj);
#endif
if (PyErr_Occurred())
return NULL;
}
if (lenobj != NULL) {
#if !defined(HAVE_LARGEFILE_SUPPORT)
l.l_len = PyInt_AsLong(lenobj);
#else
l.l_len = PyLong_Check(lenobj) ?
PyLong_AsLongLong(lenobj) :
PyInt_AsLong(lenobj);
#endif
if (PyErr_Occurred())
return NULL;
}
l.l_whence = whence;
Py_BEGIN_ALLOW_THREADS
ret = fcntl(fd, (code & LOCK_NB) ? F_SETLK : F_SETLKW, &l);
Py_END_ALLOW_THREADS
}
if (ret < 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
#endif /* defined(PYOS_OS2) && defined(PYCC_GCC) */
}
PyDoc_STRVAR(lockf_doc,
"lockf (fd, operation, length=0, start=0, whence=0)\n\
\n\
This is essentially a wrapper around the fcntl() locking calls. fd is the\n\
file descriptor of the file to lock or unlock, and operation is one of the\n\
following values:\n\
\n\
LOCK_UN - unlock\n\
LOCK_SH - acquire a shared lock\n\
LOCK_EX - acquire an exclusive lock\n\
\n\
When operation is LOCK_SH or LOCK_EX, it can also be bitwise ORed with\n\
LOCK_NB to avoid blocking on lock acquisition. If LOCK_NB is used and the\n\
lock cannot be acquired, an IOError will be raised and the exception will\n\
have an errno attribute set to EACCES or EAGAIN (depending on the operating\n\
system -- for portability, check for either value).\n\
\n\
length is the number of bytes to lock, with the default meaning to lock to\n\
EOF. start is the byte offset, relative to whence, to that the lock\n\
starts. whence is as with fileobj.seek(), specifically:\n\
\n\
0 - relative to the start of the file (SEEK_SET)\n\
1 - relative to the current buffer position (SEEK_CUR)\n\
2 - relative to the end of the file (SEEK_END)");
/* List of functions */
static PyMethodDef fcntl_methods[] = {
{"fcntl", fcntl_fcntl, METH_VARARGS, fcntl_doc},
{"ioctl", fcntl_ioctl, METH_VARARGS, ioctl_doc},
{"flock", fcntl_flock, METH_VARARGS, flock_doc},
{"lockf", fcntl_lockf, METH_VARARGS, lockf_doc},
{NULL, NULL} /* sentinel */
};
PyDoc_STRVAR(module_doc,
"This module performs file control and I/O control on file \n\
descriptors. It is an interface to the fcntl() and ioctl() Unix\n\
routines. File descriptors can be obtained with the fileno() method of\n\
a file or socket object.");
/* Module initialisation */
static int
ins(PyObject* d, char* symbol, long value)
{
PyObject* v = PyInt_FromLong(value);
if (!v || PyDict_SetItemString(d, symbol, v) < 0)
return -1;
Py_DECREF(v);
return 0;
}
#define INS(x) if (ins(d, #x, (long)x)) return -1
static int
all_ins(PyObject* d)
{
if (ins(d, "LOCK_SH", (long)LOCK_SH)) return -1;
if (ins(d, "LOCK_EX", (long)LOCK_EX)) return -1;
if (ins(d, "LOCK_NB", (long)LOCK_NB)) return -1;
if (ins(d, "LOCK_UN", (long)LOCK_UN)) return -1;
/* GNU extensions, as of glibc 2.2.4 */
#ifdef LOCK_MAND
if (ins(d, "LOCK_MAND", (long)LOCK_MAND)) return -1;
#endif
#ifdef LOCK_READ
if (ins(d, "LOCK_READ", (long)LOCK_READ)) return -1;
#endif
#ifdef LOCK_WRITE
if (ins(d, "LOCK_WRITE", (long)LOCK_WRITE)) return -1;
#endif
#ifdef LOCK_RW
if (ins(d, "LOCK_RW", (long)LOCK_RW)) return -1;
#endif
#ifdef F_DUPFD
if (ins(d, "F_DUPFD", (long)F_DUPFD)) return -1;
#endif
#ifdef F_GETFD
if (ins(d, "F_GETFD", (long)F_GETFD)) return -1;
#endif
#ifdef F_SETFD
if (ins(d, "F_SETFD", (long)F_SETFD)) return -1;
#endif
#ifdef F_GETFL
if (ins(d, "F_GETFL", (long)F_GETFL)) return -1;
#endif
#ifdef F_SETFL
if (ins(d, "F_SETFL", (long)F_SETFL)) return -1;
#endif
#ifdef F_GETLK
if (ins(d, "F_GETLK", (long)F_GETLK)) return -1;
#endif
#ifdef F_SETLK
if (ins(d, "F_SETLK", (long)F_SETLK)) return -1;
#endif
#ifdef F_SETLKW
if (ins(d, "F_SETLKW", (long)F_SETLKW)) return -1;
#endif
#ifdef F_GETOWN
if (ins(d, "F_GETOWN", (long)F_GETOWN)) return -1;
#endif
#ifdef F_SETOWN
if (ins(d, "F_SETOWN", (long)F_SETOWN)) return -1;
#endif
#ifdef F_GETSIG
if (ins(d, "F_GETSIG", (long)F_GETSIG)) return -1;
#endif
#ifdef F_SETSIG
if (ins(d, "F_SETSIG", (long)F_SETSIG)) return -1;
#endif
#ifdef F_RDLCK
if (ins(d, "F_RDLCK", (long)F_RDLCK)) return -1;
#endif
#ifdef F_WRLCK
if (ins(d, "F_WRLCK", (long)F_WRLCK)) return -1;
#endif
#ifdef F_UNLCK
if (ins(d, "F_UNLCK", (long)F_UNLCK)) return -1;
#endif
/* LFS constants */
#ifdef F_GETLK64
if (ins(d, "F_GETLK64", (long)F_GETLK64)) return -1;
#endif
#ifdef F_SETLK64
if (ins(d, "F_SETLK64", (long)F_SETLK64)) return -1;
#endif
#ifdef F_SETLKW64
if (ins(d, "F_SETLKW64", (long)F_SETLKW64)) return -1;
#endif
/* GNU extensions, as of glibc 2.2.4. */
#ifdef FASYNC
if (ins(d, "FASYNC", (long)FASYNC)) return -1;
#endif
#ifdef F_SETLEASE
if (ins(d, "F_SETLEASE", (long)F_SETLEASE)) return -1;
#endif
#ifdef F_GETLEASE
if (ins(d, "F_GETLEASE", (long)F_GETLEASE)) return -1;
#endif
#ifdef F_NOTIFY
if (ins(d, "F_NOTIFY", (long)F_NOTIFY)) return -1;
#endif
/* Old BSD flock(). */
#ifdef F_EXLCK
if (ins(d, "F_EXLCK", (long)F_EXLCK)) return -1;
#endif
#ifdef F_SHLCK
if (ins(d, "F_SHLCK", (long)F_SHLCK)) return -1;
#endif
/* OS X (and maybe others) let you tell the storage device to flush to physical media */
#ifdef F_FULLFSYNC
if (ins(d, "F_FULLFSYNC", (long)F_FULLFSYNC)) return -1;
#endif
/* For F_{GET|SET}FL */
#ifdef FD_CLOEXEC
if (ins(d, "FD_CLOEXEC", (long)FD_CLOEXEC)) return -1;
#endif
/* For F_NOTIFY */
#ifdef DN_ACCESS
if (ins(d, "DN_ACCESS", (long)DN_ACCESS)) return -1;
#endif
#ifdef DN_MODIFY
if (ins(d, "DN_MODIFY", (long)DN_MODIFY)) return -1;
#endif
#ifdef DN_CREATE
if (ins(d, "DN_CREATE", (long)DN_CREATE)) return -1;
#endif
#ifdef DN_DELETE
if (ins(d, "DN_DELETE", (long)DN_DELETE)) return -1;
#endif
#ifdef DN_RENAME
if (ins(d, "DN_RENAME", (long)DN_RENAME)) return -1;
#endif
#ifdef DN_ATTRIB
if (ins(d, "DN_ATTRIB", (long)DN_ATTRIB)) return -1;
#endif
#ifdef DN_MULTISHOT
if (ins(d, "DN_MULTISHOT", (long)DN_MULTISHOT)) return -1;
#endif
#ifdef HAVE_STROPTS_H
/* Unix 98 guarantees that these are in stropts.h. */
INS(I_PUSH);
INS(I_POP);
INS(I_LOOK);
INS(I_FLUSH);
INS(I_FLUSHBAND);
INS(I_SETSIG);
INS(I_GETSIG);
INS(I_FIND);
INS(I_PEEK);
INS(I_SRDOPT);
INS(I_GRDOPT);
INS(I_NREAD);
INS(I_FDINSERT);
INS(I_STR);
INS(I_SWROPT);
#ifdef I_GWROPT
/* despite the comment above, old-ish glibcs miss a couple... */
INS(I_GWROPT);
#endif
INS(I_SENDFD);
INS(I_RECVFD);
INS(I_LIST);
INS(I_ATMARK);
INS(I_CKBAND);
INS(I_GETBAND);
INS(I_CANPUT);
INS(I_SETCLTIME);
#ifdef I_GETCLTIME
INS(I_GETCLTIME);
#endif
INS(I_LINK);
INS(I_UNLINK);
INS(I_PLINK);
INS(I_PUNLINK);
#endif
return 0;
}
PyMODINIT_FUNC
initfcntl(void)
{
PyObject *m, *d;
/* Create the module and add the functions and documentation */
m = Py_InitModule3("fcntl", fcntl_methods, module_doc);
if (m == NULL)
return;
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
all_ins(d);
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More