mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
176 lines
4.3 KiB
C
176 lines
4.3 KiB
C
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef __BLOB_H__
|
|
#define __BLOB_H__
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "thunks.h"
|
|
|
|
OS_ENUM(os_trace_blob_flags, uint16_t,
|
|
OS_TRACE_BLOB_NEEDS_FREE = 0x0001,
|
|
OS_TRACE_BLOB_TRUNCATED = 0x0002,
|
|
);
|
|
|
|
typedef struct os_trace_blob_s {
|
|
union {
|
|
uint8_t *ob_b;
|
|
void *ob_v;
|
|
char *ob_s;
|
|
const char *ob_c;
|
|
};
|
|
uint32_t ob_len;
|
|
uint32_t ob_size;
|
|
uint32_t ob_maxsize;
|
|
uint16_t ob_flags;
|
|
bool ob_binary;
|
|
} os_trace_blob_s, *os_trace_blob_t;
|
|
|
|
#pragma mark - helpers (not to be used directly)
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
_os_trace_blob_available(os_trace_blob_t ob)
|
|
{
|
|
return ob->ob_size - !ob->ob_binary - ob->ob_len;
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
_os_trace_blob_growlen(os_trace_blob_t ob, size_t extra)
|
|
{
|
|
ob->ob_len += extra;
|
|
if (!ob->ob_binary) ob->ob_s[ob->ob_len] = '\0';
|
|
return (uint32_t)extra;
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline void
|
|
_os_trace_blob_setlen(os_trace_blob_t ob, uint32_t len)
|
|
{
|
|
ob->ob_len = len;
|
|
if (!ob->ob_binary) ob->ob_s[len] = '\0';
|
|
}
|
|
|
|
__attribute__((__visibility__("hidden")))
|
|
void
|
|
os_trace_blob_destroy_slow(os_trace_blob_t ob);
|
|
|
|
#pragma mark - initialization and simple helpers
|
|
|
|
#define os_trace_blob_init_buf(buf, binary) (os_trace_blob_s){ \
|
|
.ob_v = buf, \
|
|
.ob_binary = binary, \
|
|
.ob_size = ({ _Static_assert(sizeof(*buf) == 1, ""); countof(buf); }) \
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
os_trace_blob_max_available(os_trace_blob_t ob)
|
|
{
|
|
uint32_t used = ob->ob_len + !ob->ob_binary;
|
|
if (ob->ob_maxsize) return ob->ob_maxsize - used;
|
|
if (ob->ob_size) return ob->ob_size - used;
|
|
return 0;
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline size_t
|
|
os_trace_blob_is_empty(os_trace_blob_t ob)
|
|
{
|
|
return ob->ob_len == 0;
|
|
}
|
|
|
|
OS_MALLOC __attribute__((__visibility__("hidden")))
|
|
char *
|
|
os_trace_blob_detach(os_trace_blob_t ob, size_t *len);
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline void
|
|
os_trace_blob_assert_not_allocated(os_trace_blob_t ob)
|
|
{
|
|
if (os_unlikely(ob->ob_flags & OS_TRACE_BLOB_NEEDS_FREE)) {
|
|
OS_TRACE_INTERNAL_CRASH(0, "Buffer needs free");
|
|
}
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline void
|
|
os_trace_blob_destroy(os_trace_blob_t ob)
|
|
{
|
|
if (ob->ob_flags & OS_TRACE_BLOB_NEEDS_FREE) {
|
|
return os_trace_blob_destroy_slow(ob);
|
|
}
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline void
|
|
os_trace_blob_set_string(os_trace_blob_t ob, const char *s)
|
|
{
|
|
if (ob->ob_flags & OS_TRACE_BLOB_NEEDS_FREE) {
|
|
free(ob->ob_s);
|
|
}
|
|
*ob = (os_trace_blob_s){
|
|
.ob_c = s,
|
|
.ob_len = (uint32_t)strlen(s),
|
|
// not setting the size means "const"
|
|
};
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline void
|
|
os_trace_blob_rtrim(os_trace_blob_t ob)
|
|
{
|
|
uint32_t len = ob->ob_len;
|
|
while (len > 0 && isspace(ob->ob_s[len - 1])) len--;
|
|
_os_trace_blob_setlen(ob, len);
|
|
}
|
|
|
|
#pragma mark - appending to the blob
|
|
|
|
__attribute__((__visibility__("hidden")))
|
|
uint32_t
|
|
os_trace_blob_add_slow(os_trace_blob_t ob, const void *ptr, size_t size);
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
os_trace_blob_add(os_trace_blob_t ob, const void *ptr, size_t size)
|
|
{
|
|
if (os_unlikely(ob->ob_flags & OS_TRACE_BLOB_TRUNCATED)) {
|
|
return 0;
|
|
}
|
|
if (os_unlikely(size > _os_trace_blob_available(ob))) {
|
|
return os_trace_blob_add_slow(ob, ptr, size);
|
|
}
|
|
memcpy(ob->ob_s + ob->ob_len, ptr, size);
|
|
return _os_trace_blob_growlen(ob, size);
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
os_trace_blob_addc(os_trace_blob_t ob, int c)
|
|
{
|
|
uint8_t byte = (uint8_t)c;
|
|
return os_trace_blob_add(ob, &byte, 1);
|
|
}
|
|
|
|
OS_ALWAYS_INLINE
|
|
static inline uint32_t
|
|
os_trace_blob_add_safe_string(os_trace_blob_t ob, const char *s)
|
|
{
|
|
// safe means pure ascii no control chars
|
|
return os_trace_blob_add(ob, s, strlen(s));
|
|
}
|
|
|
|
#endif // !__LIBTRACE_BLOB_INTERNAL_H__
|