countif.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "countif.h"
  3. // ----------------------------------------------------------------------------
  4. // countif
  5. struct grouping_countif {
  6. size_t (*comparison)(NETDATA_DOUBLE, NETDATA_DOUBLE);
  7. NETDATA_DOUBLE target;
  8. size_t count;
  9. size_t matched;
  10. };
  11. static size_t countif_equal(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  12. return (v == target);
  13. }
  14. static size_t countif_notequal(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  15. return (v != target);
  16. }
  17. static size_t countif_less(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  18. return (v < target);
  19. }
  20. static size_t countif_lessequal(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  21. return (v <= target);
  22. }
  23. static size_t countif_greater(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  24. return (v > target);
  25. }
  26. static size_t countif_greaterequal(NETDATA_DOUBLE v, NETDATA_DOUBLE target) {
  27. return (v >= target);
  28. }
  29. void grouping_create_countif(RRDR *r, const char *options __maybe_unused) {
  30. struct grouping_countif *g = onewayalloc_callocz(r->internal.owa, 1, sizeof(struct grouping_countif));
  31. r->internal.grouping_data = g;
  32. if(options && *options) {
  33. // skip any leading spaces
  34. while(isspace(*options)) options++;
  35. // find the comparison function
  36. switch(*options) {
  37. case '!':
  38. options++;
  39. if(*options != '=' && *options != ':')
  40. options--;
  41. g->comparison = countif_notequal;
  42. break;
  43. case '>':
  44. options++;
  45. if(*options == '=' || *options == ':') {
  46. g->comparison = countif_greaterequal;
  47. }
  48. else {
  49. options--;
  50. g->comparison = countif_greater;
  51. }
  52. break;
  53. case '<':
  54. options++;
  55. if(*options == '>') {
  56. g->comparison = countif_notequal;
  57. }
  58. else if(*options == '=' || *options == ':') {
  59. g->comparison = countif_lessequal;
  60. }
  61. else {
  62. options--;
  63. g->comparison = countif_less;
  64. }
  65. break;
  66. default:
  67. case '=':
  68. case ':':
  69. g->comparison = countif_equal;
  70. break;
  71. }
  72. if(*options) options++;
  73. // skip everything up to the first digit
  74. while(isspace(*options)) options++;
  75. g->target = str2ndd(options, NULL);
  76. }
  77. else {
  78. g->target = 0.0;
  79. g->comparison = countif_equal;
  80. }
  81. }
  82. // resets when switches dimensions
  83. // so, clear everything to restart
  84. void grouping_reset_countif(RRDR *r) {
  85. struct grouping_countif *g = (struct grouping_countif *)r->internal.grouping_data;
  86. g->matched = 0;
  87. g->count = 0;
  88. }
  89. void grouping_free_countif(RRDR *r) {
  90. onewayalloc_freez(r->internal.owa, r->internal.grouping_data);
  91. r->internal.grouping_data = NULL;
  92. }
  93. void grouping_add_countif(RRDR *r, NETDATA_DOUBLE value) {
  94. struct grouping_countif *g = (struct grouping_countif *)r->internal.grouping_data;
  95. g->matched += g->comparison(value, g->target);
  96. g->count++;
  97. }
  98. NETDATA_DOUBLE grouping_flush_countif(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) {
  99. struct grouping_countif *g = (struct grouping_countif *)r->internal.grouping_data;
  100. NETDATA_DOUBLE value;
  101. if(unlikely(!g->count)) {
  102. value = 0.0;
  103. *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY;
  104. }
  105. else {
  106. value = (NETDATA_DOUBLE)g->matched * 100 / (NETDATA_DOUBLE)g->count;
  107. }
  108. g->matched = 0;
  109. g->count = 0;
  110. return value;
  111. }