1/* 2 * Copyright (c) 2008 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <stdbool.h> 24#include <string.h> 25#include <inttypes.h> 26#include <libutil.h> 27#include "uinteger.h" 28#include "preferences.h" 29 30struct top_uinteger top_init_uinteger(uint64_t value, bool is_negative) { 31 struct top_uinteger r; 32 33 r.is_negative = is_negative; 34 r.value = value; 35 36 return r; 37} 38 39struct top_uinteger top_sub_uinteger(const struct top_uinteger *a, const struct top_uinteger *b) { 40 struct top_uinteger r; 41 42 if(!a->is_negative && !b->is_negative) { 43 if(a->value > b->value) { 44 /* The value will fit without underflow. */ 45 r.is_negative = false; 46 r.value = a->value - b->value; 47 } else { 48 /* B is larger or we have a r.value of 0. */ 49 r.is_negative = true; 50 r.value = b->value - a->value; 51 } 52 } else if (a->is_negative && !b->is_negative) { 53 /* A is negative and B is positive. */ 54 r.is_negative = true; 55 /* 56 * The A value is negative, so actually add the amount we would subtract. 57 * Thus if a is -5 and b is 2: -5 - 2 = -7; 58 */ 59 r.value = a->value + b->value; 60 } else if(!a->is_negative && b->is_negative) { 61 /* A is positive and b is negative. */ 62 r.is_negative = false; 63 /* 64 * If say A is 2 and b is -3 we want value to be: 2 - -3 = 5; 65 */ 66 r.value = a->value + b->value; 67 } else { 68 /* They are both negative. */ 69 r.is_negative = true; 70 r.value = a->value + b->value; 71 } 72 73 if(0 == r.value) 74 r.is_negative = 0; 75 76 return r; 77} 78 79/* Return true if an error occurred. */ 80bool top_humanize_uinteger(char *buf, size_t bufsize, 81 struct top_uinteger i) { 82 83 if(i.is_negative) { 84 if(-1 == humanize_number(buf + 1, bufsize - 1, 85 (int64_t)i.value, "", 86 HN_AUTOSCALE, HN_NOSPACE | HN_B)) { 87 return true; 88 } 89 buf[0] = '-'; 90 } else { 91 if(-1 == humanize_number(buf, bufsize, 92 (int64_t)i.value, "", 93 HN_AUTOSCALE, HN_NOSPACE | HN_B)) { 94 return true; 95 } 96 } 97 98 return false; 99} 100 101bool top_sprint_uinteger(char *buf, size_t bufsize, 102 struct top_uinteger i) { 103 104 if(i.is_negative) { 105 if(-1 == snprintf(buf, bufsize, "-%" PRIu64, i.value)) 106 return true; 107 } else { 108 if(-1 == snprintf(buf, bufsize, "%" PRIu64, i.value)) 109 return true; 110 } 111 112 return false; 113} 114 115struct top_uinteger top_uinteger_calc_result(uint64_t now, uint64_t prev, 116 uint64_t beg) { 117 struct top_uinteger result, prevu, begu; 118 119 result = top_init_uinteger(now, false); 120 121 switch(top_prefs_get_mode()) { 122 case STATMODE_ACCUM: 123 begu = top_init_uinteger(beg, false); 124 result = top_sub_uinteger(&result, &begu); 125 break; 126 127 case STATMODE_DELTA: 128 prevu = top_init_uinteger(prev, false); 129 result = top_sub_uinteger(&result, &prevu); 130 break; 131 } 132 133 return result; 134} 135 136/* Return true if an error occurred. */ 137bool top_uinteger_format_result(char *buf, size_t bufsize, uint64_t now, 138 uint64_t prev, uint64_t beg) { 139 struct top_uinteger i; 140 int suffix = '\0'; 141 142 i = top_uinteger_calc_result(now, prev, beg); 143 144 if(STATMODE_DELTA == top_prefs_get_mode()) { 145 /* We don't need a suffix in delta mode. */ 146 if(top_sprint_uinteger(buf, bufsize, i)) { 147 return true; 148 } 149 } else { 150 if(now < prev) { 151 /* The value has decreased since the previous sample. */ 152 suffix = '-'; 153 } else if(now > prev) { 154 suffix = '+'; 155 } 156 157 if(-1 == snprintf(buf, bufsize, "%s%" PRIu64 "%c", 158 (i.is_negative ? "-" : ""), 159 i.value, 160 suffix)) { 161 return true; 162 } 163 } 164 165 return false; 166} 167 168 169/* Return true if an error occurred. */ 170bool top_uinteger_format_mem_result(char *buf, size_t bufsize, uint64_t now, 171 uint64_t prev, uint64_t beg) { 172 struct top_uinteger i; 173 size_t len; 174 175 i = top_uinteger_calc_result(now, prev, beg); 176 177 if(STATMODE_DELTA == top_prefs_get_mode()) { 178 /* We don't need a suffix in delta mode. */ 179 if(top_humanize_uinteger(buf, bufsize, i)) { 180 return true; 181 } 182 } else { 183 if(top_humanize_uinteger(buf, bufsize - 1, i)) { 184 return true; 185 } 186 187 len = strlen(buf); 188 189 if((len + 2) <= bufsize) { 190 if(now < prev) { 191 buf[len] = '-'; 192 buf[len + 1] = '\0'; 193 } else if(now > prev) { 194 buf[len] = '+'; 195 buf[len + 1] = '\0'; 196 } 197 } 198 } 199 200 return false; 201} 202