aboutsummaryrefslogtreecommitdiff
path: root/project/dclib/dclib-basics.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--project/dclib/dclib-basics.h1731
1 files changed, 1504 insertions, 227 deletions
diff --git a/project/dclib/dclib-basics.h b/project/dclib/dclib-basics.h
index 95e47bb..47827c7 100644
--- a/project/dclib/dclib-basics.h
+++ b/project/dclib/dclib-basics.h
@@ -14,16 +14,16 @@
* *
***************************************************************************
* *
- * Copyright (c) 2012-2021 by Dirk Clemens <wiimm@wiimm.de> *
+ * Copyright (c) 2012-2022 by Dirk Clemens <wiimm@wiimm.de> *
* *
***************************************************************************
* *
- * This program is free software; you can redistribute it and/or modify *
+ * This library is free software; 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 program is distributed in the hope that it will be useful, *
+ * This library 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. See the *
* GNU General Public License for more details. *
@@ -39,6 +39,7 @@
#include <sys/types.h>
#include <arpa/inet.h>
+#include <sys/un.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
@@ -65,8 +66,13 @@
#define SIZEOFRANGE(type,a,b) \
( offsetof(type,b) + sizeof(((type*)0)->b) - offsetof(type,a) )
-#define PTR_DISTANCE(a,b) ( (u8*)(a) - (u8*)(b) )
-#define PTR_DISTANCE_INT(a,b) ( (int)( (u8*)(a) - (u8*)(b) ))
+#define END_OF_VAR(v) ((void*)( (char*)(v) + sizeof(v) ))
+
+#define PTR_DISTANCE(a,b) ( (char*)(a) - (char*)(b) )
+#define PTR_DISTANCE_INT(a,b) ( (int)( (char*)(a) - (char*)(b) ))
+
+#define GET_INT_SIGN(type) ({ typeof(type) a=-1; a>0 ? 1 : -1; })
+#define GET_INT_TYPE(type) ((int)sizeof(type)*GET_INT_SIGN(type))
//
///////////////////////////////////////////////////////////////////////////////
@@ -79,9 +85,16 @@
#else
#define HAVE_CLOCK_GETTIME 0
#endif
-
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// external types ///////////////
///////////////////////////////////////////////////////////////////////////////
+typedef struct ColorSet_t ColorSet_t;
+typedef struct RestoreState_t RestoreState_t;
+typedef struct LogFile_t LogFile_t;
+
//
///////////////////////////////////////////////////////////////////////////////
/////////////// bits ///////////////
@@ -141,6 +154,7 @@ static inline uint Count1Bits64 ( u64 data )
}
///////////////////////////////////////////////////////////////////////////////
+// return -1 if bit not found
int FindLowest0BitBE ( cvp addr, uint size );
int FindLowest1BitBE ( cvp addr, uint size );
@@ -788,6 +802,20 @@ mem_t BehindMem ( const mem_t src, ccp ref );
//-----------------------------------------------------------------------------
+// UTF8 support
+
+mem_t MidMem8 ( const mem_t src, int begin, int count );
+mem_t ExtractMem8 ( const mem_t src, int begin, int end );
+mem_t ExtractEndMem8 ( const mem_t src, int begin, int end );
+
+static mem_t LeftMem8 ( const mem_t src, int count )
+ { return ExtractMem8(src,0,count); }
+
+static mem_t RightMem8 ( const mem_t src, int count )
+ { return ExtractEndMem8(src,-count,0); }
+
+//-----------------------------------------------------------------------------
+
// Alloc dest buffer and terminate with 0.
// If m*.len < 0, then use strlen().
@@ -800,7 +828,7 @@ int CmpMem ( const mem_t s1, const mem_t s2 );
int StrCmpMem ( const mem_t mem, ccp str );
bool LeftStrCmpMemEQ ( const mem_t mem, ccp str );
-// free a string if str is not NULL|EmptyString|MinusString
+// free a string if str is !NULL | !EmptyString | !MinusString | !IsCircBuf()
void FreeString ( ccp str );
static inline void FreeMem ( mem_t *mem )
@@ -886,24 +914,39 @@ static inline exmem_t ExMemByStringE ( ccp str, ccp end )
return em;
}
-static inline exmem_t ExMemByS ( ccp str, int len )
+static inline exmem_t ExMemByS ( cvp str, int len )
{
exmem_t em = { .data={ str, len }, .is_original=true };
return em;
}
-static inline exmem_t ExMemByE ( ccp str, ccp end )
+static inline exmem_t ExMemByE ( cvp str, cvp end )
{
- exmem_t em = { .data={ str, end-str }, .is_original=true };
+ exmem_t em = { .data={ str, (u8*)end-(u8*)str }, .is_original=true };
+ return em;
+}
+
+static inline exmem_t ExMemCalloc ( int size )
+{
+ char *data = CALLOC(size,1);
+ exmem_t em = { .data={ data, size }, .is_original=true, .is_alloced=true };
+ return em;
+}
+
+static inline exmem_t ExMemDup ( cvp src, int size )
+{
+ char *data = MEMDUP(src,size);
+ exmem_t em = { .data={ data, size+1 }, .is_original=true, .is_alloced=true };
return em;
}
//-----------------------------------------------------------------------------
// interface
-// 'em' maybe modified ignoring 'const'
-void FreeExMem ( const exmem_t *em );
-void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ); // free if CPM_MOVE
+// 'em' can be modified ignoring 'const'
+void ResetExMem ( const exmem_t *em );
+void FreeExMem ( const exmem_t *em );
+void FreeExMemCM ( const exmem_t *em, CopyMode_t copy_mode ); // free on CPM_MOVE
exmem_t AllocExMemS
(
@@ -917,13 +960,17 @@ exmem_t AllocExMemS
static inline exmem_t AllocExMemM ( mem_t src, bool try_circ, mem_t orig )
{ return AllocExMemS(src.ptr,src.len,try_circ,orig.ptr,orig.len); }
-void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode );
+void AssignExMem ( exmem_t *dest, const exmem_t *source, CopyMode_t copy_mode );
+void AssignExMemS ( exmem_t *dest, cvp source, int slen, CopyMode_t copy_mode );
+
static inline exmem_t CopyExMem ( const exmem_t *source, CopyMode_t copy_mode )
{ exmem_t em = {{0}}; AssignExMem(&em,source,copy_mode); return em; }
-exmem_t CopyExMemS ( ccp string, int slen, CopyMode_t copy_mode );
+static inline exmem_t CopyExMemS ( cvp source, int slen, CopyMode_t copy_mode )
+ { exmem_t em = {{0}}; AssignExMemS(&em,source,slen,copy_mode); return em; }
+
static inline exmem_t CopyExMemM ( const mem_t source, CopyMode_t copy_mode )
- { return CopyExMemS(source.ptr,source.len,copy_mode); }
+ { exmem_t em = {{0}}; AssignExMemS(&em,source.ptr,source.len,copy_mode); return em; }
ccp PrintExMem ( const exmem_t * em ); // print to circ-buf
@@ -1176,6 +1223,39 @@ uint PurgeCircBuf ( CircBuf_t *cb );
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// PrintMode_t ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[PrintMode_t]]
+
+typedef struct PrintMode_t
+{
+ FILE *fout; // NULL (stdout) or output file
+ const ColorSet_t
+ *cout; // NULL (no colors) or color set for 'fout'
+
+ FILE *ferr; // NULL or error file
+ const ColorSet_t
+ *cerr; // NULL (no colors) or color set for 'ferr'
+
+ FILE *flog; // if NULL: use 'ferr' or 'fout' as fallback
+ const ColorSet_t
+ *clog; // NULL (no colors) or color set for 'flog'
+ // if 'flog' is copied, use related 'col*'
+
+ ccp prefix; // NULL (no prefix) or line prefix
+ ccp eol; // NULL (LF) or end-of-line string
+ int indent; // indention after prefix
+ int debug; // debug level (ignored if <=0)
+
+ int mode; // user defined print mode
+ bool compact; // TRUE: print compact (e.g. no empty lines for readability)
+}
+PrintMode_t;
+
+void SetupPrintMode ( PrintMode_t * pm );
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// split strings ///////////////
///////////////////////////////////////////////////////////////////////////////
@@ -1280,6 +1360,7 @@ extern const char Slash200[201]; // 200 * '/' + NULL
// UTF-8 => 3 bytes per char
extern const char ThinLine300_3[901]; // 300 * '─' (U+2500) + NULL
+extern const char DoubleLine300_3[901]; // 300 * '═' (U+2550) + NULL
//-----------------------------------------------------------------------------
@@ -1336,9 +1417,14 @@ char * StringCat3E ( char * buf, ccp buf_end, ccp src1, ccp src2, ccp src3 );
char * StringCat2A ( ccp src1, ccp src2 );
char * StringCat3A ( ccp src1, ccp src2, ccp src3 );
-static inline char * StringCopySMem ( char * buf, size_t bufsize, mem_t mem )
+// center string
+ccp StringCenterE ( char * buf, ccp buf_end, ccp src, int width );
+static inline ccp StringCenterS ( char *buf, size_t bufsize, ccp src, int width )
+ { return StringCenterE(buf,buf+bufsize,src,width); }
+
+static inline char * StringCopySMem ( char *buf, size_t bufsize, mem_t mem )
{ return StringCopySM(buf,bufsize,mem.ptr,mem.len); }
-static inline char * StringCopyEMem ( char * buf, ccp buf_end, mem_t mem )
+static inline char * StringCopyEMem ( char *buf, ccp buf_end, mem_t mem )
{ return StringCopyEM(buf,buf_end,mem.ptr,mem.len); }
char * StringLowerS ( char * buf, size_t bufsize, ccp src );
@@ -1357,6 +1443,12 @@ int StrNumCmp ( ccp a, ccp b );
// count the number of equal bytes and return a value of 0 to SIZE
uint CountEqual ( cvp m1, cvp m2, uint size );
+// skip ESC & well known escape sequences (until noc-escape)
+char * SkipEscapes ( ccp str );
+char * SkipEscapesE ( ccp str, ccp end );
+char * SkipEscapesS ( ccp str, int size );
+mem_t SkipEscapesM ( mem_t mem );
+
// Concatenate path + path, return pointer to buf
// Return pointer to buf or path1|path2|buf or alloced string
char *PathCatBufPP ( char *buf, size_t bufsize, ccp path1, ccp path2 );
@@ -1495,12 +1587,14 @@ char * PrintID
/////////////// circ buf ///////////////
///////////////////////////////////////////////////////////////////////////////
-#define CIRC_BUF_MAX_ALLOC 0x0400 // request limit
-#define CIRC_BUF_SIZE 0x4000 // internal buffer size
+#define CIRC_BUF_MAX_ALLOC 0x0400 // request limit
+#define CIRC_BUF_SIZE 0x4000 // internal buffer size
// returns true if 'ptr' points into circ buffer => ignored by FreeString()
bool IsCircBuf ( cvp ptr );
+//-----------------------------------------------------------------------------
+
char * GetCircBuf
(
// Never returns NULL, but always ALIGN(4)
@@ -1510,6 +1604,21 @@ char * GetCircBuf
// ==> ERROR0(ERR_OUT_OF_MEMORY)
);
+static inline wchar_t * GetCircBufW
+(
+ // Never returns NULL, but always ALIGN(4)
+
+ u32 buf_size // wanted buffer size (wchar elements),
+ // caller must add 1 for NULL-term
+ // if final buf_size > CIRC_BUF_MAX_ALLOC:
+ // ==> ERROR0(ERR_OUT_OF_MEMORY)
+)
+{
+ return (wchar_t*)GetCircBuf(buf_size*sizeof(wchar_t));
+}
+
+//-----------------------------------------------------------------------------
+
char * CopyCircBuf
(
// Never returns NULL, but always ALIGN(4)
@@ -1563,6 +1672,28 @@ void ReleaseCircBuf
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// get line by list ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+ccp GetLineByListHelper ( const int *list, ccp beg, ccp mid, ccp end, ccp line );
+
+static inline ccp GetTopLineByList ( const int *list )
+{
+ return GetLineByListHelper(list,"┌","┬","┐","─");
+}
+
+static inline ccp GetMidLineByList ( int *list )
+{
+ return GetLineByListHelper(list,"├","┼","┤","─");
+}
+
+static inline ccp GetBottomLineByList ( int *list )
+{
+ return GetLineByListHelper(list,"└","┴","┘","─");
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// struct IntMode_t ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[IntMode_t]]
@@ -1631,6 +1762,75 @@ ccp GetIntModeName ( IntMode_t mode );
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// lt/eq/gt ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[compare_operator_t]]
+
+typedef enum compare_operator_t
+{
+ COP_LT = 1,
+ COP_EQ = 2,
+ COP_GT = 4,
+
+ COP_NE = COP_LT | COP_GT,
+ COP_LE = COP_LT | COP_EQ,
+ COP_GE = COP_GT | COP_EQ,
+
+ COP_FALSE = 0,
+ COP_TRUE = COP_LT | COP_EQ | COP_GT,
+}
+__attribute__ ((packed)) compare_operator_t;
+
+//-----------------------------------------------------------------------------
+
+char * ScanCompareOp ( compare_operator_t *dest_op, ccp arg );
+ccp GetCompareOpName ( compare_operator_t op );
+
+static inline compare_operator_t NegateCompareOp ( compare_operator_t op )
+ { return op ^ COP_TRUE; }
+
+bool CompareByOpStat ( int stat, compare_operator_t op );
+bool CompareByOpINT ( int a, compare_operator_t op, int b );
+bool CompareByOpUINT ( uint a, compare_operator_t op, uint b );
+bool CompareByOpI64 ( s64 a, compare_operator_t op, s64 b );
+bool CompareByOpU64 ( u64 a, compare_operator_t op, u64 b );
+bool CompareByOpFLT ( float a, compare_operator_t op, float b );
+bool CompareByOpDBL ( double a, compare_operator_t op, double b );
+
+static inline bool CompareByOpS ( ccp a, compare_operator_t op, ccp b )
+ { return CompareByOpStat(strcmp(a,b),op); }
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// LOWER/AUTO/UPPER ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[LowerUpper_t]]
+
+typedef enum LowerUpper_t
+{
+ LOUP_ERROR = -99,
+ LOUP_LOWER = -1,
+ LOUP_AUTO = 0,
+ LOUP_UPPER = 1,
+}
+LowerUpper_t;
+
+extern const KeywordTab_t KeyTab_LOWER_AUTO_UPPER[];
+
+int ScanKeywordLowerAutoUpper
+(
+ // returns one of LOUP_*
+
+ ccp arg, // argument to scan
+ int on_empty, // return this value on empty
+ uint max_num, // >0: additionally accept+return number <= max_num
+ ccp object // NULL (silent) or object for error messages
+);
+
+ccp GetKeywordLowerAutoUpper ( LowerUpper_t value );
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// struct FastBuf_t ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[FastBuf_t]]
@@ -1682,6 +1882,7 @@ ccp GetFastBufStatus ( const FastBuf_t *fb );
int ReserveSpaceFastBuf ( FastBuf_t *fb, uint size );
char * GetSpaceFastBuf ( FastBuf_t *fb, uint size );
+// if size<0: use strlen(source) instead
uint InsertFastBuf ( FastBuf_t *fb, int index, cvp source, int size );
char * AppendFastBuf ( FastBuf_t *fb, cvp source, int size );
char * WriteFastBuf ( FastBuf_t *fb, uint offset, cvp source, int size );
@@ -1833,39 +2034,152 @@ int ScanSplitArg
//
///////////////////////////////////////////////////////////////////////////////
-/////////////// arg_manager_t ///////////////
+/////////////// PointerList_t ///////////////
///////////////////////////////////////////////////////////////////////////////
-// [[arg_manager_t]]
+// [[PointerList_t]]
-typedef struct arg_manager_t
+typedef struct PointerList_t
{
- char **argv; // list of strings
- int argc; // number of used elements in 'argv'
- uint size; // >0: 'argv' is alloced to store # elements
- // last NULL element is not counted here
+ void **list; // 0 terminated list, 1 longer than size
+ uint used; // num of used elements of 'list'
+ uint size; // num of alloced elements of 'list'
+ int grow; // list grows by 1.5*size + grow (at least by 10)
}
-arg_manager_t;
+PointerList_t;
//-----------------------------------------------------------------------------
-void ResetArgManager ( arg_manager_t *am );
-void SetupArgManager ( arg_manager_t *am, int argc, char ** argv, bool clone );
-void AttachArgManager ( arg_manager_t *am, int argc, char ** argv );
-void CloneArgManager ( arg_manager_t *am, int argc, char ** argv );
+static inline void InitializePointerMgr ( PointerList_t *pl, int grow )
+ { DASSERT(pl); memset(pl,0,sizeof(*pl)); pl->grow = grow; }
+
+void ResetPointerMgr ( PointerList_t *pl );
+
+// if n_elem<0: add until NULL pointer
+void AddToPointerMgr ( PointerList_t *pl, const void *info );
+void AddListToPointerMgr ( PointerList_t *pl, const void **list, int n_elem );
+
+// reset==true: call ResetPointerMgr() after duplicating
+void ** DupPointerMgr ( PointerList_t *pl, bool reset );
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// ArgManager_t ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[ArgManager_t]]
+
+typedef struct ArgManager_t
+{
+ LowerUpper_t force_case; // change case?
+ char **argv; // list of strings
+ int argc; // number of used elements in 'argv'
+ uint size; // >0: 'argv' is alloced to store # elements
+ // last NULL element is not counted here
+}
+ArgManager_t;
+
+//-----------------------------------------------------------------------------
-void AddSpaceArgManager ( arg_manager_t *am, int needed_space );
+void ResetArgManager ( ArgManager_t *am );
+void SetupArgManager ( ArgManager_t *am, LowerUpper_t force_case,
+ int argc, char ** argv, bool clone );
+void AttachArgManager ( ArgManager_t *am, int argc, char ** argv );
+void CloneArgManager ( ArgManager_t *am, int argc, char ** argv );
-void CopyArgManager ( arg_manager_t *dest, const arg_manager_t *src );
-void MoveArgManager ( arg_manager_t *dest, arg_manager_t *src );
+void AddSpaceArgManager ( ArgManager_t *am, int needed_space );
-void PrepareEditArgManager ( arg_manager_t *am, int needed_space );
+void CopyArgManager ( ArgManager_t *dest, const ArgManager_t *src );
+void MoveArgManager ( ArgManager_t *dest, ArgManager_t *src );
-uint AppendArgManager ( arg_manager_t *am, ccp arg1, ccp arg2, bool move_arg );
-uint InsertArgManager ( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg );
-uint ReplaceArgManager( arg_manager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg );
-uint RemoveArgManager ( arg_manager_t *am, int pos, int count );
+void PrepareEditArgManager ( ArgManager_t *am, int needed_space );
-void DumpArgManager ( FILE *f, int indent, const arg_manager_t *am, ccp title );
+// return the pos behind last insert arguments
+uint AppendArgManager ( ArgManager_t *am, ccp arg1, ccp arg2, bool move_arg );
+uint InsertArgManager ( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg );
+uint ReplaceArgManager( ArgManager_t *am, int pos, ccp arg1, ccp arg2, bool move_arg );
+
+// return the pos at removed argument
+uint RemoveArgManager ( ArgManager_t *am, int pos, int count );
+
+uint ScanSimpleArgManager ( ArgManager_t *am, ccp src );
+uint ScanQuotedArgManager ( ArgManager_t *am, ccp src, bool is_utf8 );
+
+// NULL if for both params accepted
+bool CheckFilterArgManager ( const ArgManager_t *filter, ccp name );
+
+void DumpArgManager ( FILE *f, int indent, const ArgManager_t *am, ccp title );
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// sizeof_info_t ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[sizeof_info_t]]
+
+#define SIZEOF_INFO_TITLE(t) { -1, t },
+#define SIZEOF_INFO_ENTRY(e) { sizeof(e), #e },
+#define SIZEOF_INFO_SEP() { -2, 0 },
+#define SIZEOF_INFO_TERM() { -9, 0 },
+
+typedef struct sizeof_info_t
+{
+ int size;
+ ccp name;
+}
+__attribute__ ((packed)) sizeof_info_t;
+
+//-----------------------------------------------------------------------------
+
+// basic lists
+extern const sizeof_info_t sizeof_info_linux[]; // C and Linux types
+extern const sizeof_info_t sizeof_info_dclib[]; // dcLib types
+
+// default list of lists for GCMD_Sizeof(), terminated by 0
+extern const sizeof_info_t *sizeof_info_default[];
+extern PointerList_t SizeofInfoMgr;
+
+static inline void AddDefaultToSizeofInfoMgr(void)
+ { AddListToPointerMgr(&SizeofInfoMgr,(cvpp)sizeof_info_default,-1); }
+
+static inline void AddInfoToSizeofInfoMgr ( const sizeof_info_t *info )
+ { AddToPointerMgr(&SizeofInfoMgr,info); }
+
+static inline void AddListToSizeofInfoMgr ( const sizeof_info_t **list )
+ { AddListToPointerMgr(&SizeofInfoMgr,(cvpp)list,-1); }
+
+static inline const sizeof_info_t ** GetSizeofInfoMgrList(void)
+ { return SizeofInfoMgr.used ? (const sizeof_info_t**)SizeofInfoMgr.list : 0; }
+
+///////////////////////////////////////////////////////////////////////////////
+// [[sizeof_info_order_t]]
+
+typedef enum sizeof_info_order_t
+{
+ SIZEOF_ORDER_NONE, // don't sort output, but print categories
+ SIZEOF_ORDER_NAME, // Sort the output by name (case-insensitive)
+ // and suppress output of categories.
+ SIZEOF_ORDER_SIZE, // Sort the output by size and suppress output of categories.
+}
+sizeof_info_order_t;
+
+//-----------------------------------------------------------------------------
+
+void ListSizeofInfo
+(
+ const PrintMode_t *p_pm, // NULL or print mode
+ const sizeof_info_t **si_list, // list of list of entries
+ ArgManager_t *p_filter, // NULL or filter arguments, LOUP_LOWER recommended
+ sizeof_info_order_t order // kind of order
+);
+
+static inline void ListSizeofInfoMgr
+(
+ const PrintMode_t *p_pm, // NULL or print mode
+ PointerList_t *mgr, // valid PointerList_t
+ ArgManager_t *p_filter, // NULL or filter arguments, LOUP_LOWER recommended
+ sizeof_info_order_t order // kind of order
+)
+{
+ ListSizeofInfo(p_pm,(const sizeof_info_t**)mgr->list,p_filter,order);
+}
//
///////////////////////////////////////////////////////////////////////////////
@@ -2369,7 +2683,7 @@ extern ccp TableDecode64default, TableEncode64default;
uint GetEscapedSize
(
- // returns the needed buffer size for PrintEscapedString()
+ // returns the needed buffer size for PrintEscapedString()
ccp source, // NULL or string to print
int src_len, // length of string. if -1, str is null terminated
@@ -2465,7 +2779,7 @@ uint EncodeBase64
// returns the number of scanned bytes of 'source'
char *buf, // valid destination buffer
- uint buf_size, // size of 'buf', >= 4
+ uint buf_size, // size of 'buf' >= 4
const void *source, // NULL or data to encode
int source_len, // length of 'source'; if <0: use strlen(source)
const char encode64[64+1], // encoding table; if NULL: use TableEncode64default
@@ -2496,7 +2810,7 @@ uint EncodeBase64ml // ml: multi line
// returns the number of scanned bytes of 'source'
char *buf, // valid destination buffer
- uint buf_size, // size of 'buf', >= 4
+ uint buf_size, // size of 'buf' >= 4
const void *source, // NULL or data to encode
int source_len, // length of 'source'; if <0: use strlen(source)
const char encode64[64+1], // encoding table; if NULL: use TableEncode64default
@@ -2644,7 +2958,7 @@ uint EncodeByMode
// returns the number of valid bytes in 'buf'. Result is NULL-terminated.
char *buf, // valid destination buffer
- uint buf_size, // size of 'buf', >= 4
+ uint buf_size, // size of 'buf' >= 4
ccp source, // string to encode
int slen, // length of string. if -1, str is null terminated
EncodeMode_t emode // encoding mode
@@ -2751,6 +3065,45 @@ static char * QuoteBashCircS ( ccp src, cvp if_null, CharMode_t cm )
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// struct Escape_t ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[EscapeStat_t]]
+
+typedef enum EscapeStat_t
+{
+ ESCST_NONE, // nothing scanned (data incomplete)
+ ESCST_CHAR, // single char scanned (char behind '\e')
+ ESCST_FE, // FE scanned (single byte)
+ ESCST_SS2, // SS2 scanned ('N' + single byte), code := second char
+ ESCST_SS3, // SS3 scanned ('O' + single byte) , code := second char
+ ESCST_CSI, // 'Control Sequence Introduce' based string scanned, code := final char
+ ESCST_OSC, // 'Operating System Command' based string scanned
+
+ ESCST__N
+}
+EscapeStat_t;
+
+extern const char ecape_stat_name[ESCST__N+1][5];
+
+///////////////////////////////////////////////////////////////////////////////
+// [[Escape_t]]
+
+typedef struct Escape_t
+{
+ EscapeStat_t status; // one of EscapeStat_t
+ int scanned_len; // number of scanned chars
+ u32 code; // depends on 'status', see enum EscapeStat_t
+ mem_t esc; // if status==2: pointer+len to escape string; else (0,0)
+}
+Escape_t;
+
+//-----------------------------------------------------------------------------
+
+// returns esc->status
+EscapeStat_t CheckEscape ( Escape_t *esc, cvp source, cvp end, bool check_esc );
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// scan keywords ///////////////
///////////////////////////////////////////////////////////////////////////////
@@ -2977,35 +3330,6 @@ ccp GetKeywordOffAutoOn ( OffOn_t value );
//
///////////////////////////////////////////////////////////////////////////////
-/////////////// LOWER/AUTO/UPPER ///////////////
-///////////////////////////////////////////////////////////////////////////////
-// [[LowerUpper_t]]
-
-typedef enum LowerUpper_t
-{
- LOUP_ERROR = -99,
- LOUP_LOWER = -1,
- LOUP_AUTO = 0,
- LOUP_UPPER = 1,
-}
-LowerUpper_t;
-
-extern const KeywordTab_t KeyTab_LOWER_AUTO_UPPER[];
-
-int ScanKeywordLowerAutoUpper
-(
- // returns one of LOUP_*
-
- ccp arg, // argument to scan
- int on_empty, // return this value on empty
- uint max_num, // >0: additionally accept+return number <= max_num
- ccp object // NULL (silent) or object for error messages
-);
-
-ccp GetKeywordLowerAutoUpper ( LowerUpper_t value );
-
-//
-///////////////////////////////////////////////////////////////////////////////
/////////////// scan command lists ///////////////
///////////////////////////////////////////////////////////////////////////////
//
@@ -3280,14 +3604,15 @@ unsigned long long int str2ull ( const char *nptr, char **endptr, int base );
typedef enum sizeform_mode_t
{
DC_SFORM_ALIGN = 0x01, // aligned output
- DC_SFORM_NARROW = 0x02, // suppress space between number and unit
- DC_SFORM_UNIT1 = 0x04, // limit unit to 1 character (space for bytes)
- DC_SFORM_INC = 0x08, // increment to next factor if no fraction is lost
- DC_SFORM_PLUS = 0x10, // on signed output: print PLUS sign for values >0
- DC_SFORM_DASH = 0x20, // on NULL: print only a dash (minus sign)
+ DC_SFORM_CENTER = 0x02, // aligned and centered output
+ DC_SFORM_NARROW = 0x04, // suppress space between number and unit
+ DC_SFORM_UNIT1 = 0x08, // limit unit to 1 character (space for bytes)
+ DC_SFORM_INC = 0x10, // increment to next factor if no fraction is lost
+ DC_SFORM_PLUS = 0x20, // on signed output: print PLUS sign for values >0
+ DC_SFORM_DASH = 0x40, // on NULL: print only a dash (minus sign)
- DC_SFORM__MASK = 0x3f, // mask of above
- DC_SFORM__AUTO = 0x40, // hint for some functions to decide by themself
+ DC_SFORM__MASK = 0x7f, // mask of above
+ DC_SFORM__AUTO = 0x80, // hint for some functions to decide by themself
DC_SFORM_TINY = DC_SFORM_NARROW | DC_SFORM_UNIT1,
}
@@ -3302,6 +3627,13 @@ double RoundD7bytes ( double d );
///////////////////////////////////////////////////////////////////////////////
+// Parameters:
+// char *buf, // result buffer
+// // NULL: use a local circulary static buffer
+// size_t buf_size, // size of 'buf', ignored if buf==NULL
+// * num, // number to print
+// sizeform_mode_t mode // any of DC_SFORM_ALIGN, DC_SFORM_DASH[not *D*()]
+
char * PrintNumberU4 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode );
char * PrintNumberU5 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode );
char * PrintNumberU6 ( char *buf, size_t buf_size, u64 num, sizeform_mode_t mode );
@@ -3315,13 +3647,6 @@ char * PrintNumberD5 ( char *buf, size_t buf_size, double num, sizeform_mode_t m
char * PrintNumberD6 ( char *buf, size_t buf_size, double num, sizeform_mode_t mode );
char * PrintNumberD7 ( char *buf, size_t buf_size, double num, sizeform_mode_t mode );
-// Parameters:
-// char *buf, // result buffer
-// // NULL: use a local circulary static buffer
-// size_t buf_size, // size of 'buf', ignored if buf==NULL
-// * num, // number to print
-// sizeform_mode_t mode // any of DC_SFORM_ALIGN, DC_SFORM_DASH[not *D*()]
-
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// [[size_mode_t]]
@@ -3475,6 +3800,24 @@ u64 GetSizeU64 ( ccp src, char **end, int force_base );
double GetSizeD ( ccp src, char **end, int force_base );
//-----------------------------------------------------------------------------
+// [[range_opt_t]]
+
+typedef enum range_opt_t
+{
+ RAOPT_COLON = 0x01, // allow ':' as from/to separator
+ RAOPT_MINUS = 0x02, // allow '-' as from/to separator
+ RAOPT_HASH = 0x04, // allow '#' as from/size separator
+ RAOPT_COMMA = 0x08, // allow ',' as from/size separator
+ RAOPT_NEG = 0x10, // accept negative numbers as index relative to max_value
+ RAOPT_ASSUME_0 = 0x20, // allow ':-#,' as first char and assume 0 as first value
+ RAOPT_F_FORCE = 0x40, // flag to avoid value 0 as default alias
+ RAOPT__ALL = 0x7f, // all possible bits
+
+ RAOPT__DEFAULT = RAOPT_COLON | RAOPT_HASH,
+}
+range_opt_t;
+
+//-----------------------------------------------------------------------------
char * ScanSizeRange
(
@@ -3487,7 +3830,8 @@ char * ScanSizeRange
u64 default_factor, // use this factor if number hasn't one
u64 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- double max_value // >0: max value for open ranges
+ double max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
char * ScanSizeRangeU32
@@ -3501,7 +3845,23 @@ char * ScanSizeRangeU32
u64 default_factor, // use this factor if number hasn't one
u64 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- u32 max_value // >0: max value for open ranges
+ u32 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
+);
+
+char * ScanSizeRangeS32
+(
+ int *stat, // if not NULL: store result
+ // 0:none, 1:single, 2:range
+ s32 *num1, // not NULL: store 'from' result
+ s32 *num2, // not NULL: store 'to' result
+
+ ccp source, // source text
+ u64 default_factor, // use this factor if number hasn't one
+ u64 default_factor_add, // use this factor for summands
+ int force_base, // if 1000|1024: force multiple of this
+ s32 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
char * ScanSizeRangeU64
@@ -3515,7 +3875,23 @@ char * ScanSizeRangeU64
u64 default_factor, // use this factor if number hasn't one
u64 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- u64 max_value // >0: max value for open ranges
+ u64 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
+);
+
+char * ScanSizeRangeS64
+(
+ int *stat, // if not NULL: store result
+ // 0:none, 1:single, 2:range
+ s64 *num1, // not NULL: store 'from' result
+ s64 *num2, // not NULL: store 'to' result
+
+ ccp source, // source text
+ u64 default_factor, // use this factor if number hasn't one
+ u64 default_factor_add, // use this factor for summands
+ int force_base, // if 1000|1024: force multiple of this
+ s64 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
//-----------------------------------------------------------------------------
@@ -3531,7 +3907,8 @@ char * ScanSizeRangeList
u64 default_factor, // use this factor if number hasn't one
u64 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- double max_value // >0: max value for open ranges
+ double max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
char * ScanSizeRangeListU32
@@ -3545,7 +3922,8 @@ char * ScanSizeRangeListU32
u32 default_factor, // use this factor if number hasn't one
u32 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- u32 max_value // >0: max value for open ranges
+ u32 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
char * ScanSizeRangeListU64
@@ -3559,7 +3937,8 @@ char * ScanSizeRangeListU64
u64 default_factor, // use this factor if number hasn't one
u64 default_factor_add, // use this factor for summands
int force_base, // if 1000|1024: force multiple of this
- u64 max_value // >0: max value for open ranges
+ u64 max_value, // >0: max value for open ranges
+ range_opt_t opt // options, if 0 then use RAOPT__DEFAULT
);
//-----------------------------------------------------------------------------
@@ -3610,78 +3989,49 @@ enumError ScanSizeOptU32
//
///////////////////////////////////////////////////////////////////////////////
-/////////////// Scan Duration ///////////////
-///////////////////////////////////////////////////////////////////////////////
-// [[ScanDuration_t]]
-
-typedef enum ScanDuration_t
-{
- SDUMD_SKIP_BLANKS = 0x01, // skip leading blanks
- SDUMD_ALLOW_COLON = 0x02, // allow 'H:M' and 'H:M:S'
- SDUMD_ALLOW_DIV = 0x04, // allow fraction 'n/d' as number
-
- SDUMD_ALLOW_LIST = 0x10, // allow lists like '9h12m'
- SDUMD_ALLOW_SPACE_SEP = 0x20, // lists: allow spaces as list separator
- SDUMD_ALLOW_PLUS_SEP = 0x40, // lists: allow '+' as list separator
- SDUMD_ALLOW_MINUS_SEP = 0x80, // lists: allow '-' as list separator
-
- SDUMD_M_ALL = 0xf7,
-}
-ScanDuration_t;
-
-//-----------------------------------------------------------------------------
-
-char * ScanDuration
-(
- double *num, // not NULL: store result
- ccp source, // source text
- double default_factor, // default factor if no SI unit found
- ScanDuration_t mode
-);
-
-double GetDurationFactor ( char ch );
-
-char * ScanSIFactor
-(
- // returns end of scanned string
-
- double *num, // not NULL: store result
- ccp source, // source text
- double default_factor // return this if no factor found
-);
-
-//
-///////////////////////////////////////////////////////////////////////////////
/////////////// time & timer ///////////////
///////////////////////////////////////////////////////////////////////////////
//--- conversion factors
-#define SEC_PER_MIN 60
-#define SEC_PER_HOUR 3600
-#define SEC_PER_DAY 86400
-#define SEC_PER_WEEK 604800
+#define SEC_PER_MIN 60
+#define SEC_PER_HOUR 3600
+#define SEC_PER_DAY 86400
+#define SEC_PER_WEEK 604800
+#define SEC_PER_MONTH 2629746 // 365.2425 * SEC_PER_DAY / 12
+#define SEC_PER_QUARTER 7889238 // 365.2425 * SEC_PER_DAY / 4
+#define SEC_PER_YEAR 31556952 // 365.2425 * SEC_PER_DAY
-#define MSEC_PER_SEC 1000ull
-#define MSEC_PER_MIN (60*MSEC_PER_SEC)
-#define MSEC_PER_HOUR (3600*MSEC_PER_SEC)
-#define MSEC_PER_DAY (SEC_PER_DAY*MSEC_PER_SEC)
-#define MSEC_PER_WEEK (SEC_PER_WEEK*MSEC_PER_SEC)
+#define MSEC_PER_SEC 1000ll
+#define MSEC_PER_MIN (MSEC_PER_SEC*SEC_PER_MIN)
+#define MSEC_PER_HOUR (MSEC_PER_SEC*SEC_PER_HOUR)
+#define MSEC_PER_DAY (MSEC_PER_SEC*SEC_PER_DAY)
+#define MSEC_PER_WEEK (MSEC_PER_SEC*SEC_PER_WEEK)
+#define MSEC_PER_MONTH (MSEC_PER_SEC*SEC_PER_MONTH)
+#define MSEC_PER_QUARTER (MSEC_PER_SEC*SEC_PER_QUARTER)
+#define MSEC_PER_YEAR (MSEC_PER_SEC*SEC_PER_YEAR)
-#define USEC_PER_MSEC 1000ull
-#define USEC_PER_SEC 1000000ull
-#define USEC_PER_MIN (60*USEC_PER_SEC)
-#define USEC_PER_HOUR (3600*USEC_PER_SEC)
-#define USEC_PER_DAY (SEC_PER_DAY*USEC_PER_SEC)
-#define USEC_PER_WEEK (SEC_PER_WEEK*USEC_PER_SEC)
+#define USEC_PER_MSEC 1000ll
+#define USEC_PER_SEC 1000000ll
+#define USEC_PER_MIN (USEC_PER_SEC*SEC_PER_MIN)
+#define USEC_PER_HOUR (USEC_PER_SEC*SEC_PER_HOUR)
+#define USEC_PER_DAY (USEC_PER_SEC*SEC_PER_DAY)
+#define USEC_PER_WEEK (USEC_PER_SEC*SEC_PER_WEEK)
+#define USEC_PER_MONTH (USEC_PER_SEC*SEC_PER_MONTH)
+#define USEC_PER_QUARTER (USEC_PER_SEC*SEC_PER_QUARTER)
+#define USEC_PER_YEAR (USEC_PER_SEC*SEC_PER_YEAR)
+
+#define NSEC_PER_USEC 1000ll
+#define NSEC_PER_MSEC 1000000ll
+#define NSEC_PER_SEC 1000000000ll
+#define NSEC_PER_MIN (NSEC_PER_SEC*SEC_PER_MIN)
+#define NSEC_PER_HOUR (NSEC_PER_SEC*SEC_PER_HOUR)
+#define NSEC_PER_DAY (NSEC_PER_SEC*SEC_PER_DAY)
+#define NSEC_PER_WEEK (NSEC_PER_SEC*SEC_PER_WEEK)
+#define NSEC_PER_MONTH (NSEC_PER_SEC*SEC_PER_MONTH)
+#define NSEC_PER_QUARTER (NSEC_PER_SEC*SEC_PER_QUARTER)
+#define NSEC_PER_YEAR (NSEC_PER_SEC*SEC_PER_YEAR)
-#define NSEC_PER_USEC 1000ull
-#define NSEC_PER_MSEC 1000000ull
-#define NSEC_PER_SEC 1000000000ull
-#define NSEC_PER_MIN (60*NSEC_PER_SEC)
-#define NSEC_PER_HOUR (3600*NSEC_PER_SEC)
-#define NSEC_PER_DAY (SEC_PER_DAY*NSEC_PER_SEC)
-#define NSEC_PER_WEEK (SEC_PER_WEEK*NSEC_PER_SEC)
//--- time types
@@ -3694,6 +4044,19 @@ typedef s64 s_usec_t; // signed type to store time as microseconds
typedef u64 u_nsec_t; // unsigned type to store time as nanoseconds
typedef s64 s_nsec_t; // signed type to store time as nanoseconds
+
+//--- max values time types
+
+#define S_SEC_MAX S32_MAX
+#define U_SEC_MAX U32_MAX
+#define S_MSEC_MAX S64_MAX
+#define U_MSEC_MAX U64_MAX
+#define S_USEC_MAX S64_MAX
+#define U_USEC_MAX U64_MAX
+#define S_NSEC_MAX S64_MAX
+#define U_NSEC_MAX U64_MAX
+
+//-----------------------------------------------------------------------------
// [[DayTime_t]]
typedef struct DayTime_t
{
@@ -3716,6 +4079,14 @@ extern int timezone_adjust_isdst;
///////////////////////////////////////////////////////////////////////////////
+extern ccp micro_second_char; // default = "u"
+
+static inline void SetMicroSecondChar ( bool use_micro )
+ { micro_second_char = use_micro ? "µ" : "u"; }
+
+
+///////////////////////////////////////////////////////////////////////////////
+
void SetupTimezone ( bool force );
int GetTimezoneAdjust ( time_t tim );
@@ -3727,17 +4098,55 @@ u_msec_t GetTimeMSec ( bool localtime );
u_usec_t GetTimeUSec ( bool localtime );
u_nsec_t GetTimeNSec ( bool localtime );
+struct timespec GetClockTimer(void);
+u_sec_t GetTimerSec(void);
u_msec_t GetTimerMSec(void);
u_usec_t GetTimerUSec(void);
u_nsec_t GetTimerNSec(void);
-static inline u64 double2msec ( double d ) { return d>0.0 ? (u64)trunc( 1e3*d+0.5 ) : 0; }
-static inline u64 double2usec ( double d ) { return d>0.0 ? (u64)trunc( 1e6*d+0.5 ) : 0; }
-static inline u64 double2nsec ( double d ) { return d>0.0 ? (u64)trunc( 1e9*d+0.5 ) : 0; }
+//-----------------------------------------------------------------------------
+
+static inline u_sec_t Time2TimerSec ( u_sec_t tim, bool localtime )
+ { return tim - GetTimeSec(localtime) + GetTimerSec(); }
+
+static inline u_msec_t Time2TimerMSec ( u_msec_t tim, bool localtime )
+ { return tim - GetTimeMSec(localtime) + GetTimerMSec(); }
+
+static inline u_usec_t Time2TimerUSec ( u_usec_t tim, bool localtime )
+ { return tim - GetTimeUSec(localtime) + GetTimerUSec(); }
-static inline double msec2double ( u64 num ) { return num * 1e-3; }
-static inline double usec2double ( u64 num ) { return num * 1e-6; }
-static inline double nsec2double ( u64 num ) { return num * 1e-9; }
+static inline u_nsec_t Time2TimerNSec ( u_nsec_t tim, bool localtime )
+ { return tim - GetTimeNSec(localtime) + GetTimerNSec(); }
+
+
+static inline u_sec_t Timer2TimeSec ( u_sec_t tim, bool localtime )
+ { return tim - GetTimerSec() + GetTimeSec(localtime); }
+
+static inline u_msec_t Timer2TimeMSec ( u_msec_t tim, bool localtime )
+ { return tim - GetTimerMSec() + GetTimeMSec(localtime); }
+
+static inline u_usec_t Timer2TimeUSec ( u_usec_t tim, bool localtime )
+ { return tim - GetTimerUSec() + GetTimeUSec(localtime); }
+
+static inline u_nsec_t Timer2TimeNSec ( u_nsec_t tim, bool localtime )
+ { return tim - GetTimerNSec() + GetTimeNSec(localtime); }
+
+//-----------------------------------------------------------------------------
+
+static inline u_sec_t double2sec ( double d ) { return d>0.0 ? (u_msec_t)trunc( d+0.5 ) : 0; }
+static inline u_msec_t double2msec ( double d ) { return d>0.0 ? (u_msec_t)trunc( 1e3*d+0.5 ) : 0; }
+static inline u_usec_t double2usec ( double d ) { return d>0.0 ? (u_usec_t)trunc( 1e6*d+0.5 ) : 0; }
+static inline u_nsec_t double2nsec ( double d ) { return d>0.0 ? (u_nsec_t)trunc( 1e9*d+0.5 ) : 0; }
+
+static inline s_sec_t double2ssec ( double d ) { return (s_sec_t) floor( d+0.5 ); }
+static inline s_msec_t double2smsec ( double d ) { return (s_msec_t) floor( 1e3*d+0.5 ); }
+static inline s_usec_t double2susec ( double d ) { return (s_usec_t) floor( 1e6*d+0.5 ); }
+static inline s_nsec_t double2snsec ( double d ) { return (s_nsec_t) floor( 1e9*d+0.5 ); }
+
+static inline double sec2double ( s_sec_t num ) { return num; }
+static inline double msec2double ( s_msec_t num ) { return num * 1e-3; }
+static inline double usec2double ( s_usec_t num ) { return num * 1e-6; }
+static inline double nsec2double ( s_nsec_t num ) { return num * 1e-9; }
//--- another epoch: Monday, 2001-01-01
@@ -3747,13 +4156,57 @@ static inline double nsec2double ( u64 num ) { return num * 1e-9; }
#define EPOCH_2001_NSEC (EPOCH_2001_SEC*NSEC_PER_SEC)
///////////////////////////////////////////////////////////////////////////////
+// [[CurrentTime_t]]
+
+typedef struct CurrentTime_t
+{
+ u_sec_t sec;
+ u_msec_t msec;
+ u_usec_t usec;
+}
+CurrentTime_t;
+
+//-----------------------------------------------------------------------------
+
+CurrentTime_t GetCurrentTime ( bool localtime );
+
+extern CurrentTime_t current_time;
+static inline void UpdateCurrentTime(void)
+ { current_time = GetCurrentTime(false); }
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+// PrintRefTime*() return temporary buffer by GetCircBuf(), field width 10
+// Formats:
+// ±10h: " %k:%M:%S"
+// ±12d: " %e. %k:%M"
+// *: "%F"
+
+ccp PrintRefTime
+(
+
+ u_sec_t tim, // seconds since epoch; 0 is replaced by time()
+ u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time
+ // it is used to select format
+);
+
+ccp PrintRefTimeUTC
+(
+
+ u_sec_t tim, // seconds since epoch; 0 is replaced by time()
+ u_sec_t *ref_tim // NULL or ref_tim; if *ref_tim==0: write current time
+ // it is used to select format
+);
+
+//-----------------------------------------------------------------------------
ccp PrintTimeByFormat
(
// returns temporary buffer by GetCircBuf();
ccp format, // format string for strftime()
- time_t tim // seconds since epoch; 0 is replaced by time()
+ u_sec_t tim // seconds since epoch; 0 is replaced by time()
);
ccp PrintTimeByFormatUTC
@@ -3761,7 +4214,7 @@ ccp PrintTimeByFormatUTC
// returns temporary buffer by GetCircBuf();
ccp format, // format string for strftime()
- time_t tim // seconds since epoch; 0 is replaced by time()
+ u_sec_t tim // seconds since epoch; 0 is replaced by time()
);
//-----------------------------------------------------------------------------
@@ -3786,6 +4239,24 @@ ccp PrintNSecByFormatUTC
uint nsec // nanosecond of second
);
+ccp PrintNTimeByFormat
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_nsec_t ntime
+);
+
+ccp PrintNTimeByFormatUTC
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_nsec_t ntime
+);
+
//-----------------------------------------------------------------------------
static inline ccp PrintUSecByFormat
@@ -3814,6 +4285,70 @@ static inline ccp PrintUSecByFormatUTC
return PrintNSecByFormatUTC(format,tim,usec*NSEC_PER_USEC);
}
+ccp PrintUTimeByFormat
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_usec_t utime
+);
+
+ccp PrintUTimeByFormatUTC
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_usec_t utime
+);
+
+//-----------------------------------------------------------------------------
+
+static inline ccp PrintMSecByFormat
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ time_t tim, // seconds since epoch
+ uint msec // millisecond of second
+)
+{
+ return PrintNSecByFormat(format,tim,msec*NSEC_PER_MSEC);
+}
+
+static inline ccp PrintMSecByFormatUTC
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ time_t tim, // seconds since epoch
+ uint msec // millisecond of second
+)
+{
+ return PrintNSecByFormatUTC(format,tim,msec*NSEC_PER_MSEC);
+}
+
+ccp PrintMTimeByFormat
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_msec_t mtime
+);
+
+ccp PrintMTimeByFormatUTC
+(
+ // returns temporary buffer by GetCircBuf();
+
+ ccp format, // format string for strftime()
+ // 1-9 '@' in row replaced by digits of 'usec'
+ u_msec_t mtime
+);
+
//-----------------------------------------------------------------------------
ccp PrintTimevalByFormat
@@ -3926,7 +4461,7 @@ ccp PrintTimer3 // helper function
u64 sec, // seconds to print
int usec, // 0...999999: usec fraction,
// otherwise suppress ms/us output
- bool aligned // true: print aligned 3 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
);
static inline ccp PrintTimerSec3
@@ -3935,10 +4470,10 @@ static inline ccp PrintTimerSec3
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_sec_t sec, // seconds to print
- bool aligned // true: print aligned 3 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer3(buf,buf_size,sec,-1,aligned);
+ return PrintTimer3(buf,buf_size,sec,-1,mode);
}
static inline ccp PrintTimerMSec3
@@ -3947,10 +4482,10 @@ static inline ccp PrintTimerMSec3
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_msec_t msec, // microseconds to print
- bool aligned // true: print aligned 3 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer3(buf,buf_size,msec/1000,msec%1000*1000,aligned);
+ return PrintTimer3(buf,buf_size,msec/1000,msec%1000*1000,mode);
}
static inline ccp PrintTimerUSec3
@@ -3959,10 +4494,10 @@ static inline ccp PrintTimerUSec3
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_usec_t usec, // microseconds to print
- bool aligned // true: print aligned 3 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer3(buf,buf_size,usec/1000000,usec%1000000,aligned);
+ return PrintTimer3(buf,buf_size,usec/1000000,usec%1000000,mode);
}
//-----------------------------------------------------------------------------
@@ -3975,7 +4510,7 @@ ccp PrintTimer4 // helper function
u64 sec, // seconds to print
int usec, // 0...999999: usec fraction,
// otherwise suppress ms/us output
- bool aligned // true: print aligned 4 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
);
static inline ccp PrintTimerSec4
@@ -3984,10 +4519,10 @@ static inline ccp PrintTimerSec4
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_sec_t sec, // seconds to print
- bool aligned // true: print aligned 4 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer4(buf,buf_size,sec,-1,aligned);
+ return PrintTimer4(buf,buf_size,sec,-1,mode);
}
static inline ccp PrintTimerMSec4
@@ -3996,10 +4531,10 @@ static inline ccp PrintTimerMSec4
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_msec_t msec, // microseconds to print
- bool aligned // true: print aligned 4 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer4(buf,buf_size,msec/1000,msec%1000*1000,aligned);
+ return PrintTimer4(buf,buf_size,msec/MSEC_PER_SEC,msec%MSEC_PER_SEC*USEC_PER_SEC,mode);
}
static inline ccp PrintTimerUSec4
@@ -4008,23 +4543,36 @@ static inline ccp PrintTimerUSec4
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_usec_t usec, // microseconds to print
- bool aligned // true: print aligned 4 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
+)
+{
+ return PrintTimer4(buf,buf_size,usec/USEC_PER_SEC,usec%USEC_PER_SEC,mode);
+}
+
+static inline ccp PrintTimerNSec4
+(
+ char * buf, // result buffer (>4 bytes)
+ // If NULL, a local circulary static buffer is used
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ u_nsec_t nsec, // nanoseconds to print
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_DASH
)
{
- return PrintTimer4(buf,buf_size,usec/1000000,usec%1000000,aligned);
+ const u_usec_t usec = nsec / NSEC_PER_USEC;
+ return PrintTimer4(buf,buf_size,usec/USEC_PER_SEC,usec%USEC_PER_SEC,mode);
}
//-----------------------------------------------------------------------------
-ccp PrintTimer6 // helper function
+ccp PrintTimer6N // helper function
(
char * buf, // result buffer (>6 bytes)
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u64 sec, // seconds to print
- int usec, // 0...999999: usec fraction,
- // otherwise suppress ms/us output
- bool aligned // true: print aligned 6 character output
+ int nsec, // 0...999999999: nsec fraction,
+ // otherwise suppress ms/us/ns output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH
);
static inline ccp PrintTimerSec6
@@ -4033,10 +4581,10 @@ static inline ccp PrintTimerSec6
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_sec_t sec, // seconds to print
- bool aligned // true: print aligned 6 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH
)
{
- return PrintTimer6(buf,buf_size,sec,-1,aligned);
+ return PrintTimer6N(buf,buf_size,sec,-1,mode);
}
static inline ccp PrintTimerMSec6
@@ -4045,10 +4593,11 @@ static inline ccp PrintTimerMSec6
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_msec_t msec, // microseconds to print
- bool aligned // true: print aligned 6 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH
)
{
- return PrintTimer6(buf,buf_size,msec/1000,msec%1000*1000,aligned);
+ return PrintTimer6N( buf, buf_size,
+ msec/MSEC_PER_SEC, msec%MSEC_PER_SEC*NSEC_PER_MSEC, mode );
}
static inline ccp PrintTimerUSec6
@@ -4057,10 +4606,24 @@ static inline ccp PrintTimerUSec6
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
u_usec_t usec, // microseconds to print
- bool aligned // true: print aligned 6 character output
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH
+)
+{
+ return PrintTimer6N( buf, buf_size,
+ usec/USEC_PER_SEC, usec%USEC_PER_SEC*NSEC_PER_USEC, mode );
+}
+
+static inline ccp PrintTimerNSec6
+(
+ char * buf, // result buffer (>6 bytes)
+ // If NULL, a local circulary static buffer is used
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ u_nsec_t nsec, // nanoseconds to print
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_CENTER | DC_SFORM_DASH
)
{
- return PrintTimer6(buf,buf_size,usec/1000000,usec%1000000,aligned);
+ return PrintTimer6N( buf, buf_size,
+ nsec/NSEC_PER_SEC, nsec%NSEC_PER_SEC, mode );
}
//-----------------------------------------------------------------------------
@@ -4071,19 +4634,31 @@ ccp PrintTimerUSec4s
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
s_usec_t usec, // microseconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
);
+static inline ccp PrintTimerNSec4s
+(
+ char * buf, // result buffer (>4 bytes)
+ // If NULL, a local circulary static buffer is used
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ s_nsec_t nsec, // nanoseconds to print
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
+)
+{
+ return PrintTimerUSec4s(buf,buf_size,nsec/NSEC_PER_USEC,mode);
+}
+
static inline ccp PrintTimerMSec4s
(
char * buf, // result buffer (>4 bytes)
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
s_msec_t msec, // milliseconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
)
{
- return PrintTimerUSec4s(buf,buf_size,1000*msec,mode);
+ return PrintTimerUSec4s(buf,buf_size,msec*USEC_PER_MSEC,mode);
}
static inline ccp PrintTimerSec4s
@@ -4092,7 +4667,7 @@ static inline ccp PrintTimerSec4s
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
int sec, // seconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
)
{
return PrintTimerUSec4s(buf,buf_size,1000000ll*sec,mode);
@@ -4100,13 +4675,22 @@ static inline ccp PrintTimerSec4s
//-----------------------------------------------------------------------------
+ccp PrintTimerNSec7s
+(
+ char * buf, // result buffer (>7 bytes)
+ // If NULL, a local circulary static buffer is used
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ s_nsec_t nsec, // nanoseconds to print
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
+);
+
ccp PrintTimerUSec7s
(
char * buf, // result buffer (>7 bytes)
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
s_usec_t usec, // microseconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
);
static inline ccp PrintTimerMSec7s
@@ -4115,7 +4699,7 @@ static inline ccp PrintTimerMSec7s
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
s_msec_t msec, // milliseconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
)
{
return PrintTimerUSec7s(buf,buf_size,1000*msec,mode);
@@ -4127,12 +4711,169 @@ static inline ccp PrintTimerSec7s
// If NULL, a local circulary static buffer is used
size_t buf_size, // size of 'buf', ignored if buf==NULL
int sec, // seconds to print
- sizeform_mode_t mode // support of DC_SFORM_ALIGN, DC_SFORM_PLUS
+ sizeform_mode_t mode // DC_SFORM_ALIGN | DC_SFORM_PLUS | DC_SFORM_DASH
)
{
return PrintTimerUSec7s(buf,buf_size,1000000ll*sec,mode);
}
+//-----------------------------------------------------------------------------
+
+ccp PrintAge3Sec
+(
+ u_sec_t now, // NULL or current time by GetTimeSec(false)
+ u_sec_t time // time to print
+);
+
+ccp PrintAge4Sec
+(
+ u_sec_t now, // NULL or current time by GetTimeSec(false)
+ u_sec_t time // time to print
+);
+
+ccp PrintAge6Sec
+(
+ u_sec_t now, // NULL or current time by GetTimeSec(false)
+ u_sec_t time // time to print
+);
+
+ccp PrintAge7Sec
+(
+ u_sec_t now, // NULL or current time by GetTimeSec(false)
+ u_sec_t time // time to print
+);
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// Scan Duration ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[ScanDuration_t]]
+
+typedef enum ScanDuration_t
+{
+ SDUMD_SKIP_BLANKS = 0x01, // skip leading blanks
+ SDUMD_ALLOW_COLON = 0x02, // allow 'H:M' and 'H:M:S'
+ SDUMD_ALLOW_DIV = 0x04, // allow fraction 'n/d' as number
+ SDUMD_ALLOW_CAPITALS = 0x08, // allow upper case letters
+
+ SDUMD_ALLOW_LIST = 0x10, // allow lists like '9h12m'
+ SDUMD_ALLOW_SPACE_SEP = 0x20, // lists: allow spaces as list separator
+ SDUMD_ALLOW_PLUS_SEP = 0x40, // lists: allow '+' as list separator
+ SDUMD_ALLOW_MINUS_SEP = 0x80, // lists: allow '-' as list separator
+
+ SDUMD_M_DEFAULT = 0xf7,
+ SDUMD_M_ALL = 0xff,
+}
+ScanDuration_t;
+
+//-----------------------------------------------------------------------------
+
+char * ScanDuration
+(
+ // Returns a pointer to the the first not used character.
+ // On error, it is 'source' and '*seconds' is set to 0.0.
+
+ double *seconds, // not NULL: store result (number of seconds)
+ ccp source, // source text
+ double default_factor, // default factor if no SI unit found
+ ScanDuration_t mode // flags
+);
+
+double GetDurationFactor ( char ch );
+
+char * ScanSIFactor
+(
+ // returns end of scanned string
+
+ double *num, // not NULL: store result
+ ccp source, // source text
+ double default_factor // return this if no factor found
+);
+
+//-----------------------------------------------------------------------------
+
+// simple interfaces to ScanDuration(), SDUMD_M_DEFAULT is used as mode
+double str2duration ( ccp src, char **endptr, double default_factor );
+
+
+static inline u_sec_t str2sec ( ccp src, char **endptr )
+ { return double2sec(str2duration(src,endptr,1.0)); }
+
+static inline u_msec_t str2msec ( ccp src, char **endptr )
+ { return double2msec(str2duration(src,endptr,1.0)); }
+
+static inline u_usec_t str2usec ( ccp src, char **endptr )
+ { return double2usec(str2duration(src,endptr,1.0)); }
+
+static inline u_nsec_t str2nsec ( ccp src, char **endptr )
+ { return double2nsec(str2duration(src,endptr,1.0)); }
+
+
+static inline s_sec_t str2ssec ( ccp src, char **endptr )
+ { return double2ssec(str2duration(src,endptr,1.0)); }
+
+static inline s_msec_t str2smsec ( ccp src, char **endptr )
+ { return double2smsec(str2duration(src,endptr,1.0)); }
+
+static inline s_usec_t str2susec ( ccp src, char **endptr )
+ { return double2susec(str2duration(src,endptr,1.0)); }
+
+static inline s_nsec_t str2snsec ( ccp src, char **endptr )
+ { return double2snsec(str2duration(src,endptr,1.0)); }
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// Signals & Sleep ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+extern volatile int SIGINT_level;
+extern volatile int SIGHUP_level;
+extern volatile int SIGALRM_level;
+extern volatile int SIGCHLD_level;
+extern volatile int SIGPIPE_level;
+extern volatile int SIGUSR1_level;
+extern volatile int SIGUSR2_level;
+
+// no timout for SIGPIPE
+extern u_sec_t SIGINT_sec;
+extern u_sec_t SIGHUP_sec;
+extern u_sec_t SIGALRM_sec;
+extern u_sec_t SIGCHLD_sec;
+extern u_sec_t SIGUSR1_sec;
+extern u_sec_t SIGUSR2_sec;
+
+extern int SIGINT_level_max;
+extern bool ignore_SIGINT;
+extern bool ignore_SIGHUP;
+
+extern int redirect_signal_pid;
+extern LogFile_t log_signal_file;
+
+
+extern volatile int SIGINT_level;
+extern volatile int SIGHUP_level;
+extern volatile int SIGALRM_level;
+extern volatile int SIGPIPE_level;
+
+extern int SIGINT_level_max;
+extern bool ignore_SIGINT;
+extern bool ignore_SIGHUP;
+
+void SetupSignalHandler ( int max_sigint_level, FILE *log_file );
+
+//-----------------------------------------------------------------------------
+
+int SleepNSec ( s_nsec_t nsec );
+
+static inline int SleepUSec ( s_usec_t usec )
+ { return SleepNSec( usec * NSEC_PER_USEC ); }
+
+static inline int SleepMSec ( s_msec_t msec )
+ { return SleepNSec( msec * NSEC_PER_MSEC ); }
+
+static inline int SleepSec ( s_sec_t sec )
+ { return SleepNSec( sec * NSEC_PER_SEC ); }
+
//
///////////////////////////////////////////////////////////////////////////////
/////////////// scan date & time ///////////////
@@ -4362,13 +5103,383 @@ static inline ccp year2text
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// usage counter ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if IS_DEVELOP
+ #define TEST_USAGE_COUNT 0
+ #define USAGE_COUNT_ENABLED 0
+#else
+ #define TEST_USAGE_COUNT 0
+ #define USAGE_COUNT_ENABLED 0
+#endif
+
+#if TEST_USAGE_COUNT
+ #define USAGE_COUNT_ENTRIES 11 // number of entries
+#else
+ #define USAGE_COUNT_ENTRIES 30 // number of entries
+#endif
+
+#define USAGE_COUNT_FIRST_ADD 8 // first entry where values wil be added
+#define USAGE_COUNT_NEXT_MIN(v) (15*(v)/8)
+
+//-----------------------------------------------------------------------------
+// [[UsageParam_t]]
+
+typedef struct UsageParam_t
+{
+ uint used; // number of used entries
+ bool enabled; // TRUE: statistics are enabled
+ bool is_active; // TRUE: counter is active (set by framework)
+
+ //--- not saved/restored
+
+ bool dirty; // TRUE: record needs an update @ 'update_nsec'
+ u_nsec_t update_nsec; // next update, based on GetTimerNSec()
+ u_nsec_t force_update_nsec; // force next update, based on GetTimerNSec()
+}
+UsageParam_t;
+
+//-----------------------------------------------------------------------------
+// [[UsageCountEntry_t]]
+
+typedef struct UsageCountEntry_t
+{
+ u64 count; // counter
+ u_nsec_t elapsed_nsec; // elapsed time, by GetTimerNSec()
+ u_sec_t time_sec; // time of record, by GetTimeSec(false)
+ float top1s; // = 100.0*(utime+stime)/elapsed for 1s
+ float top5s; // = 100.0*(utime+stime)/elapsed for 5s
+}
+__attribute__ ((packed)) UsageCountEntry_t;
+
+//-----------------------------------------------------------------------------
+// [[UsageCount_t]]
+
+typedef struct UsageCount_t
+{
+ UsageParam_t par; // base parameters
+ UsageCountEntry_t ref; // reference with absolute values
+ #if TEST_USAGE_COUNT
+ UsageCountEntry_t entry[USAGE_COUNT_ENTRIES+1]; // list of entries with delta values
+ #else
+ UsageCountEntry_t entry[USAGE_COUNT_ENTRIES]; // list of entries with delta values
+ #endif
+}
+UsageCount_t;
+
+//-----------------------------------------------------------------------------
+
+extern int usage_count_enabled;
+
+void EnableUsageCount(void);
+static inline void DisableUsageCount(void) { usage_count_enabled--; }
+
+//-----------------------------------------------------------------------------
+
+// n_rec<0: clear from end, n_rec>=0: clear from index
+void ClearUsageCount ( UsageCount_t *uc, int count );
+
+// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*()
+void UpdateUsageCount ( UsageCount_t *uc, u_nsec_t now_nsec );
+void UpdateUsageCountIncrement ( UsageCount_t *uc );
+void UpdateUsageCountAdd ( UsageCount_t *uc, int add );
+static inline void UsageCountIncrement ( UsageCount_t *uc )
+ { UpdateUsageCountAdd(uc,1); }
+
+// stat about last 'nsec' nanoseconds
+UsageCountEntry_t GetUsageCount ( const UsageCount_t *uc, s_nsec_t nsec );
+
+void AddUsageCountEntry ( UsageCountEntry_t *dest, const UsageCountEntry_t *add );
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// wait counter ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[UsageDurationEntry_t]]
+
+typedef struct UsageDurationEntry_t
+{
+ u_nsec_t elapsed_nsec; // elapsed time, by GetTimerNSec()
+ u_nsec_t total_nsec; // total waiting time
+ u_nsec_t top_nsec; // top waiting time
+ u64 count; // number of events
+ u_sec_t time_sec; // time of record, by GetTimeSec(false)
+ float top_cnt_1s; // top number of counts in 1 sec
+ float top_cnt_5s; // top number of counts in 5 sec
+}
+__attribute__ ((packed)) UsageDurationEntry_t;
+
+//-----------------------------------------------------------------------------
+// [[UsageDuration_t]]
+
+typedef struct UsageDuration_t
+{
+ UsageParam_t par; // base parameters
+ UsageDurationEntry_t ref; // reference with absolute values
+ #if TEST_USAGE_COUNT
+ UsageDurationEntry_t entry[USAGE_COUNT_ENTRIES+1]; // list of entries with delta values
+ #else
+ UsageDurationEntry_t entry[USAGE_COUNT_ENTRIES]; // list of entries with delta values
+ #endif
+}
+UsageDuration_t;
+
+//-----------------------------------------------------------------------------
+
+// n_rec<0: clear from end, n_rec>=0: clear from index
+void ClearUsageDuration ( UsageDuration_t *ud, int count );
+
+// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*()
+void UpdateUsageDuration ( UsageDuration_t *ud, u_nsec_t now_nsec );
+void UpdateUsageDurationAdd ( UsageDuration_t *ud, int add, u_nsec_t wait_nsec, u_nsec_t top_nsec );
+void UpdateUsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec );
+void UsageDurationIncrement ( UsageDuration_t *ud, u_nsec_t wait_nsec );
+
+// stat about last 'nsec' nanoseconds
+UsageDurationEntry_t GetUsageDuration ( const UsageDuration_t *ud, s_nsec_t nsec );
+
+void AddUsageDurationEntry ( UsageDurationEntry_t *dest, const UsageDurationEntry_t *add );
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// usage counter mgr ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[ListUsageFunc]]
+
+typedef struct UsageCtrl_t UsageCtrl_t;
+
+enum
+{
+ LUC_PM_STANDARD, // standard view
+ LUC_PM_RAW, // raw values, not supported by ListUsageCount()
+ LUC_PM_SUMMARY, // summary
+ LUC_PM__USER // base value for user defined modes
+};
+
+typedef void (*ListUsageFunc)
+(
+ PrintMode_t *pm, // valid print mode
+ const UsageCtrl_t *uci, // valid object to list
+ int print_mode, // see LUC_PM_*
+ s_nsec_t limit_nsec // >0: limit output until # is reached
+);
+
+//-----------------------------------------------------------------------------
+
+typedef void (*UpdateUsageFunc)
+(
+ const UsageCtrl_t *uci, // valid object to update
+ u_nsec_t now_usec // NULL or current time by GetTimerNSec()
+);
+
+//-----------------------------------------------------------------------------
+// [[UsageCtrl_t]]
+
+typedef struct UsageCtrl_t
+{
+ UsageParam_t *par; // higher prioritiy than uc->par and ud->par
+ UsageCount_t *uc; // not NULL for usage counters
+ UsageDuration_t *ud; // not NULL for wait counters
+
+ UpdateUsageFunc update_func; // not NULL: Call this function to update
+ ListUsageFunc list_func; // not NULL: Call this function to list
+
+ ccp title; // NULL or title
+ ccp key1; // first key, upper case
+ ccp key2; // NULL or second key, upper case
+
+ ccp srt_load; // NULL or prefix vor SRT reading to allow prefix changes
+ ccp srt_prefix; // NULL prefix or SRT reading + writing
+ // If NULL: don't save/restore
+ // 'srt_load' is scanned before 'srt_prefix'
+
+ float *color_val; // 6 values for mark,info,gint,warn,err,bad
+ // if NULL then use system list
+ u_nsec_t *color_dur; // 6 values for mark,info,gint,warn,err,bad
+ // if NULL then use system list
+}
+UsageCtrl_t;
+
+//-----------------------------------------------------------------------------
+
+extern PointerList_t usage_count_mgr;
+
+// NOW_NSEC: 0 or GetTimerNSec(), but not GetTime*()
+u_nsec_t MaintainUsageByMgr ( u_nsec_t now_nsec );
+void UpdateByUCI ( const UsageCtrl_t *uci, u_nsec_t now_nsec );
+void UpdateUsageByMgr ( u_nsec_t now_nsec );
+void AddToUsageMgr ( const UsageCtrl_t *uci );
+
+void ListUsageCount
+(
+ PrintMode_t *p_pm, // NULL or print mode
+ const UsageCtrl_t *uci, // NULL or object to list
+ int print_mode, // see LUC_PM_*
+ s_nsec_t limit_nsec // >0: limit output until # is reached
+);
+
+void ListUsageDuration
+(
+ PrintMode_t *p_pm, // NULL or print mode
+ const UsageCtrl_t *uci, // NULL or object to list
+ int print_mode, // see LUC_PM_*
+ s_nsec_t limit_nsec // >0: limit output until # is reached
+);
+
+static inline UsageParam_t * GetUsageParam ( const UsageCtrl_t *uci )
+ { DASSERT(uci); return uci->par ? uci->par : uci->uc ? &uci->uc->par : uci->ud ? &uci->ud->par : 0; }
+
+static inline char GetUsageTypeChar ( const UsageCtrl_t *uci )
+ { return !uci ? '-' : uci->uc ? 'C' : uci->ud ? 'D' : uci->par ? 'x' : '?'; }
+
+void SaveCurrentStateByUsageCountMgr ( FILE *f, uint fw_name );
+void RestoreStateByUsageCountMgr ( RestoreState_t *rs );
+
+///////////////////////////////////////////////////////////////////////////////
+// [[IntervalInfo_t]]
+
+typedef struct IntervalInfo_t
+{
+ u_nsec_t nsec;
+ u_usec_t usec;
+ ccp name;
+}
+IntervalInfo_t;
+
+extern const IntervalInfo_t interval_info[];
+
+//
+///////////////////////////////////////////////////////////////////////////////
+/////////////// cpu usage ///////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#if TEST_USAGE_COUNT
+ #define CPU_USAGE_ENTRIES 11 // number of entries
+#else
+ #define CPU_USAGE_ENTRIES 30 // number of entries
+#endif
+
+#if IS_DEVELOP
+ #define CPU_USAGE_ENABLED 0 // initial value for cpu_usage.par.enabled
+#else
+ #define CPU_USAGE_ENABLED 0 // initial value for cpu_usage.par.enabled
+#endif
+
+#define CPU_USAGE_FIRST_ADD 8 // first entry where values wil be added
+#define CPU_USAGE_NEXT_MIN(v) (15*(v)/8)
+
+//-----------------------------------------------------------------------------
+// [[CpuUsageEntry_t]]
+
+typedef struct CpuUsageEntry_t
+{
+ u_usec_t elapsed_usec; // elapsed time, by GetTimerUSec()
+ u_usec_t utime_usec; // user CPU time used
+ u_usec_t stime_usec; // system CPU time used
+ u_sec_t time_sec; // time of record, by GetTimeUSec(false)
+ float top1s; // = 100.0*(utime+stime)/elapsed for 1s
+ float top5s; // = 100.0*(utime+stime)/elapsed for 5s
+ u32 n_wait; // number of waits (poll() or select())
+ float topw1s; // top number of waits in 1 sec
+ float topw5s; // top number of waits in 5 sec
+}
+__attribute__ ((packed)) CpuUsageEntry_t;
+
+//-----------------------------------------------------------------------------
+// [[CpuUsage_t]]
+
+typedef struct CpuUsage_t
+{
+ UsageParam_t par; // base parameters
+ CpuUsageEntry_t ref; // reference with absolute values
+ #if TEST_USAGE_COUNT
+ CpuUsageEntry_t entry[CPU_USAGE_ENTRIES+1]; // list of entries with delta values
+ #else
+ CpuUsageEntry_t entry[CPU_USAGE_ENTRIES]; // list of entries with delta values
+ #endif
+}
+CpuUsage_t;
+
+//-----------------------------------------------------------------------------
+
+extern CpuUsage_t cpu_usage;
+extern const UsageCtrl_t cpu_usage_ctrl;
+
+void UpdateCpuUsage(void);
+void UpdateCpuUsageByUCI ( const UsageCtrl_t *, u_nsec_t ); // both params ignored
+void UpdateCpuUsageIncrement(void);
+
+void ListCpuUsage
+(
+ PrintMode_t *p_pm, // NULL or print mode
+ const UsageCtrl_t *uci, // ignored!
+ int print_mode, // see LUC_PM_*
+ s_nsec_t limit_nsec // >0: limit output until # is reached
+);
+
+// stat about last 'usec' microseconds
+CpuUsageEntry_t GetCpuUsage ( s_usec_t usec );
+uint GetCpuUsagePercent ( s_usec_t usec );
+
+void AddCpuEntry ( CpuUsageEntry_t *dest, const CpuUsageEntry_t *add );
+
+static inline uint GetCpuEntryPercent ( const CpuUsageEntry_t *entry )
+{
+ DASSERT(entry);
+ return entry->elapsed_usec
+ ? 100 * ( entry->utime_usec + entry->stime_usec + entry->elapsed_usec/200 )
+ / entry->elapsed_usec
+ : 0;
+}
+
+static inline double GetCpuEntryRatio ( const CpuUsageEntry_t *entry )
+{
+ DASSERT(entry);
+ return entry->elapsed_usec
+ ? (double)(entry->utime_usec + entry->stime_usec ) / entry->elapsed_usec
+ : 0.0;
+}
+
+//-----------------------------------------------------------------------------
+
+// get percent, returns previuis valus if delay is <10ms
+double get_rusage_percent (void);
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// sockaddr support ///////////////
///////////////////////////////////////////////////////////////////////////////
-// [[sockaddr_t]] [[sockaddr_in_t]] [[sockaddr_un_t]] [[sockaddr_info_t]]
+// [[sockaddr_in46_t]]
+
+typedef struct sockaddr_in46_t
+{
+ union
+ {
+ sa_family_t family; // is first member of each sockaddr_* structure
+ sockaddr_in4_t in4;
+ sockaddr_in6_t in6;
+ };
+}
+sockaddr_in46_t;
+
+//-----------------------------------------------------------------------------
+// [[sockaddr_dclib_t]]
+
+typedef struct sockaddr_dclib_t
+{
+ union
+ {
+ sa_family_t family; // is first member of each sockaddr_* structure
+ sockaddr_in4_t in4;
+ sockaddr_in6_t in6;
+ sockaddr_un_t un;
+ };
+}
+sockaddr_dclib_t;
-typedef struct sockaddr sockaddr_t;
-typedef struct sockaddr_in sockaddr_in_t;
-typedef struct sockaddr_un sockaddr_un_t;
+//-----------------------------------------------------------------------------
+// [[sockaddr_info_t]]
typedef struct sockaddr_info_t
{
@@ -4377,7 +5488,7 @@ typedef struct sockaddr_info_t
}
sockaddr_info_t;
-//-----------------------------------------------------------------------------
+///////////////////////////////////////////////////////////////////////////////
// [[doxygen]]
static inline sockaddr_info_t CreateSockaddrInfo ( cvp sa, uint size )
@@ -4402,24 +5513,95 @@ static inline void SetupSockaddrInfo ( sockaddr_info_t *sai, cvp sa, uint size )
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// ScanIP4 ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[ipv4_class_t]]
+
+typedef enum ipv4_class_t
+{
+ CIP4_ERROR = -1, // error
+ CIP4_INVALID = 0, // not an IPv4
+ CIP4_NUMERIC, // 32 bit number only
+ CIP4_ABBREV, // abbreviated IPv4 (trailing point)
+ CIP4_CLASS_A, // IPv4 in class-A notation
+ CIP4_CLASS_B, // IPv4 in class-B notation
+ CIP4_CLASS_C, // IPv4 in class-C notation
+}
+ipv4_class_t;
+
+//-----------------------------------------------------------------------------
+
+ipv4_class_t ScanIP4
+(
+ ipv4_t *ret_ip4, // not NULL: return numeric IPv4 here
+ ccp addr, // address to analyze
+ int addr_len // length of addr; if <0: use strlen(addr)
+);
+
+//-----------------------------------------------------------------------------
+
+char * NormalizeIP4
+(
+ // Return a pointer to dest if valid IPv4,
+ // Otherwise return 0 and buf is not modifieid.
+
+ char *buf, // result buffer, can be 'addr'
+ // if NULL: use a local circulary static buffer
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ bool c_notation, // TRUE: force lass-C notation (a.b.c.d)
+
+ ccp addr, // address to analyze
+ int addr_len // length of addr; if <0: use strlen(addr)
+);
+
+//-----------------------------------------------------------------------------
+
+static inline ipv4_class_t CheckIP4
+(
+ ccp addr, // address to analyze
+ int addr_len // length of addr; if <0: use strlen(addr)
+)
+{
+ return ScanIP4(0,addr,addr_len);
+}
+
+//-----------------------------------------------------------------------------
+
+int dclib_aton ( ccp addr, struct in_addr *inp );
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// PrintIP4*() ///////////////
///////////////////////////////////////////////////////////////////////////////
+#define FW_IPV4_N 10 // 4294967295
#define FW_IPV4_A 12 // 255.16777215
#define FW_IPV4_B 13 // 255.255.65535
#define FW_IPV4_C 15 // 255.255.255.255
#define FW_IPV4_PORT 5 // 65535
+#define FW_IPV4_N_PORT (FW_IPV4_N+1+FW_IPV4_PORT)
#define FW_IPV4_A_PORT (FW_IPV4_A+1+FW_IPV4_PORT)
#define FW_IPV4_B_PORT (FW_IPV4_B+1+FW_IPV4_PORT)
#define FW_IPV4_C_PORT (FW_IPV4_C+1+FW_IPV4_PORT)
//-----------------------------------------------------------------------------
+char * PrintIP4N
+(
+ // print as unsigned number (CIP4_NUMERIC)
+
+ char *buf, // result buffer
+ // NULL: use a local circulary static buffer
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ u32 ip4, // IP4 to print
+ s32 port // 0..0xffff: add ':port'
+);
+
char * PrintIP4A
(
- // print in A-notation
+ // print in A-notation (CIP4_CLASS_A)
char *buf, // result buffer
// NULL: use a local circulary static buffer
@@ -4430,7 +5612,7 @@ char * PrintIP4A
char * PrintIP4B
(
- // print in A-notation
+ // print in B-notation (CIP4_CLASS_B)
char *buf, // result buffer
// NULL: use a local circulary static buffer
@@ -4480,6 +5662,20 @@ char * PrintAlignedIP4
);
//-----------------------------------------------------------------------------
+// print by enum ipv4_class_t
+
+char * PrintIP4ByMode
+(
+ char *buf, // result buffer
+ // NULL: use a local circulary static buffer
+ size_t buf_size, // size of 'buf', ignored if buf==NULL
+ u32 ip4, // IP4 to print
+ ipv4_class_t mode, // CIP4_NUMERIC | CIP4_CLASS_A | CIP4_CLASS_B:
+ // force numeric or class-A/B output; otherwise class-C output
+ s32 port // 0..0xffff: add ':port'
+);
+
+//-----------------------------------------------------------------------------
struct sockaddr_in;
static inline char * PrintIP4sa
@@ -4491,9 +5687,10 @@ static inline char * PrintIP4sa
const struct sockaddr_in *sa // socket address
)
{
- DASSERT(sa);
- return PrintIP4(buf,buf_size,
- ntohl(sa->sin_addr.s_addr), ntohs(sa->sin_port) );
+ return sa
+ ? PrintIP4(buf,buf_size,
+ ntohl(sa->sin_addr.s_addr), ntohs(sa->sin_port) )
+ : "-";
}
static inline char * PrintRightIP4sa
@@ -4790,7 +5987,8 @@ exmem_key_t * AppendEML ( exmem_list_t * eml, ccp key, CopyMode_t cm_key,
const exmem_t *data, CopyMode_t cm_data );
// Return true if item found and removed
-bool RemoveEML ( exmem_list_t * eml, ccp key );
+bool RemoveByIndexEML ( exmem_list_t * eml, int index );
+bool RemoveByKeyEML ( exmem_list_t * eml, ccp key );
// find first pattern that matches
@@ -4808,6 +6006,55 @@ void AddStandardSymbolsEML ( exmem_list_t * eml, bool overwrite );
//
///////////////////////////////////////////////////////////////////////////////
+/////////////// MultiColumn ///////////////
+///////////////////////////////////////////////////////////////////////////////
+// [[MultiColumn_t]]
+
+typedef struct MultiColumn_t
+{
+ FILE *f; // NULL or output file
+ const ColorSet_t
+ *colset; // NULL or color set for the frame
+ ccp prefix; // NULL or line prefix
+ int indent; // indention after prefix
+ ccp sep; // NULL or separator for frame_mode 0 and 1
+ ccp eol; // NULL or end-of-line string
+
+ int fw; // max field width
+ int min_rows; // minimal number of rows before MC
+ int max_cols; // >0: maximal number columns
+
+ int frame_mode; // 0:ASCII, 1:single line, 2:double line
+ bool print_header; // TRUE: print column header
+ bool print_footer; // TRUE: print footer line
+
+ ccp head_key; // NULL or name of key column, default="Name"
+ ccp head_val; // NULL or name of value column, default="Value"
+
+ int debug; // >0: print basic debug info
+ // >1: be verbose
+
+ exmem_list_t list; // list of parameters to print
+}
+MultiColumn_t;
+
+//-----------------------------------------------------------------------------
+
+void ResetMultiColumn ( MultiColumn_t *mc );
+
+// return the number of printed lines including header and footer, or -1 on error
+int PrintMultiColumn ( const MultiColumn_t *mc );
+
+// Wrapper for short definition lines
+// opt == 0 align right value
+// opt >= 1 align left and try field width of # for value
+
+exmem_key_t * PutLineMC ( MultiColumn_t *mc, uint opt, ccp key, ccp value, CopyMode_t cm_value );
+exmem_key_t * PrintLineMC ( MultiColumn_t *mc, uint opt, ccp key, ccp format, ... )
+ __attribute__ ((__format__(__printf__,4,5)));
+
+//
+///////////////////////////////////////////////////////////////////////////////
/////////////// Memory Map ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[MemMapItem_t]]
@@ -5122,6 +6369,7 @@ uint DropDataBuf
///////////////////////////////////////////////////////////////////////////////
/////////////// ResizeElement_t, ResizeHelper_t ///////////////
///////////////////////////////////////////////////////////////////////////////
+// [[ResizeElement_t]]
typedef struct ResizeElement_t
{
@@ -5131,6 +6379,7 @@ typedef struct ResizeElement_t
ResizeElement_t;
//-----------------------------------------------------------------------------
+// [[ResizeHelper_t]]
typedef struct ResizeHelper_t
{
@@ -5393,6 +6642,11 @@ typedef enum SaveRestoreType_t
SRT_DEF_ARRAY, // define/end an array of structs
+ SRT_MODE__BEGIN, //--- begin of modes
+ SRT_MODE_ASSIGN, // load option: assign numeric values (default)
+ SRT_MODE_ADD, // load option: add numeric values
+ SRT_MODE__END, //--- end of modes
+
SRT__IS_LIST, //----- from here: print lists; also used as separator
SRT_STRING_FIELD, // var is StringField_t
@@ -5411,10 +6665,18 @@ typedef struct SaveRestoreTab_t
uint offset; // offset of variable
uint size; // sizeof( var or string )
ccp name; // name in configuration file
- s16 n_elem; // >0: is array with N elements
- // <0: is array with -N elements, use last SRT_COUNT
- u8 type; // SaveRestoreType_t
- u8 emode; // EncodeMode_t
+
+ union
+ {
+ struct
+ {
+ s16 n_elem; // >0: is array with N elements
+ // <0: is array with -N elements, use last SRT_COUNT
+ u8 type; // SaveRestoreType_t
+ u8 emode; // EncodeMode_t
+ };
+ //struct SaveRestoreTab_t *ref;
+ };
}
__attribute__ ((packed)) SaveRestoreTab_t;
@@ -5424,7 +6686,8 @@ __attribute__ ((packed)) SaveRestoreTab_t;
// #undef SRT_NAME
// #define SRT_NAME name_of_the_struct
-#define DEF_SRT_VAR(v,ne,n,t,e) {offsetof(SRT_NAME,v),sizeof(((SRT_NAME*)0)->v),n,ne,t,e}
+#define DEF_SRT_VAR(v,ne,n,t,e) {offsetof(SRT_NAME,v),sizeof(((SRT_NAME*)0)->v),n, \
+ .n_elem=ne,.type=t,.emode=e}
#define DEF_SRT_BOOL(v,n) DEF_SRT_VAR(v,1,n,SRT_BOOL,0)
#define DEF_SRT_UINT(v,n) DEF_SRT_VAR(v,1,n,SRT_UINT,0)
@@ -5458,7 +6721,7 @@ __attribute__ ((packed)) SaveRestoreTab_t;
#define DEF_SRT_ARRAY(v,n,t,e) \
{offsetof(SRT_NAME,v), sizeof(((SRT_NAME*)0)->v[0]), n, \
- sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v), t, e }
+ .n_elem=sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v), .type=t, .emode=e }
#define DEF_SRT_BOOL_A(v,n) DEF_SRT_ARRAY(v,n,SRT_BOOL,0)
#define DEF_SRT_UINT_A(v,n) DEF_SRT_ARRAY(v,n,SRT_UINT,0)
@@ -5475,7 +6738,7 @@ __attribute__ ((packed)) SaveRestoreTab_t;
#define DEF_SRT_ARRAY_C(v,n,t,e) \
{offsetof(SRT_NAME,v), sizeof(((SRT_NAME*)0)->v[0]), n, \
- -(s16)(sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v)), t, e }
+ .n_elem=-(s16)(sizeof(((SRT_NAME*)0)->v)/sizeof(*((SRT_NAME*)0)->v)), .type=t, .emode=e }
#define DEF_SRT_BOOL_AC(v,n) DEF_SRT_ARRAY_C(v,n,SRT_BOOL,0)
#define DEF_SRT_UINT_AC(v,n) DEF_SRT_ARRAY_C(v,n,SRT_UINT,0)
@@ -5492,29 +6755,34 @@ __attribute__ ((packed)) SaveRestoreTab_t;
#define DEF_SRT_ARRAY_FL(f,l) \
{offsetof(SRT_NAME,f), sizeof(((SRT_NAME*)0)->f), 0, \
- (offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f))/sizeof(((SRT_NAME*)0)->f)+1, \
- SRT_DEF_ARRAY, 0 }
+ .n_elem=(offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f))/sizeof(((SRT_NAME*)0)->f)+1, \
+ .type=SRT_DEF_ARRAY }
#define DEF_SRT_ARRAY_FLC(f,l) \
{offsetof(SRT_NAME,f), sizeof(((SRT_NAME*)0)->f), 0, \
- -(s16)((offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f)) \
- /sizeof(((SRT_NAME*)0)->f)+1), SRT_DEF_ARRAY, 0 }
+ .n_elem=-(s16)((offsetof(SRT_NAME,l)-offsetof(SRT_NAME,f)) \
+ /sizeof(((SRT_NAME*)0)->f)+1), .type=SRT_DEF_ARRAY }
#define DEF_SRT_ARRAY_N(v,ne) DEF_SRT_VAR(v[0],ne,0,SRT_DEF_ARRAY,0)
#define DEF_SRT_ARRAY_A(v) DEF_SRT_ARRAY(v,0,SRT_DEF_ARRAY,0)
#define DEF_SRT_ARRAY_AC(v) DEF_SRT_ARRAY_C(v,0,SRT_DEF_ARRAY,0)
-#define DEF_SRT_ARRAY_END() {0,0,0,0,SRT_DEF_ARRAY,0}
+#define DEF_SRT_ARRAY_END() {0,0,0,.type=SRT_DEF_ARRAY}
//--- global array of structs
-#define DEF_SRT_ARRAY_GN(ne) {0,sizeof(SRT_NAME),0,ne,SRT_DEF_ARRAY,0}
-#define DEF_SRT_ARRAY_GA(v) {0,sizeof(*v),0,sizeof(v)/sizeof(*v),SRT_DEF_ARRAY,0}
+#define DEF_SRT_ARRAY_GN(ne) {0,sizeof(SRT_NAME),0,.n_elem=ne,.type=SRT_DEF_ARRAY}
+#define DEF_SRT_ARRAY_GA(v) {0,sizeof(*v),0,.n_elem=sizeof(v)/sizeof(*v),.type=SRT_DEF_ARRAY}
+
+//--- modes
+
+#define DEF_SRT_MODE_ASSIGN() {0,0,0,.type=SRT_MODE_ASSIGN}
+#define DEF_SRT_MODE_ADD() {0,0,0,.type=SRT_MODE_ADD}
//--- special
-#define DEF_SRT_SEPARATOR() {0,0,0,0,SRT__IS_LIST,0}
-#define DEF_SRT_COMMENT(c) {0,0,c,0,SRT__IS_LIST,0}
-#define DEF_SRT_TERM() {0,0,0,0,SRT__TERM,0}
+#define DEF_SRT_SEPARATOR() {0,0,0,.type=SRT__IS_LIST}
+#define DEF_SRT_COMMENT(c) {0,0,c,.type=SRT__IS_LIST}
+#define DEF_SRT_TERM() {0,0,0,.type=SRT__TERM}
///////////////////////////////////////////////////////////////////////////////
@@ -5549,6 +6817,13 @@ void RestoreStateByTable
ccp prefix // NULL or prefix for names
);
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+extern const SaveRestoreTab_t SRT_UsageCount[];
+extern const SaveRestoreTab_t SRT_UsageDuration[];
+extern const SaveRestoreTab_t SRT_CpuUsage[];
+
//
///////////////////////////////////////////////////////////////////////////////
/////////////// GrowBuffer_t ///////////////
@@ -5811,11 +7086,13 @@ extern int opt_new; // default 0
float double2float ( double d ); // reduce precision
uint CreateUniqueIdN ( int range );
-static inline uint CreateUniqueId() { return CreateUniqueIdN(1); }
-static inline uint CreateUniqueIdNBO() { return htonl(CreateUniqueIdN(1)); }
+static inline uint CreateUniqueId(void) { return CreateUniqueIdN(1); }
+static inline uint CreateUniqueIdNBO(void) { return htonl(CreateUniqueIdN(1)); }
void Sha1Hex2Bin ( sha1_hash_t bin, ccp src, ccp end );
void Sha1Bin2Hex ( sha1_hex_t hex, cvp bin );
+
+// return CircBuf()
ccp GetSha1Hex ( cvp bin );
///////////////////////////////////////////////////////////////////////////////