<commit_before>/**
 * Copyright (c) 2014 NetEase, Inc. and other Pomelo contributors
 * MIT Licensed.
 */

#include <assert.h>
#include <string.h>

#include <Python.h>

#include <pomelo.h>

#ifdef _WIN32
#define PY_POMELO_EXPORT __declspec(dllexport)
#else
#define PY_POMELO_EXPORT
#endif

static void default_destructor(void* ex_data)
{
    PyObject* ev_cb = (PyObject*) ex_data;

    PyGILState_STATE state;
    state = PyGILState_Ensure();

    Py_XDECREF(ev_cb);

    PyGILState_Release(state);
}

static void default_request_cb(const pc_request_t* req, int rc, const char* resp)
{
    PyGILState_STATE state;
    int enable_poll;
    pc_client_t* client = pc_request_client(req);
    PyObject* req_cb = (PyObject* )pc_request_ex_data(req);
    PyObject* args;
    PyObject* result;

    assert(client && req_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(iz)", rc, resp);
    assert(args);

    result = PyEval_CallObject(req_cb, args);
    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(req_cb);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static void default_notify_cb(const pc_notify_t* notify, int rc)
{
    PyGILState_STATE state;
    int enable_poll;
    pc_client_t* client = pc_notify_client(notify);
    PyObject* notify_cb = (PyObject* )pc_notify_ex_data(notify);
    PyObject* args;
    PyObject* result;

    assert(client && notify_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(i)", rc);
    assert(args);

    result = PyEval_CallObject(notify_cb, args);

    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(notify_cb);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static void default_event_cb(pc_client_t* client, int ev_type, void* ex_data, const char* arg1, const char* arg2)
{
    PyGILState_STATE state;
    int enable_poll;
    PyObject* ev_cb = (PyObject*)ex_data;
    PyObject* args;
    PyObject* result;

    assert(client && ev_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(izz)", ev_type, arg1, arg2);
    assert(args);

    result = PyEval_CallObject(ev_cb, args);

    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static int local_storage_cb(pc_local_storage_op_t op, char* data, size_t* len, void* ex_data)
{
    PyObject* lc_cb = (PyObject*)ex_data;
    PyObject* args = NULL;
    PyObject* result = NULL;
    int ret = -1;
    char* res = NULL;

    PyGILState_STATE state;
    state = PyGILState_Ensure();

    if (op == PC_LOCAL_STORAGE_OP_WRITE) {
        args = Py_BuildValue("(is#)", op, data, *len);

        assert(args);

        result = PyEval_CallObject(lc_cb, args);
        if (result == NULL) {
            PyErr_Print();
            abort();
        } else {
            assert(PyInt_Check(result));
            ret = PyInt_AsLong(result);
        }

        Py_XDECREF(result);
        Py_XDECREF(args);

        PyGILState_Release(state);

        return ret;
    } else {
        args = Py_BuildValue("(i)", op);
        assert(args);
        result = PyEval_CallObject(lc_cb, args);

        if (result == NULL) {
            PyErr_Print();
            abort();
        } else {
            assert(PyString_Check(result) || result == Py_None);
            if (result != Py_None) {
                res = PyString_AsString(result);
            }
        }

        Py_XDECREF(args);
        Py_XDECREF(result);

        PyGILState_Release(state);

        if (res) {
            *len = strlen(res);
            if (*len == 0) {
                return -1;
            }

            if (data) {
                strncpy(data, res, *len);
            }
            return 0;
        } else {
            return -1;
        }
    }
    // never go to here.
    return -1;
}

static PyObject* lib_init(PyObject* self, PyObject* args)
{
    int log_level;
    char* ca_file = NULL;
    char* ca_path = NULL;
    if (!PyArg_ParseTuple(args, "i|zz:lib_init", 
                &log_level, &ca_file, &ca_path)) { 
       return NULL;
    }

#if !defined(PC_NO_UV_TLS_TRANS)
    if (ca_file || ca_path) {
        tr_uv_tls_set_ca_file(ca_file, ca_path);
    }
#endif

    pc_lib_set_default_log_level(log_level); 
    pc_lib_init(NULL, NULL, NULL, "Python Client");

    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* lib_cleanup(PyObject* self, PyObject* args)
{
    if (!PyArg_ParseTuple(args, ":lib_cleanup")) { 
       return NULL;
    }<commit_msg>py: fix using memory after free'd<commit_after>/**
 * Copyright (c) 2014 NetEase, Inc. and other Pomelo contributors
 * MIT Licensed.
 */

#include <assert.h>
#include <string.h>

#include <Python.h>

#include <pomelo.h>

#ifdef _WIN32
#define PY_POMELO_EXPORT __declspec(dllexport)
#else
#define PY_POMELO_EXPORT
#endif

static void default_destructor(void* ex_data)
{
    PyObject* ev_cb = (PyObject*) ex_data;

    PyGILState_STATE state;
    state = PyGILState_Ensure();

    Py_XDECREF(ev_cb);

    PyGILState_Release(state);
}

static void default_request_cb(const pc_request_t* req, int rc, const char* resp)
{
    PyGILState_STATE state;
    int enable_poll;
    pc_client_t* client = pc_request_client(req);
    PyObject* req_cb = (PyObject* )pc_request_ex_data(req);
    PyObject* args;
    PyObject* result;

    assert(client && req_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(iz)", rc, resp);
    assert(args);

    result = PyEval_CallObject(req_cb, args);
    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(req_cb);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static void default_notify_cb(const pc_notify_t* notify, int rc)
{
    PyGILState_STATE state;
    int enable_poll;
    pc_client_t* client = pc_notify_client(notify);
    PyObject* notify_cb = (PyObject* )pc_notify_ex_data(notify);
    PyObject* args;
    PyObject* result;

    assert(client && notify_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(i)", rc);
    assert(args);

    result = PyEval_CallObject(notify_cb, args);

    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(notify_cb);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static void default_event_cb(pc_client_t* client, int ev_type, void* ex_data, const char* arg1, const char* arg2)
{
    PyGILState_STATE state;
    int enable_poll;
    PyObject* ev_cb = (PyObject*)ex_data;
    PyObject* args;
    PyObject* result;

    assert(client && ev_cb);
    enable_poll = pc_client_config(client)->enable_polling;

    if (!enable_poll) {
        state = PyGILState_Ensure();
    }

    args = Py_BuildValue("(izz)", ev_type, arg1, arg2);
    assert(args);

    result = PyEval_CallObject(ev_cb, args);

    if (result == NULL) {
        PyErr_Print();
        abort();
    }

    Py_XDECREF(args);
    Py_XDECREF(result);

    if (!enable_poll) {
        PyGILState_Release(state);
    }
}

static int local_storage_cb(pc_local_storage_op_t op, char* data, size_t* len, void* ex_data)
{
    PyObject* lc_cb = (PyObject*)ex_data;
    PyObject* args = NULL;
    PyObject* result = NULL;
    int ret = -1;
    char* res = NULL;

    PyGILState_STATE state;
    state = PyGILState_Ensure();

    if (op == PC_LOCAL_STORAGE_OP_WRITE) {
        args = Py_BuildValue("(is#)", op, data, *len);

        assert(args);

        result = PyEval_CallObject(lc_cb, args);
        if (result == NULL) {
            PyErr_Print();
            abort();
        } else {
            assert(PyInt_Check(result));
            ret = PyInt_AsLong(result);
        }

    } else {

        args = Py_BuildValue("(i)", op);
        assert(args);
        result = PyEval_CallObject(lc_cb, args);

        if (result == NULL) {
            PyErr_Print();
            abort();
        } else {
            assert(PyString_Check(result) || result == Py_None);
            if (result != Py_None) {
                res = PyString_AsString(result);
                if (res) {
                    *len = strlen(res);
                    if (*len != 0) {
                        if (data) {
                            memcpy(data, res, *len);
                        }
                        ret = 0;
                    }
                } /* if (res) */
            }
        }
    }

    Py_XDECREF(result);
    Py_XDECREF(args);
    PyGILState_Release(state);

    return ret;
}

static PyObject* lib_init(PyObject* self, PyObject* args)
{
    int log_level;
    char* ca_file = NULL;
    char* ca_path = NULL;
    if (!PyArg_ParseTuple(args, "i|zz:lib_init", 
                &log_level, &ca_file, &ca_path)) { 
       return NULL;
    }

#if !defined(PC_NO_UV_TLS_TRANS)
    if (ca_file || ca_path) {
        tr_uv_tls_set_ca_file(ca_file, ca_path);
    }
#endif

    pc_lib_set_default_log_level(log_level); 
    pc_lib_init(NULL, NULL, NULL, "Python Client");

    Py_INCREF(Py_None);
    return Py_None;
}

static PyObject* lib_cleanup(PyObject* self, PyObject* args)
{
    if (!PyArg_ParseTuple(args, ":lib_cleanup")) { 
       return NULL;
    }
{'fraction_non_alphanumeric': 0.1217224687373941, 'fraction_numerical': 0.002924566357402178, 'mean_word_length': 2.463849109325882, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5780230', 'n_tokens_mistral': 3518, 'n_tokens_neox': 3498, 'n_words': 693}