/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
#if !defined(NET_FOSSIL_SCM_FSL_UTIL_H_INCLUDED)
#define NET_FOSSIL_SCM_FSL_UTIL_H_INCLUDED
/*
** Copyright (c) 2013 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
** drh@hwaci.com
** http://www.hwaci.com/drh/
**
*******************************************************************************
*/
#include "fossil-config.h" /* MUST come first b/c of config macros */
#include <stdio.h> /* FILE type */
#include <stdarg.h> /* va_list */
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct fsl_allocator fsl_allocator;
typedef struct fsl_buffer fsl_buffer;
typedef struct fsl_error fsl_error;
typedef struct fsl_finalizer fsl_finalizer;
typedef struct fsl_fstat fsl_fstat;
typedef struct fsl_list fsl_list;
typedef struct fsl_outputer fsl_outputer;
typedef struct fsl_state fsl_state;
/**
** fsl_uuid_str and fsl_uuid_cstr are "for documentation and
** readability purposes" typedefs used to denote strings which the
** API requires to be in the form of Fossil UUID strings. Such
** strings are exactly FSL_UUID_STRLEN bytes long plus a
** terminating NUL byte and contain only lower-case hexadecimal
** bytes. Where this typedef is used, the library requires,
** enforces, and/or assumes (at different times) that fsl_is_uuid()
** returns true for such strings (if they are not NULL, though not
** all contexts allow a NULL UUID). These typedef are _not_ used to
** denote arguments which may refer to partial UUIDs or symbolic
** names, only 100% bonafide Fossil UUIDs (which are different from
** RFC4122 UUIDs).
**
** The API guarantees that this typedef will always be (char *) and
** that fsl_uuid_cstr will always ben (char const *), and thus it
** is safe/portable to use those type instead of thse. These
** typedefs serve only to improve the readability of certain APIs
** by implying (through the use of this typedef) the preconditions
** defined for UUID strings.
**
** @see fsl_is_uuid()
*/
typedef char * fsl_uuid_str;
/**
** The const counterpart of fsl_uuid_str.
**
** @see fsl_is_uuid()
*/
typedef char const * fsl_uuid_cstr;
/**
** Returns true (non-0) if str is not NULL, is exactly
** FSL_UUID_STRLEN bytes long, and contains only lower-case
** hexadecimal characters, else returns false (0).
**
** Note that Fossil UUIDs are not RFC4122 UUIDs, but are SHA1
** hash strings. Don't let that disturb you. As Tim Berners-Lee
** writes:
**
** 'The assertion that the space of URIs is a universal space
** sometimes encounters opposition from those who feel there should
** not be one universal space. These people need not oppose the
** concept because it is not of a single universal space: Indeed,
** the fact that URIs form universal space does not prevent anyone
** else from forming their own universal space, which of course by
** definition would be able to envelop within it as a subset the
** universal URI space. Therefore the web meets the "independent
** design" test, that if a similar system had been concurrently and
** independently invented elsewhere, in such a way that the
** arbitrary design decisions were made differently, when they met
** later, the two systems could be made to interoperate.'
**
** Source: http://www.w3.org/DesignIssues/Axioms.html
**
** (Just mentally translate URI as UUID.)
*/
char fsl_is_uuid(char const * str);
/**
** Expects str to be a string containing an unsigned decimal
** value. Returns its decoded value, or -1 on error.
*/
fsl_size_t fsl_str_to_size(char const * str);
/**
** Expects str to be a string containing a decimal value,
** optionally with a leading sign. Returns its decoded value, or
** dflt if !str or on error.
*/
fsl_int_t fsl_str_to_int(char const * str, fsl_int_t dflt);
/**
** Generic list container type. This is used heavily by the Fossil
** API for storing arrays of dynamically-allocated objects. It is
** not useful as a non-pointer-array replacement.
**
** It is up to the APIs using this type to manage the entry count
** member and use fsl_list_reserve() to manage the "capacity"
** member.
**
** @see fsl_list_reserve()
** @see fsl_list_append()
** @see fsl_list_visit()
*/
struct fsl_list {
/**
** Array of entries. It contains this->capacity entries,
** this->count of which are "valid" (in use).
*/
void ** list;
/**
** Number of "used" entries in the list.
*/
fsl_size_t used;
/**
** Number of slots allocated in this->list. Use fsl_list_reserve()
** to modify this. Doing so might move the this->list pointer but
** the values it points to will stay stable.
*/
fsl_size_t capacity;
};
/**
** Empty-initialized fsl_list structure, intended for const-copy
** initialization.
*/
#define fsl_list_empty_m { NULL, 0, 0 }
/**
** Empty-initialized fsl_list structure, intended for copy
** initialization.
*/
extern const fsl_list fsl_list_empty;
/**
** Generic interface for finalizing/freeing memory. Intended
** primarily for use as a destructor/finalizer for high-level
** structs. Implementations must semantically behave like free(mem),
** regardless of whether or not they actually free the memory. At
** the very least, they generally should clean up any memory owned by
** mem (e.g. db resources or buffers), even if they do not free() mem.
** some implementations assume that mem is stack-allocated
** and they only clean up resources owned by mem.
**
** The state parameter is any state needed by the finalizer
** (e.g. a memory allocation context) and mem is the memory which is
** being finalized.
**
** The exact interpretaion of the state and mem are of course
** implementation-specific.
*/
typedef void (*fsl_finalizer_f)( void * state, void * mem );
/**
** Generic interface for memory finalizers.
*/
struct fsl_finalizer {
/**
** State to be passed as the first argument to f().
*/
void * state;
/**
** Finalizer function. Should be called like this->f( this->state, ... ).
*/
fsl_finalizer_f f;
};
/** Empty-initialized fsl_finalizer struct. */
#define fsl_finalizer_empty_m {NULL,NULL}
/**
** fsl_finalizer_f() impl which requires that mem be-a
** (fsl_buffer*). This function frees all memory associated with
** that buffer and zeroes out the structure, but does not free mem
** (because it is rare that fsl_buffers are created on the
** heap). The state parameter is ignored.
*/
int fsl_finalizer_f_buffer( void * state, void * mem );
/**
** Generic state-with-finalizer holder. Used for binding
** client-specified state to another other object, such that a
** client-specified finalizer is called with the other object is
** cleaned up.
*/
struct fsl_state {
/**
** Arbitrary context-dependent state.
*/
void * state;
/**
** Finalizer for this->state. If used, it should be called like:
**
** @code
** this->finalize.f( this->finalize.state, this->state );
** @endcode
**
** After which this->state must be treated as if it has been
** free(3)'d.
*/
fsl_finalizer finalize;
};
/** Empty-initialized fsl_state struct. */
#define fsl_state_empty_m {NULL,fsl_finalizer_empty_m}
/**
** Empty-initialized fsl_state struct, intended for
** copy-initializing.
*/
extern const fsl_state fsl_state_empty;
/**
** Generic interface for streaming out data. Implementations must
** write n bytes from s to their destination channel and return 0 on
** success, non-0 on error (assumed to be a value from the fsl_rc_t
** enum). The state parameter is the implementation-specified
** output channel.
*/
typedef int (*fsl_output_f)( void * state,
void const * src, fsl_size_t n );
/**
** Generic interface for flushing arbitrary output streams. Must
** return 0 on success, non-0 on error, but the result code "should"
** (to avoid downstream confusion) be one of the fsl_rc_t
** values. When in doubt, return FSL_RC_IO on error.
*/
typedef int (*fsl_flush_f)(void * state);
/**
** Generic interface for streaming in data. Implementations must
** read (at most) *n bytes from their input, copy it to dest, assign
** *n to the number of bytes actually read, return 0 on success, and
** return non-0 on error (assumed to be a value from the fsl_rc_t
** enum). When called, *n is the max length to read. On return, *n
** is the actual amount read. The state parameter is the
** implementation-specified input file/buffer/whatever channel.
*/
typedef int (*fsl_input_f)( void * state, void * dest, fsl_size_t * n );
/**
** fsl_output_f() implementation which requires state to be
** a writeable (FILE*) handle.
*/
int fsl_output_f_FILE( void * state, void const * src, fsl_size_t n );
/**
** An interface which encapsulates data for managing an output
** destination, primarily intended for use with fsl_output(). Why
** abstract it to this level? So that we can do interesting things
** like output to buffers, files, sockets, etc., using the core
** output mechanism. e.g. so script bindings can send their output
** to the same channel used by the library and other library
** clients.
*/
struct fsl_outputer {
/**
** Output channel.
*/
fsl_output_f out;
/**
** flush() implementation.
*/
fsl_flush_f flush;
/**
** State to be used when calling this->out(), namely:
** this->out( this->state.state, ... ).
*/
fsl_state state;
};
/** Empty-initialized fsl_outputer instance. */
#define fsl_outputer_empty_m {NULL,NULL,fsl_state_empty_m}
/** Empty-initialized fsl_outputer instance, intended for
copy-initializing.
*/
extern const fsl_outputer fsl_outputer_empty;
/**
** A fsl_outputer instance which is initialized to output to a
** (FILE*). To use it, this value then set the copy's state.state
** member to an opened-for-write (FILE*) handle. By default it will
** use stdout. Its finalizer (if called!) will fclose(3)
** self.state.state if self.state.state is not one of (stdout,
** stderr). To disable the closing behaviour (and not close the
** file), set self.state.finalize.f to NULL (but then be sure that
** the file handle outlives this object and to fclose(3) it when
** finished with it).
*/
extern const fsl_outputer fsl_outputer_FILE;
/**
** fsl_outputer initializer which uses fsl_flush_f_FILE(),
** fsl_output_f_FILE(), and fsl_finalizer_f_FILE().
*/
#define fsl_outputer_FILE_m { \
fsl_output_f_FILE, \
fsl_flush_f_FILE, \
{/*state*/ \
NULL, \
{NULL,fsl_finalizer_f_FILE} \
} \
}
/**
** Generic stateful alloc/free/realloc() interface.
**
** Implementations must behave as follows:
**
** - If 0==n then semantically behave like free(3) and return
** NULL.
**
** - If 0!=n and !mem then semantically behave like malloc(3), returning
** newly-allocated memory on success and NULL on error.
**
** - If 0!=n and NULL!=mem then semantically behave like
** realloc(3). Note that realloc specifies: "If n was equal to 0,
** either NULL or a pointer suitable to be passed to free() is
** returned." Which is kind of useless, and thus implementations
** MUST return NULL when n==0.
*/
typedef void *(*fsl_realloc_f)(void * state, void * mem, fsl_size_t n);
/**
** Holds an allocator function and its related state.
*/
struct fsl_allocator {
/**
** Base allocator function. It must be passed this->state
** as its first parameter.
*/
fsl_realloc_f f;
/**
** State intended to be passed as the first parameter to
** this->f().
*/
void * state;
};
/** Empty-initialized fsl_allocator instance. */
#define fsl_allocator_empty_m {NULL,NULL}
/**
** A fsl_realloc_f() implementation which uses the standard
** malloc()/free()/realloc(). The state parameter is ignored.
*/
void * fsl_realloc_f_stdalloc(void * state, void * mem, fsl_size_t n);
/**
** A fsl_flush_f() impl which expects _FILE to be-a (FILE*) opened
** for writing, which this function passes the call on to
** fflush(). If fflush() returns 0, so does this function, else it
** returns non-0.
*/
int fsl_flush_f_FILE(void * _FILE);
/**
** A fsl_finalizer_f() impl which requires that mem be-a (FILE*).
** This function passes that FILE to fsl_fclose(). The state
** parameter is ignored.
*/
void fsl_finalizer_f_FILE( void * state, void * mem );
/**
** A fsl_output_f() impl which requires state to be-a (FILE*), which
** this function passes the call on to fwrite(). Returns 0 on
** success, FSL_RC_IO on error.
*/
int fsl_output_f_FILE( void * state, void const * src, fsl_size_t n );
/**
** A fsl_output_f() impl which requires state to be-a (fsl_buffer*),
** which this function passes to fsl_buffer_append(). Returns 0 on
** success, FSL_RC_OOM (probably) on error.
*/
int fsl_output_f_buffer( void * state, void const * src, fsl_size_t n );
/**
** A fsl_input_f() implementation which requires that state be
** a readable (FILE*) handle.
*/
int fsl_input_f_FILE( void * state, void * dest, fsl_size_t * n );
/**
** A generic streaming routine which copies data from an
** fsl_input_f() to an fsl_outpuf_f().
**
** Reads all data from inF() in chunks of an unspecified size and
** passes them on to outF(). It reads until inF() returns fewer
** bytes than requested. Returns the result of the last call to
** outF() or (only if reading fails) inF(). Returns FSL_RC_MISUSE
** if inF or ouF are NULL.
**
** Here is an example which basically does the same thing as the
** cat(1) command on Unix systems:
**
** @code
** fsl_stream( fsl_input_f_FILE, stdin, fsl_output_f_FILE, stdout );
** @endcode
**
** Or copy a FILE to a buffer:
**
** @code
** fsl_buffer myBuf = fsl_buffer_empty;
** rc = fsl_stream( fsl_input_f_FILE, stdin, fsl_output_f_buffer, &myBuf );
** // Note that on error myBuf might be partially populated.
** // Eventually clean up the buffer:
** fsl_buffer_clear(&myBuf);
** @endcode
**
*/
int fsl_stream( fsl_input_f inF, void * inState,
fsl_output_f outF, void * outState );
/**
**
** A general-purpose buffer class, analog to Fossil v1's Blob
** class. It is not called fsl_blob to avoid confusion with DB-side
** Blobs. Buffers are used extensively in fossil to do everything
** from reading files to compressing artifacts to creating
** dynamically-formatted strings. Because they are such a pervasive
** low-level type, and have such a simple structure, their members
** (unlike most other structs in this API) may be considered public
** and used directly by client code (as long as they do not mangle
** their state, e.g. by setting this->capacity smaller than
** this->used!).
**
** @see fsl_buffer_reserve()
** @see fsl_buffer_append()
** @see fsl_buffer_appendf()
** @see fsl_buffer_cstr()
** @see fsl_buffer_size()
** @see fsl_buffer_capacity()
** @see fsl_buffer_clear()
*/
struct fsl_buffer {
/**
** The raw memory owned by this buffer. It is this->capacity bytes
** long, of which this->used are considered "used" by the client.
** The difference beween (this->capacity - this->used) represents
** space the buffer has available for use before it will require
** another expansion/reallocation.
*/
unsigned char * mem;
/**
** Number of bytes allocated for this buffer.
*/
fsl_size_t capacity;
/**
** Number of "used" bytes in the buffer. This is generally
** interpreted as the string length of this->mem, and the buffer
** APIs which add data to a buffer always ensure that
** this->capacity is large enough to account for a trailing NUL
** byte in this->mem.
**
** Library routines which manipulate buffers must ensure that
** (this->used<=this->capacity) is always true, expanding the
** buffer if necessary. Much of the API assumes that precondition
** is always met, and any violation of it opens the code to
** undefined behaviour (which is okay, just don't ever break that
** precondition). Most APIs ensure that (used<capacity) is always
** true (as opposed to used<=capacity) because they add a
** trailing NUL byte which is not counted in the "used" length.
*/
fsl_size_t used;
};
/** Empty-initialized fsl_buffer instance. */
#define fsl_buffer_empty_m {NULL,0U,0U}
/** Empty-initialized fsl_buffer instance. */
extern const fsl_buffer fsl_buffer_empty;
/**
** A container for storing generic error state. It is used
** to propagate error state between layers of the API back
** to the client.
**
** @see fsl_error_set()
** @see fsl_error_get()
** @see fsl_error_move()
** @see fsl_error_clear()
*/
struct fsl_error {
/**
** Error message text is stored in this->msg.mem. The usable text
** part is this->msg.used bytes long.
*/
fsl_buffer msg;
/**
** Error code, generally assumed to be a fsl_rc_t value.
**
** Potential todo: change this to fsl_rc_t to help ensure that we
** don't get cross-API result code polution (e.g. from sqlite)?
*/
int code;
};
/** Empty-initialized fsl_error instance. */
#define fsl_error_empty_m {fsl_buffer_empty_m,0}
/** Empty-initialized fsl_error instance. */
extern const fsl_error fsl_error_empty;
/**
** Populates err with the given code and formatted string, replacing
** any existing state. If fmt==NULL then fsl_rc_cstr(rc) is used to
** get the error string.
**
** Returns code on success, some other non-0 code on error.
**
** As a special case, if 0==code then fmt is ignored and the error
** state is cleared. This will not free any memory held by err but
** will re-set its string to start with a NUL byte, ready for
** re-use later on.
**
** As a special case, if code==FSL_RC_OOM then fmt is ignored
** to avoid a memory allocation (which would presumably fail).
**
** @see fsl_error_get()
** @see fsl_error_clear()
** @see fsl_error_move()
*/
int fsl_error_set( fsl_error * err, int code, char const * fmt,
... );
/**
** va_list counterpart to fsl_error_set().
*/
int fsl_error_setv( fsl_error * err, int code, char const * fmt,
va_list args );
/**
** Fetches the error state from err. If !err it returns
** FSL_RC_MISUSE without side-effects, else it returns err's current
** error code.
**
** If str is not NULL then *str will be assigned to the raw
** (NUL-terminated) error string (which might be empty or even
** NULL). The memory for the string is owned by err and may be
** invalidated by any calls which take err as a non-const parameter
** OR which might modify it indirectly through its container, so
** the client is required to copy it if it is needed for later on.
**
** If len is not NULL then *len will be assigned to the length of
** the returned string (in bytes).
**
** @see fsl_error_set()
** @see fsl_error_clear()
** @see fsl_error_move()
*/
int fsl_error_get( fsl_error const * err, char const ** str, fsl_size_t * len );
/**
** Frees up any resources owned by err and sets its error code to 0,
** but does not free err. This is harmless no-op if !err or if err
** holds no dynamically allocated no memory.
**
** @see fsl_error_set()
** @see fsl_error_get()
** @see fsl_error_move()
*/
void fsl_error_clear( fsl_error * err );
/**
** Swaps the error state of the two given error objects.
**
** This "uplifts" an error from the 'from' object to the 'to'
** object. After this returns 'to' will contain the prior error
** state of 'from' and 'from' will contain the old error message
** memory of 'to' but will be re-set to the non-error state (we
** keep the buffer memory intact for later reuse, though).
**
** Results are undefined if either parameter is NULL or either is
** not properly initialized. i.e. neither may refer to uninitialized
** memory. Copying fsl_error_empty at declaration-time is a simple
** way to ensure that instances are cleanly initialized.
*/
void fsl_error_move( fsl_error * from, fsl_error * to );
/**
** Returns the given Unix Epoch timestamp value as its approximate
** Julian Day value. Note that the calculation does not account for
** leap seconds.
*/
fsl_double_t fsl_unix_to_julian( fsl_time_t unixEpoch );
/**
** Returns the current Unix Epoch time converted to its approximate
** Julian form. Equivalent to fsl_unix_to_julian( time(0) );
*/
fsl_double_t fsl_julian_now();
/**
** Returns the given Unix Epoch time value formatted as an ISO8601
** string. Returns NULL on allocation error, else a string 19
** bytes long plus a terminating NUL
** (e.g. "2013-08-19T20:35:49"). The returned memory must
** eventually be freed using fsl_free().
*/
char * fsl_unix_to_iso8601( fsl_time_t j );
/**
** Returns non-0 (true) if the first 10 digits of z _appear_ to
** form the start of an ISO date string (YYYY-MM-DD). Whether or
** not the string is really a valid date is left for downstream
** code to determine. Returns 0 (false) in all other cases,
** including if z is NULL.
*/
char fsl_str_is_date(const char *z);
/**
** Reserves at least n bytes of capacity in buf. Returns 0 on
** success, FSL_RC_OOM if allocation fails, FSL_RC_MISUSE if !buf.
**
** This does not change buf->used, nor will it shrink the buffer
** (reduce buf->capacity) unless n is 0, in which case it
** immediately frees buf->mem and sets buf->capacity and buf->used
** to 0.
**
** @see fsl_buffer_resize()
** @see fsl_buffer_clear()
*/
int fsl_buffer_reserve( fsl_buffer * buf, fsl_size_t n );
/**
** Convenience equivalent of fsl_buffer_reserve(buf,0).
** This a no-op if buf==NULL.
*/
void fsl_buffer_clear( fsl_buffer * buf );
/**
** Resets buf->used to 0 and sets buf->mem[0] (if buf->mem is not
** NULL) to 0. Does not (de)allocate memory, only changes the
** logical "used" size of the buffer. Returns 0 on success,
** FSL_RC_MISUSE if !buf.
**
** Achtung for v1 porters: this function's semantics are much
** different from the v1 blob_reset(). To get those semantics, use
** fsl_buffer_reserve(buf, 0) or its convenience form
** fsl_buffer_clear().
*/
int fsl_buffer_reset( fsl_buffer * buf );
/**
** Similar to fsl_buffer_reserve() except that...
**
** - It does not free all memory when n==0. Instead it essentially
** makes the memory a length-0, NUL-terminated string.
**
** - It will try to shrink (realloc) buf's memory if (n<buf->capacity).
**
** - It sets buf->capacity to (n+1) and buf->used to n. This routine
** allocates one extra byte to ensure that buf is always
** NUL-terminated.
**
** - On success it always NUL-terminates the buffer at
** offset buf->used.
**
** Returns 0 on success, FSL_RC_MISUSE if !buf, FSL_RC_OOM if
** (re)allocation fails.
**
** @see fsl_buffer_reserve()
** @see fsl_buffer_clear()
*/
int fsl_buffer_resize( fsl_buffer * buf, fsl_size_t n );
/**
** Swaps the contents of the left and right arguments. Results are
** undefined if either argument is NULL or points to uninitialized
** memory.
*/
void fsl_buffer_swap( fsl_buffer * left, fsl_buffer * right );
/**
** Similar fsl_buffer_swap() but it also optionally frees one of
** the buffer's memories after swapping them. If clearWhich is
** negative then the left buffer (1st arg) is cleared _after_
** swapping (i.e., the NEW left hand side gets cleared). If
** clearWhich is greater than 0 then the right buffer (2nd arg) is
** cleared _after_ swapping (i.e. the NEW right hand side gets
** cleared). If clearWhich is 0, this function behaves identically
** to fsl_buffer_swap().
*/
void fsl_buffer_swap_free( fsl_buffer * left, fsl_buffer * right, char clearWhich );
/**
**
** Appends the first n bytes of src, plus a NUL byte, to b,
** expanding b as necessary and incrementing b->used by n. If n is
** less than 0 then the equivalent of fsl_strlen((char const*)src)
** is used to calculate the length.
**
** If n is 0 (or negative and !*src), this function ensures that
** b->mem is at least 1 byte long and sets the first byte to 0
** (note that (b->used+n == b->used), so its effective length does
** not change in that case).
**
** src may only be NULL if n==0. If passed (src==NULL, n!=0) then
** FSL_RC_RANGE is returned.
**
** Returns 0 on success, FSL_RC_MISUSE if !f, !b, or !src,
** FSL_RC_OOM if allocation of memory fails.
**
** If this function succeeds, it guarantees that it NUL-terminates
** the buffer (but that the NUL terminator is not counted in
** b->used).
*/
int fsl_buffer_append( fsl_buffer * b,
void const * src, fsl_int_t n );
/**
** Uses fsl_appendf() to append formatted output to the given buffer.
** Returns 0 on success, FSL_RC_MISUSE if !f or !dest,
*/
int fsl_buffer_appendf( fsl_buffer * dest,
char const * fmt, ... );
/** va_list counterpart to fsl_buffer_appendfv(). */
int fsl_buffer_appendfv( fsl_buffer * dest,
char const * fmt, va_list args );
/**
** Compresses the first pIn->used bytes of pIn to pOut. It is ok for
** pIn and pOut to be the same blob.
**
** pOut must either be the same as pIn or else cleanly
** initialized/empty.
**
** Results are undefined if any argument is NULL.
**
** Returns 0 on success, FSL_RC_OOM on allocation error, and FSL_RC_ERROR
** if the lower-level compression routines fail.
**
** TODO: add a streaming variant which takes the input from a
** fsl_input_f() and pushes the output to a fsl_output_f(). The code
** exists in the libwhio source tree already.
**
** TODO: if pOut!=pIn1 then re-use pOut's memory, if it has any.
*/
int fsl_buffer_compress(fsl_buffer const *pIn, fsl_buffer *pOut);
/**
** Compress the concatenation of a blobs pIn1 and pIn2 into pOut.
**
** pOut must be either uninitialized or must be the same as either pIn1 or
** pIn2.
**
** Results are undefined if any argument is NULL.
**
** Returns 0 on success, FSL_RC_OOM on allocation error, and FSL_RC_ERROR
** if the lower-level compression routines fail.
**
** TODO: if pOut!=(pIn1 or pIn2) then re-use its memory, if it has any.
*/
int fsl_buffer_compress2(fsl_buffer const *pIn1,
fsl_buffer const *pIn2, fsl_buffer *pOut);
/**
** Uncompress buffer pIn and store the result in pOut. It is ok for
** pIn and pOut to be the same buffer. Returns 0 on success. On
** error pOut is not modified.
**
** pOut must be either cleanly initialized/empty or the same as pIn.
**
** Results are undefined if any argument is NULL.
**
** Returns 0 on success, FSL_RC_OOM on allocation error, and
** FSL_RC_ERROR if the lower-level decompression routines fail.
**
** TODO: add a streaming variant which takes the input from a
** fsl_input_f() and pushes the output to a fsl_output_f(). The code
** exists in the libwhio source tree already.
**
** TODO: if pOut!=(pIn1 or pIn2) then re-use its memory, if it has any.
*/
int fsl_buffer_uncompress(fsl_buffer const *pIn, fsl_buffer *pOut);
/**
** Returns true if this function believes that mem (which must be
** at least len bytes of valid memory long) appears to have been
** compressed by fsl_buffer_compress() or equivalent. This is not a
** 100% reliable check - it could potentially have false positives
** on certain inputs, but that is thought to be unlikely (at least
** for text data).
**
** Returns 0 if mem is NULL.
*/
char fsl_data_is_compressed(unsigned char const * mem, fsl_size_t len);
/**
** Equivalent to fsl_data_is_compressed(buf->mem, buf->used).
*/
char fsl_buffer_is_compressed(fsl_buffer const * buf);
/**
** If fsl_data_is_compressed(mem,len) returns true then this function
** returns the uncompressed size of the data, else it returns a negative
** value.
*/
fsl_int_t fsl_data_uncompressed_size(unsigned char const *mem, fsl_size_t len);
/**
** The fsl_buffer counterpart of fsl_data_uncompressed_size().
*/
fsl_int_t fsl_buffer_uncompressed_size(fsl_buffer const * b);
/**
** Equivalent to ((char const *)b->mem), but returns NULL if !b. The
** returned memory is effectively b->used bytes long unless the user
** decides to apply his own conventions.
**
** @see fsl_buffer_str()
** @see fsl_buffer_cstr2()
*/
char const * fsl_buffer_cstr(fsl_buffer const *b);
/**
** If buf is not NULL and has any memory allocated to it, that
** memory is returned. If both b and len are not NULL then *len is
** set to b->used. If b has no dynamic memory then NULL is returned
** and *len (if len is not NULL) is set to 0.
**
** @see fsl_buffer_str()
** @see fsl_buffer_cstr()
**/
char const * fsl_buffer_cstr2(fsl_buffer const *b, fsl_size_t * len);
/**
** Equivalent to ((char *)b->mem), but returns NULL if !b. The
** returned memory is effectively b->used bytes long unless the user
** decides to apply his own conventions.
*/
char * fsl_buffer_str(fsl_buffer const *b);
/**
** Returns the "used" size of b, or 0 if !b.
*/
fsl_size_t fsl_buffer_size(fsl_buffer const * b);
/**
** Returns the current capacity of b, or 0 if !b.
*/
fsl_size_t fsl_buffer_capacity(fsl_buffer const * b);
/**
** Compares the contents of buffers lhs and rhs using memcmp(3)
** semantics. Return negative, zero, or positive if the first
** buffer is less then, equal to, or greater than the second.
** Results are undefined if either argument is NULL.
**
** When buffers of different length match on the first N bytes,
** where N is the shorter of the two buffers' lengths, it treats the
** shorter buffer as being "less than" the longer one.
*/
int fsl_buffer_compare(fsl_buffer const * lhs, fsl_buffer const * rhs);
/**
** Compare two buffers in constant (a.k.a. O(1)) time and return
** zero if they are equal. Constant time comparison only applies
** for buffers of the same length. If lengths are different,
** immediately returns 1.
*/
int fsl_buffer_compare_O1(fsl_buffer const * lhs, fsl_buffer const * rhs);
/**
** Overwrites dest's contents with those of src (reusing dest's memory
** if it has any). Results are undefined if either pointer is NULL
** or invalid. Returns 0 on success, FSL_RC_OOM on allocation error.
*/
int fsl_buffer_copy( fsl_buffer const * src, fsl_buffer * dest );
/**
** Apply the delta in pDelta to the original content pOriginal to
** generate the target content pTarget. All three pointers must point
** to properly initialized memory.
**
** If pTarget==pOriginal then this is a destructive operation,
** replacing the original's content with its new form.
**
** Return 0 on success.
**
** @see fsl_buffer_delta_apply()
** @see fsl_delta_apply()
** @see fsl_delta_apply2()
*/
int fsl_buffer_delta_apply( fsl_buffer const * pOriginal,
fsl_buffer const * pDelta,
fsl_buffer * pTarget);
/**
** Identical to fsl_buffer_delta_apply() except that if
** delta application fails then any error messages/codes
** are written to pErr if it is not NULL.
**
** @see fsl_buffer_delta_apply()
** @see fsl_delta_apply()
** @see fsl_delta_apply2()
*/
int fsl_buffer_delta_apply2( fsl_buffer const * pOriginal,
fsl_buffer const * pDelta,
fsl_buffer * pTarget,
fsl_error * pErr);
/**
** Uses a fsl_input_f() function to buffer input into a fsl_buffer.
**
** dest must be a non-NULL, initialized (though possibly empty)
** fsl_buffer object. Its contents, if any, will be overwritten by
** this function, and any memory it holds might be re-used.
**
** The src function is called, and passed the state parameter, to
** fetch the input. If it returns non-0, this function returns that
** error code. src() is called, possibly repeatedly, until it
** reports that there is no more data.
**
** Whether or not this function succeeds, dest still owns any memory
** pointed to by dest->mem, and the client must eventually free it
** by calling fsl_buffer_reserve(dest,0).
**
** dest->mem might (and possibly will) be (re)allocated by this
** function, so any pointers to it held from before this call might
** be invalidated by this call.
**
** On error non-0 is returned and dest has almost certainly been
** modified but its state must be considered incomplete.
**
** Errors include:
**
** dest or src are NULL (FSL_RC_MISUSE)
**
** Allocation error (FSL_RC_OOM)
**
** src() returns an error code
**
** Whether or not the state parameter may be NULL depends on the src
** implementation requirements.
**
** On success dest will contain the contents read from the input
** source. dest->used will be the length of the read-in data, and
** dest->mem will point to the memory. dest->mem is automatically
** NUL-terminated if this function succeeds, but dest->used does not
** count that terminator. On error the state of dest->mem must be
** considered incomplete, and is not guaranteed to be
** NUL-terminated.
**
** Example usage:
**
** @code
** fsl_buffer buf = fsl_buffer_empty;
** int rc = fsl_buffer_fill_from( &buf,
** fsl_input_f_FILE,
** stdin );
** if( rc ){
** fprintf(stderr,"Error %d (%s) while filling buffer.\n",
** rc, fsl_rc_cstr(rc));
** fsl_buffer_reserve( &buf, 0 );
** return ...;
** }
** ... use the buf->mem ...
** ... clean up the buffer ...
** fsl_buffer_reserve( &buf, 0 );
** @endcode
**
** To take over ownership of the buffer's memory, do:
**
** @code
** void * mem = buf.mem;
** buf = fsl_buffer_empty;
** @endcode
**
** In which case the memory must eventually be passed to fsl_free()
** to free it.
*/
int fsl_buffer_fill_from( fsl_buffer * dest, fsl_input_f src, void * state );
/**
** A fsl_buffer_fill_from() proxy which overwrite's dest->mem with
** the contents of the given FILE handler (which must be opened for
** read access). Returns 0 on success, after which dest->mem
** contains dest->used bytes of content from the input source. On
** error dest may be partially filled.
*/
int fsl_buffer_fill_from_FILE( fsl_buffer * dest, FILE * src );
/**
** Wrapper for fsl_buffer_fill_from_FILE() which gets its input
** from the given file name.
**
** Uses fsl_fopen() to open the file, so it supports the name '-'
** as an alias for stdin.
*/
int fsl_buffer_fill_from_filename( fsl_buffer * dest, char const * filename );
/**
** Writes the given buffer to the given filename. Returns 0 on success,
** FSL_RC_MISUSE if !b or !fname, FSL_RC_IO if opening or writing fails.
**
** Uses fsl_fopen() to open the file, so it supports the name '-'
** as an alias for stdout.
*/
int fsl_buffer_to_filename( fsl_buffer * b, char const * fname );
/**
** Works like fsl_appendfv(), but appends all output to a
** dynamically-allocated string, expanding the string as necessary
** to collect all formatted data. The returned NUL-terminated string
** is owned by the caller and it must be cleaned up using
** fsl_free(...). If !fmt, NULL is returned. It is conceivable that
** it returns NULL on a zero-length formatted string, e.g. (%.*s)
** with (0,"...") as arguments, but it will only do that if the
** whole format string resolves to empty.
*/
char * fsl_mprintf( char const * fmt, ... );
/**
** va_list counterpart to fsl_mprintf().
*/
char * fsl_mprintfv(char const * fmt, va_list vargs );
/**
** An sprintf(3) clone which uses fsl_appendf() for the formatting.
** Outputs at most n bytes to dest and returns the number of bytes
** output. Returns a negative value if !dest or !fmt. Returns 0
** without side-effects if !n or !*fmt.
**
** If the destination buffer is long enough (this function returns
** a non-negative value less than n), this function NUL-terminates it.
** If it returns n then there was no space for the terminator.
**
**/
fsl_int_t fsl_snprintf( char * dest, fsl_size_t n, char const * fmt, ... );
/** va_list counterpart to fsl_snprintf() */
fsl_int_t fsl_snprintfv( char * dest, fsl_size_t n, char const * fmt, va_list args );
/**
** Equivalent to fsl_strndup(src,-1).
*/
char * fsl_strdup( char const * src );
/**
** Similar to strndup(3) but returns NULL if !src. The returned
** memory must eventually be passed to fsl_free(). Returns NULL on
** allocation error. If len is less than 0 and src is not NULL then
** fsl_strlen() is used to calculate its length.
*/
char * fsl_strndup( char const * src, fsl_int_t len );
/**
** Equivalent to strlen(3) but returns 0 if src is NULL.
** Note that it counts bytes, not UTF characters.
*/
fsl_size_t fsl_strlen( char const * src );
/**
** Like strcmp(3) except that it accepts NULL pointers. NULL sorts
** before all non-NULL string pointers. Also, this routine
** performs a binary comparison that does not consider locale.
*/
int fsl_strcmp( char const * lhs, char const * rhs );
/**
** Case-insensitive form of fsl_strcmp().
*/
int fsl_stricmp(const char *zA, const char *zB);
/**
** fsl_strcmp() variant which compares at most nByte bytes of the
** given strings, case-insensitively. If nByte is less than 0 then
** fsl_strlen(zB) is used to obtain the length for comparision
** purposes.
*/
int fsl_strnicmp(const char *zA, const char *zB, fsl_int_t nByte);
/**
** fsl_strcmp() variant which compares at most nByte bytes of the
** given strings, case-sensitively. Returns 0 if nByte is 0.
*/
int fsl_strncmp(const char *zA, const char *zB, fsl_size_t nByte);
/**
** Equivalent to fsl_strncmp(lhs, rhs, FSL_UUID_STRLEN).
*/
int fsl_uuidcmp( fsl_uuid_cstr lhs, fsl_uuid_cstr rhs );
/**
** Returns false if s is NULL or starts with any of (0 (NUL), '0'
** (ASCII zero), 'f', 'n', "off"), case-insensitively, else it
** returns true.
*/
char fsl_str_bool( char const * s );
/**
** Flags for use with fsl_db_open() and friends.
*/
enum fsl_open_flags {
/**
** The "no flags" value.
*/
FSL_OPEN_F_NONE = 0,
/**
** Flag for fsl_db_open() specifying that the db should be opened
** in read-only mode.
*/
FSL_OPEN_F_RO = 0x01,
/**
** Flag for fsl_db_open() specifying that the db should be opened
** in read-write mode, but should not create the db if it does
** not already exist.
*/
FSL_OPEN_F_RW = 0x02,
/**
** Flag for fsl_db_open() specifying that the db should be opened in
** read-write mode, creating the db if it does not already exist.
*/
FSL_OPEN_F_CREATE = 0x04,
/**
** Shorthand for RW+CREATE flags.
*/
FSL_OPEN_F_RWC = FSL_OPEN_F_RW | FSL_OPEN_F_CREATE,
/**
** Tells fsl_repo_open_xxx() to confirm that the db
** is a repository.
*/
FSL_OPEN_F_SCHEMA_VALIDATE = 0x20
};
/**
** _Almost_ equivalent to fopen(3) but:
**
** - expects name to be UTF8-encoded.
**
** - If name=="-", it returns one of stdin or stdout, depending on
** the mode string: stdout is returned if 'w' or '+' appear,
** otherwise stdin.
**
** If at all possible, use fsl_close() to close these handles, as it
** has logic to skip closing the standard streams.
**
**
** Potential TODOs:
**
** - extend mode string to support 'x', meaning "exclusive", analog
** to open(2)'s O_EXCL flag. Barring race conditions, we have
** enough infrastructure to implement that. (It turns out that
** glibc's fopen() supports an 'x' with exactly this meaning.)
**
** - extend mode to support a 't', meaning "temporary". The idea
** would be that we delete the file from the FS right after
** opening, except that Windows can't do that.
*/
FILE * fsl_fopen(char const * name, char const *mode);
/**
** Passes f to fclose(3) unless f is NULL or one of (stdin, stdout,
** stderr).
*/
void fsl_fclose(FILE * f);
/**
** @typedef fsl_int_t (*fsl_appendf_f)( void * arg, char const * data, fsl_int_t n )
**
** The fsl_appendf_f typedef is used to provide fsl_appendfv() with
** a flexible output routine, so that it can be easily send its
** output to arbitrary targets.
**
** The policies which implementations need to follow are:
**
** - arg is an implementation-specific pointer (may be 0) which is
** passed to fsl_appendf(). fsl_appendfv() doesn't know what this
** argument is but passes it to its fsl_appendf_f
** argument. Typically this pointer will be an object or resource
** handle to which string data is pushed.
**
** - The 'data' parameter is the data to append. The API does not
** currently guaranty that data containing embeded NULs will
** survive the ride through fsl_appendf() and its delegates friends
** (but it "should work").
**
** - n is the number of bytes to read from data. The fact that n is
** of a signed type is historical. It can be treated as an unsigned
** type for purposes of fsl_appendf().
**
** - Returns, on success, the number of bytes appended (may be 0).
**
** - Returns, on error, an implementation-specified negative
** number. Returning a negative error code will cause
** fsl_appendfv() to stop processing and return. Note that 0 is a
** success value (some printf format specifiers do not add anything
** to the output).
*/
typedef fsl_int_t (*fsl_appendf_f)( void * arg,
char const * data,
fsl_int_t n );
/**
** This function works similarly to classical printf
** implementations, but instead of outputing somewhere specific, it
** uses a callback function to push its output somewhere. This
** allows it to be used for arbitrary external representations. It
** can be used, for example, to output to an external string, a UI
** widget, or file handle (it can also emulate printf by outputing
** to stdout this way).
**
** INPUTS:
**
** pfAppend: The is a fsl_appendf_f function which is responsible
** for accumulating the output. If pfAppend returns a negative
** value then processing stops immediately.
**
** pfAppendArg: is ignored by this function but passed as the first
** argument to pfAppend. pfAppend will presumably use it as a data
** store for accumulating its string.
**
** fmt: This is the format string, as in the usual printf(3), except
** that it supports more options (detailed below).
**
** ap: This is a pointer to a list of arguments. Same as in
** vprintf() and friends.
**
**
** OUTPUTS:
**
** The return value is the total number of characters sent to the
** function "func", or a negative number on a pre-output error. If
** this function returns an integer greater than 1 it is in general
** impossible to know if all of the elements were output. As such
** failure can only happen if the callback function returns an
** error, and this type of error is very rare in a printf-like
** context, this is not considered to be a significant problem. (The
** same is true for any classical printf implementations.) Clients
** may use their own state objects which can propagate errors from
** their own internals back to the caller, but generically speaking
** it is difficult to trace errors back through this routine. Then
** again, it only breaks when using using a broken output routine or
** bad output state.
**
** Most printf-style specifiers work as they do in standard printf()
** implementations. There might be some very minor differences, but
** the more common format specifiers work as most developers expect
** them to. In addition...
**
** Current (documented) printf extensions:
**
** (If you are NOT reading this via doxygen-processed sources: the
** percent signs below are doubled for the sake of doxygen, and
** each pair refers to only a single percent sign in the format
** string.)
**
** %%z works like %%s, but takes a non-const (char *) and deletes
** the string (using fsl_free()) after appending it to the output.
**
** %%h (HTML) works like $%s but converts certain characters (namely
** '<' and '&') to their HTML escaped equivalents.
**
** %%t (URL encode) works like %%s but converts certain characters
** into a representation suitable for use in an HTTP URL. (e.g. ' '
** gets converted to %%20)
**
** %%T (URL decode) does the opposite of %t - it decodes URL-encoded
** strings and outputs their decoded form.
**
** %%r requires an int and renders it in "ordinal form". That is,
** the number 1 converts to "1st" and 398 converts to "398th".
**
** %%q quotes a string as required for SQL. That is, '\''
** characters get doubled. It does NOT included the outer quotes
** and NULL values get replaced by the string "(NULL) (without
** quotes). See %%Q...
**
** %%Q works like %%q, but includes the outer '\'' characters and
** NULL pointers get output as the string literal "NULL" (without
** quotes), i.e. an SQL NULL.
**
** %%/: works like %%s but normalizes path-like strings by
** replacing backslashes with the One True Slash.
**
** %%b: works like %%s but takes its input from a (fsl_buffer*)
** argument.
**
** %%B: works like %%Q but takes its input from a (fsl_buffer*)
** argument.
**
** %%F: works like %%s but runs the output through
** fsl_bytes_fossilize(). This requires dynamic memory allocation,
** so is less efficient than re-using a client-provided buffer with
** fsl_bytes_fossilize() if the client needs to fossilize more than
** one element.
**
** These extensions may be disabled by setting certain macros when
** compiling fsl_appendf.c (see that file for details).
**
**
** FIXME? fsl_appendf_f() is an artifact of older code from which
** this implementation derives. The first parameter should arguably
** be replaced with fsl_output_f(), which does the same thing _but_
** has different return semantics (more reliable, because the
** current semantics report partial success as success in some
** cases). Doing this would require us to change the return
** semantics of this function, but that wouldn't necessarily be a
** bad thing (we don't rely on sprintf()-like return semantics all
** that much, AFAIK?). Or we just add a proxy which forwards to a
** fsl_output_f(). Oh, hey, that's what fsl_outputf() does.
*/
fsl_int_t fsl_appendfv(fsl_appendf_f pfAppend, void * pfAppendArg,
const char *fmt, va_list ap );
/**
** Identical to fsl_appendfv() but takes a (...) ellipses list
** instead of a va_list.
*/
fsl_int_t fsl_appendf(fsl_appendf_f pfAppend,
void * pfAppendArg,
const char *fmt,
... );
/**
** A fsl_appendf_f() impl which requires that state be an opened,
** writable (FILE*) handle.
*/
fsl_int_t fsl_appendf_f_FILE( void * state,
char const * s, fsl_int_t n );
/**
** Emulates fprintf() using fsl_appendf(). Returns the result of
** passing the data through fsl_appendf() to the given file handle.
*/
fsl_int_t fsl_fprintf( FILE * fp, char const * fmt, ... );
/**
** The va_list counterpart of fsl_fprintf().
*/
fsl_int_t fsl_fprintfv( FILE * fp, char const * fmt, va_list args );
/**
** Possibly reallocates self->list, changing its size. This function
** ensures that self->list has at least n entries. If n is 0 then
** the list is deallocated (but the self object is not), BUT THIS
** DOES NOT DO ANY TYPE-SPECIFIC CLEANUP of the items. If n is less
** than or equal to self->capacity then there are no side effects. If
** n is greater than self->capacity, self->list is reallocated and
** self->capacity is adjusted to be at least n (it might be bigger -
** this function may pre-allocate a larger value).
**
** Passing an n of 0 when self->capacity is 0 is a no-op.
**
** Newly-allocated slots will be initialized with NUL bytes.
**
** Returns 0 on success, FSL_RC_MISUSE if !self, FSL_RC_OOM if
** reservation of new elements fails.
**
** The return value should be used like this:
**
** @code
** fsl_size_t const n = number of bytes to allocate;
** int const rc = fsl_list_reserve( myList, n );
** if( rc ) { ... error ... }
** @endcode
*/
int fsl_list_reserve( fsl_list * self, fsl_size_t n );
/**
** Appends a bitwise copy of cp to self->list, expanding the list as
** necessary and adjusting self->used.
**
** Ownership of cp is unchanged by this call. cp may not be NULL.
**
** Returns 0 on success, FSL_RC_MISUSE if any argument is NULL, or
** FSL_RC_OOM on allocation error.
*/
int fsl_list_append( fsl_list * self, void * cp );
/** @typedef typedef int (*fsl_list_visitor_f)(void * p, void * visitorState )
**
** Generic visitor interface for fsl_list lists. Used by
** fsl_list_visit(). p is the pointer held by that list entry and
** visitorState is the 4th argument passed to fsl_list_visit().
**
** Implementations must return 0 on success. Any other value causes
** looping to stop and that value to be returned, but interpration
** of the value is up to the caller (it might or might not be an
** error, depending on the context). Note that client code may use
** custom values, and is not restricted to FSL_RC_xxx values.
**
*/
typedef int (*fsl_list_visitor_f)(void * obj, void * visitorState );
/**
** A fsl_list_visitor_f() implementation which requires that obj be
** arbitrary memory which can legally be passed to fsl_free()
** (which this function does). The visitorState parameter is
** ignored.
*/
int fsl_list_v_fsl_free(void * obj, void * visitorState );
/**
** For each item in self->list, visitor(item,visitorState) is
** called. The item is owned by self. The visitor function MUST
** NOT free the item (unless the visitor is a finalizer!), but may
** manipulate its contents if application rules do not specify
** otherwise.
**
** If order is 0 or greater then the list is traversed from start
** to finish, else it is traverse from end to begin.
**
** Returns 0 on success, non-0 on error.
**
** If visitor() returns non-0 then looping stops and that code is
** returned.
*/
int fsl_list_visit( fsl_list const * self, char order,
fsl_list_visitor_f visitor, void * visitorState );
/**
** A list clean-up routine which takes a callback to clean up its
** contents.
**
** Passes each element in the given list to
** childFinalizer(item,finalizerState). If that returns non-0,
** processing stops and that value is returned, otherwise
** fsl_list_reserve(list,0) is called and 0 is returned.
**
** @see fsl_list_visit_free()
**/
int fsl_list_clear( fsl_list * list, fsl_list_visitor_f childFinalizer,
void * finalizerState );
/**
** Similar to fsl_list_clear(list, fsl_list_v_fsl_free, NULL), but
** only clears the list itself if the second argument is true,
** otherwise it sets the list's length to 0 but keeps its memory
** intact for later use.
**
** Be sure only to use this on lists of types for which fsl_free()
** is legal. i.e. don't use it on a list of fsl_deck objects or
** other types which have their own finalizers.
**
** Results are undefined if list is NULL.
**
** @see fsl_list_clear()
*/
void fsl_list_visit_free( fsl_list * list, char freeListMem );
/**
**
**
** Works similarly to the visit operation without the _p suffix
** except that the pointer the visitor function gets is a (**)
** pointing back to the entry within this list. That means that
** callers can assign the entry in the list to another value during
** the traversal process (e.g. set it to 0). If shiftIfNulled is
** true then if the callback sets the list's value to 0 then it is
** removed from the list and self->used is adjusted (self->capacity
** is not changed).
*/
int fsl_list_visit_p( fsl_list * self, char order, char shiftIfNulled,
fsl_list_visitor_f visitor, void * visitorState );
/**
** Sorts the given list using the given comparison function. Neither
** argument may be NULL. The arugments passed to the comparison function
** will be pointers to pointers to the original entries, and may (depending
** on how the list is used) point to NULL.
*/
void fsl_list_sort( fsl_list * li, int (*cmp)( void const * lhs, void const * rhs ));
/**
** Returns 0 if the given file is readable. Flags may be any values
** accepted by the accept(2) resp. _waccept() system calls.
*/
int fsl_file_access(const char *zFilename, int flags);
/**
** Compute a canonical pathname for a file or directory.
** Make the name absolute if it is relative.
** Remove redundant / characters.
** Remove all /./ path elements.
** Convert /A/../ to just /.
** If the slash parameter is non-zero, the trailing slash, if any,
** is retained.
**
** Returns 0 on success, FSL_RC_MISUSE if !zOrigName or !pOut,
** FSL_RC_OOM if an allocation fails.
**
** pOut is _appended_ to, so be sure to set pOut->used=0 (or pass it
** to fsl_buffer_reset()) before calling this if you want to start
** writing at the beginning.
*/
int fsl_file_canonical_name(const char *zOrigName,
fsl_buffer *pOut, char slash);
/**
** Writes the absolute path name of the current directory to zBuf,
** which must be at least nBuf bytes long (nBuf includes the space
** for a trailing NUL terminator).
**
** Returns FSL_RC_RANGE if the name would be too long for nBuf,
** FSL_RC_IO if it cannot determine the current directory (e.g. a
** side effect of having removed the directory at runtime or similar
** things), and 0 on success.
**
** On success, if outLen is not NULL then the length of the string
** written to zBuf is assigned to *outLen. The output string is
** always NUL-terminated.
**
** On Windows, the name is converted from unicode to UTF8 and all '\\'
** characters are converted to '/'. No conversions are needed on
** Unix.
*/
int fsl_getcwd(char *zBuf, fsl_size_t nBuf, fsl_size_t * outLen);
/**
** Return true if the filename given is a valid filename for
** a file in a repository. Valid filenames follow all of the
** following rules:
**
** * Does not begin with "/"
** * Does not contain any path element named "." or ".."
** * Does not contain any of these characters in the path: "\"
** * Does not end with "/".
** * Does not contain two or more "/" characters in a row.
** * Contains at least one character
**
** Invalid UTF8 characters result in a false return if bStrictUtf8 is
** true. If bStrictUtf8 is false, invalid UTF8 characters are silently
** ignored. See http://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences
** and http://en.wikipedia.org/wiki/Unicode (for the noncharacters).
**
** Fossil compatibility note: the bStrictUtf8 flag must be true
** when parsing new manifests but is false when parsing legacy
** manifests, for backwards compatibility.
**
** z must be NUL terminated. Results are undefined if !z.
*/
char fsl_is_simple_pathname(const char *z, char bStrictUtf8);
/**
** Return the size of a file in bytes. Returns -1 if the file does
** not exist or is not stat(2)able.
*/
fsl_size_t fsl_file_size(const char *zFilename);
/**
** Return the modification time for a file. Return -1 if the file
** does not exist or is not stat(2)able.
*/
fsl_time_t fsl_file_mtime(const char *zFilename);
/**
** Don't use this. The wd (working directory) family of functions
** might or might-not be necessary and in any case they require
** a fsl_cx context argument because they require repo-specific
** "allow-symlinks" setting.
** Return TRUE if the named file is an ordinary file or symlink
** and symlinks are allowed.
**
** Return false for directories, devices, fifos, etc.
*/
int fsl_file_wd_isfile_or_link(const char *zFilename);
/**
** Return TRUE if the named file is an ordinary file. Return false
** for directories, devices, fifos, symlinks, etc.
*/
int fsl_file_isfile(const char *zFilename);
/**
** Returns true if the given path appears to be absolute, else
** false. On Unix a path is absolute if it starts with a '/'. On
** Windows a path is also absolute if it starts with a letter, a
** colon, and a backslash.
*/
char fsl_file_is_absolute_path(const char *zPath);
/**
** Simplify a filename by
**
** * Convert all \ into / on windows and cygwin
** * removing any trailing and duplicate /
** * removing /./
** * removing /A/../
**
** Changes are made in-place. Return the new name length. If the
** slash parameter is non-zero, the trailing slash, if any, is
** retained. If n is <0 then fsl_strlen(z) is used to calculate the
** length.
*/
fsl_size_t fsl_file_simplify_name(char *z, fsl_int_t n_, char slash);
/**
** Return non-zero if string z matches glob pattern zGlob and zero
** if the pattern does not match. Always returns 0 if either
** argument is NULL.
**
** Globbing rules:
**
** '*' Matches any sequence of zero or more characters.
**
** '?' Matches exactly one character.
**
** [...] Matches one character from the enclosed list of
** characters.
**
** [^...] Matches one character not in the enclosed list.
*/
char fsl_str_glob(const char *zGlob, const char *z);
/**
** Returns true, else false if the given letter is an ASCII alphabet
** character.
*/
char fsl_isalpha(int c);
char fsl_islower(int c);
char fsl_isspace(int c);
char fsl_islower(int c);
char fsl_isupper(int c);
char fsl_isdigit(int c);
char fsl_tolower(int c);
char fsl_toupper(int c);
char fsl_isalpha(int c);
char fsl_isalnum(int c);
#ifdef _WIN32
/**
** Translate MBCS to UTF-8. Return a pointer to the translated
** text. ACHTUNG: Call fsl_mbcs_free() (not fsl_free()) to
** deallocate any memory used to store the returned pointer when
** done.
*/
char * fsl_mbcs_to_utf8(char const * mbcs);
/**
** Frees a string allocated from fsl_mbcs_to_utf8(). Results are undefined
** if mbcs was allocated using any other mechanism.
*/
void fsl_mbcs_free(char * mbcs);
#endif
/* _WIN32 */
/**
** Deallocates the given memory, which must have been allocated
** from fsl_unicode_to_utf8(), fsl_utf8_to_unicode(), or any
** function which explicitly documents this function as being the
** proper finalizer for its returned memory.
*/
void fsl_unicode_free(void *);
/**
** Translate UTF-8 to Unicode for use in system calls. Returns a
** pointer to the translated text. The returned value must
** eventually be passed to fsl_unicode_free() to deallocate any
** memory used to store the returned pointer when done.
**
** This function exists only for Windows. On other platforms
** it behaves like fsl_strdup().
**
** The returned type is (wchar_t*) on Windows and (char*)
** everywhere else.
*/
void *fsl_utf8_to_unicode(const char *zUtf8);
/**
** Translates Unicode text into UTF-8. Return a pointer to the
** translated text. Call fsl_unicode_free() to deallocate any
** memory used to store the returned pointer when done.
**
** This function exists only for Windows. On other platforms it
** behaves like fsl_strdup().
*/
char *fsl_unicode_to_utf8(const void *zUnicode);
/**
** Translate text from the OS's character set into UTF-8. Return a
** pointer to the translated text. Call fsl_filename_free() to
** deallocate any memory used to store the returned pointer when
** done.
**
** This function must not convert '\' to '/' on Windows/Cygwin, as
** it is used in places where we are not sure it's really filenames
** we are handling, e.g. fsl_getenv() or handling the argv
** arguments from main().
**
** On Windows, translate some characters in the in the range
** U+F001 - U+F07F (private use area) to ASCII. Cygwin sometimes
** generates such filenames. See:
** <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
*/
char *fsl_filename_to_utf8(const void *zFilename);
/**
** Translate text from UTF-8 to the OS's filename character set.
** Return a pointer to the translated text. Call
** fsl_filename_free() to deallocate any memory used to store the
** returned pointer when done.
**
** On Windows, characters in the range U+0001 to U+0031 and the
** characters '"', '*', ':', '<', '>', '?' and '|' are invalid in
** filenames. Therefore, translate those to characters in the in the
** range U+F001 - U+F07F (private use area), so those characters
** never arrive in any Windows API. The filenames might look
** strange in Windows explorer, but in the cygwin shell everything
** looks as expected.
**
** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
**
** The returned type is (wchar_t*) on Windows and (char*)
** everywhere else.
*/
void *fsl_utf8_to_filename(const char *zUtf8);
/**
** Deallocate pOld, which must have been allocated by
** fsl_filename_to_utf8(), fsl_utf8_to_filename(), fsl_getenv(), or
** another routine which explicitly documents this function as
** being the proper finalizer for its returned memory.
*/
void fsl_filename_free(void *pOld);
/**
** Returns a (possible) copy of the environment variable with the
** given key, or NULL if no entry is found. The returned value must
** be passed to fsl_filename_free() to free it. ACHTUNG: DO NOT
** MODIFY the returned value - on Unix systems it is _not_ a
** copy. That interal API inconsistency "should" be resolved
** (==return a copy from here, but that means doing it everywhere)
** to avoid memory ownership problems later on.
**
** Why return a copy? Because native strings from at least one of
** the more widespread OSes often have to be converted to something
** portable and this requires allocation on such platforms, but
** not on Unix. For API transparency, that means all platforms get
** the copy(-like) behaviour.
**/
char *fsl_getenv(const char *zName);
/**
** Returns a positive value if zFilename is a directory, 0 if
** zFilename does not exist, or a negative value if zFilename
** exists but is something other than a directory. Results are
** undefined if zFilename is NULL.
*/
char fsl_dir_check(const char *zFilename);
/**
** Deletes the given file from the filesystem. Returns 0 on
** success.
*/
int fsl_file_unlink(const char *zFilename);
/**
** Create the directory with the given name if it does not already
** exist. If forceFlag is true, delete any prior non-directory
** object with the same name.
**
** If the directory already exists, 0 is returned, not an error.
**
** Return 0 on success, non-0 on error.
*/
int fsl_mkdir(const char *zName, char forceFlag);
/**
** Uses fsl_getenv() to look for the environment variables
** (FOSSIL_USER, (Windows: USERNAME), (Unix: USER, LOGNAME)). If
** it finds one it returns a copy of that value, which must
** eventually be passed to fsl_free() to free it (NOT
** fsl_filename_free(), though fsl_getenv() requires that one). If
** it finds no match, or if copying the entry fails, it returns
** NULL.
*/
char * fsl_guess_user_name();
/**
** Tries to find the user's home directory. If found, 0 is
** returned, tgt's memory is _overwritten_ (not appended) with the
** path, and tgt->used is set to the path's string length. (Design
** note: the overwrite behaviour is inconsistent with must of the
** API, but the implementation currently requires this.)
**
** If requireWriteAccess is true then the directory is checked for
** write access, and FSL_RC_ACCESS is returned if that check
** fails. For historical (possibly techinical?) reasons, this check
** is only performed on Unix platforms. On others this argument is
** ignored. When writing code on Windows, it may be necessary to
** assume that write access is necessary on non-Windows platform,
** and to pass 1 for the second argument even though it is ignored
** on Windows.
**
** On error non-0 is returned and tgt is updated with an error
** string OR (if the error was an allocation error while appending
** to the path or allocating MBCS strings for Windows), it returns
** FSL_RC_OOM and tgt "might" be updated with a partial path (up to
** the allocation error), and "might" be empty (if the allocation
** error happens early on).
**
** This routine does not canonicalize/transform the home directory
** path provided by the environment, other than to convert the
** string byte encoding on some platforms. i.e. if the environment
** says that the home directory is "../" then this function will
** return that value, possibly to the eventual disappointment of
** the caller.
**
** Result codes include:
**
** - FSL_RC_OK (0) means a home directory was found and tgt is
** populated with its path.
**
** - FSL_RC_NOT_FOUND means the home directory (platform-specific)
** could not be found.
**
** - FSL_RC_ACCESS if the home directory is not writable and
** requireWriteAccess is true. Unix platforms only -
** requireWriteAccess is ignored on others.
**
** - FSL_RC_TYPE if the home (as determined via inspection of the
** environment) is not a directory.
**
** - FSL_RC_OOM if a memory (re)allocation fails.
*/
int fsl_find_home_dir( fsl_buffer * tgt, char requireWriteAccess );
/**
** Values for use with the fsl_fstat::mode field.
*/
enum fsl_fstat_type_t {
FSL_FSTAT_TYPE_UNKNOWN = 0,
/** Indicates a directory filesystem entry. */
FSL_FSTAT_TYPE_DIR,
/** Indicates a non-directory, non-symlink filesystem entry. */
FSL_FSTAT_TYPE_FILE,
/** Indicates a symlink filesystem entry. */
FSL_FSTAT_TYPE_LINK
};
typedef enum fsl_fstat_type_t fsl_fstat_type_t;
/**
** Bitmask values for use with the fsl_fstat::perms field.
*/
enum fsl_fstat_perm_t {
/**
** Sentinel value.
*/
FSL_FSTAT_PERM_UNKNOWN = 0,
/**
** The executable bit, as understood by Fossil. Fossil does not
** differentiate between different +x values for user/group/other.
*/
FSL_FSTAT_PERM_EXE = 0x01
};
typedef enum fsl_fstat_perm_t fsl_fstat_perm_t;
/**
** A simple wrapper around the stat(2) structure resp. _stat/_wstat
** (on Windows). It exposes only the aspects of stat(2) info which
** Fossil works with, and not any platform-/filesystem-specific
** details except the executable bit for the permissions mode.
**/
struct fsl_fstat {
/**
** Indicates the type of filesystem object.
*/
fsl_fstat_type_t type;
/**
** The creation time stat'd file, in... well, the man pages
** (neither for Linux nor Windows) do not specify exactly what
** unit this is. Let's assume seconds since the start of the Unix
** Epoch.
*/
fsl_time_t ctime;
/**
** Last modification time.
*/
fsl_time_t mtime;
/**
** The size of the stat'd file, in bytes.
*/
fsl_size_t size;
/**
** Not yet used.
**
** TODO: decide whether we want to expose all OS/FS-level
** permissions or just the executable bit (as v1 does).
** fsl_fstat is intended to be used in more generic contexts than
** v1's fossil_stat(), so it "might" make sense to expose those
** here, even though fossil will only track the exec permission.
*/
int perms;
};
/** Empty-initialized fsl_fstat structure. */
#define fsl_fstat_empty_m {FSL_FSTAT_TYPE_UNKNOWN,0,0,0,0}
/** Empty-initialize fsl_fstat instance, intended for copy
construction. */
extern const fsl_fstat fsl_fstat_empty;
/**
** Runs the OS's stat(2) equivalent to populate fst with
** information about the given file.
**
** Returns 0 on success, FSL_RC_MISUSE if zFilename is NULL or
** starts with a NUL byte, or if fst is NULL. Returns
** FSL_RC_NOT_FOUND if no filesystem entry is found for the given
** name. Returns FSL_RC_IO if the underlying stat() (or equivalent)
** fails for other reasons (because MS apparently doesn't document
** the errno values which can be set by _wstati64()).
**
** The derefSymlinks argument is ignored on non-Unix platforms. On
** Unix platforms, if derefSymlinks is non-0 then stat(2) is used,
** else lstat(2) (if available on the platform) is used. For most
** cases clients should pass non-0. They should only pass 0 if they
** need to differentiate between symlinks and files.
**
** The fsl_fstat_type_t family of flags can be used to determine
** the type of the filesystem object being stat()'d (file,
** directory, or symlink). It does apply any special logic for
** platform-specific oddities other than symlinks (e.g. character
** devices and such).
**/
int fsl_stat(const char *zFilename, fsl_fstat * fst,
char derefSymlinks );
/**
** Create a new delta between the memory zIn and zOut.
**
** The delta is written into a preallocated buffer, zDelta, which
** must be at least 60 bytes longer than the target memory, zOut.
** The delta string will be NUL-terminated, but it might also
** contain embedded NUL characters if either the zSrc or zOut files
** are binary.
**
** On success this function returns 0 and the length of the delta
** string, in bytes, excluding the final NUL terminator character,
** is written to *deltaSize.
**
** Returns FSL_RC_MISUSE if any of the pointer arguments are NULL
** and FSL_RC_OOM if memory allocation fails during generation of
** the delta. Returns FSL_RC_RANGE if lenSrc or lenOut are "too
** big" (if they cause an overflow in the math).
**
** Output Format:
**
** The delta begins with a base64 number followed by a newline.
** This number is the number of bytes in the TARGET file. Thus,
** given a delta file z, a program can compute the size of the
** output file simply by reading the first line and decoding the
** base-64 number found there. The fsl_delta_applied_size()
** routine does exactly this.
**
** After the initial size number, the delta consists of a series of
** literal text segments and commands to copy from the SOURCE file.
** A copy command looks like this:
**
** (Achtung: extra backslashes are for Doxygen's benefit - not
** visible in the processsed docs.)
**
** NNN\@MMM,
**
** where NNN is the number of bytes to be copied and MMM is the
** offset into the source file of the first byte (both base-64).
** If NNN is 0 it means copy the rest of the input file. Literal
** text is like this:
**
** NNN:TTTTT
**
** where NNN is the number of bytes of text (base-64) and TTTTT is
** the text.
**
** The last term is of the form
**
** NNN;
**
** In this case, NNN is a 32-bit bigendian checksum of the output
** file that can be used to verify that the delta applied
** correctly. All numbers are in base-64.
**
** Pure text files generate a pure text delta. Binary files
** generate a delta that may contain some binary data.
**
** Algorithm:
**
** The encoder first builds a hash table to help it find matching
** patterns in the source file. 16-byte chunks of the source file
** sampled at evenly spaced intervals are used to populate the hash
** table.
**
** Next we begin scanning the target file using a sliding 16-byte
** window. The hash of the 16-byte window in the target is used to
** search for a matching section in the source file. When a match
** is found, a copy command is added to the delta. An effort is
** made to extend the matching section to regions that come before
** and after the 16-byte hash window. A copy command is only
** issued if the result would use less space that just quoting the
** text literally. Literal text is added to the delta for sections
** that do not match or which can not be encoded efficiently using
** copy commands.
**
** @see fsl_delta_applied_size()
** @see fsl_delta_apply()
*/
int fsl_delta_create( unsigned char const *zSrc, fsl_size_t lenSrc,
unsigned char const *zOut, fsl_size_t lenOut,
unsigned char *zDelta, fsl_size_t * deltaSize);
/**
** Works identically to fsl_delta_create() but sends its output to
** the given output function. out(outState,...) may be called any
** number of times to emit delta output. Each time it is called it
** should append the new bytes to its output channel.
**
** The semantics of the return value and the first four arguments
** are identical tofsl_delta_create(), with these ammendments
** regarding the return:
**
** - Returns FSL_RC_MISUSE if any of (zSrc, zOut, out) are NULL.
**
** - If out() returns non-0 at any time, delta generation is
** aborted and that code is returned.
**
** Example usage:
**
** @code
** int rc = fsl_delta_create( v1, v1len, v2, v2len,
** fsl_output_f_FILE, stdout);
** @endcode
*/
int fsl_delta_create2( unsigned char const *zSrc, fsl_size_t lenSrc,
unsigned char const *zOut, fsl_size_t lenOut,
fsl_output_f out, void * outState);
/**
** A fsl_delta_create() wrapper which uses the first two arguments
** as the original and "new" content versions to delta, and outputs
** the delta to the 3rd argument (overwriting any existing contents
** and re-using any memory it had allocated).
**
** Returns 0 on success.
*/
int fsl_buffer_delta_create( fsl_buffer const * src,
fsl_buffer const * newVers,
fsl_buffer * delta);
/**
** Apply a delta created using fsl_delta_create().
**
** The output buffer must be big enough to hold the whole output
** file and a NUL terminator at the end. The
** fsl_delta_applied_size() routine can be used to determine that
** size.
**
** zSrc represents the original sources to apply the delta to.
** It must be at least lenSrc bytes of valid memory.
**
** zDelta holds the delta (created using fsl_delta_create()),
** and it must be lenDelta bytes long.
**
** On success this function returns 0 and writes the applied delta
** to zOut.
**
** Returns FSL_RC_MISUSE if any pointer argument is NULL. Returns
** FSL_RC_RANGE if lenSrc or lenDelta are "too big" (if they cause
** an overflow in the math). Invalid delta input can cause any of
** FSL_RC_RANGE, FSL_RC_DELTA_INVALID_TERMINATOR,
** FSL_RC_CHECKSUM_MISMATCH, FSL_RC_SIZE_MISMATCH, or
** FSL_RC_DELTA_INVALID_OPERATOR to be returned.
**
** Refer to the fsl_delta_create() documentation above for a
** description of the delta file format.
**
** @see fsl_delta_applied_size()
** @see fsl_delta_create()
** @see fsl_delta_apply2()
*/
int fsl_delta_apply( unsigned char const *zSrc, fsl_size_t lenSrc,
unsigned char const *zDelta, fsl_size_t lenDelta,
unsigned char *zOut );
/**
** Functionally identical to fsl_delta_apply() but any errors generated
** during application of the delta are described in more detail
** in pErr. If pErr is NULL this behaves exactly as documented for
** fsl_delta_apply().
*/
int fsl_delta_apply2( unsigned char const *zSrc,
fsl_size_t lenSrc,
unsigned char const *zDelta,
fsl_size_t lenDelta,
unsigned char *zOut,
fsl_error * pErr);
/*
** Calculates the size (in bytes) of the output from applying a the
** given delta. On success 0 is returned and *appliedSize will be
** updated with the amount of memory required for applying the
** delta. zDelta must point to lenDelta bytes of memory in the
** format emitted by fsl_delta_create(). It is legal for appliedSize
** to point to the same memory as the 2nd argument.
**
** Returns FSL_RC_MISUSE if any pointer argument is NULL. Returns
** FSL_RC_RANGE if lenDelta is too short to be a delta. Returns
** FSL_RC_DELTA_INVALID_TERMINATOR if the delta's encoded length
** is not properly terminated.
**
** This routine is provided so that an procedure that is able to
** call fsl_delta_apply() can learn how much space is required for
** the output and hence allocate nor more space that is really
** needed.
**
** TODO?: consolidate 2nd and 3rd parameters into one i/o parameter?
**
** @see fsl_delta_apply()
** @see fsl_delta_create()
*/
int fsl_delta_applied_size(unsigned char const *zDelta,
fsl_size_t lenDelta,
fsl_size_t * appliedSize);
/**
** "Fossilizes" the first len bytes of the given input string. If
** (len<0) then fsl_strlen(inp) is used to calculate its length.
** The output is appended to out, which is expanded as needed and
** out->used is updated accordingly. Returns 0 on success,
** FSL_RC_MISUSE if !inp or !out. Returns 0 without side-effects if
** 0==len or (!*inp && len<0). Returns FSL_RC_OOM if reservation of
** the output buffer fails (it is expanded, at most, one time by
** this function).
**
** Fossilization replaces the following bytes/sequences with the
** listed replacements:
**
** (Achtung: usage of doubled backslashes here it just to please
** doxygen - they will show up as single slashes in the processed
** output.)
**
** - Backslashes are doubled.
**
** - (\\n, \\r, \\v, \\t, \\f) are replaced with \\\\X, where X is the
** conventional encoding letter for that escape sequence.
**
** - Spaces are replaced with \\s.
**
** - Embedded NULs are replaced by \\0 (numeric 0, not character
** '0').
*/
int fsl_bytes_fossilize( unsigned char const * inp, fsl_int_t len,
fsl_buffer * out );
/**
** "Defossilizes" bytes encoded by fsl_bytes_fossilize() in-place.
** inp must be a string encoded by fsl_bytes_fossilize(), and the
** decoding processes stops at the first unescaped NUL terminator.
** It has no error conditions except for !inp or if inp is not
** NUL-terminated, both of which invoke in undefined behaviour.
**
** If resultLen is not NULL then *resultLen is set to the resulting string
** length.
**
*/
void fsl_bytes_defossilize( unsigned char * inp, fsl_size_t * resultLen );
/**
** Defossilizes the contents of b. Equivalent to:
** fsl_bytes_defossilize( b->mem, &b->used );
*/
void fsl_buffer_defossilize( fsl_buffer * b );
/**
** Return true (non-0) if the input string contains only valid base-16
** digits. If any invalid characters appear in the string, return
** 0 (false).
*/
char fsl_validate16(const char *zIn, fsl_size_t nIn);
/**
** The input string is a base16 value. Convert it into its canonical
** form. This means that digits are all lower case and that conversions
** like "l"->"1" and "O"->"0" occur.
*/
void fsl_canonical16(char *z, fsl_size_t n);
/**
** Decode a N-character base-16 number into base-256. N must be a
** multiple of 2. The output buffer must be at least N/2 characters
** in length. Returns 0 on success.
*/
int fsl_decode16(const unsigned char *zIn, unsigned char *pOut, fsl_size_t N);
/**
** Encode a N-digit base-256 in base-16. N is the byte length of pIn
** and zOut must be at least (N*2+1) bytes long (the extra is for a
** terminating NUL). Returns zero on success, FSL_RC_MISUSE if !pIn
** or !zOut.
*/
int fsl_encode16(const unsigned char *pIn, unsigned char *zOut, fsl_size_t N);
/**
** Tries to convert the value of errNo, which is assumed to come
** from the global errno, to a fsl_rc_t code. If it can, it returns
** something approximating the errno value, else it returns dflt.
**
** Example usage:
**
** @code
** FILE * f = fsl_fopen("...", "...");
** int rc = f ? 0 : fsl_errno_to_rc(errno, FSL_RC_IO);
** ...
** @endcode
**
** Why require the caller to pass in errno, instead of accessing it
** directly from this function? To avoid the the off-chance that
** something changes errno between the call and the conversion
** (whether or not that's possible is as yet undetermined). It can
** also be used by clients to map to explicit errno values to
** fsl_rc_t values, e.g. fsl_errno_to_rc(EROFS,-1) returns
** FSL_RC_ACCESS.
*/
int fsl_errno_to_rc(int errNo, int dflt);
/**
** Make the given string safe for HTML by converting every "<" into
** "<", every ">" into ">", every "&" into "&", and
** encode " as " so that it can appear as an argument to
** markup.
**
** The escaped output is send to out(oState,...).
**
** Returns 0 on success or if there is nothing to do (input has a
** length of 0). Returns FSL_RC_MISUSE if !out or !zIn. If out()
** returns a non-0 code then that value is returned to the caller.
**
** If n is negative, fsl_strlen() is used to calculate zIn's length.
*/
int fsl_htmlize(fsl_output_f out, void * oState,
const char *zIn, fsl_int_t n);
/**
** Functionally equivalent to fsl_htmlize() but optimized to perform
** only a single allocation.
**
** Returns 0 on success or if there is nothing to do (input has a
** length of 0). Returns FSL_RC_MISUSE if !p or !zIn, and
** FSL_RC_OOM on allocation error.
**
** If n is negative, fsl_strlen() is used to calculate zIn's length.
*/
int fsl_htmlize_to_buffer(fsl_buffer *p, const char *zIn, fsl_int_t n);
/**
** Equivalent to fsl_htmlize_to_buffer() but returns the result as a
** new string which must eventually be fsl_free()d by the caller.
**
** Returns NULL for invalidate arguments or allocation error.
*/
char *fsl_htmlize_str(const char *zIn, fsl_int_t n);
/**
** If c is a character Fossil likes to HTML-escape, assigns *xlate
** to its transformed form, else set it to NULL. Returns 1 for
** untransformed characters and the strlen of *xlate for others.
** Bytes returned via xlate are static and immutable.
**
** Results are undefined if xlate is NULL.
*/
fsl_size_t fsl_htmlize_xlate(int c, char const ** xlate);
/**
** Flags for use with text-diff generation APIs,
** e.g. fsl_diff_text().
**
** Maintenance reminder: these values are holy and must not be
** changed without also changing the corresponding code in
** fsl_diff.c.
*/
enum fsl_diff_flag_t {
/** Inline (not side-by-side) diff */
FSL_DIFF_INLINE = 0x00,
/** Ignore end-of-line whitespace */
FSL_DIFF_IGNORE_EOLWS = 0x01,
/** Generate a side-by-side diff */
FSL_DIFF_SIDEBYSIDE = 0x02,
/** Missing shown as empty files */
FSL_DIFF_VERBOSE = 0x04,
/** Show filenames only */
FSL_DIFF_BRIEF = 0x08,
/** Render for HTML. */
FSL_DIFF_HTML = 0x10,
/** Show line numbers. */
FSL_DIFF_LINENO = 0x20,
/** Warn about whitespace. */
FSL_DIFF_WS_WARNING = 0x40,
/** Suppress optimizations (debug). */
FSL_DIFF_NOOPT = 0x0100,
/** Invert the diff (debug). */
FSL_DIFF_INVERT = 0x0200,
/** Use context even if zero. */
FSL_DIFF_CONTEXT_EX = 0x0400,
/** Only display if not "too big." */
FSL_DIFF_NOTTOOBIG = 0x0800
};
/**
** Generates a textual diff from two text inputs and writes
** it to the given output function.
**
** pA and pB are the buffers to diff.
**
** contextLines is the number of lines of context to output (or
** some default if <= 0). This parameter has a built-in limit
** of 2^16, and values larger than that get truncated.
**
** sbsWidth specifies the width (in characters) of the side-by-side
** columns. If sbsWidth is not 0 then this function behaves as if
** diffFlags contains the FSL_DIFF_SIDEBYSIDE flag. If sbsWidth is
** negative, OR if diffFlags explicitly contains
** FSL_DIFF_SIDEBYSIDE and sbsWidth is 0, then some default width
** is used. This parameter has a built-in limit of 255, and values
** larger than that get truncated to 255.
**
** diffFlags is a mask of fsl_diff_flag_t values. Not all of the
** fsl_diff_flag_t flags are yet [sup]ported.
**
** The output is sent to out(outState,...). If out() returns non-0
** during processing, processing stops and that result is returned
** to the caller of this function.
**
** Returns 0 on success, FSL_RC_OOM on allocation error,
** FSL_RC_MISUSE if any arguments are invalid, FSL_RC_TYPE if any
** of the content appears to be binary (contains embedded NUL
** bytes).
**
** None of (pA, pB, out) may be NULL.
**
** TODOs:
**
** - Add a predicate function for outputing only matching
** differences, analog to fossil(1)'s regex support (but more
** flexible).
**
** - Expose the raw diff-generation bits via the internal API
** to facilitate/enable the creation of custom diff formats.
*/
int fsl_diff_text(fsl_buffer const *pA, fsl_buffer const *pB,
fsl_output_f out, void * outState,
short contextLines, short sbsWidth,
int diffFlags );
/**
** Functionally equivalent to:
**
** @code:
** fsl_diff_text(pA, pB, fsl_output_f_buffer, pOut,
** contextLines, sbsWidth, diffFlags);
** @endcode
**
** Except that it returns FSL_RC_MISUSE if !pOut.
*/
int fsl_diff_text_to_buffer(fsl_buffer const *pA, fsl_buffer const *pB,
fsl_buffer *pOut, short contextLines,
short sbsWidth, int diffFlags );
#if defined(__cplusplus)
} /*extern "C"*/
#endif
#endif
/* NET_FOSSIL_SCM_FSL_UTIL_H_INCLUDED */