/*- * Copyright (c) 2014-2019 MongoDB, Inc. * Copyright (c) 2008-2014 WiredTiger, Inc. * All rights reserved. * * See the file LICENSE for redistribution information. */ #include "wt_internal.h" /* * Streaming interface to packing. * * This allows applications to pack or unpack records one field at a time. */ struct __wt_pack_stream { WT_PACK pack; uint8_t *end, *p, *start; }; /* * wiredtiger_pack_start -- * Open a stream for packing. */ int wiredtiger_pack_start(WT_SESSION *wt_session, const char *format, void *buffer, size_t size, WT_PACK_STREAM **psp) { WT_DECL_RET; WT_PACK_STREAM *ps; WT_SESSION_IMPL *session; session = (WT_SESSION_IMPL *)wt_session; WT_RET(__wt_calloc_one(session, &ps)); WT_ERR(__pack_init(session, &ps->pack, format)); ps->p = ps->start = buffer; ps->end = ps->p + size; *psp = ps; if (0) { err: (void)wiredtiger_pack_close(ps, NULL); } return (ret); } /* * wiredtiger_unpack_start -- * Open a stream for unpacking. */ int wiredtiger_unpack_start(WT_SESSION *wt_session, const char *format, const void *buffer, size_t size, WT_PACK_STREAM **psp) { return (wiredtiger_pack_start( wt_session, format, (void *)buffer, size, psp)); } /* * wiredtiger_pack_close -- * Close a packing stream. */ int wiredtiger_pack_close(WT_PACK_STREAM *ps, size_t *usedp) { if (usedp != NULL) *usedp = WT_PTRDIFF(ps->p, ps->start); __wt_free(ps->pack.session, ps); return (0); } /* * wiredtiger_pack_item -- * Pack an item. */ int wiredtiger_pack_item(WT_PACK_STREAM *ps, WT_ITEM *item) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'U': case 'u': pv.u.item.data = item->data; pv.u.item.size = item->size; WT_RET(__pack_write( session, &pv, &ps->p, (size_t)(ps->end - ps->p))); break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_pack_int -- * Pack a signed integer. */ int wiredtiger_pack_int(WT_PACK_STREAM *ps, int64_t i) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'b': case 'h': case 'i': case 'l': case 'q': pv.u.i = i; WT_RET(__pack_write( session, &pv, &ps->p, (size_t)(ps->end - ps->p))); break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_pack_str -- * Pack a string. */ int wiredtiger_pack_str(WT_PACK_STREAM *ps, const char *s) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'S': case 's': pv.u.s = s; WT_RET(__pack_write( session, &pv, &ps->p, (size_t)(ps->end - ps->p))); break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_pack_uint -- * Pack an unsigned int. */ int wiredtiger_pack_uint(WT_PACK_STREAM *ps, uint64_t u) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'B': case 'H': case 'I': case 'L': case 'Q': case 'R': case 'r': case 't': pv.u.u = u; WT_RET(__pack_write( session, &pv, &ps->p, (size_t)(ps->end - ps->p))); break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_unpack_item -- * Unpack an item. */ int wiredtiger_unpack_item(WT_PACK_STREAM *ps, WT_ITEM *item) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'U': case 'u': WT_RET(__unpack_read(session, &pv, (const uint8_t **)&ps->p, (size_t)(ps->end - ps->p))); item->data = pv.u.item.data; item->size = pv.u.item.size; break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_unpack_int -- * Unpack a signed integer. */ int wiredtiger_unpack_int(WT_PACK_STREAM *ps, int64_t *ip) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'b': case 'h': case 'i': case 'l': case 'q': WT_RET(__unpack_read(session, &pv, (const uint8_t **)&ps->p, (size_t)(ps->end - ps->p))); *ip = pv.u.i; break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_unpack_str -- * Unpack a string. */ int wiredtiger_unpack_str(WT_PACK_STREAM *ps, const char **sp) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'S': case 's': WT_RET(__unpack_read(session, &pv, (const uint8_t **)&ps->p, (size_t)(ps->end - ps->p))); *sp = pv.u.s; break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * wiredtiger_unpack_uint -- * Unpack an unsigned integer. */ int wiredtiger_unpack_uint(WT_PACK_STREAM *ps, uint64_t *up) { WT_DECL_PACK_VALUE(pv); WT_SESSION_IMPL *session; session = ps->pack.session; /* Lower-level packing routines treat a length of zero as unchecked. */ if (ps->p >= ps->end) return (ENOMEM); WT_RET(__pack_next(&ps->pack, &pv)); switch (pv.type) { case 'B': case 'H': case 'I': case 'L': case 'Q': case 'R': case 'r': case 't': WT_RET(__unpack_read(session, &pv, (const uint8_t **)&ps->p, (size_t)(ps->end - ps->p))); *up = pv.u.u; break; default: return (__wt_illegal_value(session, pv.type)); } return (0); } /* * __wt_ext_pack_start -- * WT_EXTENSION.pack_start method. */ int __wt_ext_pack_start(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const char *format, void *buffer, size_t size, WT_PACK_STREAM **psp) { WT_CONNECTION_IMPL *conn; conn = (WT_CONNECTION_IMPL *)wt_api->conn; if (wt_session == NULL) wt_session = (WT_SESSION *)conn->default_session; return (wiredtiger_pack_start(wt_session, format, buffer, size, psp)); } /* * __wt_ext_unpack_start -- * WT_EXTENSION.unpack_start */ int __wt_ext_unpack_start(WT_EXTENSION_API *wt_api, WT_SESSION *wt_session, const char *format, const void *buffer, size_t size, WT_PACK_STREAM **psp) { WT_CONNECTION_IMPL *conn; conn = (WT_CONNECTION_IMPL *)wt_api->conn; if (wt_session == NULL) wt_session = (WT_SESSION *)conn->default_session; return (wiredtiger_unpack_start(wt_session, format, buffer, size, psp)); } /* * __wt_ext_pack_close -- * WT_EXTENSION.pack_close */ int __wt_ext_pack_close(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, size_t *usedp) { WT_UNUSED(wt_api); return (wiredtiger_pack_close(ps, usedp)); } /* * __wt_ext_pack_item -- * WT_EXTENSION.pack_item */ int __wt_ext_pack_item(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, WT_ITEM *item) { WT_UNUSED(wt_api); return (wiredtiger_pack_item(ps, item)); } /* * __wt_ext_pack_int -- * WT_EXTENSION.pack_int */ int __wt_ext_pack_int(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, int64_t i) { WT_UNUSED(wt_api); return (wiredtiger_pack_int(ps, i)); } /* * __wt_ext_pack_str -- * WT_EXTENSION.pack_str */ int __wt_ext_pack_str(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, const char *s) { WT_UNUSED(wt_api); return (wiredtiger_pack_str(ps, s)); } /* * __wt_ext_pack_uint -- * WT_EXTENSION.pack_uint */ int __wt_ext_pack_uint(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, uint64_t u) { WT_UNUSED(wt_api); return (wiredtiger_pack_uint(ps, u)); } /* * __wt_ext_unpack_item -- * WT_EXTENSION.unpack_item */ int __wt_ext_unpack_item(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, WT_ITEM *item) { WT_UNUSED(wt_api); return (wiredtiger_unpack_item(ps, item)); } /* * __wt_ext_unpack_int -- * WT_EXTENSION.unpack_int */ int __wt_ext_unpack_int(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, int64_t *ip) { WT_UNUSED(wt_api); return (wiredtiger_unpack_int(ps, ip)); } /* * __wt_ext_unpack_str -- * WT_EXTENSION.unpack_str */ int __wt_ext_unpack_str(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, const char **sp) { WT_UNUSED(wt_api); return (wiredtiger_unpack_str(ps, sp)); } /* * __wt_ext_unpack_uint -- * WT_EXTENSION.unpack_uint */ int __wt_ext_unpack_uint(WT_EXTENSION_API *wt_api, WT_PACK_STREAM *ps, uint64_t *up) { WT_UNUSED(wt_api); return (wiredtiger_unpack_uint(ps, up)); }