c/src/core/util.h (206 lines of code) (raw):

#ifndef _PROTON_SRC_UTIL_H #define _PROTON_SRC_UTIL_H 1 /* * * 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 "buffer.h" #include <errno.h> #ifndef __cplusplus #include <stdbool.h> #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <proton/codec.h> #include <proton/types.h> #include "object_private.h" #if __cplusplus extern "C" { #endif ssize_t pn_quote_data(char *dst, size_t capacity, const char *src, size_t size); struct pn_string_t; int pn_quote(struct pn_string_t *dst, const char *src, size_t size); bool pn_env_bool(const char *name); pn_timestamp_t pn_timestamp_min(pn_timestamp_t a, pn_timestamp_t b); extern const pn_class_t PN_CLASSCLASS(pn_strdup)[]; static inline bool pn_bytes_equal(const pn_bytes_t a, const pn_bytes_t b) { return (a.size == b.size && !memcmp(a.start, b.start, a.size)); } static inline pn_bytes_t pn_bytes_dup(pn_bytes_t in) { if (in.size) { char* rbytes = malloc(in.size); memcpy(rbytes, in.start, in.size); return (pn_bytes_t){in.size, rbytes}; } else { return (pn_bytes_t){0, NULL}; } } static inline void pn_bytes_free(pn_bytes_t in) { free((void*)in.start); } static inline void pni_switch_to_data(pn_bytes_t *bytes, pn_data_t **data) { if (*data == NULL) { *data = pn_data(0); } if (bytes->start) { pn_data_clear(*data); pn_data_decode(*data, bytes->start, bytes->size); pn_data_rewind(*data); pn_bytes_free(*bytes); *bytes = (pn_bytes_t){0, NULL}; } } static inline pn_rwbytes_t pn_rwbytes_alloc(size_t size) { char* space = malloc(size); size_t s = space ? size : 0; return (pn_rwbytes_t){.size=s, .start=space}; } static inline pn_rwbytes_t pn_rwbytes_realloc(pn_rwbytes_t *in, size_t size) { char* space = realloc(in->start, size); size_t s = space ? size : 0; *in = (pn_rwbytes_t){.size=s, .start=space}; return *in; } static inline void pn_rwbytes_free(pn_rwbytes_t in) { free((void*)in.start); } static inline bool pni_switch_to_raw_bytes(pn_rwbytes_t scratch, pn_data_t **data, pn_bytes_t *bytes) { if (pn_data_size(*data)) { pn_data_rewind(*data); ssize_t size = pn_data_encode(*data, scratch.start, scratch.size); if (size == PN_OVERFLOW) return false; pn_bytes_free(*bytes); *bytes = pn_bytes_dup((pn_bytes_t){.size=size, .start=scratch.start}); pn_data_clear(*data); } return true; } static inline void pni_switch_to_raw(pn_rwbytes_t *scratch, pn_data_t **data, pn_bytes_t *bytes) { if (*data == NULL || pn_data_size(*data)==0) { return; } ssize_t data_size = 0; if (PN_OVERFLOW == (data_size = pn_data_encode(*data, scratch->start, scratch->size))) { pn_rwbytes_realloc(scratch, pn_data_encoded_size(*data)); data_size = pn_data_encode(*data, scratch->start, scratch->size); } pn_bytes_free(*bytes); *bytes = pn_bytes_dup((pn_bytes_t){.size=data_size, .start=scratch->start}); pn_data_clear(*data); } static inline void pni_switch_to_raw_multiple(pn_rwbytes_t *scratch, pn_data_t **data, pn_bytes_t *bytes) { if (!*data || pn_data_size(*data) == 0) { return; } pn_data_rewind(*data); // Rewind and position to first node so data type is defined. pn_data_next(*data); if (pn_data_type(*data) == PN_ARRAY) { switch (pn_data_get_array(*data)) { case 0: pn_bytes_free(*bytes); *bytes = (pn_bytes_t){0, NULL}; pn_data_clear(*data); break; case 1: pn_data_enter(*data); pn_data_narrow(*data); pni_switch_to_raw(scratch, data, bytes); break; default: pni_switch_to_raw(scratch, data, bytes); } } else { pni_switch_to_raw(scratch, data, bytes); } } static inline void pni_write16(char *bytes, uint16_t value) { bytes[0] = 0xFF & (value >> 8); bytes[1] = 0xFF & (value ); } static inline void pni_write32(char *bytes, uint32_t value) { bytes[0] = 0xFF & (value >> 24); bytes[1] = 0xFF & (value >> 16); bytes[2] = 0xFF & (value >> 8); bytes[3] = 0xFF & (value ); } static inline uint16_t pni_read16(const char *bytes) { uint16_t a = (uint8_t) bytes[0]; uint16_t b = (uint8_t) bytes[1]; uint16_t r = a << 8 | b; return r; } static inline uint32_t pni_read32(const char *bytes) { uint32_t a = pni_read16(bytes); uint32_t b = pni_read16(&bytes[2]); uint32_t r = a << 16 | b; return r; } static inline uint64_t pni_read64(const char *bytes) { uint64_t a = pni_read32(bytes); uint64_t b = pni_read32(&bytes[4]); uint64_t r = a << 32 | b; return r; } /* Create a literal bytes value, e.g. PN_BYTES_LITERAL(foo) == pn_bytes(3, "foo") */ #define PN_BYTES_LITERAL(X) (pn_bytes(sizeof(#X)-1, #X)) #define DIE_IFR(EXPR, STRERR) \ do { \ int __code__ = (EXPR); \ if (__code__) { \ fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, \ #EXPR, STRERR(__code__), __code__); \ exit(-1); \ } \ } while (0) #define DIE_IFE(EXPR) \ do { \ if ((EXPR) == -1) { \ int __code__ = errno; \ fprintf(stderr, "%s:%d: %s: %s (%d)\n", __FILE__, __LINE__, \ #EXPR, strerror(__code__), __code__); \ exit(-1); \ } \ } while (0) #define LL_HEAD(ROOT, LIST) ((ROOT)-> LIST ## _head) #define LL_TAIL(ROOT, LIST) ((ROOT)-> LIST ## _tail) #define LL_ADD(ROOT, LIST, NODE) \ { \ (NODE)-> LIST ## _next = NULL; \ (NODE)-> LIST ## _prev = (ROOT)-> LIST ## _tail; \ if (LL_TAIL(ROOT, LIST)) \ LL_TAIL(ROOT, LIST)-> LIST ## _next = (NODE); \ LL_TAIL(ROOT, LIST) = (NODE); \ if (!LL_HEAD(ROOT, LIST)) LL_HEAD(ROOT, LIST) = (NODE); \ } #define LL_POP(ROOT, LIST, TYPE) \ { \ if (LL_HEAD(ROOT, LIST)) { \ TYPE *_old = LL_HEAD(ROOT, LIST); \ LL_HEAD(ROOT, LIST) = LL_HEAD(ROOT, LIST)-> LIST ## _next; \ _old-> LIST ## _next = NULL; \ if (_old == LL_TAIL(ROOT, LIST)) { \ LL_TAIL(ROOT, LIST) = NULL; \ } else { \ LL_HEAD(ROOT, LIST)-> LIST ## _prev = NULL; \ } \ } \ } #define LL_REMOVE(ROOT, LIST, NODE) \ { \ if ((NODE)-> LIST ## _prev) \ (NODE)-> LIST ## _prev-> LIST ## _next = (NODE)-> LIST ## _next; \ if ((NODE)-> LIST ## _next) \ (NODE)-> LIST ## _next-> LIST ## _prev = (NODE)-> LIST ## _prev; \ if ((NODE) == LL_HEAD(ROOT, LIST)) \ LL_HEAD(ROOT, LIST) = (NODE)-> LIST ## _next; \ if ((NODE) == LL_TAIL(ROOT, LIST)) \ LL_TAIL(ROOT, LIST) = (NODE)-> LIST ## _prev; \ } #define pn_min(X,Y) ((X) > (Y) ? (Y) : (X)) #define pn_max(X,Y) ((X) < (Y) ? (Y) : (X)) #if __cplusplus } #endif #endif /* util.h */