You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.3 KiB

10 years ago
  1. /* -*- coding: utf-8 -*-
  2. * ----------------------------------------------------------------------
  3. * Copyright © 2013, RedJack, LLC.
  4. * All rights reserved.
  5. *
  6. * Please see the COPYING file in this distribution for license details.
  7. * ----------------------------------------------------------------------
  8. */
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include "libcork/core/types.h"
  12. #include "libcork/core/u128.h"
  13. /* From http://stackoverflow.com/questions/8023414/how-to-convert-a-128-bit-integer-to-a-decimal-ascii-string-in-c */
  14. const char *
  15. cork_u128_to_decimal(char *dest, cork_u128 val)
  16. {
  17. uint32_t n[4];
  18. char *s = dest;
  19. char *p = dest;
  20. unsigned int i;
  21. /* This algorithm assumes that n[3] is the MSW. */
  22. n[3] = cork_u128_be32(val, 0);
  23. n[2] = cork_u128_be32(val, 1);
  24. n[1] = cork_u128_be32(val, 2);
  25. n[0] = cork_u128_be32(val, 3);
  26. memset(s, '0', CORK_U128_DECIMAL_LENGTH - 1);
  27. s[CORK_U128_DECIMAL_LENGTH - 1] = '\0';
  28. for (i = 0; i < 128; i++) {
  29. unsigned int j;
  30. unsigned int carry;
  31. carry = (n[3] >= 0x80000000);
  32. /* Shift n[] left, doubling it */
  33. n[3] = ((n[3] << 1) & 0xFFFFFFFF) + (n[2] >= 0x80000000);
  34. n[2] = ((n[2] << 1) & 0xFFFFFFFF) + (n[1] >= 0x80000000);
  35. n[1] = ((n[1] << 1) & 0xFFFFFFFF) + (n[0] >= 0x80000000);
  36. n[0] = ((n[0] << 1) & 0xFFFFFFFF);
  37. /* Add s[] to itself in decimal, doubling it */
  38. for (j = CORK_U128_DECIMAL_LENGTH - 1; j-- > 0; ) {
  39. s[j] += s[j] - '0' + carry;
  40. carry = (s[j] > '9');
  41. if (carry) {
  42. s[j] -= 10;
  43. }
  44. }
  45. }
  46. while ((p[0] == '0') && (p < &s[CORK_U128_DECIMAL_LENGTH - 2])) {
  47. p++;
  48. }
  49. return p;
  50. }
  51. const char *
  52. cork_u128_to_hex(char *buf, cork_u128 val)
  53. {
  54. uint64_t hi = val._.be64.hi;
  55. uint64_t lo = val._.be64.lo;
  56. if (hi == 0) {
  57. snprintf(buf, CORK_U128_HEX_LENGTH, "%" PRIx64, lo);
  58. } else {
  59. snprintf(buf, CORK_U128_HEX_LENGTH, "%" PRIx64 "%016" PRIx64, hi, lo);
  60. }
  61. return buf;
  62. }
  63. const char *
  64. cork_u128_to_padded_hex(char *buf, cork_u128 val)
  65. {
  66. uint64_t hi = val._.be64.hi;
  67. uint64_t lo = val._.be64.lo;
  68. snprintf(buf, CORK_U128_HEX_LENGTH, "%016" PRIx64 "%016" PRIx64, hi, lo);
  69. return buf;
  70. }