parse_size.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "parse_size.h"
  2. #include <util/generic/yexception.h>
  3. #include <util/generic/ylimits.h>
  4. #include <util/string/cast.h>
  5. #include <util/stream/output.h>
  6. namespace {
  7. enum ESuffixShifts {
  8. ESS_KILO_BYTES = 10,
  9. ESS_MEGA_BYTES = 20,
  10. ESS_GIGA_BYTES = 30,
  11. ESS_TERA_BYTES = 40,
  12. };
  13. bool TryShiftValue(ui64& value, ui64 shift) {
  14. if (value > (Max<ui64>() >> shift)) {
  15. return false;
  16. }
  17. value <<= shift;
  18. return true;
  19. }
  20. ui64 ShiftValue(ui64 value, ui64 shift) {
  21. if (!TryShiftValue(value, shift)) {
  22. ythrow yexception() << "value overflow '" << value << " << " << shift << "'";
  23. } else {
  24. return value;
  25. }
  26. }
  27. }
  28. namespace NSize {
  29. ui64 ParseSize(TStringBuf str) {
  30. if (! str.size())
  31. ythrow yexception() << "Wrong size " << str;
  32. char suff = tolower(str[str.size() - 1]);
  33. if (isdigit(suff))
  34. return FromString<ui64>(str);
  35. ui64 shift = 1;
  36. switch (suff) {
  37. case 'k':
  38. shift = ESS_KILO_BYTES;
  39. break;
  40. case 'm':
  41. shift = ESS_MEGA_BYTES;
  42. break;
  43. case 'g':
  44. shift = ESS_GIGA_BYTES;
  45. break;
  46. case 't':
  47. shift = ESS_TERA_BYTES;
  48. break;
  49. default:
  50. ythrow yexception() << "Unknown suffix " << str;
  51. }
  52. ui64 value = FromString<ui64>(str.substr(0, str.size() - 1));
  53. if (!TryShiftValue(value, shift)) {
  54. ythrow yexception() << "Value overflow " << str;
  55. } else {
  56. return value;
  57. }
  58. }
  59. TSize FromKiloBytes(ui64 value) {
  60. return TSize(ShiftValue(value, ESS_KILO_BYTES));
  61. }
  62. TSize FromMegaBytes(ui64 value) {
  63. return TSize(ShiftValue(value, ESS_MEGA_BYTES));
  64. }
  65. TSize FromGigaBytes(ui64 value) {
  66. return TSize(ShiftValue(value, ESS_GIGA_BYTES));
  67. }
  68. TSize FromTeraBytes(ui64 value) {
  69. return TSize(ShiftValue(value, ESS_TERA_BYTES));
  70. }
  71. }
  72. template <>
  73. NSize::TSize FromStringImpl<NSize::TSize>(const char* data, size_t len) {
  74. return NSize::TSize(NSize::ParseSize(TStringBuf(data, len)));
  75. }
  76. template <>
  77. void Out<NSize::TSize>(IOutputStream& os, const NSize::TSize& size) {
  78. os << size.GetValue();
  79. }