mirror of
https://git.sr.ht/~calebccff/pbsplash
synced 2026-01-12 12:38:41 -09:00
add timespec lib, decouple animation from frambuffer rate
This commit is contained in:
parent
4a98f0a0cf
commit
3c96de11dd
7 changed files with 1099 additions and 129 deletions
125
.clang-format
125
.clang-format
|
|
@ -1,119 +1,10 @@
|
||||||
#
|
BasedOnStyle: LLVM
|
||||||
# clang-format configuration file.
|
|
||||||
#
|
|
||||||
# For more information, see:
|
|
||||||
#
|
|
||||||
# Documentation/process/clang-format.rst
|
|
||||||
# https://clang.llvm.org/docs/ClangFormat.html
|
|
||||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
|
||||||
#
|
|
||||||
# Copied from Linux @ 5.18.0
|
|
||||||
---
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
AlignAfterOpenBracket: Align
|
|
||||||
AlignConsecutiveAssignments: false
|
|
||||||
AlignConsecutiveDeclarations: false
|
|
||||||
AlignConsecutiveMacros: AcrossEmptyLines
|
|
||||||
#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
|
||||||
AlignOperands: true
|
|
||||||
AlignTrailingComments: false
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
|
||||||
AllowShortBlocksOnASingleLine: false
|
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: None
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
|
||||||
AlwaysBreakTemplateDeclarations: false
|
|
||||||
BinPackArguments: true
|
|
||||||
BinPackParameters: true
|
|
||||||
BraceWrapping:
|
|
||||||
AfterClass: false
|
|
||||||
AfterControlStatement: false
|
|
||||||
AfterEnum: false
|
|
||||||
AfterFunction: true
|
|
||||||
AfterNamespace: true
|
|
||||||
AfterObjCDeclaration: false
|
|
||||||
AfterStruct: false
|
|
||||||
AfterUnion: false
|
|
||||||
#AfterExternBlock: false # Unknown to clang-format-5.0
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
IndentBraces: false
|
|
||||||
#SplitEmptyFunction: true # Unknown to clang-format-4.0
|
|
||||||
#SplitEmptyRecord: true # Unknown to clang-format-4.0
|
|
||||||
#SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
|
||||||
BreakBeforeTernaryOperators: false
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakStringLiterals: false
|
|
||||||
ColumnLimit: 80
|
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
|
||||||
#CompactNamespaces: false # Unknown to clang-format-4.0
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ConstructorInitializerIndentWidth: 8
|
|
||||||
ContinuationIndentWidth: 8
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
DisableFormat: false
|
|
||||||
ExperimentalAutoDetectBinPacking: false
|
|
||||||
#FixNamespaceComments: false # Unknown to clang-format-4.0
|
|
||||||
|
|
||||||
IncludeBlocks: Preserve
|
|
||||||
IncludeCategories:
|
|
||||||
- Regex: '.*'
|
|
||||||
Priority: 1
|
|
||||||
IncludeIsMainRegex: '(Test)?$'
|
|
||||||
IndentCaseLabels: false
|
|
||||||
#IndentPPDirectives: None # Unknown to clang-format-5.0
|
|
||||||
IndentWidth: 8
|
IndentWidth: 8
|
||||||
IndentWrappedFunctionNames: false
|
|
||||||
JavaScriptQuotes: Leave
|
|
||||||
JavaScriptWrapImports: true
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
MacroBlockBegin: ''
|
|
||||||
MacroBlockEnd: ''
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
NamespaceIndentation: None
|
|
||||||
#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
|
||||||
ObjCBlockIndentWidth: 8
|
|
||||||
ObjCSpaceAfterProperty: true
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
|
|
||||||
# Taken from git's rules
|
|
||||||
#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 30
|
|
||||||
PenaltyBreakComment: 10
|
|
||||||
PenaltyBreakFirstLessLess: 0
|
|
||||||
PenaltyBreakString: 10
|
|
||||||
PenaltyExcessCharacter: 100
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
|
|
||||||
PointerAlignment: Right
|
|
||||||
ReflowComments: false
|
|
||||||
SortIncludes: false
|
|
||||||
#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceAfterTemplateKeyword: true
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
|
||||||
#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
|
||||||
SpaceBeforeParens: ControlStatements
|
|
||||||
#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Standard: Cpp03
|
|
||||||
TabWidth: 8
|
|
||||||
UseTab: Always
|
UseTab: Always
|
||||||
...
|
BreakBeforeBraces: Linux
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: true
|
||||||
|
AcrossEmptyLines: true
|
||||||
|
AcrossComments: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
|
@ -1420,7 +1420,8 @@ void nsvgRasterizeText(NSVGrasterizer* r,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i == 0 && strcmp(shape->id, "OpenSansRegular") == 0)
|
if (i == 0 && strcmp(shape->id, "OpenSansRegular") == 0)
|
||||||
tx -= shape->horizAdvX * scale;
|
tx = xStart - charWidth;
|
||||||
|
//tx -= shape->horizAdvX * scale * 0.5;
|
||||||
|
|
||||||
if (shape->fill.type != NSVG_PAINT_NONE) {
|
if (shape->fill.type != NSVG_PAINT_NONE) {
|
||||||
nsvg__resetPool(r);
|
nsvg__resetPool(r);
|
||||||
|
|
|
||||||
73
include/timespec.h
Normal file
73
include/timespec.h
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* Functions for working with timespec structures
|
||||||
|
* Written by Daniel Collins (2017-2021)
|
||||||
|
* timespec_mod by Alex Forencich (2019)
|
||||||
|
* Various contributions by Ingo Albrecht (2021)
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
* distribute this software, either in source code form or as a compiled
|
||||||
|
* binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
* means.
|
||||||
|
*
|
||||||
|
* In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
* of this software dedicate any and all copyright interest in the
|
||||||
|
* software to the public domain. We make this dedication for the benefit
|
||||||
|
* of the public at large and to the detriment of our heirs and
|
||||||
|
* successors. We intend this dedication to be an overt act of
|
||||||
|
* relinquishment in perpetuity of all present and future rights to this
|
||||||
|
* software under copyright law.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DAN_TIMESPEC_H
|
||||||
|
#define DAN_TIMESPEC_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct timespec timespec_add(struct timespec ts1, struct timespec ts2);
|
||||||
|
struct timespec timespec_sub(struct timespec ts1, struct timespec ts2);
|
||||||
|
struct timespec timespec_mod(struct timespec ts1, struct timespec ts2);
|
||||||
|
|
||||||
|
struct timespec timespec_min(struct timespec ts1, struct timespec ts2);
|
||||||
|
struct timespec timespec_max(struct timespec ts1, struct timespec ts2);
|
||||||
|
struct timespec timespec_clamp(struct timespec ts1, struct timespec min, struct timespec max);
|
||||||
|
|
||||||
|
int timespec_cmp(struct timespec ts1, struct timespec ts2);
|
||||||
|
bool timespec_eq(struct timespec ts1, struct timespec ts2);
|
||||||
|
bool timespec_gt(struct timespec ts1, struct timespec ts2);
|
||||||
|
bool timespec_ge(struct timespec ts1, struct timespec ts2);
|
||||||
|
bool timespec_lt(struct timespec ts1, struct timespec ts2);
|
||||||
|
bool timespec_le(struct timespec ts1, struct timespec ts2);
|
||||||
|
|
||||||
|
struct timespec timespec_from_double(double s);
|
||||||
|
double timespec_to_double(struct timespec ts);
|
||||||
|
struct timespec timespec_from_timeval(struct timeval tv);
|
||||||
|
struct timeval timespec_to_timeval(struct timespec ts);
|
||||||
|
struct timespec timespec_from_ms(long milliseconds);
|
||||||
|
long timespec_to_ms(struct timespec ts);
|
||||||
|
|
||||||
|
struct timespec timespec_normalise(struct timespec ts);
|
||||||
|
|
||||||
|
struct timespec timespec_now();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !DAN_TIMESPEC_H */
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
|
#include "pbsplash.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <tfblib/tfblib.h>
|
|
||||||
#include <tfblib/tfb_colors.h>
|
#include <tfblib/tfb_colors.h>
|
||||||
#include "pbsplash.h"
|
#include <tfblib/tfblib.h>
|
||||||
|
|
||||||
struct col color = { .r = 255, .g = 255, .b = 255, .a = 255 };
|
struct col color = {.r = 255, .g = 255, .b = 255, .a = 255};
|
||||||
|
|
||||||
#define PI 3.1415926535897932384626433832795
|
#define PI 3.1415926535897932384626433832795
|
||||||
#define n_circles 3
|
#define n_circles 3
|
||||||
#define speed 5
|
#define speed 2.5
|
||||||
|
|
||||||
static void circles_wave(int frame, int w, int y_off, long dpi)
|
static void circles_wave(int frame, int w, int y_off, long dpi)
|
||||||
{
|
{
|
||||||
unsigned int t_col = tfb_make_color(color.r, color.g, color.b);
|
unsigned int t_col = tfb_make_color(color.r, color.g, color.b);
|
||||||
int f = frame * speed;
|
int f = round(frame * speed);
|
||||||
|
|
||||||
int rad = MM_TO_PX(dpi, 1);
|
int rad = MM_TO_PX(dpi, 1);
|
||||||
int dist = rad * 3.5;
|
int dist = rad * 3.5;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
src = [
|
src = [
|
||||||
'animate.c',
|
'animate.c',
|
||||||
'nanosvg.c',
|
'nanosvg.c',
|
||||||
|
'timespec.c',
|
||||||
'pbsplash.c',
|
'pbsplash.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@
|
||||||
#define NANOSVG_ALL_COLOR_KEYWORDS // Include full list of color keywords.
|
#define NANOSVG_ALL_COLOR_KEYWORDS // Include full list of color keywords.
|
||||||
#include "nanosvg.h"
|
#include "nanosvg.h"
|
||||||
#include "nanosvgrast.h"
|
#include "nanosvgrast.h"
|
||||||
|
#include "timespec.h"
|
||||||
#include "pbsplash.h"
|
#include "pbsplash.h"
|
||||||
|
|
||||||
#define MSG_MAX_LEN 4096
|
#define MSG_MAX_LEN 4096
|
||||||
#define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg"
|
#define DEFAULT_FONT_PATH "/usr/share/pbsplash/OpenSans-Regular.svg"
|
||||||
#define LOGO_SIZE_MAX_MM 40
|
#define LOGO_SIZE_MAX_MM 45
|
||||||
#define FONT_SIZE_PT 9
|
#define FONT_SIZE_PT 9
|
||||||
#define FONT_SIZE_B_PT 6
|
#define FONT_SIZE_B_PT 6
|
||||||
#define B_MESSAGE_OFFSET_MM 3
|
#define B_MESSAGE_OFFSET_MM 3
|
||||||
|
|
@ -172,7 +172,7 @@ static const char *getTextDimensions(const NSVGimage *font, const char *text, fl
|
||||||
|
|
||||||
char *out_text = zalloc(strlen(text) + 1);
|
char *out_text = zalloc(strlen(text) + 1);
|
||||||
|
|
||||||
*width = font->defaultHorizAdv * scale;
|
*width = 2; //font->defaultHorizAdv * scale;
|
||||||
// The height is simply the height of the font * the scale factor
|
// The height is simply the height of the font * the scale factor
|
||||||
*height = fontHeight;
|
*height = fontHeight;
|
||||||
|
|
||||||
|
|
@ -195,7 +195,7 @@ static const char *getTextDimensions(const NSVGimage *font, const char *text, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shape) {
|
if (shape) {
|
||||||
*width += (float)shapes[i]->horizAdvX * scale + 2;
|
*width += (float)shapes[i]->horizAdvX * scale;
|
||||||
} else {
|
} else {
|
||||||
*width += font->defaultHorizAdv * scale;
|
*width += font->defaultHorizAdv * scale;
|
||||||
}
|
}
|
||||||
|
|
@ -547,19 +547,36 @@ no_messages:
|
||||||
tfb_flush_window();
|
tfb_flush_window();
|
||||||
tfb_flush_fb();
|
tfb_flush_fb();
|
||||||
|
|
||||||
int frame = 0;
|
int tick = 0;
|
||||||
int tty = open(active_tty, O_RDWR);
|
int tty = open(active_tty, O_RDWR);
|
||||||
if (!tty) {
|
if (!tty) {
|
||||||
fprintf(stderr, "Failed to open tty %s (%d)\n", active_tty, errno);
|
fprintf(stderr, "Failed to open tty %s (%d)\n", active_tty, errno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct timespec epoch, start, end, diff;
|
||||||
|
int target_fps = 60;
|
||||||
|
float tickrate = 60.0;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &epoch);
|
||||||
while (!terminate) {
|
while (!terminate) {
|
||||||
if (!animation) {
|
if (!animation) {
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
animate_frame(frame++, screenWidth, animation_y, dpi_info.dpi);
|
clock_gettime(CLOCK_REALTIME, &start);
|
||||||
|
tick = timespec_to_double(timespec_sub(start, epoch)) * tickrate;
|
||||||
|
animate_frame(tick, screenWidth, animation_y, dpi_info.dpi);
|
||||||
tfb_flush_fb();
|
tfb_flush_fb();
|
||||||
|
clock_gettime(CLOCK_REALTIME, &end);
|
||||||
|
diff = timespec_sub(end, start);
|
||||||
|
//printf("%05d: %09ld\n", tick, diff.tv_nsec);
|
||||||
|
if (diff.tv_nsec < 1000000000 / target_fps) {
|
||||||
|
struct timespec sleep_time = {
|
||||||
|
.tv_sec = 0,
|
||||||
|
.tv_nsec = 1000000000 / target_fps - diff.tv_nsec,
|
||||||
|
};
|
||||||
|
nanosleep(&sleep_time, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
|
||||||
987
src/timespec.c
Normal file
987
src/timespec.c
Normal file
|
|
@ -0,0 +1,987 @@
|
||||||
|
/* Functions for working with timespec structures
|
||||||
|
* Written by Daniel Collins (2017-2021)
|
||||||
|
* timespec_mod by Alex Forencich (2019)
|
||||||
|
* Various contributions by Ingo Albrecht (2021)
|
||||||
|
*
|
||||||
|
* This is free and unencumbered software released into the public domain.
|
||||||
|
*
|
||||||
|
* Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
* distribute this software, either in source code form or as a compiled
|
||||||
|
* binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
* means.
|
||||||
|
*
|
||||||
|
* In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
* of this software dedicate any and all copyright interest in the
|
||||||
|
* software to the public domain. We make this dedication for the benefit
|
||||||
|
* of the public at large and to the detriment of our heirs and
|
||||||
|
* successors. We intend this dedication to be an overt act of
|
||||||
|
* relinquishment in perpetuity of all present and future rights to this
|
||||||
|
* software under copyright law.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
* OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file timespec.c
|
||||||
|
* \brief Functions for working with timespec structures.
|
||||||
|
*
|
||||||
|
* This library aims to provide a comprehensive set of functions with
|
||||||
|
* well-defined behaviour that handle all edge cases (e.g. negative values) in
|
||||||
|
* a sensible manner.
|
||||||
|
*
|
||||||
|
* Negative values are allowed in the tv_sec and/or tv_usec field of timespec
|
||||||
|
* structures, tv_usec is always relative to tv_sec, so mixing positive and
|
||||||
|
* negative values will produce consistent results:
|
||||||
|
*
|
||||||
|
* <PRE>
|
||||||
|
* { tv_sec = 1, tv_nsec = 500000000 } == 1.5 seconds
|
||||||
|
* { tv_sec = 1, tv_nsec = 0 } == 1.0 seconds
|
||||||
|
* { tv_sec = 1, tv_nsec = -500000000 } == 0.5 seconds
|
||||||
|
* { tv_sec = 0, tv_nsec = 500000000 } == 0.5 seconds
|
||||||
|
* { tv_sec = 0, tv_nsec = 0 } == 0.0 seconds
|
||||||
|
* { tv_sec = 0, tv_nsec = -500000000 } == -0.5 seconds
|
||||||
|
* { tv_sec = -1, tv_nsec = 500000000 } == -0.5 seconds
|
||||||
|
* { tv_sec = -1, tv_nsec = 0 } == -1.0 seconds
|
||||||
|
* { tv_sec = -1, tv_nsec = -500000000 } == -1.5 seconds
|
||||||
|
* </PRE>
|
||||||
|
*
|
||||||
|
* Furthermore, any timespec structure processed or returned by library functions
|
||||||
|
* is normalised according to the rules in timespec_normalise().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "timespec.h"
|
||||||
|
|
||||||
|
#define NSEC_PER_SEC 1000000000
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns the result of adding two timespec structures.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_add(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
/* Normalise inputs to prevent tv_nsec rollover if whole-second values
|
||||||
|
* are packed in it.
|
||||||
|
*/
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
ts1.tv_sec += ts2.tv_sec;
|
||||||
|
ts1.tv_nsec += ts2.tv_nsec;
|
||||||
|
|
||||||
|
return timespec_normalise(ts1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns the result of subtracting ts2 from ts1.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_sub(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
/* Normalise inputs to prevent tv_nsec rollover if whole-second values
|
||||||
|
* are packed in it.
|
||||||
|
*/
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
ts1.tv_sec -= ts2.tv_sec;
|
||||||
|
ts1.tv_nsec -= ts2.tv_nsec;
|
||||||
|
|
||||||
|
return timespec_normalise(ts1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_mod(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns the remainder left over after dividing ts1 by ts2 (ts1%ts2).
|
||||||
|
*/
|
||||||
|
struct timespec timespec_mod(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
bool neg1 = false;
|
||||||
|
bool neg2 = false;
|
||||||
|
|
||||||
|
/* Normalise inputs to prevent tv_nsec rollover if whole-second values
|
||||||
|
* are packed in it.
|
||||||
|
*/
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
/* If ts2 is zero, just return ts1
|
||||||
|
*/
|
||||||
|
if (ts2.tv_sec == 0 && ts2.tv_nsec == 0)
|
||||||
|
{
|
||||||
|
return ts1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If inputs are negative, flip and record sign
|
||||||
|
*/
|
||||||
|
if (ts1.tv_sec < 0 || ts1.tv_nsec < 0)
|
||||||
|
{
|
||||||
|
neg1 = true;
|
||||||
|
ts1.tv_sec = -ts1.tv_sec;
|
||||||
|
ts1.tv_nsec = -ts1.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts2.tv_sec < 0 || ts2.tv_nsec < 0)
|
||||||
|
{
|
||||||
|
neg2 = true;
|
||||||
|
ts2.tv_sec = -ts2.tv_sec;
|
||||||
|
ts2.tv_nsec = -ts2.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shift ts2 until it is larger than ts1 or is about to overflow
|
||||||
|
*/
|
||||||
|
while ((ts2.tv_sec < (LONG_MAX >> 1)) && timespec_ge(ts1, ts2))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
ts2.tv_nsec <<= 1;
|
||||||
|
ts2.tv_sec <<= 1;
|
||||||
|
if (ts2.tv_nsec > NSEC_PER_SEC)
|
||||||
|
{
|
||||||
|
ts2.tv_nsec -= NSEC_PER_SEC;
|
||||||
|
ts2.tv_sec++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Division by repeated subtraction
|
||||||
|
*/
|
||||||
|
while (i >= 0)
|
||||||
|
{
|
||||||
|
if (timespec_ge(ts1, ts2))
|
||||||
|
{
|
||||||
|
ts1 = timespec_sub(ts1, ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
if (ts2.tv_sec & 1)
|
||||||
|
{
|
||||||
|
ts2.tv_nsec += NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
ts2.tv_nsec >>= 1;
|
||||||
|
ts2.tv_sec >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If signs differ and result is nonzero, subtract once more to cross zero
|
||||||
|
*/
|
||||||
|
if (neg1 ^ neg2 && (ts1.tv_sec != 0 || ts1.tv_nsec != 0))
|
||||||
|
{
|
||||||
|
ts1 = timespec_sub(ts1, ts2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore sign
|
||||||
|
*/
|
||||||
|
if (neg1)
|
||||||
|
{
|
||||||
|
ts1.tv_sec = -ts1.tv_sec;
|
||||||
|
ts1.tv_nsec = -ts1.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_min(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Return the lesser one of the two given timespec values.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_min(struct timespec ts1, struct timespec ts2) {
|
||||||
|
if(timespec_le(ts1, ts2)) {
|
||||||
|
return ts1;
|
||||||
|
} else {
|
||||||
|
return ts2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_max(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Return the greater one of the two given timespec values.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_max(struct timespec ts1, struct timespec ts2) {
|
||||||
|
if(timespec_ge(ts1, ts2)) {
|
||||||
|
return ts1;
|
||||||
|
} else {
|
||||||
|
return ts2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_clamp(struct timespec ts, struct timespec min, struct timespec max)
|
||||||
|
* \brief Clamp the value of TS between MIN and MAX.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_clamp(struct timespec ts, struct timespec min, struct timespec max) {
|
||||||
|
if(timespec_gt(ts, max)) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
if(timespec_lt(ts, min)) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn int timespec_cmp(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns (1, 0, -1) if ts1 is (greater than, equal to, less than) to ts2.
|
||||||
|
*/
|
||||||
|
int timespec_cmp(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
if(ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec == ts2.tv_nsec)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if((ts1.tv_sec > ts2.tv_sec)
|
||||||
|
|| (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec > ts2.tv_nsec))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn bool timespec_eq(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns true if the two timespec structures are equal.
|
||||||
|
*/
|
||||||
|
bool timespec_eq(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
return (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec == ts2.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn bool timespec_gt(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns true if ts1 is greater than ts2.
|
||||||
|
*/
|
||||||
|
bool timespec_gt(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec > ts2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn bool timespec_ge(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns true if ts1 is greater than or equal to ts2.
|
||||||
|
*/
|
||||||
|
bool timespec_ge(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
return (ts1.tv_sec > ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec >= ts2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn bool timespec_lt(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns true if ts1 is less than ts2.
|
||||||
|
*/
|
||||||
|
bool timespec_lt(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec < ts2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn bool timespec_le(struct timespec ts1, struct timespec ts2)
|
||||||
|
* \brief Returns true if ts1 is less than or equal to ts2.
|
||||||
|
*/
|
||||||
|
bool timespec_le(struct timespec ts1, struct timespec ts2)
|
||||||
|
{
|
||||||
|
ts1 = timespec_normalise(ts1);
|
||||||
|
ts2 = timespec_normalise(ts2);
|
||||||
|
|
||||||
|
return (ts1.tv_sec < ts2.tv_sec || (ts1.tv_sec == ts2.tv_sec && ts1.tv_nsec <= ts2.tv_nsec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_from_double(double s)
|
||||||
|
* \brief Converts a fractional number of seconds to a timespec.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_from_double(double s)
|
||||||
|
{
|
||||||
|
struct timespec ts = {
|
||||||
|
.tv_sec = s,
|
||||||
|
.tv_nsec = (s - (long)(s)) * NSEC_PER_SEC,
|
||||||
|
};
|
||||||
|
|
||||||
|
return timespec_normalise(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn double timespec_to_double(struct timespec ts)
|
||||||
|
* \brief Converts a timespec to a fractional number of seconds.
|
||||||
|
*/
|
||||||
|
double timespec_to_double(struct timespec ts)
|
||||||
|
{
|
||||||
|
return ((double)(ts.tv_sec) + ((double)(ts.tv_nsec) / NSEC_PER_SEC));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_from_timeval(struct timeval tv)
|
||||||
|
* \brief Converts a timeval to a timespec.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_from_timeval(struct timeval tv)
|
||||||
|
{
|
||||||
|
struct timespec ts = {
|
||||||
|
.tv_sec = tv.tv_sec,
|
||||||
|
.tv_nsec = tv.tv_usec * 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
return timespec_normalise(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timeval timespec_to_timeval(struct timespec ts)
|
||||||
|
* \brief Converts a timespec to a timeval.
|
||||||
|
*/
|
||||||
|
struct timeval timespec_to_timeval(struct timespec ts)
|
||||||
|
{
|
||||||
|
ts = timespec_normalise(ts);
|
||||||
|
|
||||||
|
struct timeval tv = {
|
||||||
|
.tv_sec = ts.tv_sec,
|
||||||
|
.tv_usec = ts.tv_nsec / 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return tv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_from_ms(long milliseconds)
|
||||||
|
* \brief Converts an integer number of milliseconds to a timespec.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_from_ms(long milliseconds)
|
||||||
|
{
|
||||||
|
struct timespec ts = {
|
||||||
|
.tv_sec = (milliseconds / 1000),
|
||||||
|
.tv_nsec = (milliseconds % 1000) * 1000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return timespec_normalise(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn long timespec_to_ms(struct timespec ts)
|
||||||
|
* \brief Converts a timespec to an integer number of milliseconds.
|
||||||
|
*/
|
||||||
|
long timespec_to_ms(struct timespec ts)
|
||||||
|
{
|
||||||
|
return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \fn struct timespec timespec_normalise(struct timespec ts)
|
||||||
|
* \brief Normalises a timespec structure.
|
||||||
|
*
|
||||||
|
* Returns a normalised version of a timespec structure, according to the
|
||||||
|
* following rules:
|
||||||
|
*
|
||||||
|
* 1) If tv_nsec is >=1,000,000,00 or <=-1,000,000,000, flatten the surplus
|
||||||
|
* nanoseconds into the tv_sec field.
|
||||||
|
*
|
||||||
|
* 2) If tv_nsec is negative, decrement tv_sec and roll tv_nsec up to represent
|
||||||
|
* the same value attainable by ADDING nanoseconds to tv_sec.
|
||||||
|
*/
|
||||||
|
struct timespec timespec_normalise(struct timespec ts)
|
||||||
|
{
|
||||||
|
while(ts.tv_nsec >= NSEC_PER_SEC)
|
||||||
|
{
|
||||||
|
++(ts.tv_sec);
|
||||||
|
ts.tv_nsec -= NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(ts.tv_nsec <= -NSEC_PER_SEC)
|
||||||
|
{
|
||||||
|
--(ts.tv_sec);
|
||||||
|
ts.tv_nsec += NSEC_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ts.tv_nsec < 0)
|
||||||
|
{
|
||||||
|
/* Negative nanoseconds isn't valid according to POSIX.
|
||||||
|
* Decrement tv_sec and roll tv_nsec over.
|
||||||
|
*/
|
||||||
|
|
||||||
|
--(ts.tv_sec);
|
||||||
|
ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timespec timespec_now()
|
||||||
|
{
|
||||||
|
struct timespec t;
|
||||||
|
clock_gettime(CLOCK_REALTIME, &t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define TEST_NORMALISE(ts_sec, ts_nsec, expect_sec, expect_nsec) { \
|
||||||
|
struct timespec in = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \
|
||||||
|
struct timespec got = timespec_normalise(in); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: timespec_normalise({%ld, %ld}) returned wrong values\n", __FILE__, __LINE__, \
|
||||||
|
(long)(ts_sec), (long)(ts_nsec)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_BINOP(func, ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect_sec, expect_nsec) { \
|
||||||
|
struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \
|
||||||
|
struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \
|
||||||
|
struct timespec got = func(ts1, ts2); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf(#func "({%ld, %ld}, {%ld, %ld}) returned wrong values\n", \
|
||||||
|
(long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_TRINOP(func, ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, ts3_sec, ts3_nsec, expect_sec, expect_nsec) { \
|
||||||
|
struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \
|
||||||
|
struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \
|
||||||
|
struct timespec ts3 = { .tv_sec = ts3_sec, .tv_nsec = ts3_nsec }; \
|
||||||
|
struct timespec got = func(ts1, ts2, ts3); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf(#func "({%ld, %ld}, {%ld, %ld}, {%ld, %ld}) returned wrong values\n", \
|
||||||
|
(long)(ts1_sec), (long)(ts1_nsec), \
|
||||||
|
(long)(ts2_sec), (long)(ts2_nsec), \
|
||||||
|
(long)(ts3_sec), (long)(ts3_nsec)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_TEST_FUNC(func, ts1_sec, ts1_nsec, ts2_sec, ts2_nsec, expect) { \
|
||||||
|
struct timespec ts1 = { .tv_sec = ts1_sec, .tv_nsec = ts1_nsec }; \
|
||||||
|
struct timespec ts2 = { .tv_sec = ts2_sec, .tv_nsec = ts2_nsec }; \
|
||||||
|
int got = func(ts1, ts2); \
|
||||||
|
if(got != expect) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: " #func "({%ld, %ld}, {%ld, %ld}) returned %d, expected %s\n", __FILE__, __LINE__, \
|
||||||
|
(long)(ts1_sec), (long)(ts1_nsec), (long)(ts2_sec), (long)(ts2_nsec), \
|
||||||
|
got, #expect); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FROM_DOUBLE(d_secs, expect_sec, expect_nsec) { \
|
||||||
|
struct timespec got = timespec_from_double(d_secs); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: timespec_from_double(%f) returned wrong values\n", __FILE__, __LINE__, (double)(d_secs)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_TO_DOUBLE(ts_sec, ts_nsec, expect) { \
|
||||||
|
struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \
|
||||||
|
double got = timespec_to_double(ts); \
|
||||||
|
if(got != expect) { \
|
||||||
|
printf("%s:%d: timespec_to_double({%ld, %ld}) returned wrong value\n", __FILE__, __LINE__, \
|
||||||
|
(long)(ts_sec), (long)(ts_nsec)); \
|
||||||
|
printf(" Expected: %f\n", (double)(expect)); \
|
||||||
|
printf(" Got: %f\n", got); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FROM_TIMEVAL(in_sec, in_usec, expect_sec, expect_nsec) { \
|
||||||
|
struct timeval tv = { .tv_sec = in_sec, .tv_usec = in_usec }; \
|
||||||
|
struct timespec got = timespec_from_timeval(tv); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: timespec_from_timeval({%ld, %ld}) returned wrong values\n", __FILE__, __LINE__, \
|
||||||
|
(long)(in_sec), (long)(in_usec)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_TO_TIMEVAL(ts_sec, ts_nsec, expect_sec, expect_usec) { \
|
||||||
|
struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \
|
||||||
|
struct timeval got = timespec_to_timeval(ts); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_usec != expect_usec) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: timespec_to_timeval({%ld, %ld}) returned wrong values\n", __FILE__, __LINE__, \
|
||||||
|
(long)(ts_sec), (long)(ts_nsec)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_usec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_usec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_FROM_MS(msecs, expect_sec, expect_nsec) { \
|
||||||
|
struct timespec got = timespec_from_ms(msecs); \
|
||||||
|
if(got.tv_sec != expect_sec || got.tv_nsec != expect_nsec) \
|
||||||
|
{ \
|
||||||
|
printf("%s:%d: timespec_from_ms(%ld) returned wrong values\n", __FILE__, __LINE__, (long)(msecs)); \
|
||||||
|
printf(" Expected: {%ld, %ld}\n", (long)(expect_sec), (long)(expect_nsec)); \
|
||||||
|
printf(" Got: {%ld, %ld}\n", (long)(got.tv_sec), (long)(got.tv_nsec)); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST_TO_MS(ts_sec, ts_nsec, expect) { \
|
||||||
|
struct timespec ts = { .tv_sec = ts_sec, .tv_nsec = ts_nsec }; \
|
||||||
|
long got = timespec_to_ms(ts); \
|
||||||
|
if(got != expect) { \
|
||||||
|
printf("%s:%d: timespec_to_ms({%ld, %ld}) returned wrong value\n", __FILE__, __LINE__, \
|
||||||
|
(long)(ts_sec), (long)(ts_nsec)); \
|
||||||
|
printf(" Expected: %ld\n", (long)(expect)); \
|
||||||
|
printf(" Got: %ld\n", got); \
|
||||||
|
++result; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
// timespec_add
|
||||||
|
|
||||||
|
TEST_BINOP(timespec_add, 0,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_add, 0,0, 1,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,0, 0,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,0, 1,0, 2,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,500000000, 1,0, 2,500000000);
|
||||||
|
TEST_BINOP(timespec_add, 1,0, 1,500000000, 2,500000000);
|
||||||
|
TEST_BINOP(timespec_add, 1,500000000, 1,500000000, 3,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,500000000, 1,499999999, 2,999999999);
|
||||||
|
TEST_BINOP(timespec_add, 1,500000000, 1,500000000, 3,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,999999999, 1,999999999, 3,999999998);
|
||||||
|
TEST_BINOP(timespec_add, 0,500000000, 1,500000000, 2,0);
|
||||||
|
TEST_BINOP(timespec_add, 1,500000000, 0,500000000, 2,0);
|
||||||
|
|
||||||
|
// timespec_sub
|
||||||
|
|
||||||
|
TEST_BINOP(timespec_sub, 0,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_sub, 1,0, 0,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_sub, 1,0, 1,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_sub, 1,500000000, 0,500000000, 1,0);
|
||||||
|
TEST_BINOP(timespec_sub, 5,500000000, 2,999999999, 2,500000001);
|
||||||
|
TEST_BINOP(timespec_sub, 0,0, 1,0, -1,0);
|
||||||
|
TEST_BINOP(timespec_sub, 0,500000000, 1,500000000, -1,0);
|
||||||
|
TEST_BINOP(timespec_sub, 0,0, 1,500000000, -2,500000000);
|
||||||
|
TEST_BINOP(timespec_sub, 1,0, 1,500000000, -1,500000000);
|
||||||
|
TEST_BINOP(timespec_sub, 1,0, 1,499999999, -1,500000001);
|
||||||
|
|
||||||
|
// timespec_mod
|
||||||
|
|
||||||
|
TEST_BINOP(timespec_mod, 0,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 0,0, 1,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,0, 0,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,0, 1,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 10,0, 1,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 10,0, 3,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_mod, 10,0, -3,0, -2,0);
|
||||||
|
TEST_BINOP(timespec_mod, -10,0, 3,0, 2,0);
|
||||||
|
TEST_BINOP(timespec_mod, -10,0, -3,0, -1,0);
|
||||||
|
TEST_BINOP(timespec_mod, 10,0, 5,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 10,0, -5,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, -10,0, 5,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, -10,0, -5,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,500000000, 0,500000000, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 5,500000000, 2,999999999, 2,500000001);
|
||||||
|
TEST_BINOP(timespec_mod, 0,500000000, 1,500000000, 0,500000000);
|
||||||
|
TEST_BINOP(timespec_mod, 0,0, 1,500000000, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,0, 1,500000000, 1,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,0, 0,1, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, 1,123456789, 0,1000, 0,789);
|
||||||
|
TEST_BINOP(timespec_mod, 1,0, 0,9999999, 0,100);
|
||||||
|
TEST_BINOP(timespec_mod, 12345,54321, 0,100001, 0,5555);
|
||||||
|
TEST_BINOP(timespec_mod, LONG_MAX,0, 0,1, 0,0);
|
||||||
|
TEST_BINOP(timespec_mod, LONG_MAX,0, LONG_MAX,1, LONG_MAX,0);
|
||||||
|
|
||||||
|
// timespec_clamp
|
||||||
|
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,0, 0,0, 0,0, 0,0);
|
||||||
|
|
||||||
|
TEST_TRINOP(timespec_clamp, 1000,0, 2000,0, 3000,0, 2000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 1500,0, 2000,0, 3000,0, 2000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 1999,0, 2000,0, 3000,0, 2000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2000,0, 2000,0, 3000,0, 2000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2001,0, 2000,0, 3000,0, 2001,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2250,0, 2000,0, 3000,0, 2250,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2500,0, 2000,0, 3000,0, 2500,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2750,0, 2000,0, 3000,0, 2750,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 2999,0, 2000,0, 3000,0, 2999,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 3000,0, 2000,0, 3000,0, 3000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 3001,0, 2000,0, 3000,0, 3000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 3500,0, 2000,0, 3000,0, 3000,0);
|
||||||
|
TEST_TRINOP(timespec_clamp, 4000,0, 2000,0, 3000,0, 3000,0);
|
||||||
|
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,1000, 0,2000, 0,3000, 0,2000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,1500, 0,2000, 0,3000, 0,2000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,1999, 0,2000, 0,3000, 0,2000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2000, 0,2000, 0,3000, 0,2000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2001, 0,2000, 0,3000, 0,2001);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2250, 0,2000, 0,3000, 0,2250);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2500, 0,2000, 0,3000, 0,2500);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2750, 0,2000, 0,3000, 0,2750);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,2999, 0,2000, 0,3000, 0,2999);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,3000, 0,2000, 0,3000, 0,3000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,3001, 0,2000, 0,3000, 0,3000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,3500, 0,2000, 0,3000, 0,3000);
|
||||||
|
TEST_TRINOP(timespec_clamp, 0,4000, 0,2000, 0,3000, 0,3000);
|
||||||
|
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-1000, 0,-3000, 0,-2000, 0,-2000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-1500, 0,-3000, 0,-2000, 0,-2000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-1999, 0,-3000, 0,-2000, 0,-2000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-3000, 0,-3000, 0,-2000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2001, 0,-3000, 0,-2000, 0,-2001);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2250, 0,-3000, 0,-2000, 0,-2250);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2500, 0,-3000, 0,-2000, 0,-2500);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2750, 0,-3000, 0,-2000, 0,-2750);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2999, 0,-3000, 0,-2000, 0,-2999);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2000, 0,-3000, 0,-2000, 0,-2000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-3001, 0,-3000, 0,-2000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-3500, 0,-3000, 0,-2000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2000, 0,-3000, 0,-2000, 0,-2000);
|
||||||
|
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-4000, 0,-3000, 0,3000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-3001, 0,-3000, 0,3000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-3000, 0,-3000, 0,3000, 0,-3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-2999, 0,-3000, 0,3000, 0,-2999);
|
||||||
|
TEST_TRINOP(timespec_clamp,0,-1500, 0,-3000, 0,3000, 0,-1500);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, -1, 0,-3000, 0,3000, 0, -1);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 0, 0,-3000, 0,3000, 0, 0);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 1, 0,-3000, 0,3000, 0, 1);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 1500, 0,-3000, 0,3000, 0, 1500);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 2999, 0,-3000, 0,3000, 0, 2999);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 3000, 0,-3000, 0,3000, 0, 3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 3001, 0,-3000, 0,3000, 0, 3000);
|
||||||
|
TEST_TRINOP(timespec_clamp,0, 4000, 0,-3000, 0,3000, 0, 3000);
|
||||||
|
|
||||||
|
// timespec_min
|
||||||
|
|
||||||
|
TEST_BINOP(timespec_min, 0,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_min, 0,0, 1,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_min, 1,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_min, 1,0, 1,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_min, 10,0, 1,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_min, 10,0, 3,0, 3,0);
|
||||||
|
TEST_BINOP(timespec_min, 10,0, -3,0, -3,0);
|
||||||
|
TEST_BINOP(timespec_min, -10,0, 3,0, -10,0);
|
||||||
|
TEST_BINOP(timespec_min, -10,0, -3,0, -10,0);
|
||||||
|
TEST_BINOP(timespec_min, 10,0, 5,0, 5,0);
|
||||||
|
TEST_BINOP(timespec_min, 10,0, -5,0, -5,0);
|
||||||
|
TEST_BINOP(timespec_min, -10,0, 5,0, -10,0);
|
||||||
|
TEST_BINOP(timespec_min, -10,0, -5,0, -10,0);
|
||||||
|
TEST_BINOP(timespec_min, 1,500000000, 0,500000000, 0,500000000);
|
||||||
|
TEST_BINOP(timespec_min, 5,500000000, 2,999999999, 2,999999999);
|
||||||
|
TEST_BINOP(timespec_min, 0,500000000, 1,500000000, 0,500000000);
|
||||||
|
TEST_BINOP(timespec_min, 0,0, 1,500000000, 0,0);
|
||||||
|
TEST_BINOP(timespec_min, 1,0, 1,500000000, 1,0);
|
||||||
|
TEST_BINOP(timespec_min, 1,0, 0,1, 0,1);
|
||||||
|
TEST_BINOP(timespec_min, 1,123456789, 0,1000, 0,1000);
|
||||||
|
TEST_BINOP(timespec_min, 1,0, 0,9999999, 0,9999999);
|
||||||
|
TEST_BINOP(timespec_min, 12345,54321, 0,100001, 0,100001);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MIN,0, 0,1, LONG_MIN,0);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MIN,0, 0,-1, LONG_MIN,0);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MIN,0, LONG_MAX,0, LONG_MIN,0);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MIN,0, LONG_MIN,0, LONG_MIN,0);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MAX,0, 0,1, 0,1);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MAX,0, 0,-1, 0,-1);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MAX,0, LONG_MAX,0, LONG_MAX,0);
|
||||||
|
TEST_BINOP(timespec_min, LONG_MAX,0, LONG_MIN,0, LONG_MIN,0);
|
||||||
|
|
||||||
|
// timespec_max
|
||||||
|
|
||||||
|
TEST_BINOP(timespec_max, 0,0, 0,0, 0,0);
|
||||||
|
TEST_BINOP(timespec_max, 0,0, 1,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_max, 1,0, 0,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_max, 1,0, 1,0, 1,0);
|
||||||
|
TEST_BINOP(timespec_max, 10,0, 1,0, 10,0);
|
||||||
|
TEST_BINOP(timespec_max, 10,0, 3,0, 10,0);
|
||||||
|
TEST_BINOP(timespec_max, 10,0, -3,0, 10,0);
|
||||||
|
TEST_BINOP(timespec_max, -10,0, 3,0, 3,0);
|
||||||
|
TEST_BINOP(timespec_max, -10,0, -3,0, -3,0);
|
||||||
|
TEST_BINOP(timespec_max, 10,0, 5,0, 10,0);
|
||||||
|
TEST_BINOP(timespec_max, 10,0, -5,0, 10,0);
|
||||||
|
TEST_BINOP(timespec_max, -10,0, 5,0, 5,0);
|
||||||
|
TEST_BINOP(timespec_max, -10,0, -5,0, -5,0);
|
||||||
|
TEST_BINOP(timespec_max, 1,500000000, 0,500000000, 1,500000000);
|
||||||
|
TEST_BINOP(timespec_max, 5,500000000, 2,999999999, 5,500000000);
|
||||||
|
TEST_BINOP(timespec_max, 0,500000000, 1,500000000, 1,500000000);
|
||||||
|
TEST_BINOP(timespec_max, 0,0, 1,500000000, 1,500000000);
|
||||||
|
TEST_BINOP(timespec_max, 1,0, 1,500000000, 1,500000000);
|
||||||
|
TEST_BINOP(timespec_max, 1,0, 0,1, 1,0);
|
||||||
|
TEST_BINOP(timespec_max, 1,123456789, 0,1000, 1,123456789);
|
||||||
|
TEST_BINOP(timespec_max, 1,0, 0,9999999, 1,0);
|
||||||
|
TEST_BINOP(timespec_max, 12345,54321, 0,100001, 12345,54321);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MIN,0, 0,1, 0,1);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MIN,0, 0,-1, 0,-1);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MIN,0, LONG_MAX,0, LONG_MAX,0);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MIN,0, LONG_MIN,0, LONG_MIN,0);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MAX,0, 0,1, LONG_MAX,0);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MAX,0, 0,-1, LONG_MAX,0);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MAX,0, LONG_MAX,0, LONG_MAX,0);
|
||||||
|
TEST_BINOP(timespec_max, LONG_MAX,0, LONG_MIN,0, LONG_MAX,0);
|
||||||
|
|
||||||
|
// timespec_cmp
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 0,0, 0,0, 0);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 100,0, 100,0, 0);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -100,0, -100,0, 0);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 1,0, 0,0, 1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 0,0, 1,0, -1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 0,1, 0,0, 1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 0,0, 0,1, -1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 1,0, 0,100, 1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, 0,100 , 1,0, -1);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -0,-0, 0,0, 0);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -10,-500000000, -11,500000000, 0);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -10,-500000001, -11,499999999, 0);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -10,-500000001, -11,500000001, -1);
|
||||||
|
TEST_TEST_FUNC(timespec_cmp, -11,500000001, -10,-500000001, 1);
|
||||||
|
|
||||||
|
// timespec_eq
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 0,0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 100,0, 100,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -200,0, -200,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 0,300, 0,300, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 0,-400, 0,-400, true);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 100,1, 100,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 101,0, 100,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -100,0, 100,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, 0,10, 0,-10, false);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -0,-0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -10,-500000000, -11,500000000, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -10,-500000001, -11,499999999, true);
|
||||||
|
TEST_TEST_FUNC(timespec_eq, -10,-500000001, -11,500000001, false);
|
||||||
|
|
||||||
|
// timespec_gt
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 1,0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 0,0, -1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 0,1, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 0,0, 0,-1, true);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 1,0, 1,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 1,1, 1,1, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -1,0, 0,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 0,-1, 0,0, false);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_gt, 0,0, -0,-0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -10,-500000000, -11,500000000, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -11,500000000, -10,-500000000, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -10,-500000001, -11,499999999, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -11,499999999, -11,499999999, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -10,-500000001, -11,500000001, false);
|
||||||
|
TEST_TEST_FUNC(timespec_gt, -11,500000001, -10,-500000001, true);
|
||||||
|
|
||||||
|
// timespec_ge
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 1,0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 0,0, -1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 0,1, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 0,0, 0,-1, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 1,0, 1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 1,1, 1,1, true);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -1,0, 0,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 0,-1, 0,0, false);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_ge, 0,0, -0,-0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -10,-500000000, -11,500000000, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -11,500000000, -10,-500000000, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -10,-500000001, -11,499999999, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -11,499999999, -11,499999999, true);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -10,-500000001, -11,500000001, false);
|
||||||
|
TEST_TEST_FUNC(timespec_ge, -11,500000001, -10,-500000001, true);
|
||||||
|
|
||||||
|
// timespec_lt
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,0, 1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -1,0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,0, 0,1, true);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,-1, 0,0, true);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 1,0, 1,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 1,1, 1,1, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,0, -1,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,0, 0,-1, false);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_lt, 0,0, -0,-0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -10,-500000000, -11,500000000, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -11,500000000, -10,-500000000, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -10,-500000001, -11,499999999, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -11,499999999, -11,499999999, false);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -10,-500000001, -11,500000001, true);
|
||||||
|
TEST_TEST_FUNC(timespec_lt, -11,500000001, -10,-500000001, false);
|
||||||
|
|
||||||
|
// timespec_le
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,0, 1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -1,0, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,0, 0,1, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,-1, 0,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, 1,0, 1,0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, 1,1, 1,1, true);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,0, -1,0, false);
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,0, 0,-1, false);
|
||||||
|
|
||||||
|
TEST_TEST_FUNC(timespec_le, 0,0, -0,-0, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -10,-500000000, -11,500000000, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -11,500000000, -10,-500000000, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -10,-500000001, -11,499999999, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -11,499999999, -11,499999999, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -10,-500000001, -11,500000001, true);
|
||||||
|
TEST_TEST_FUNC(timespec_le, -11,500000001, -10,-500000001, false);
|
||||||
|
|
||||||
|
// timespec_from_double
|
||||||
|
|
||||||
|
TEST_FROM_DOUBLE(0.0, 0,0);
|
||||||
|
TEST_FROM_DOUBLE(10.0, 10,0);
|
||||||
|
TEST_FROM_DOUBLE(-10.0, -10,0);
|
||||||
|
TEST_FROM_DOUBLE(0.5, 0,500000000);
|
||||||
|
TEST_FROM_DOUBLE(-0.5, -1,500000000);
|
||||||
|
TEST_FROM_DOUBLE(10.5, 10,500000000);
|
||||||
|
TEST_FROM_DOUBLE(-10.5, -11,500000000);
|
||||||
|
|
||||||
|
// timespec_to_double
|
||||||
|
|
||||||
|
TEST_TO_DOUBLE(0,0, 0.0);
|
||||||
|
TEST_TO_DOUBLE(10,0, 10.0);
|
||||||
|
TEST_TO_DOUBLE(-10,0, -10.0);
|
||||||
|
TEST_TO_DOUBLE(0,500000000, 0.5);
|
||||||
|
TEST_TO_DOUBLE(0,-500000000, -0.5);
|
||||||
|
TEST_TO_DOUBLE(10,500000000, 10.5);
|
||||||
|
TEST_TO_DOUBLE(10,-500000000, 9.5);
|
||||||
|
TEST_TO_DOUBLE(-10,500000000, -9.5);
|
||||||
|
TEST_TO_DOUBLE(-10,-500000000, -10.5);
|
||||||
|
|
||||||
|
// timespec_from_timeval
|
||||||
|
|
||||||
|
TEST_FROM_TIMEVAL(0,0, 0,0);
|
||||||
|
TEST_FROM_TIMEVAL(1,0, 1,0);
|
||||||
|
TEST_FROM_TIMEVAL(1000,0, 1000,0);
|
||||||
|
TEST_FROM_TIMEVAL(0,0, 0,0);
|
||||||
|
TEST_FROM_TIMEVAL(-1,0, -1,0);
|
||||||
|
TEST_FROM_TIMEVAL(-1000,0, -1000,0);
|
||||||
|
|
||||||
|
TEST_FROM_TIMEVAL(1,1, 1,1000);
|
||||||
|
TEST_FROM_TIMEVAL(1,1000, 1,1000000);
|
||||||
|
TEST_FROM_TIMEVAL(1,-1, 0,999999000);
|
||||||
|
TEST_FROM_TIMEVAL(1,-1000, 0,999000000);
|
||||||
|
TEST_FROM_TIMEVAL(-1,-1, -2,999999000);
|
||||||
|
TEST_FROM_TIMEVAL(-1,-1000, -2,999000000);
|
||||||
|
|
||||||
|
// timespec_to_timeval
|
||||||
|
|
||||||
|
TEST_TO_TIMEVAL(0,0, 0,0);
|
||||||
|
TEST_TO_TIMEVAL(1,0, 1,0);
|
||||||
|
TEST_TO_TIMEVAL(10,0, 10,0);
|
||||||
|
TEST_TO_TIMEVAL(-1,0, -1,0);
|
||||||
|
TEST_TO_TIMEVAL(-10,0, -10,0);
|
||||||
|
|
||||||
|
TEST_TO_TIMEVAL(1,1, 1,0);
|
||||||
|
TEST_TO_TIMEVAL(1,999, 1,0);
|
||||||
|
TEST_TO_TIMEVAL(1,1000, 1,1);
|
||||||
|
TEST_TO_TIMEVAL(1,1001, 1,1);
|
||||||
|
TEST_TO_TIMEVAL(1,2000, 1,2);
|
||||||
|
TEST_TO_TIMEVAL(1,2000000, 1,2000);
|
||||||
|
|
||||||
|
TEST_TO_TIMEVAL(1,-1, 0,999999);
|
||||||
|
TEST_TO_TIMEVAL(1,-999, 0,999999);
|
||||||
|
TEST_TO_TIMEVAL(1,-1000, 0,999999);
|
||||||
|
TEST_TO_TIMEVAL(1,-1001, 0,999998);
|
||||||
|
TEST_TO_TIMEVAL(1,-2000, 0,999998);
|
||||||
|
TEST_TO_TIMEVAL(1,-2000000, 0,998000);
|
||||||
|
|
||||||
|
TEST_TO_TIMEVAL(-1,-1, -2,999999);
|
||||||
|
TEST_TO_TIMEVAL(-1,-999, -2,999999);
|
||||||
|
TEST_TO_TIMEVAL(-1,-1000, -2,999999);
|
||||||
|
TEST_TO_TIMEVAL(-1,-1001, -2,999998);
|
||||||
|
TEST_TO_TIMEVAL(-1,-2000, -2,999998);
|
||||||
|
TEST_TO_TIMEVAL(-1,-2000000, -2,998000);
|
||||||
|
|
||||||
|
TEST_TO_TIMEVAL(1,1500000000, 2,500000);
|
||||||
|
TEST_TO_TIMEVAL(1,-1500000000, -1,500000);
|
||||||
|
TEST_TO_TIMEVAL(-1,-1500000000, -3,500000);
|
||||||
|
|
||||||
|
// timespec_from_ms
|
||||||
|
|
||||||
|
TEST_FROM_MS(0, 0,0);
|
||||||
|
TEST_FROM_MS(1, 0,1000000);
|
||||||
|
TEST_FROM_MS(-1, -1,999000000);
|
||||||
|
TEST_FROM_MS(1500, 1,500000000);
|
||||||
|
TEST_FROM_MS(-1000, -1,0);
|
||||||
|
TEST_FROM_MS(-1500, -2,500000000);
|
||||||
|
|
||||||
|
// timespec_to_ms
|
||||||
|
|
||||||
|
TEST_TO_MS(0,0, 0);
|
||||||
|
TEST_TO_MS(10,0, 10000);
|
||||||
|
TEST_TO_MS(-10,0, -10000);
|
||||||
|
TEST_TO_MS(0,500000000, 500);
|
||||||
|
TEST_TO_MS(0,-500000000, -500);
|
||||||
|
TEST_TO_MS(10,500000000, 10500);
|
||||||
|
TEST_TO_MS(10,-500000000, 9500);
|
||||||
|
TEST_TO_MS(-10,500000000, -9500);
|
||||||
|
TEST_TO_MS(-10,-500000000, -10500);
|
||||||
|
|
||||||
|
// timespec_normalise
|
||||||
|
|
||||||
|
TEST_NORMALISE(0,0, 0,0);
|
||||||
|
|
||||||
|
TEST_NORMALISE(0,1000000000, 1,0);
|
||||||
|
TEST_NORMALISE(0,1500000000, 1,500000000);
|
||||||
|
TEST_NORMALISE(0,-1000000000, -1,0);
|
||||||
|
TEST_NORMALISE(0,-1500000000, -2,500000000);
|
||||||
|
|
||||||
|
TEST_NORMALISE(5,1000000000, 6,0);
|
||||||
|
TEST_NORMALISE(5,1500000000, 6,500000000);
|
||||||
|
TEST_NORMALISE(-5,-1000000000, -6,0);
|
||||||
|
TEST_NORMALISE(-5,-1500000000, -7,500000000);
|
||||||
|
|
||||||
|
TEST_NORMALISE(0,2000000000, 2,0);
|
||||||
|
TEST_NORMALISE(0,2100000000, 2,100000000);
|
||||||
|
TEST_NORMALISE(0,-2000000000, -2,0);
|
||||||
|
TEST_NORMALISE(0,-2100000000, -3,900000000);
|
||||||
|
|
||||||
|
TEST_NORMALISE(1,-500000001, 0,499999999);
|
||||||
|
TEST_NORMALISE(1,-500000000, 0,500000000);
|
||||||
|
TEST_NORMALISE(1,-499999999, 0,500000001);
|
||||||
|
TEST_NORMALISE(0,-499999999, -1,500000001);
|
||||||
|
|
||||||
|
TEST_NORMALISE(-1,500000000, -1,500000000);
|
||||||
|
TEST_NORMALISE(-1,499999999, -1,499999999);
|
||||||
|
|
||||||
|
if(result > 0)
|
||||||
|
{
|
||||||
|
printf("%d tests failed\n", result);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
printf("All tests passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!result; /* Don't overflow the exit status */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Loading…
Reference in a new issue