Logo
Home page Net-SNMP

Archive Search:

Require all words?

Site Search:
Google
Main Page | Modules | Data Structures | File List | Data Fields | Related Pages | Examples

int64.c

00001 
00008 #include <net-snmp/net-snmp-config.h>
00009 #include <sys/types.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 #if HAVE_STRING_H
00014 #include <string.h>
00015 #else
00016 #include <strings.h>
00017 #endif
00018 #if HAVE_WINSOCK_H
00019 #include <winsock.h>
00020 #endif
00021 
00022 #include <net-snmp/types.h>
00023 #include <net-snmp/library/int64.h>
00024 #include <net-snmp/library/snmp_assert.h>
00025 #include <net-snmp/library/snmp_debug.h>
00026 #include <net-snmp/library/snmp_logging.h>
00027 
00028 #define TRUE 1
00029 #define FALSE 0
00030 
00039 void
00040 divBy10(U64 u64, U64 * pu64Q, unsigned int *puR)
00041 {
00042     unsigned long   ulT;
00043     unsigned long   ulQ;
00044     unsigned long   ulR;
00045 
00046 
00047     /*
00048      * top 16 bits 
00049      */
00050     ulT = (u64.high >> 16) & 0x0ffff;
00051     ulQ = ulT / 10;
00052     ulR = ulT % 10;
00053     pu64Q->high = ulQ << 16;
00054 
00055     /*
00056      * next 16 
00057      */
00058     ulT = (u64.high & 0x0ffff);
00059     ulT += (ulR << 16);
00060     ulQ = ulT / 10;
00061     ulR = ulT % 10;
00062     pu64Q->high = pu64Q->high | ulQ;
00063 
00064     /*
00065      * next 16 
00066      */
00067     ulT = ((u64.low >> 16) & 0x0ffff) + (ulR << 16);
00068     ulQ = ulT / 10;
00069     ulR = ulT % 10;
00070     pu64Q->low = ulQ << 16;
00071 
00072     /*
00073      * final 16 
00074      */
00075     ulT = (u64.low & 0x0ffff);
00076     ulT += (ulR << 16);
00077     ulQ = ulT / 10;
00078     ulR = ulT % 10;
00079     pu64Q->low = pu64Q->low | ulQ;
00080 
00081     *puR = (unsigned int) (ulR);
00082 
00083 
00084 }                               /* divBy10 */
00085 
00086 
00094 void
00095 multBy10(U64 u64, U64 * pu64P)
00096 {
00097     unsigned long   ulT;
00098     unsigned long   ulP;
00099     unsigned long   ulK;
00100 
00101 
00102     /*
00103      * lower 16 bits 
00104      */
00105     ulT = u64.low & 0x0ffff;
00106     ulP = ulT * 10;
00107     ulK = ulP >> 16;
00108     pu64P->low = ulP & 0x0ffff;
00109 
00110     /*
00111      * next 16 
00112      */
00113     ulT = (u64.low >> 16) & 0x0ffff;
00114     ulP = (ulT * 10) + ulK;
00115     ulK = ulP >> 16;
00116     pu64P->low = (ulP & 0x0ffff) << 16 | pu64P->low;
00117 
00118     /*
00119      * next 16 bits 
00120      */
00121     ulT = u64.high & 0x0ffff;
00122     ulP = (ulT * 10) + ulK;
00123     ulK = ulP >> 16;
00124     pu64P->high = ulP & 0x0ffff;
00125 
00126     /*
00127      * final 16 
00128      */
00129     ulT = (u64.high >> 16) & 0x0ffff;
00130     ulP = (ulT * 10) + ulK;
00131     ulK = ulP >> 16;
00132     pu64P->high = (ulP & 0x0ffff) << 16 | pu64P->high;
00133 
00134 
00135 }                               /* multBy10 */
00136 
00137 
00145 void
00146 incrByU16(U64 * pu64, unsigned int u16)
00147 {
00148     unsigned long   ulT1;
00149     unsigned long   ulT2;
00150     unsigned long   ulR;
00151     unsigned long   ulK;
00152 
00153 
00154     /*
00155      * lower 16 bits 
00156      */
00157     ulT1 = pu64->low;
00158     ulT2 = ulT1 & 0x0ffff;
00159     ulR = ulT2 + u16;
00160     ulK = ulR >> 16;
00161     if (ulK == 0) {
00162         pu64->low = ulT1 + u16;
00163         return;
00164     }
00165 
00166     /*
00167      * next 16 bits 
00168      */
00169     ulT2 = (ulT1 >> 16) & 0x0ffff;
00170     ulR = ulT2 + 1;
00171     ulK = ulR >> 16;
00172     if (ulK == 0) {
00173         pu64->low = ulT1 + u16;
00174         return;
00175     }
00176 
00177     /*
00178      * next 32 - ignore any overflow 
00179      */
00180     pu64->low = (ulT1 + u16) & 0x0FFFFFFFFL;
00181     pu64->high++;
00182 #if SIZEOF_LONG != 4
00183     pu64->high &= 0xffffffff;
00184 #endif
00185 }                               /* incrByV16 */
00186 
00187 void
00188 incrByU32(U64 * pu64, unsigned int u32)
00189 {
00190     unsigned int    tmp;
00191     tmp = pu64->low;
00192     pu64->low += u32;
00193 #if SIZEOF_LONG != 4
00194     pu64->low &= 0xffffffff;
00195 #endif
00196     if (pu64->low < tmp) {
00197         pu64->high++;
00198 #if SIZEOF_LONG != 4
00199         pu64->high &= 0xffffffff;
00200 #endif
00201     }
00202 }
00203 
00207 void
00208 u64Subtract(const U64 * pu64one, const U64 * pu64two, U64 * pu64out)
00209 {
00210     if (pu64one->low < pu64two->low) {
00211         pu64out->low = 0xffffffff - pu64two->low + pu64one->low + 1;
00212         pu64out->high = pu64one->high - pu64two->high - 1;
00213     } else {
00214         pu64out->low = pu64one->low - pu64two->low;
00215         pu64out->high = pu64one->high - pu64two->high;
00216     }
00217 }
00218 
00222 void
00223 u64Incr(U64 * pu64out, const U64 * pu64one)
00224 {
00225     pu64out->high += pu64one->high;
00226 #if SIZEOF_LONG != 4
00227     pu64out->high &= 0xffffffff;
00228 #endif
00229     incrByU32(pu64out, pu64one->low);
00230 }
00231 
00235 void
00236 u64UpdateCounter(U64 * pu64out, const U64 * pu64one, const U64 * pu64two)
00237 {
00238     U64 tmp;
00239     u64Subtract(pu64one, pu64two, &tmp);
00240     u64Incr(pu64out, &tmp);
00241 }
00242 
00246 void
00247 u64Copy(U64 * pu64one, const U64 * pu64two)
00248 {
00249     pu64one->high = pu64two->high;
00250     pu64one->low =  pu64two->low;
00251 }
00252 
00259 void
00260 zeroU64(U64 * pu64)
00261 {
00262     pu64->low = 0;
00263     pu64->high = 0;
00264 }                               /* zeroU64 */
00265 
00266 
00273 int
00274 isZeroU64(const U64 * pu64)
00275 {
00276 
00277     if ((pu64->low == 0) && (pu64->high == 0))
00278         return (TRUE);
00279     else
00280         return (FALSE);
00281 
00282 }                               /* isZeroU64 */
00283 
00304 int
00305 netsnmp_c64_check_for_32bit_wrap(struct counter64 *old_val,
00306                                  struct counter64 *new_val,
00307                                  int adjust)
00308 {
00309     if( (NULL == old_val) || (NULL == new_val) )
00310         return -1;
00311 
00312     DEBUGMSGTL(("9:c64:check_wrap", "check wrap 0x%0x.0x%0x 0x%0x.0x%0x\n",
00313                 old_val->high, old_val->low, new_val->high, new_val->low));
00314     
00315     /*
00316      * check for wraps
00317      */
00318     if ((new_val->low >= old_val->low) &&
00319         (new_val->high == old_val->high)) {
00320         DEBUGMSGTL(("9:c64:check_wrap", "no wrap\n"));
00321         return 0;
00322     }
00323 
00324     /*
00325      * low wrapped. did high change?
00326      */
00327     if (new_val->high == old_val->high) {
00328         DEBUGMSGTL(("c64:check_wrap", "32 bit wrap\n"));
00329         if (adjust) {
00330             ++new_val->high;
00331 #if SIZEOF_LONG != 4
00332             new_val->high &= 0xffffffff;
00333 #endif
00334         }
00335         return 32;
00336     }
00337     else if ((new_val->high == (old_val->high + 1)) ||
00338              ((0 == new_val->high) && (0xffffffff == old_val->high))) {
00339         DEBUGMSGTL(("c64:check_wrap", "64 bit wrap\n"));
00340         return 64;
00341     }
00342 
00343     return -2;
00344 }
00345 
00381 int
00382 netsnmp_c64_check32_and_update(struct counter64 *prev_val, struct counter64 *new_val,
00383                                struct counter64 *old_prev_val, int *need_wrap_check)
00384 {
00385     int rc;
00386 
00387     /*
00388      * counters are 32bit or unknown (which we'll treat as 32bit).
00389      * update the prev values with the difference between the
00390      * new stats and the prev old_stats:
00391      *    prev->stats += (new->stats - prev->old_stats)
00392      */
00393     if ((NULL == need_wrap_check) || (0 != *need_wrap_check)) {
00394         rc = netsnmp_c64_check_for_32bit_wrap(old_prev_val,new_val, 1);
00395         if (rc < 0) {
00396             snmp_log(LOG_ERR,"c64 32 bit check failed\n");
00397             return -1;
00398         }
00399     }
00400     else
00401         rc = 0;
00402     
00403     /*
00404      * update previous values
00405      */
00406     (void) u64UpdateCounter(prev_val, new_val, old_prev_val);
00407 
00408     /*
00409      * if wrap check was 32 bit, undo adjust, now that prev is updated
00410      */
00411     if (32 == rc) {
00412         /*
00413          * check wrap incremented high, so reset it. (Because having
00414          * high set for a 32 bit counter will confuse us in the next update).
00415          */
00416         netsnmp_assert(1 == new_val->high);
00417         new_val->high = 0;
00418     }
00419     else if (64 == rc) {
00420         /*
00421          * if we really have 64 bit counters, the summing we've been
00422          * doing for prev values should be equal to the new values.
00423          */
00424         if ((prev_val->low != new_val->low) ||
00425             (prev_val->high != new_val->high)) {
00426             snmp_log(LOG_ERR, "looks like a 64bit wrap, but prev!=new\n");
00427             return -2;
00428         }
00429         else if (NULL != need_wrap_check)
00430             *need_wrap_check = 0;
00431     }
00432     
00433     return 0;
00434 }
00435 
00436 void
00437 printU64(char *buf,     /* char [I64CHARSZ+1]; */
00438                          const U64 * pu64) {
00439     U64             u64a;
00440     U64             u64b;
00441 
00442     char            aRes[I64CHARSZ + 1];
00443     unsigned int    u;
00444     int             j;
00445 
00446     u64a.high = pu64->high;
00447     u64a.low = pu64->low;
00448     aRes[I64CHARSZ] = 0;
00449     for (j = 0; j < I64CHARSZ; j++) {
00450         divBy10(u64a, &u64b, &u);
00451         aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u);
00452         u64a.high = u64b.high;
00453         u64a.low = u64b.low;
00454         if (isZeroU64(&u64a))
00455             break;
00456     }
00457     strcpy(buf, &aRes[(I64CHARSZ - 1) - j]);
00458 }
00459 
00460 void
00461 printI64(char *buf,     /* char [I64CHARSZ+1]; */
00462                          const U64 * pu64) {
00463     U64             u64a;
00464     U64             u64b;
00465 
00466     char            aRes[I64CHARSZ + 1];
00467     unsigned int    u;
00468     int             j, sign = 0;
00469 
00470     if (pu64->high & 0x80000000) {
00471         u64a.high = ~pu64->high;
00472         u64a.low = ~pu64->low;
00473         sign = 1;
00474         incrByU32(&u64a, 1);    /* bit invert and incr by 1 to print 2s complement */
00475     } else {
00476         u64a.high = pu64->high;
00477         u64a.low = pu64->low;
00478     }
00479 
00480     aRes[I64CHARSZ] = 0;
00481     for (j = 0; j < I64CHARSZ; j++) {
00482         divBy10(u64a, &u64b, &u);
00483         aRes[(I64CHARSZ - 1) - j] = (char) ('0' + u);
00484         u64a.high = u64b.high;
00485         u64a.low = u64b.low;
00486         if (isZeroU64(&u64a))
00487             break;
00488     }
00489     if (sign == 1) {
00490         aRes[(I64CHARSZ - 1) - j - 1] = '-';
00491         strcpy(buf, &aRes[(I64CHARSZ - 1) - j - 1]);
00492         return;
00493     }
00494     strcpy(buf, &aRes[(I64CHARSZ - 1) - j]);
00495 }
00496 
00497 int
00498 read64(U64 * i64, const char *str)
00499 {
00500     U64             i64p;
00501     unsigned int    u;
00502     int             sign = 0;
00503     int             ok = 0;
00504 
00505     zeroU64(i64);
00506     if (*str == '-') {
00507         sign = 1;
00508         str++;
00509     }
00510 
00511     while (*str && isdigit(*str)) {
00512         ok = 1;
00513         u = *str - '0';
00514         multBy10(*i64, &i64p);
00515         memcpy(i64, &i64p, sizeof(i64p));
00516         incrByU16(i64, u);
00517         str++;
00518     }
00519     if (sign) {
00520         i64->high = ~i64->high;
00521         i64->low = ~i64->low;
00522         incrByU16(i64, 1);
00523     }
00524     return ok;
00525 }
00526 
00527 
00528 
00529 
00530 #ifdef TESTING
00531 void
00532 main(int argc, char *argv[])
00533 {
00534     int             i;
00535     int             j;
00536     int             l;
00537     unsigned int    u;
00538     U64             u64a;
00539     U64             u64b;
00540 #define MXSZ 20
00541     char            aRes[MXSZ + 1];
00542 
00543 
00544     if (argc < 2) {
00545         printf("This program takes numbers from the command line\n"
00546                "and prints them out.\n" "Usage: test <unsignedInt>...\n");
00547         exit(1);
00548     }
00549 
00550     aRes[MXSZ] = 0;
00551 
00552     for (i = 1; i < argc; i++) {
00553         l = strlen(argv[i]);
00554         zeroU64(&u64a);
00555         for (j = 0; j < l; j++) {
00556             if (!isdigit(argv[i][j])) {
00557                 printf("Argument is not a number \"%s\"\n", argv[i]);
00558                 exit(1);
00559             }
00560             u = argv[i][j] - '0';
00561             multBy10(u64a, &u64b);
00562             u64a = u64b;
00563             incrByU16(&u64a, u);
00564         }
00565 
00566         printf("number \"%s\" in hex is '%08x%08x'h\n",
00567                argv[i], u64a.high, u64a.low);
00568 
00569         printf("number is \"%s\"\n", printU64(&u64a));
00570         for (j = 0; j < MXSZ; j++) {
00571             divBy10(u64a, &u64b, &u);
00572             aRes[(MXSZ - 1) - j] = (char) ('0' + u);
00573             u64a = u64b;
00574             if (isZeroU64(&u64a))
00575                 break;
00576         }
00577 
00578         printf("number is \"%s\"\n", &aRes[(MXSZ - 1) - j]);
00579     }
00580     exit(0);
00581 }                               /* main */
00582 #endif                          /* TESTING */
00583 
00584 /*
00585  * file: test.c 
00586  */

Generated on Fri Dec 30 13:47:45 2005 for net-snmp by  doxygen 1.3.9.1

Valid CSS!


Last modified: Thursday, 01-Mar-2007 16:20:09 PST
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.