string_helpers.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /*
  2. * Helpers for formatting and printing strings
  3. *
  4. * Copyright 31 August 2008 James Bottomley
  5. */
  6. #include <linux/kernel.h>
  7. #include <linux/math64.h>
  8. #include <linux/module.h>
  9. #include <linux/string_helpers.h>
  10. /**
  11. * string_get_size - get the size in the specified units
  12. * @size: The size to be converted
  13. * @units: units to use (powers of 1000 or 1024)
  14. * @buf: buffer to format to
  15. * @len: length of buffer
  16. *
  17. * This function returns a string formatted to 3 significant figures
  18. * giving the size in the required units. Returns 0 on success or
  19. * error on failure. @buf is always zero terminated.
  20. *
  21. */
  22. int string_get_size(u64 size, const enum string_size_units units,
  23. char *buf, int len)
  24. {
  25. const char *units_10[] = { "B", "KB", "MB", "GB", "TB", "PB",
  26. "EB", "ZB", "YB", NULL};
  27. const char *units_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB",
  28. "EiB", "ZiB", "YiB", NULL };
  29. const char **units_str[] = {
  30. [STRING_UNITS_10] = units_10,
  31. [STRING_UNITS_2] = units_2,
  32. };
  33. const int divisor[] = {
  34. [STRING_UNITS_10] = 1000,
  35. [STRING_UNITS_2] = 1024,
  36. };
  37. int i, j;
  38. u64 remainder = 0, sf_cap;
  39. char tmp[8];
  40. tmp[0] = '\0';
  41. for (i = 0; size > divisor[units] && units_str[units][i]; i++)
  42. remainder = do_div(size, divisor[units]);
  43. sf_cap = size;
  44. for (j = 0; sf_cap*10 < 1000; j++)
  45. sf_cap *= 10;
  46. if (j) {
  47. remainder *= 1000;
  48. do_div(remainder, divisor[units]);
  49. snprintf(tmp, sizeof(tmp), ".%03lld",
  50. (unsigned long long)remainder);
  51. tmp[j+1] = '\0';
  52. }
  53. snprintf(buf, len, "%lld%s%s", (unsigned long long)size,
  54. tmp, units_str[units][i]);
  55. return 0;
  56. }
  57. EXPORT_SYMBOL(string_get_size);