Crypt-SecretBuffer

 view release on metacpan or  search on metacpan

SecretBuffer.h  view on Meta::CPAN

#ifndef CRYPT_SECRETBUFFER_H

/* 'data' is an array of bytes allocated to 'capacity'.
 * 'len' is how much of the buffer is holding data.  All bytes beyond are zeros
 * 'stringify_sv' is initially NULL, but exists after the first stringify event
 * 'wrapper' is the object to which this struct is attached (via Magic)
 *   and will normally be an HV, but could potentially be other things if
 *   'secret_buffer_from_magic' was called on a non-HV ref with AUTOCREATE flag
 */
typedef struct {
   char *data;
   size_t len, capacity;
   SV *stringify_sv;
   SV *wrapper;
} secret_buffer;

struct secret_buffer_charset;
typedef struct secret_buffer_charset secret_buffer_charset;

/* Given a Regexp-ref either return a cached secret_buffer_charset from a
 * previous call, or build a new one by
 * analyzing the regexp, then cache it in MAGIC.
 * The regexp must be a single character class specification and nothing else,
 * but it may use the case-insensitive flag.  If the pattern uses anything more
 * than simple characters or ranges, the bitmap is determined by passing the
 * range of characters 0..255 through `s/$patern//g` and building the bitmap
 * from the result.
 */
extern secret_buffer_charset * secret_buffer_charset_from_regexpref(SV *ref);

/* Test whether the charset contains an 8-bit byte.
 * This relies solely on the bitmap.
 */
extern bool secret_buffer_charset_test_byte(const secret_buffer_charset *cset, U8 b);

/* Test whether the charset contains a unicode character.  This uses the perl regex
 * engine if the codepoint is higher than 0x7F, to ensure correct matching.
 */
extern bool secret_buffer_charset_test_codepoint(const secret_buffer_charset *cset, U32 cp);

/* encoding flags can be combined with other flags */
#define SECRET_BUFFER_ENCODING_MASK      0xFF
#define SECRET_BUFFER_ENCODING_ISO8859_1    0
#define SECRET_BUFFER_ENCODING_ASCII        1
#define SECRET_BUFFER_ENCODING_UTF8         2
#define SECRET_BUFFER_ENCODING_UTF16LE      3
#define SECRET_BUFFER_ENCODING_UTF16BE      4
#define SECRET_BUFFER_ENCODING_HEX          5
#define SECRET_BUFFER_ENCODING_BASE64       6
#define SECRET_BUFFER_ENCODING_I32          7
#define SECRET_BUFFER_ENCODING_MAX          7

#define SECRET_BUFFER_ENCODING_IS_UNICODE(x)  \
   (  (x) == SECRET_BUFFER_ENCODING_UTF8      \
   || (x) == SECRET_BUFFER_ENCODING_UTF16LE   \
   || (x) == SECRET_BUFFER_ENCODING_UTF16BE   \
   || (x) == SECRET_BUFFER_ENCODING_ISO8859_1 \
   )

/* secret_buffer_parse struct is used as a generic way to support parsing on whole
 * secret_buffers or on spans within one, or even a span within a perl SV.
 * Crypt::SecretBuffer::Span does not have a public struct for now, but can be
 * used to initialize a parse struct using secret_buffer_parse_init_from_sv.
 */
typedef struct {
   const U8 *pos, *lim;
   const char *error;
   int encoding;
   U8 pos_bit, lim_bit;
   secret_buffer *sbuf; /* may be NULL when referencing a span from a plain PV */
} secret_buffer_parse;

/* secret_buffer_parse with writable characters */
typedef struct {
   U8 *pos, *lim;
   const char *error;
   int encoding;
   U8 pos_bit, lim_bit;
   secret_buffer *sbuf; /* may be NULL when referencing a span from a plain PV */
} secret_buffer_parse_rw;

/* Initialize a parse struct, and also verify that the described span is within the
 * defined length of the buffer.  If not, it returns false and sets ->error.
 */
extern bool secret_buffer_parse_init(secret_buffer_parse *parse,
   secret_buffer *buf, size_t pos, size_t lim, int encoding);

/* Initialize a parse struct, either from a Span, or a SecretBuffer, or a plain Scalar.
 */
extern bool secret_buffer_parse_init_from_sv(secret_buffer_parse *parse, SV *sv);

/* Create a Crypt::SecretBuffer::Span object, returning a mortal ref */
extern SV * secret_buffer_span_new_obj(secret_buffer *buf, size_t pos, size_t lim, int encoding);

/* Create a Crypt::SecretBuffer::Span object for the specified span of a SecretBuffer
 * and return a mortal ref to that object.  The parse struct 'sbuf' field must not be NULL
 * because the span needs to hold a reference to it.
 */
extern SV * secret_buffer_span_new_obj_from_parse(secret_buffer_parse *p);

