以下代码将字符串形式的尺寸描述转换成字节数

时间:2022-12-14 22:42:40
  1 #include <stdio.h>
  2 
  3 #define SECTOR_SIZE_DEFAULT   512LL
  4 #define KILOBYTE_SIZE 1000LL
  5 #define MEGABYTE_SIZE 1000000LL
  6 #define GIGABYTE_SIZE 1000000000LL
  7 #define TERABYTE_SIZE 1000000000000LL
  8 #define KIBIBYTE_SIZE 1024LL
  9 #define MEBIBYTE_SIZE 1048576LL
 10 #define GIBIBYTE_SIZE 1073741824LL
 11 #define TEBIBYTE_SIZE 1099511627776LL
 12 
 13 typedef enum {
 14     DIGIT_UNIT_BYTE,
 15     DIGIT_UNIT_KILOBYTE,
 16     DIGIT_UNIT_MEGABYTE,
 17     DIGIT_UNIT_GIGABYTE,
 18     DIGIT_UNIT_TERABYTE,
 19     DIGIT_UNIT_KIBIBYTE,
 20     DIGIT_UNIT_MEBIBYTE,
 21     DIGIT_UNIT_GIBIBYTE,
 22     DIGIT_UNIT_TEBIBYTE
 23 } DigitUnit;
 24 
 25 /* Inefficiently removes all spaces from a string, in-place. */
 26 static void
 27 strip_string (char* str)
 28 {
 29     int i;
 30 
 31     for (i = 0; str[i] != 0; i++) {
 32         if (isspace (str[i])) {
 33             int j;
 34             for (j = i + 1; str[j] != 0; j++)
 35                 str[j - 1] = str[j];
 36         }
 37     }
 38 }
 39 
 40 /* Find non-number suffix.  Eg: find_suffix("32Mb") returns a pointer to
 41  * "Mb". */
 42 static char*
 43 find_suffix (const char* str)
 44 {
 45     while (str[0] != 0 && (isdigit (str[0]) || strchr(",.-", str[0])))
 46         str++;
 47     return (char *) str;
 48 }
 49 
 50 static DigitUnit
 51 parse_unit_suffix (const char* suffix)
 52 {
 53     if (strlen (suffix) > 1 && tolower (suffix[1]) == 'i') {
 54         switch (tolower (suffix[0])) {
 55             case 'k': return DIGIT_UNIT_KIBIBYTE;
 56             case 'm': return DIGIT_UNIT_MEBIBYTE;
 57             case 'g': return DIGIT_UNIT_GIBIBYTE;
 58             case 't': return DIGIT_UNIT_TEBIBYTE;
 59         }
 60     } else if (strlen (suffix) > 0) {
 61         switch (tolower (suffix[0])) {
 62             case 'b': return DIGIT_UNIT_BYTE;
 63             case 'k': return DIGIT_UNIT_KILOBYTE;
 64             case 'm': return DIGIT_UNIT_MEGABYTE;
 65             case 'g': return DIGIT_UNIT_GIGABYTE;
 66             case 't': return DIGIT_UNIT_TERABYTE;
 67         }
 68     }
 69 
 70     return -1;
 71 }
 72 
 73 long long unit_parse (const char *str)
 74 {
 75     char *suffix;
 76     long long byte = -1;
 77     long long byte_block = 1;
 78 
 79     strip_string (str);
 80     suffix = find_suffix (str);
 81 
 82     DigitUnit unit = parse_unit_suffix (suffix);
 83 
 84     switch (unit) {
 85     case DIGIT_UNIT_BYTE:
 86         break;
 87     case DIGIT_UNIT_KILOBYTE:
 88         byte_block = KILOBYTE_SIZE;
 89         break;
 90     case DIGIT_UNIT_MEGABYTE:
 91         byte_block = MEGABYTE_SIZE;
 92         break;
 93     case DIGIT_UNIT_GIGABYTE:
 94         byte_block = GIGABYTE_SIZE;
 95         break;
 96     case DIGIT_UNIT_TERABYTE:
 97         byte_block = TERABYTE_SIZE;
 98         break;
 99     case DIGIT_UNIT_KIBIBYTE:
100         byte_block = KIBIBYTE_SIZE;
101         break;
102     case DIGIT_UNIT_MEBIBYTE:
103         byte_block = MEBIBYTE_SIZE;
104         break;
105     case DIGIT_UNIT_GIBIBYTE:
106         byte_block = GIBIBYTE_SIZE;
107         break;
108     case DIGIT_UNIT_TEBIBYTE:
109         byte_block = TEBIBYTE_SIZE;
110         break;
111     }
112 
113     double temp = 0;
114     if (sscanf (str, "%lf", &temp) == 1)
115         byte = temp * byte_block;
116 
117     return byte;
118 }
119 
120 
121 int main (int argc, char **argv)
122 {
123     if (argc > 1)
124         printf ("%lld\n", unit_parse (argv[1]));
125     return 0;
126 }