static int handle_append_flags(pycbc_Bucket *self, PyObject **flagsobj) { unsigned long val = 0; if (*flagsobj == NULL || *flagsobj == Py_None) { *flagsobj = pycbc_helpers.fmt_utf8_flags; return 0; } if (self->tc) { return 0; /* let the transcoder handle it */ } val = pycbc_IntAsUL(*flagsobj); if (val == (unsigned long)-1) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "invalid flags", *flagsobj); return -1; } if ((val & PYCBC_FMT_BYTES) == PYCBC_FMT_BYTES) { return 0; } else if ((val & PYCBC_FMT_UTF8) == PYCBC_FMT_UTF8) { return 0; } PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Only FMT_BYTES and FMT_UTF8 are supported for append/prepend", *flagsobj); return -1; }
static int do_call_tc(pycbc_Bucket *conn, PyObject *obj, PyObject *flags, PyObject **result, int mode) { PyObject *meth = NULL; PyObject *args = NULL; PyObject *strlookup = NULL; int ret = -1; switch (mode) { case ENCODE_KEY: strlookup = pycbc_helpers.tcname_encode_key; args = PyTuple_Pack(1, obj); break; case DECODE_KEY: strlookup = pycbc_helpers.tcname_decode_key; args = PyTuple_Pack(1, obj); break; case ENCODE_VALUE: strlookup = pycbc_helpers.tcname_encode_value; args = PyTuple_Pack(2, obj, flags); break; case DECODE_VALUE: strlookup = pycbc_helpers.tcname_decode_value; args = PyTuple_Pack(2, obj, flags); break; } if (args == NULL) { PYCBC_EXC_WRAP(PYCBC_EXC_INTERNAL, 0, "Couldn't build arguments"); goto GT_DONE; } meth = PyObject_GetAttr(conn->tc, strlookup); if (!meth) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Couldn't find transcoder method", conn->tc); goto GT_DONE; } *result = PyObject_Call(meth, args, NULL); if (*result) { ret = 0; } else { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "User-Defined transcoder failed", obj); } GT_DONE: Py_XDECREF(meth); Py_XDECREF(args); return ret; }
static void mk_sd_error(pycbc__SDResult *res, pycbc_MultiResult *mres, lcb_error_t rc, size_t ix) { PyObject *spec = PyTuple_GET_ITEM(res->specs, ix); PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_LCBERR, rc, "Subcommand failure", spec); pycbc_multiresult_adderr(mres); }
/** * This is only called if 'o' is not bytes */ static PyObject* convert_to_bytesobj(PyObject *o) { PyObject *bytesobj = NULL; pycbc_assert(!PyBytes_Check(o)); if (PyUnicode_Check(o)) { bytesobj = PyUnicode_AsUTF8String(o); } if (!bytesobj) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Couldn't convert object to bytes", o); } return bytesobj; }
static int load_cached_method(PyObject *obj, PyObject *attr, PyObject **target, int optional) { *target = PyObject_GetAttr(obj, attr); if (*target) { if (!PyCallable_Check(*target)) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Invalid IOPS object", obj); return -1; } return 0; } if (optional) { PyErr_Clear(); return 0; } return -1; }
static int handle_item_kv(pycbc_Item *itm, PyObject *options, const struct storecmd_vars *scv, struct single_key_context *skc) { int rv; PyObject *ttl_O = NULL, *flagsobj_Oalt = NULL, *igncas_O = NULL; PyObject *frag_O = NULL; static char *itm_optlist[] = { "ttl", "format", "ignore_cas", "fragment", NULL }; lcb_cas_t itmcas = itm->cas; skc->value = itm->value; if (options) { rv = PyArg_ParseTupleAndKeywords(pycbc_DummyTuple, options, "|OOOO", itm_optlist, &ttl_O, &flagsobj_Oalt, &igncas_O, &frag_O); if (!rv) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Couldn't parse item options"); return -1; } if (ttl_O) { if (-1 == pycbc_get_ttl(ttl_O, &skc->ttl, 1)) { return -1; } if (!skc->ttl) { skc->ttl = scv->ttl; } } if (flagsobj_Oalt && flagsobj_Oalt != Py_None) { skc->flagsobj = flagsobj_Oalt; } if (igncas_O && PyObject_IsTrue(igncas_O)) { itmcas = 0; } if (frag_O == NULL) { if (scv->operation == LCB_APPEND || scv->operation == LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "append/prepend must provide options with 'fragment' specifier"); return -1; } } else { if (scv->operation != LCB_APPEND && scv->operation != LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "'fragment' only valid for append/prepend"); return -1; } skc->value = frag_O; } } else { if (scv->operation == LCB_APPEND || scv->operation == LCB_PREPEND) { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "append/prepend must provide options with 'fragment' specifier"); return -1; } } if (!skc->value) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Value is empty", skc->value); return -1; } skc->cas = itmcas; return 0; }
static int encode_common(PyObject **o, void **buf, size_t *nbuf, lcb_uint32_t flags) { PyObject *bytesobj; Py_ssize_t plen; int rv; if (flags == PYCBC_FMT_UTF8) { #if PY_MAJOR_VERSION == 2 if (PyString_Check(*o)) { #else if (0) { #endif bytesobj = *o; Py_INCREF(*o); } else { if (!PyUnicode_Check(*o)) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Must be unicode or string", *o); return -1; } bytesobj = PyUnicode_AsUTF8String(*o); } } else if (flags == PYCBC_FMT_BYTES) { if (PyBytes_Check(*o) || PyByteArray_Check(*o)) { bytesobj = *o; Py_INCREF(*o); } else { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Must be bytes or bytearray", *o); return -1; } } else { PyObject *args = NULL; PyObject *helper; if (flags == PYCBC_FMT_PICKLE) { helper = pycbc_helpers.pickle_encode; } else if (flags == PYCBC_FMT_JSON) { helper = pycbc_helpers.json_encode; } else { PYCBC_EXC_WRAP(PYCBC_EXC_ARGUMENTS, 0, "Unrecognized format"); return -1; } args = PyTuple_Pack(1, *o); bytesobj = PyObject_CallObject(helper, args); Py_DECREF(args); if (!bytesobj) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Couldn't encode value", *o); return -1; } if (!PyBytes_Check(bytesobj)) { PyObject *old = bytesobj; bytesobj = convert_to_bytesobj(old); Py_DECREF(old); if (!bytesobj) { return -1; } } } if (PyByteArray_Check(bytesobj)) { *buf = PyByteArray_AS_STRING(bytesobj); plen = PyByteArray_GET_SIZE(bytesobj); rv = 0; } else { rv = PyBytes_AsStringAndSize(bytesobj, (char**)buf, &plen); } if (rv < 0) { Py_DECREF(bytesobj); PYCBC_EXC_WRAP(PYCBC_EXC_ENCODING, 0, "Couldn't encode value"); return -1; } *nbuf = plen; *o = bytesobj; return 0; } static int decode_common(PyObject **vp, const char *buf, size_t nbuf, lcb_uint32_t flags) { PyObject *decoded = NULL; lcb_U32 c_flags, l_flags; c_flags = flags & PYCBC_FMT_COMMON_MASK; l_flags = flags & PYCBC_FMT_LEGACY_MASK; #define FMT_MATCHES(fmtbase) \ (c_flags == PYCBC_FMT_COMMON_##fmtbase || l_flags == PYCBC_FMT_LEGACY_##fmtbase) if (FMT_MATCHES(UTF8)) { decoded = convert_to_string(buf, nbuf, CONVERT_MODE_UTF8_ONLY); if (!decoded) { return -1; } } else if (FMT_MATCHES(BYTES)) { GT_BYTES: decoded = convert_to_string(buf, nbuf, CONVERT_MODE_BYTES_ONLY); pycbc_assert(decoded); } else { PyObject *converter = NULL; PyObject *args = NULL; PyObject *first_arg = NULL; if (FMT_MATCHES(PICKLE)) { converter = pycbc_helpers.pickle_decode; first_arg = convert_to_string(buf, nbuf, CONVERT_MODE_BYTES_ONLY); pycbc_assert(first_arg); } else if (FMT_MATCHES(JSON)) { converter = pycbc_helpers.json_decode; first_arg = convert_to_string(buf, nbuf, CONVERT_MODE_UTF8_ONLY); if (!first_arg) { return -1; } } else { PyErr_Warn(PyExc_UserWarning, "Unrecognized flags. Forcing bytes"); goto GT_BYTES; } pycbc_assert(first_arg); args = PyTuple_Pack(1, first_arg); decoded = PyObject_CallObject(converter, args); Py_DECREF(args); Py_DECREF(first_arg); } if (!decoded) { PyObject *bytes_tmp = PyBytes_FromStringAndSize(buf, nbuf); PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ENCODING, 0, "Failed to decode bytes", bytes_tmp); Py_XDECREF(bytes_tmp); return -1; } *vp = decoded; return 0; #undef FMT_MATCHES }
int pycbc_tc_encode_value(pycbc_Bucket *conn, PyObject **value, PyObject *flag_v, void **buf, size_t *nbuf, lcb_uint32_t *flags) { PyObject *flags_obj; PyObject *orig_value; PyObject *new_value = NULL; PyObject *result_tuple = NULL; lcb_uint32_t flags_stackval; int rv; Py_ssize_t plen; orig_value = *value; if (!flag_v) { flag_v = conn->dfl_fmt; } if (!conn->tc) { if (flag_v == pycbc_helpers.fmt_auto) { flag_v = pycbc_tc_determine_format(*value); } rv = pycbc_get_u32(flag_v, &flags_stackval); if (rv < 0) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Bad value for flags", flag_v); return -1; } *flags = flags_stackval; return encode_common(value, buf, nbuf, flags_stackval); } /** * Calling into Transcoder */ rv = do_call_tc(conn, orig_value, flag_v, &result_tuple, ENCODE_VALUE); if (rv < 0) { return -1; } if (!PyTuple_Check(result_tuple) || PyTuple_GET_SIZE(result_tuple) != 2) { PYCBC_EXC_WRAP_EX(PYCBC_EXC_ENCODING, 0, "Expected return of (bytes, flags)", orig_value, result_tuple); Py_XDECREF(result_tuple); return -1; } new_value = PyTuple_GET_ITEM(result_tuple, 0); flags_obj = PyTuple_GET_ITEM(result_tuple, 1); if (new_value == NULL || flags_obj == NULL) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_INTERNAL, 0, "Tuple GET_ITEM had NULL", result_tuple); Py_XDECREF(result_tuple); return -1; } rv = pycbc_get_u32(flags_obj, &flags_stackval); if (rv < 0) { Py_XDECREF(result_tuple); PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0, "Transcoder.encode_value() returned a bad " "value for flags", orig_value); return -1; } *flags = flags_stackval; rv = PyBytes_AsStringAndSize(new_value, (char**)buf, &plen); if (rv == -1) { Py_XDECREF(result_tuple); PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0, "Value returned by Transcoder.encode_value() " "could not be converted to bytes", orig_value); return -1; } *value = new_value; *nbuf = plen; Py_INCREF(new_value); Py_XDECREF(result_tuple); return 0; }
int pycbc_tc_encode_value(pycbc_Bucket *conn, PyObject *srcbuf, PyObject *srcflags, pycbc_pybuffer *dstbuf, lcb_U32 *dstflags) { PyObject *flags_obj; PyObject *new_value = NULL; PyObject *result_tuple = NULL; lcb_U32 flags_stackval; int rv; Py_ssize_t plen; if (!srcflags) { srcflags = conn->dfl_fmt; } if (!conn->tc) { if (srcflags == pycbc_helpers.fmt_auto) { srcflags = pycbc_tc_determine_format(srcbuf); } rv = pycbc_get_u32(srcflags, &flags_stackval); if (rv < 0) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_ARGUMENTS, 0, "Bad value for flags", srcflags); return -1; } *dstflags = flags_stackval; return encode_common(srcbuf, dstbuf, flags_stackval); } /** * Calling into Transcoder */ rv = do_call_tc(conn, srcbuf, srcflags, &result_tuple, ENCODE_VALUE); if (rv < 0) { return -1; } if (!PyTuple_Check(result_tuple) || PyTuple_GET_SIZE(result_tuple) != 2) { PYCBC_EXC_WRAP_EX(PYCBC_EXC_ENCODING, 0, "Expected return of (bytes, flags)", srcbuf, result_tuple); Py_XDECREF(result_tuple); return -1; } new_value = PyTuple_GET_ITEM(result_tuple, 0); flags_obj = PyTuple_GET_ITEM(result_tuple, 1); if (new_value == NULL || flags_obj == NULL) { PYCBC_EXC_WRAP_OBJ(PYCBC_EXC_INTERNAL, 0, "Tuple GET_ITEM had NULL", result_tuple); Py_XDECREF(result_tuple); return -1; } rv = pycbc_get_u32(flags_obj, &flags_stackval); if (rv < 0) { Py_XDECREF(result_tuple); PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0, "Transcoder.encode_value() returned a bad " "value for flags", srcbuf); return -1; } *dstflags = flags_stackval; rv = PyBytes_AsStringAndSize(new_value, (char**)&dstbuf->buffer, &plen); if (rv == -1) { Py_XDECREF(result_tuple); PYCBC_EXC_WRAP_VALUE(PYCBC_EXC_ENCODING, 0, "Value returned by Transcoder.encode_value() " "could not be converted to bytes", srcbuf); return -1; } dstbuf->pyobj = new_value; dstbuf->length = plen; Py_INCREF(new_value); Py_XDECREF(result_tuple); return 0; }