| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "python_private.h" // must be first! |
| #include "qpid/dispatch/python_embedded.h" |
| |
| #include "entity.h" |
| |
| #include "dispatch_private.h" |
| |
| #include "qpid/dispatch/error.h" |
| |
| struct qd_entity_t { |
| PyObject py_object; /* Any object supporting __set/get_item__, e.g. dict. */ |
| }; |
| |
| static PyObject* qd_entity_get_py(qd_entity_t* entity, const char* attribute) { |
| PyObject *py_key = PyUnicode_FromString(attribute); |
| if (!py_key) return NULL; /* Don't set qd_error, caller will set if needed. */ |
| PyObject *value = PyObject_GetItem((PyObject*)entity, py_key); |
| Py_DECREF(py_key); |
| return value; |
| } |
| |
| bool qd_entity_has(qd_entity_t* entity, const char *attribute) { |
| PyObject *value = qd_entity_get_py(entity, attribute); |
| Py_XDECREF(value); |
| PyErr_Clear(); /* Ignore errors */ |
| return value != NULL; |
| } |
| |
| char *qd_entity_get_string(qd_entity_t *entity, const char* attribute) { |
| qd_error_clear(); |
| PyObject *py_obj = qd_entity_get_py(entity, attribute); |
| char *str = py_string_2_c(py_obj); |
| Py_XDECREF(py_obj); |
| if (!str) qd_error_py(); |
| return str; |
| } |
| |
| long qd_entity_get_long(qd_entity_t *entity, const char* attribute) { |
| qd_error_clear(); |
| PyObject *py_obj = qd_entity_get_py(entity, attribute); |
| if (py_obj && !PyLong_Check(py_obj)) { |
| // 2.6 PyLong_AsLong fails to 'cast' non-long types |
| // so we have to manually cast it first: |
| PyObject *py_tmp = PyNumber_Long(py_obj); |
| Py_XDECREF(py_obj); |
| py_obj = py_tmp; |
| } |
| long result = py_obj ? PyLong_AsLong(py_obj) : -1; |
| Py_XDECREF(py_obj); |
| qd_error_py(); |
| return result; |
| } |
| |
| bool qd_entity_get_bool(qd_entity_t *entity, const char* attribute) { |
| qd_error_clear(); |
| PyObject *py_obj = qd_entity_get_py(entity, attribute); |
| bool result = py_obj ? PyObject_IsTrue(py_obj) : false; |
| Py_XDECREF(py_obj); |
| qd_error_py(); |
| return result; |
| } |
| |
| |
| char *qd_entity_opt_string(qd_entity_t *entity, const char* attribute, const char* default_value) |
| { |
| if (qd_entity_has(entity, attribute)) |
| return qd_entity_get_string(entity, attribute); |
| else |
| return default_value ? strdup(default_value) : NULL; |
| } |
| |
| long qd_entity_opt_long(qd_entity_t *entity, const char* attribute, long default_value) { |
| if (qd_entity_has(entity, attribute)) { |
| long result = qd_entity_get_long(entity, attribute); |
| if (!qd_error_code()) |
| return result; |
| } |
| return default_value; |
| } |
| |
| bool qd_entity_opt_bool(qd_entity_t *entity, const char* attribute, bool default_value) { |
| if (qd_entity_has(entity, attribute)) { |
| bool result = qd_entity_get_bool(entity, attribute); |
| if (!qd_error_code()) |
| return result; |
| } |
| return default_value; |
| } |
| |
| |
| pn_data_t *qd_entity_opt_map(qd_entity_t *entity, const char *attribute) |
| { |
| if (!qd_entity_has(entity, attribute)) |
| return NULL; |
| |
| PyObject *py_obj = qd_entity_get_py(entity, attribute); |
| assert(py_obj); // qd_entity_has() indicates py_obj != NULL |
| |
| if (!PyDict_Check(py_obj)) { |
| qd_error(QD_ERROR_CONFIG, "Invalid type: map expected"); |
| Py_XDECREF(py_obj); |
| return NULL; |
| } |
| |
| pn_data_t *pn_map = pn_data(0); |
| if (!pn_map) { |
| qd_error(QD_ERROR_ALLOC, "Map allocation failure"); |
| Py_XDECREF(py_obj); |
| return NULL; |
| } |
| |
| qd_error_t rc = qd_py_to_pn_data(py_obj, pn_map); |
| Py_XDECREF(py_obj); |
| |
| if (rc != QD_ERROR_NONE) { |
| qd_error(QD_ERROR_ALLOC, "Failed to convert python map"); |
| pn_data_free(pn_map); |
| return NULL; |
| } |
| |
| return pn_map; |
| } |
| |
| |
| /** |
| * Set a value for an entity attribute. If py_value == NULL then clear the attribute. |
| * If the attribute exists and is a list, append this value to the list. |
| * |
| * NOTE: This function will Py_XDECREF(py_value). |
| */ |
| qd_error_t qd_entity_set_py(qd_entity_t* entity, const char* attribute, PyObject* py_value) { |
| qd_error_clear(); |
| |
| int result = 0; |
| PyObject *py_key = PyUnicode_FromString(attribute); |
| if (py_key) { |
| if (py_value == NULL) { /* Delete the attribute */ |
| result = PyObject_DelItem((PyObject*)entity, py_key); |
| PyErr_Clear(); /* Ignore error if it isn't there. */ |
| } |
| else { |
| PyObject *old = PyObject_GetItem((PyObject*)entity, py_key); |
| PyErr_Clear(); /* Ignore error if it isn't there. */ |
| if (old && PyList_Check(old)) /* Add to list */ |
| result = PyList_Append(old, py_value); |
| else /* Set attribute */ |
| result = PyObject_SetItem((PyObject*)entity, py_key, py_value); |
| Py_XDECREF(old); |
| } |
| } |
| Py_XDECREF(py_key); |
| Py_XDECREF(py_value); |
| return (py_key == NULL || result < 0) ? qd_error_py() : QD_ERROR_NONE; |
| } |
| |
| qd_error_t qd_entity_set_string(qd_entity_t *entity, const char* attribute, const char *value) { |
| return qd_entity_set_py(entity, attribute, value ? PyUnicode_FromString(value) : 0); |
| } |
| |
| qd_error_t qd_entity_set_longp(qd_entity_t *entity, const char* attribute, const long *value) { |
| return qd_entity_set_py(entity, attribute, value ? PyLong_FromLong(*value) : 0); |
| } |
| |
| qd_error_t qd_entity_set_boolp(qd_entity_t *entity, const char *attribute, const bool *value) { |
| return qd_entity_set_py(entity, attribute, value ? PyBool_FromLong(*value) : 0); |
| } |
| |
| qd_error_t qd_entity_set_long(qd_entity_t *entity, const char* attribute, long value) { |
| return qd_entity_set_longp(entity, attribute, &value); |
| } |
| |
| qd_error_t qd_entity_set_bool(qd_entity_t *entity, const char *attribute, bool value) { |
| return qd_entity_set_boolp(entity, attribute, &value); |
| } |
| |
| qd_error_t qd_entity_clear(qd_entity_t *entity, const char *attribute) { |
| return qd_entity_set_py(entity, attribute, 0); |
| } |
| |
| #define CHECK(err) if (err) return qd_error_code() |
| |
| qd_error_t qd_entity_set_list(qd_entity_t *entity, const char *attribute) { |
| CHECK(qd_entity_clear(entity, attribute)); |
| return qd_entity_set_py(entity, attribute, PyList_New(0)); |
| } |
| |
| |
| qd_error_t qd_entity_set_map(qd_entity_t *entity, const char *attribute) { |
| //CHECK(qd_entity_clear(entity, attribute)); |
| return qd_entity_set_py(entity, attribute, PyDict_New()); |
| } |
| |
| qd_error_t qd_entity_set_map_key_value_int(qd_entity_t *entity, const char *attribute, const char *key, int value) |
| { |
| if (!key) |
| return QD_ERROR_VALUE; |
| |
| PyObject *py_key = PyUnicode_FromString(key); |
| PyObject *py_value = PyLong_FromLong(value); |
| PyObject *py_attribute = PyUnicode_FromString(attribute); |
| |
| qd_error_t ret = QD_ERROR_NONE; |
| |
| if (PyDict_Contains((PyObject*)entity, py_attribute) == 1) { |
| PyObject* dict = PyDict_GetItem((PyObject*)entity, py_attribute); |
| if (PyDict_SetItem(dict, py_key, py_value) < 0) |
| ret = QD_ERROR_PYTHON; |
| } |
| else |
| ret = QD_ERROR_VALUE; |
| |
| Py_XDECREF(py_key); |
| Py_XDECREF(py_value); |
| Py_XDECREF(py_attribute); |
| |
| return ret; |
| } |
| |
| qd_error_t qd_entity_set_map_key_value_string(qd_entity_t *entity, const char *attribute, const char *key, const char *value) |
| { |
| if (!key) |
| return QD_ERROR_VALUE; |
| |
| PyObject *py_key = PyUnicode_FromString(key); |
| PyObject *py_value = PyUnicode_FromString(value); |
| PyObject *py_attribute = PyUnicode_FromString(attribute); |
| |
| qd_error_t ret = QD_ERROR_NONE; |
| |
| if (PyDict_Contains((PyObject*)entity, py_attribute) == 1) { |
| PyObject* dict = PyDict_GetItem((PyObject*)entity, py_attribute); |
| if (PyDict_SetItem(dict, py_key, py_value) < 0) |
| ret = QD_ERROR_PYTHON; |
| } |
| else |
| ret = QD_ERROR_VALUE; |
| |
| Py_XDECREF(py_key); |
| Py_XDECREF(py_value); |
| Py_XDECREF(py_attribute); |
| |
| return ret; |
| } |
| |