/* Scan through a SecretBuffer looking for the first (and maybe also last)
 * character belonging to a set.  The 'pos' and 'lim' of the parse struct
 * define the range that will be searched, and will be updated with the result
 * of the scan.  If pos == lim at the end, the character was not found.
 * Returns true if the scan completed (found or not) and false if it was
 * interrupted by an invalid character.
 *
 * The _NEGATE flag can be used to negate the charset without altering it.
 *
 * The _REVERSE flag can be used to search backward from [lim-1] back to [pos],
 * in which case 'lim' will be updated with the results of the scan.
 *
 * The _SPAN flag requests that after finding the first match and updating
 * 'pos' (or 'lim' if reversed), it will then begin looking for a character not
 * belonging to the charset, and then update 'lim'. (or 'pos' if reversed)
 *
 * If the parse state specifies an encoding, pos and lim must be at character
 * boundaries, and invalid characters will stop the parse and store a message
 * in ->error, also updating pos (or lim) to indicate the byte offset.
 * Note that every codepoint higher than 255 compared to a charset with the
 * maybe_unicode flag will call out to the perl regex engine and be a bit slow.
 */
#define SECRET_BUFFER_MATCH_REVERSE    0x0100
#define SECRET_BUFFER_MATCH_NEGATE     0x0200
#define SECRET_BUFFER_MATCH_MULTI      0x0400
#define SECRET_BUFFER_MATCH_ANCHORED   0x0800
#define SECRET_BUFFER_MATCH_CONST_TIME 0x1000
extern bool secret_buffer_match(secret_buffer_parse *p, SV *pattern, int flags);
extern bool secret_buffer_match_charset(secret_buffer_parse *p, secret_buffer_charset *cset, int flags);
extern bool secret_buffer_match_bytestr(secret_buffer_parse *p, char *data, size_t datalen, int flags);

/* Count number of bytes required to transcode the source.
 * If the source contains an invalid character for its encoding, or that codepoint
 * can't be encoded as the dst_encoding, this returns -1 and sets src->error
 * and also sets src->pos pointing at the character that could not be converted.
 */
extern SSize_t secret_buffer_sizeof_transcode(secret_buffer_parse *src, int dst_encoding);

/* Transcode from source to destination, respecting the ->encoding of each.
 */
extern bool secret_buffer_transcode(secret_buffer_parse *src, secret_buffer_parse_rw *dst);

/* Copy characters from a parse struct to a Perl SV, optionally appending.
 * This respects the src->encoding, as opposed to secret_buffer_splice which always copies
 * bytes even if the source is a ::Span with an encoding.
 */
extern bool secret_buffer_copy_to(secret_buffer_parse *src, SV *dst_sv, int encoding, bool append);

/* Create a new Crypt::SecretBuffer object with a mortal ref and return its secret_buffer
 * struct pointer.
 * If ref_out is NULL then the mortal ref remains mortal, and as your function exits the next
 * FREETMPS destroys the ref which destroys the object which destroys the magic which destroys
 * the secret_buffer struct which also clears it.
 * If you supply a pointer to receive ref_out, you can then increment the refcount or copy the
 * ref to a new SV if you want to keep the object.  As a weak-ref, it's also convenient to push
 * onto perl's stack.
 * Always returns a secret_buffer, or croaks on failure.
 */
extern secret_buffer * secret_buffer_new(size_t capacity, SV **ref_out);

/* Given a SV which you expect to be a reference to a blessed object with SecretBuffer
 * magic, return the secret_buffer struct pointer.
 * With no flags, this returns NULL if any of the above assumption are not correct.
 * Specify AUTOCREATE to create a new secret_buffer (and attach with magic) if it is a blessed
 * object and doesn't have the magic yet.
 * Specify OR_DIE if you want an exception instead of NULL return value.
 * Specify UNDEF_OK if you want input C<undef> to translate to C<NULL> even when OR_DIE is
 * requested.  i.e. undef becomes NULL but something which is not a SecretBuffer dies.
 */
#define SECRET_BUFFER_MAGIC_AUTOCREATE 1
#define SECRET_BUFFER_MAGIC_OR_DIE     2
#define SECRET_BUFFER_MAGIC_UNDEF_OK   4
extern secret_buffer * secret_buffer_from_magic(SV *ref, int flags);

/* Reallocate (or free) the buffer of secret_buffer, fully erasing it before deallocation.
 * If capacity is zero, the buffer will be freed and 'data' pointer set to NULL.
 * Any other size will allocate exactly that number of bytes, copy any previous bytes,
 * wipe the old buffer, and free it.
 */
extern void secret_buffer_realloc(secret_buffer *buf, size_t new_capacity);



( run in 0.878 second using v1.01-cache-2.11-cpan-e1769b4cff6 )