#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#include <libutil.h>
#include "uinteger.h"
#include "preferences.h"
bool first_sample = true;
struct top_uinteger top_init_uinteger(uint64_t value, bool is_negative) {
struct top_uinteger r;
r.is_negative = is_negative;
r.value = value;
return r;
}
struct top_uinteger top_sub_uinteger(const struct top_uinteger *a, const struct top_uinteger *b) {
struct top_uinteger r;
if(!a->is_negative && !b->is_negative) {
if(a->value > b->value) {
r.is_negative = false;
r.value = a->value - b->value;
} else {
r.is_negative = true;
r.value = b->value - a->value;
}
} else if (a->is_negative && !b->is_negative) {
r.is_negative = true;
r.value = a->value + b->value;
} else if(!a->is_negative && b->is_negative) {
r.is_negative = false;
r.value = a->value + b->value;
} else {
r.is_negative = true;
r.value = a->value + b->value;
}
if(0 == r.value)
r.is_negative = 0;
return r;
}
bool top_humanize_uinteger(char *buf, size_t bufsize,
struct top_uinteger i) {
if(i.is_negative) {
if(-1 == humanize_number(buf + 1, bufsize - 1,
(int64_t)i.value, "",
HN_AUTOSCALE, HN_NOSPACE | HN_B)) {
return true;
}
buf[0] = '-';
} else {
if(-1 == humanize_number(buf, bufsize,
(int64_t)i.value, "",
HN_AUTOSCALE, HN_NOSPACE | HN_B)) {
return true;
}
}
return false;
}
bool top_sprint_uinteger(char *buf, size_t bufsize,
struct top_uinteger i) {
if(i.is_negative) {
if(-1 == snprintf(buf, bufsize, "-%" PRIu64, i.value))
return true;
} else {
if(-1 == snprintf(buf, bufsize, "%" PRIu64, i.value))
return true;
}
return false;
}
struct top_uinteger top_uinteger_calc_result(uint64_t now, uint64_t prev,
uint64_t beg) {
struct top_uinteger result, prevu, begu;
result = top_init_uinteger(now, false);
switch(top_prefs_get_mode()) {
case STATMODE_ACCUM:
begu = top_init_uinteger(beg, false);
result = top_sub_uinteger(&result, &begu);
break;
case STATMODE_DELTA:
prevu = top_init_uinteger(prev, false);
result = top_sub_uinteger(&result, &prevu);
break;
}
return result;
}
bool top_uinteger_format_result(char *buf, size_t bufsize, uint64_t now,
uint64_t prev, uint64_t beg) {
struct top_uinteger i;
int suffix = '\0';
i = top_uinteger_calc_result(now, prev, beg);
if(STATMODE_DELTA == top_prefs_get_mode()) {
if(top_sprint_uinteger(buf, bufsize, i)) {
return true;
}
} else {
if (!first_sample) {
if(now < prev) {
suffix = '-';
} else if(now > prev) {
suffix = '+';
}
}
if(-1 == snprintf(buf, bufsize, "%s%" PRIu64 "%c",
(i.is_negative ? "-" : ""),
i.value, suffix)) {
return true;
}
}
return false;
}
bool top_uinteger_format_mem_result(char *buf, size_t bufsize, uint64_t now,
uint64_t prev, uint64_t beg) {
struct top_uinteger i;
size_t len;
i = top_uinteger_calc_result(now, prev, beg);
if(STATMODE_DELTA == top_prefs_get_mode()) {
if(top_humanize_uinteger(buf, bufsize, i)) {
return true;
}
} else {
if(top_humanize_uinteger(buf, bufsize - 1, i)) {
return true;
}
len = strlen(buf);
if((len + 2) <= bufsize && !first_sample) {
if(now < prev) {
buf[len] = '-';
buf[len + 1] = '\0';
} else if(now > prev) {
buf[len] = '+';
buf[len + 1] = '\0';
}
}
}
return false;
}