swigutil_py.c
来自「linux subdivision ying gai ke yi le ba」· C语言 代码 · 共 1,316 行 · 第 1/3 页
C
1,316 行
/*
* swigutil_py.c: utility functions for the SWIG Python bindings
*
* ====================================================================
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://subversion.tigris.org/license-1.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
*
* This software consists of voluntary contributions made by many
* individuals. For exact contribution history, see the revision
* history and logs, available at http://subversion.tigris.org/.
* ====================================================================
*/
#include <Python.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <apr_pools.h>
#include <apr_hash.h>
#include <apr_portable.h>
#include <apr_thread_proc.h>
#include "svn_string.h"
#include "svn_opt.h"
#include "svn_delta.h"
#if SVN_SWIG_VERSION >= 103024
#if SVN_SWIG_VERSION >= 103025
#include <swiglabels.swg>
#endif
#include <swigrun.swg>
#include <python/pyrun.swg>
#include <runtime.swg>
#endif
#include "swigutil_py.h"
/*** Manage the Global Interpreter Lock ***/
/* If both Python and APR have threads available, we can optimize ourselves
* by releasing the global interpreter lock when we drop into our SVN calls.
*
* In svn_types.i, svn_swig_py_release_py_lock is called before every
* function, then svn_swig_py_acquire_py_lock is called after every
* function. So, if these functions become no-ops, then Python will
* start to block...
*
* The Subversion libraries can be assumed to be thread-safe *only* when
* APR_HAS_THREAD is 1. The APR pool allocations aren't thread-safe unless
* APR_HAS_THREAD is 1.
*/
#if defined(WITH_THREAD) && APR_HAS_THREADS
#define ACQUIRE_PYTHON_LOCK
#endif
#ifdef ACQUIRE_PYTHON_LOCK
static apr_threadkey_t *_saved_thread_key = NULL;
static apr_pool_t *_saved_thread_pool = NULL;
#endif
void svn_swig_py_release_py_lock(void)
{
#ifdef ACQUIRE_PYTHON_LOCK
PyThreadState *thread_state;
if (_saved_thread_key == NULL) {
/* This is ugly. We call svn_swig_py_release_py_lock before executing any
subversion function. Thus it gets called before any call to
apr_initialize in our script. This means we have to call
apr_initialize ourselves, or otherwise we won't be able to
create our pool. */
apr_initialize();
/* Obviously, creating a top-level pool for this is pretty stupid. */
apr_pool_create(&_saved_thread_pool, NULL);
apr_threadkey_private_create(&_saved_thread_key, NULL, _saved_thread_pool);
}
thread_state = PyEval_SaveThread();
apr_threadkey_private_set(thread_state, _saved_thread_key);
#endif
}
void svn_swig_py_acquire_py_lock(void)
{
#ifdef ACQUIRE_PYTHON_LOCK
void *val;
PyThreadState *thread_state;
apr_threadkey_private_get(&val, _saved_thread_key);
thread_state = val;
PyEval_RestoreThread(thread_state);
#endif
}
/*** Custom SubversionException stuffs. ***/
/* Global SubversionException class object. */
static PyObject *SubversionException = NULL;
PyObject *svn_swig_py_exception_type(void)
{
Py_INCREF(SubversionException);
return SubversionException;
}
PyObject *svn_swig_py_register_exception(void)
{
/* If we haven't created our exception class, do so. */
if (SubversionException == NULL)
{
SubversionException = PyErr_NewException
((char *)"libsvn._core.SubversionException", NULL, NULL);
}
/* Regardless, return the exception class. */
return svn_swig_py_exception_type();
}
void svn_swig_py_svn_exception(svn_error_t *err)
{
PyObject *exc_ob, *apr_err_ob;
if (err == NULL)
return;
/* Make an integer for the error code. */
apr_err_ob = PyInt_FromLong(err->apr_err);
if (apr_err_ob == NULL)
return;
/* Instantiate a SubversionException object. */
exc_ob = PyObject_CallFunction(SubversionException, (char *)"sO",
err->message, apr_err_ob);
if (exc_ob == NULL)
{
Py_DECREF(apr_err_ob);
return;
}
/* Set the "apr_err" attribute of the exception to our error code. */
if (PyObject_SetAttrString(exc_ob, (char *)"apr_err", apr_err_ob) == -1)
{
Py_DECREF(apr_err_ob);
Py_DECREF(exc_ob);
return;
}
/* Finished with the apr_err object. */
Py_DECREF(apr_err_ob);
/* Set the error state to our exception object. */
PyErr_SetObject(SubversionException, exc_ob);
/* Finished with the exc_ob object. */
Py_DECREF(exc_ob);
}
/*** Helper/Conversion Routines ***/
static PyObject *make_pointer(const char *typename, void *ptr)
{
/* ### cache the swig_type_info at some point? */
return SWIG_NewPointerObj(ptr, SWIG_TypeQuery(typename), 0);
}
/* for use by the "O&" format specifier */
static PyObject *make_ob_pool(void *ptr)
{
return make_pointer("apr_pool_t *", ptr);
}
/* for use by the "O&" format specifier */
static PyObject *make_ob_window(void *ptr)
{
return make_pointer("svn_txdelta_window_t *", ptr);
}
/* for use by the "O&" format specifier */
static PyObject *make_ob_status(void *ptr)
{
return make_pointer("svn_wc_status_t *", ptr);
}
/* for use by the "O&" format specifier */
static PyObject *make_ob_fs_root(void *ptr)
{
return make_pointer("svn_fs_root_t *", ptr);
}
static PyObject *convert_hash(apr_hash_t *hash,
PyObject * (*converter_func)(void *value,
void *ctx),
void *ctx)
{
apr_hash_index_t *hi;
PyObject *dict = PyDict_New();
if (dict == NULL)
return NULL;
for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) {
const void *key;
void *val;
PyObject *value;
apr_hash_this(hi, &key, NULL, &val);
value = (*converter_func)(val, ctx);
if (value == NULL) {
Py_DECREF(dict);
return NULL;
}
/* ### gotta cast this thing cuz Python doesn't use "const" */
if (PyDict_SetItemString(dict, (char *)key, value) == -1) {
Py_DECREF(value);
Py_DECREF(dict);
return NULL;
}
Py_DECREF(value);
}
return dict;
}
static PyObject *convert_to_swigtype(void *value, void *ctx)
{
/* ctx is a 'swig_type_info *' */
return SWIG_NewPointerObj(value, ctx, 0);
}
static PyObject *convert_svn_string_t(void *value, void *ctx)
{
/* ctx is unused */
const svn_string_t *s = value;
/* ### borrowing from value in the pool. or should we copy? note
### that copying is "safest" */
/* ### gotta cast this thing cuz Python doesn't use "const" */
return PyBuffer_FromMemory((void *)s->data, s->len);
}
static PyObject *convert_svn_client_commit_item_t(void *value, void *ctx)
{
PyObject *list;
PyObject *path, *kind, *url, *rev, *cf_url, *state;
svn_client_commit_item_t *item = value;
/* ctx is unused */
list = PyList_New(6);
if (item->path)
path = PyString_FromString(item->path);
else
{
path = Py_None;
Py_INCREF(Py_None);
}
if (item->url)
url = PyString_FromString(item->url);
else
{
url = Py_None;
Py_INCREF(Py_None);
}
if (item->copyfrom_url)
cf_url = PyString_FromString(item->copyfrom_url);
else
{
cf_url = Py_None;
Py_INCREF(Py_None);
}
kind = PyInt_FromLong(item->kind);
rev = PyInt_FromLong(item->revision);
state = PyInt_FromLong(item->state_flags);
if (! (list && path && kind && url && rev && cf_url && state))
{
Py_XDECREF(list);
Py_XDECREF(path);
Py_XDECREF(kind);
Py_XDECREF(url);
Py_XDECREF(rev);
Py_XDECREF(cf_url);
Py_XDECREF(state);
return NULL;
}
PyList_SET_ITEM(list, 0, path);
PyList_SET_ITEM(list, 1, kind);
PyList_SET_ITEM(list, 2, url);
PyList_SET_ITEM(list, 3, rev);
PyList_SET_ITEM(list, 4, cf_url);
PyList_SET_ITEM(list, 5, state);
return list;
}
PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash)
{
return convert_hash(hash, convert_svn_string_t, NULL);
}
PyObject *svn_swig_py_convert_hash(apr_hash_t *hash, swig_type_info *type)
{
return convert_hash(hash, convert_to_swigtype, type);
}
PyObject *svn_swig_py_c_strings_to_list(char **strings)
{
PyObject *list = PyList_New(0);
char *s;
while ((s = *strings++) != NULL) {
PyObject *ob = PyString_FromString(s);
if (ob == NULL)
goto error;
if (PyList_Append(list, ob) == -1)
goto error;
}
return list;
error:
Py_DECREF(list);
return NULL;
}
const apr_array_header_t *svn_swig_py_strings_to_array(PyObject *source,
apr_pool_t *pool)
{
int targlen;
apr_array_header_t *temp;
if (!PySequence_Check(source)) {
PyErr_SetString(PyExc_TypeError, "not a sequence");
return NULL;
}
targlen = PySequence_Length(source);
temp = apr_array_make(pool, targlen, sizeof(const char *));
/* APR_ARRAY_IDX doesn't actually increment the array item count
(like, say, apr_array_push would). */
temp->nelts = targlen;
while (targlen--) {
PyObject *o = PySequence_GetItem(source, targlen);
if (o == NULL)
return NULL;
if (!PyString_Check(o)) {
Py_DECREF(o);
PyErr_SetString(PyExc_TypeError, "not a string");
return NULL;
}
APR_ARRAY_IDX(temp, targlen, const char *) = PyString_AS_STRING(o);
Py_DECREF(o);
}
return temp;
}
/*** apr_array_header_t conversions. To create a new type of
converter, simply copy-n-paste one of these function and tweak
the creation of the PyObject *ob. ***/
PyObject *svn_swig_py_array_to_list(const apr_array_header_t *array)
{
PyObject *list = PyList_New(array->nelts);
int i;
for (i = 0; i < array->nelts; ++i) {
PyObject *ob =
PyString_FromString(APR_ARRAY_IDX(array, i, const char *));
if (ob == NULL)
goto error;
PyList_SET_ITEM(list, i, ob);
}
return list;
error:
Py_DECREF(list);
return NULL;
}
PyObject *svn_swig_py_revarray_to_list(const apr_array_header_t *array)
{
PyObject *list = PyList_New(array->nelts);
int i;
for (i = 0; i < array->nelts; ++i) {
PyObject *ob
= PyInt_FromLong(APR_ARRAY_IDX(array, i, svn_revnum_t));
if (ob == NULL)
goto error;
PyList_SET_ITEM(list, i, ob);
}
return list;
error:
Py_DECREF(list);
return NULL;
}
static PyObject *
commit_item_array_to_list(const apr_array_header_t *array)
{
PyObject *list = PyList_New(array->nelts);
int i;
for (i = 0; i < array->nelts; ++i) {
PyObject *ob = convert_svn_client_commit_item_t
(APR_ARRAY_IDX(array, i, svn_client_commit_item_t *), NULL);
if (ob == NULL)
goto error;
PyList_SET_ITEM(list, i, ob);
}
return list;
error:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?