Files
mars-matrixssl/core/psPrnf.h
Janne Johansson 8735be1654 MatrixSSL 3.9.5
2017-12-13 16:02:09 +02:00

338 lines
12 KiB
C

/**
* @file psPrnf.h
* @version $Format:%h%d$
*
* Extended formatting: Allow complex objects to be printed with
* printf() style formatting.
*
* These macros and functions can be used in programs using SafeZone
* and MatrixSSL software or related software components.
*/
/*
* Copyright (c) 2017 INSIDE Secure Corporation
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _h_PS_CORECONFIG
# ifdef MATRIX_CONFIGURATION_INCDIR_FIRST
# include <coreConfig.h> /* Must be first included */
# else
# include "coreConfig.h" /* Must be first included */
# endif
#endif /* _h_PS_CORECONFIG */
#include "osdep-types.h"
/* Only needs stub psPool_t. */
#ifndef PS_POOL_T_DEFINED
#define PS_POOL_T_DEFINED
typedef int32 psPool_t;
#endif
#ifndef _h_PS_PRNF
#include <stdarg.h>
# define _h_PS_PRNF
# ifndef PS_NO_PRNF
# define PS_PRNF_STRUCT_VARIABLE_LENGTH_MEMBER 1
# ifdef __STDC_VERSION__
# if __STDC_VERSION__ >= 199901L
# undef PS_PRNF_STRUCT_VARIABLE_LENGTH_MEMBER
# define PS_PRNF_STRUCT_VARIABLE_LENGTH_MEMBER /* empty */
# endif
# endif
struct psPrnfStrNode
{
struct psPrnfStrNode *next;
char *str;
char strstorage[PS_PRNF_STRUCT_VARIABLE_LENGTH_MEMBER];
};
typedef struct
{
struct psPrnfStrNode *list;
int err;
} psPrnf_t;
/** Extended format.
Use this instead of "%s" formatting code to format using PSA_HEX() and other
extended formats. */
#define PSF "%s"
#define PSFS_(x) #x
#define PSFS(x) PSFS_(x)
/** Extended format with length constraints.
Provide constant integers to use as minimum and maximum length of resulting formatting.
If input is shorter than the field, spaces will be added on left.
If input is longer than the field, the field is truncated on right.
@warning Truncation from right is not recommended for (big) integers, as it is not
a common convention to truncate rightmost digits.
Either minsz or maxsz can be omitted.
*/
#define PSFX(minsz, maxsz) "%" PSFS(minsz) "." PSFS(maxsz) "s"
/** Extended format with length constraints aligned left.
Provide constant integers to use as minimum and maximum length of resulting formatting.
If input is shorter than the field, spaces will be added on right.
If input is longer than the field, the field is truncated on right.
@warning Truncation from right is not recommended for (big) integers, as it is not
a common convention to truncate rightmost digits.
Either minsz or maxsz can be omitted.
*/
#define PSFLX(minsz, maxsz) "%-" PSFS(minsz) "." PSFS(maxsz) "s"
/** Check if formatting errors took place.
The printing functions will allow some output even presence of errors, like NULL pointers
or memory allocation failures. These issue will be repalced with place holders on formatted
string. This macro allows to check if formatting error has been detected.
*/
#define PSPRNF_ERR() (psPrnfCtx.err)
/** Indefinite size string.
Some functions accept this instead of size as identifier to request determination of size from
string (using strlen()).
*/
#define PS_SIZE_STR (~(psSizeL_t)0)
/* Functions: intentionally undocumented, because these are invoked via
macros. */
char *psPrnfDup(psPrnf_t *ctx, const char *src, psSizeL_t sz, const char *def);
char *psPrnfDupFree(psPrnf_t *ctx, char *src, psSizeL_t sz, const char *def);
char *psPrnfDup2(psPrnf_t *ctx, const char *src, psSizeL_t sz,
const char *src2, psSizeL_t sz2, const char *def);
char *psPrnfCopyDupFree(psPrnf_t *ctx, const char *src, psSizeL_t sz,
char *src2, psSizeL_t sz2, const char *def);
char *psPrnfDupf(psPrnf_t *ctx, const char *def, const char *fmt, ...);
const char *psPrnfBool(psBool_t b);
const char *psPrnfStr(psPrnf_t *ctx, const char *str);
const char *psPrnfSStr(psPrnf_t *ctx, const char *str, psSizeL_t len);
const char *psPrnfQStr(psPrnf_t *ctx, const char *str);
const char *psPrnfHex(psPrnf_t *ctx, const unsigned char *hex, psSizeL_t len);
const char *psPrnfHex2(psPrnf_t *ctx, const unsigned char *hex, psSizeL_t len);
const char *psPrnfBase64(psPrnf_t *ctx, const unsigned char *octets, psSizeL_t len,
int(*formatter)(const unsigned char *, size_t, const char *, char **));
const char *psPrnfIpv4(psPrnf_t *ctx, uint32_t ipv4_addr);
int psPrnf_(psPrnf_t *ctx, const char *fmt, ...) __attribute__((__format__(printf, 2, 3)));
int psSnprnf_(char *str, psSizeL_t size, psPrnf_t *ctx, const char *fmt, ...) __attribute__((__format__(printf, 4, 5)));
char *psAsprnf_(psPool_t *pool, psPrnf_t *ctx, const char *fmt, ...) __attribute__((__format__(printf, 3, 4)));
/** Extended formatted printing.
The function behaves like printf, except it requires
#PS_PRNF_CTX in functions using the printing. In return for use of
#PS_PRNF_CTX, the user may use extended formatting codes
PSA_STR(), PSA_SSTR(), PSA_OSTR(), PSA_HEX() etc.
*/
#define psPrnf(...) psPrnf_(&psPrnfCtx, __VA_ARGS__)
/** Extended formatted printing into string.
The function behaves like snprintf, except it requires
#PS_PRNF_CTX in functions using the printing. In return for use of
#PS_PRNF_CTX, the user may use extended formatting codes
PSA_STR(), PSA_SSTR(), PSA_OSTR(), PSA_HEX() etc.
*/
#define psSnprnf(buf, sz, ...) psSnprnf_((buf), (sz), &psPrnfCtx, __VA_ARGS__)
/** Extended formatted printing into newly allocated string.
The function behaves like snprintf, except it requires
#PS_PRNF_CTX in functions using the printing. In return for use of
#PS_PRNF_CTX, the user may use extended formatting codes
PSA_STR(), PSA_SSTR(), PSA_OSTR(), PSA_HEX() etc.
*/
#define psAsprnf(pool, ...) psAsprnf_((pool), &psPrnfCtx, __VA_ARGS__)
/** Extended format a string.
Format argument as a string in psPrnf() output.
There needs to be #PSF, PSFX() or PSFLX() in the equivalent position
on format string.
Example:
@code
psPrnf(PSF PSF PSLN, PSA_STR("hello"), PSA_STR(", world!"));
@endcode
**/
#define PSA_STR(str) psPrnfStr(&psPrnfCtx, (str))
/** Extended format ASCII string.
Format argument as a string in psPrnf() output.
There needs to be #PSF, PSFX() or PSFLX() in the equivalent position
on format string. This formatting function will protect against
non-ASCII characters and control characters in the string. They are printed
as . characters, similar to `hd` command.
Example:
@code
psPrnf(PSF PSLN, PSA_SSTR("hello\n"));
@endcode
**/
#define PSA_SSTR(str, len) psPrnfSStr(&psPrnfCtx, (str), (len))
/** Extended format string with quoting.
Format argument as a string in psPrnf() output.
There needs to be #PSF, PSFX() or PSFLX() in the equivalent position
on format string. This formatting function will protect against
non-ASCII characters and control characters in the string. They are printed
as \xXX notation. The resulting strings are often suitable for inclusion
in C source code.
Example:
@code
psPrnf(PSF PSLN, PSA_QSTR("hello\n"));
@endcode
**/
#define PSA_QSTR(str) psPrnfQStr(&psPrnfCtx, (str))
/** Linefeed character. */
#define PSLN "\n"
/** Extended format octet string as hex digits.
Format argument (unsigned char pointer) as a string containing hexadecimal
numbers. Formatting operation is constant time: timing will only reveal
length of the octet string.
Example:
@code
psPrnf(PSF " me!" PSLN, PSA_HEX((unsigned char *)"\xFE\xED", 2));
@endcode
*/
#define PSA_HEX(octetstring, len) psPrnfHex(&psPrnfCtx, (octetstring), (len))
/** Extended format octet string as base64.
Format argument (unsigned char pointer) as a string containing base64 encoding.
@note The formatting requires `cl_pem.h`.
*/
#define PSA_BASE64(octetstring, len) \
psPrnfBase64(&psPrnfCtx, (octetstring), (len), \
(int(*)(const unsigned char *, size_t, const char *, char **)) &CL_PEM_EncodeAlloc)
/** Extended format big integer as hexadecimal.
Format argument (CL_BUC_t *) as a string containing hexadecimal
numbers. Note: Executing this macro requires `cl_bu.h`.
@note The resulting string will always have 0x prefix to identify number format.
*/
#define PSA_BUC(buc_p) \
psPrnfCopyDupFree(&psPrnfCtx, "0x", 2, CL_BUC_ExportHexStr(buc_p), (PS_SIZE_STR), "[HEX]")
/** Extended format big integer as hexadecimal (no prefix).
Format argument (CL_BUC_t *) as a string containing hexadecimal
numbers. Note: Executing this macro requires `cl_bu.h`.
@note The string never contains initial 0x prefix. Use PSA_BUC() instead for printing
hexadecimal number with prefix.
*/
#define PSA_BUC_HEX(buc_p) \
psPrnfDupFree(&psPrnfCtx, CL_BUC_ExportHexStr(buc_p), (PS_SIZE_STR), "[HEX]")
/** Extended format big integer as hexadecimal (no prefix).
Format arguments (SLMWord p[], SLMWords) as a string containing
number.
Note: Executing this macro requires `slm.h`.
*/
#define PSA_SLMW_HEX(p, n) \
psPrnfHex2(&psPrnfCtx, ((unsigned char *)(p)), (4 * (n)))
/** Extended format big integer as hexadecimal (no prefix).
Format argument (CL_BUC_t *) as a string containing decimal number.
Note: Executing this macro requires `cl_bu.h`.
*/
#define PSA_BUC_DEC(buc_p) \
psPrnfDupFree(&psPrnfCtx, CL_BUC_ExportDecStr(buc_p), (PS_SIZE_STR), "[NUMBER]")
/** Extended format boolean.
Format argument (bool) as a string containing true or false.
*/
#define PSA_BOOL(bool) psPrnfBool(bool)
/** Extended format IPV4 address.
Format argument (in_addr_t) as a string containing decimal number.
@note Executing this macro requires `arpa/inet.h`.
The function is multi-threading safe unlike inet_ntoa() on some systems.
*/
#define PSA_IPV4(ipv4_addr) \
psPrnfIpv4(&psPrnfCtx, (uint32_t) (ipv4_addr))
/** Piece of ASN.1 data.
Format piece of data within memory, assuming it contains ASN.1 DER encoded
data. Note: Executing this macro requires `asn1.h`.
@note The macro takes six arguments: pointer, length, number of der
elements to process, maximum formatting depth, maximum field length and
optional flags. See asnFormatDer() for details of underlying formatting
function.
In most cases, ptr, len, 1, 1, 0, 0 sufficies to format single element
without recursion and ptr, len, 0, 0, 0, 0 is good when trying to print
recursively as many elements as possible.
*/
#define PSA_DER(der, derlen, maxelem, maxdepth, maxelemlen, flags) \
psPrnfDupFree(&psPrnfCtx, asnFormatDer(NULL, (der), (derlen), (maxelem), \
(maxdepth), (maxelemlen), (flags)), \
(PS_SIZE_STR), "[DER]")
# endif
#endif
/* Allow multiple inclusion with changing of PS_NO_PRF macro. */
#undef PS_PRNF_CTX
#ifdef PS_NO_PRNF
# define PS_PRNF_CTX extern int no_ps_prnf_ctx /* N/A: Formatting. */
#else
# ifdef __GNUC__
/** Extended printing formatting buffer.
Function needs to use this macro within local variable declarations
to make use of psPrnf(). */
# define PS_PRNF_CTX \
psPrnf_t psPrnfCtx __attribute__((__unused__)) = { NULL, 0 }
# else
# define PS_PRNF_CTX psPrnf_t psPrnfCtx = { NULL, 0 }
# endif
#endif
/* end of psPrnf.h */