logo

cmd-timer

run command at a specific interval git clone https://anongit.hacktivis.me/git/cmd-timer.git

strtodur.c (2331B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include "strtodur.h"
  6. #include <assert.h>
  7. #include <ctype.h>
  8. #include <errno.h> // errno
  9. #include <stdio.h> // fprintf, perror, sscanf
  10. #include <string.h> // strerror
  11. const char *errstr_nan = "Not a number";
  12. int
  13. strtodur(char *s, struct timespec *dur)
  14. {
  15. if(s == 0) return 0;
  16. assert(dur);
  17. float total = 0.0;
  18. while(*s != '\0')
  19. {
  20. float in = 0.0;
  21. if(s[0] != '.' && s[0] != ',')
  22. {
  23. int parsed = 0;
  24. float res = 0.0;
  25. errno = 0;
  26. if(sscanf(s, "%10f%n", &res, &parsed) < 1)
  27. {
  28. const char *errstr = errstr_nan;
  29. if(errno != 0)
  30. {
  31. errstr = strerror(errno);
  32. errno = 0;
  33. }
  34. fprintf(
  35. stderr, "%s: error: strtodur failed scanning '%s' as a number: %s\n", argv0, s, errstr);
  36. return -1;
  37. }
  38. in += res;
  39. s += parsed;
  40. }
  41. if((s[0] == '.' || s[0] == ','))
  42. {
  43. if(s[1] == '\0')
  44. {
  45. s++;
  46. goto dot_skip;
  47. }
  48. float fraction = 0.0;
  49. if(s[0] == ',') s[0] = '.';
  50. int parsed = 0;
  51. errno = 0;
  52. if(sscanf(s, "%10f%n", &fraction, &parsed) < 1)
  53. {
  54. const char *errstr = errstr_nan;
  55. if(errno != 0)
  56. {
  57. errstr = strerror(errno);
  58. errno = 0;
  59. }
  60. fprintf(stderr,
  61. "%s: error: strtodur failed scanning decimal part '%s' as a number: %s\n",
  62. argv0,
  63. s,
  64. errstr);
  65. return -1;
  66. }
  67. if(parsed == 0) parsed++;
  68. in += fraction;
  69. s += parsed;
  70. }
  71. if(s[0] != '\0' && s[0] != ',' && s[0] != '.')
  72. {
  73. if(s[1] != '\0' && !isdigit(s[1]))
  74. {
  75. fprintf(stderr,
  76. "%s: error: duration suffix '%s' is too long, should be only one character\n",
  77. argv0,
  78. s);
  79. return -1;
  80. }
  81. switch(s[0])
  82. {
  83. case 's': // seconds
  84. break;
  85. case 'm': // minutes
  86. in *= 60;
  87. break;
  88. case 'h': // hours
  89. in *= 60 * 60;
  90. break;
  91. case 'd': // days
  92. in *= 24 * 60 * 60;
  93. break;
  94. default:
  95. fprintf(stderr, "%s: error: Unknown duration suffix '%c'\n", argv0, s[0]);
  96. return -1;
  97. }
  98. s++;
  99. }
  100. dot_skip:
  101. total += in;
  102. }
  103. dur->tv_sec = total;
  104. dur->tv_nsec = (total - dur->tv_sec) * 1000000000;
  105. return 0;
  106. }