home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 7662 / gttool_src_bin.7z / gttool / src / path.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2014-08-01  |  4.8 KB  |  200 lines

  1. #include "path.h"
  2.  
  3. #include <windows.h>
  4.  
  5. struct PathDescriptor
  6. {
  7.     char* path;
  8.     uint32_t max_length;
  9.     uint32_t length;
  10. };
  11.  
  12. void generate_file_path_prefix(PathDescriptor* const descriptor, const char prefix)
  13. {
  14.     if (!descriptor->max_length) {
  15.         return;
  16.     } else if (descriptor->max_length == 1) {
  17.         descriptor->path[0] = '\0';
  18.         descriptor->length = 0;
  19.     } else {
  20.         descriptor->path[0] = prefix;
  21.         descriptor->path[1] = '\0';
  22.         descriptor->length = 1;
  23.     }
  24. }
  25.  
  26. uint32_t generate_file_path_key(const uint32_t c, const uint32_t key_length, const uint32_t id)
  27. {
  28.     if (!key_length)
  29.         return id;
  30.  
  31.     uint32_t mask = 1u << key_length;
  32.     uint32_t key = id;
  33.     for (unsigned int i = 0; i < key_length; ++i) {
  34.         key <<= 1;
  35.         if ((key & mask) != 0)
  36.             key ^= c;
  37.     }
  38.  
  39.     return key;
  40. }
  41.  
  42. void append_to_file_path(PathDescriptor* const descriptor, char c)
  43. {
  44.     if (descriptor->max_length - descriptor->length <= 1)
  45.         return;
  46.     descriptor->path[descriptor->length++] = c;
  47.     descriptor->path[descriptor->length] = '\0';
  48. }
  49.  
  50. void stringize_file_path_key(PathDescriptor* const descriptor, const uint32_t key, const uint32_t key_length)
  51. {
  52.     if (!key_length)
  53.         return;
  54.  
  55.     static const char kALPHABET[] = { "K59W4S6H7DOVJPERUQMT8BAIC2YLG30Z1FNX" };
  56.     static const size_t kALPHABET_LENGTH = sizeof(kALPHABET) - 1;
  57.  
  58.     char key_string[16];
  59.     memset(key_string, 0, sizeof(key_string));
  60.  
  61.     uint64_t x = key;
  62.     for (uint32_t i = 0; i < key_length; ++i) {
  63.         const uint64_t y = ((x * 954437177) >> 32) >> 3;
  64.         const uint64_t z = x - (y * 4 + y * 32);
  65.         assert(z >= 0 && z < kALPHABET_LENGTH);
  66.         key_string[i] = kALPHABET[z];
  67.         x = y;
  68.     }
  69.  
  70.     uint32_t pos;
  71.     if (key_length % 2 == 0) {
  72.         append_to_file_path(descriptor, '/');
  73.         append_to_file_path(descriptor, key_string[key_length - 1]);
  74.         pos = key_length - 2;
  75.     } else {
  76.         pos = key_length - 1;
  77.     }
  78.  
  79.     while (true) {
  80.         append_to_file_path(descriptor, key_string[pos]);
  81.         if (!pos)
  82.             break;
  83.         append_to_file_path(descriptor, '/');
  84.         append_to_file_path(descriptor, key_string[pos - 1]);
  85.         pos -= 2;
  86.     }
  87. }
  88.  
  89. char* generate_file_path(const uint32_t id, char* const path, const uint32_t max_length)
  90. {
  91.     PathDescriptor descriptor;
  92.     descriptor.path = path;
  93.     descriptor.max_length = max_length;
  94.  
  95.     int32_t x = static_cast<int32_t>(id);
  96.     if (x < 1024) {
  97.         generate_file_path_prefix(&descriptor, 'K');
  98.         stringize_file_path_key(&descriptor, generate_file_path_key(1177, 10, x), 2);
  99.         return descriptor.path;
  100.     }
  101.     x -= 1024;
  102.     if (x < 32768) {
  103.         generate_file_path_prefix(&descriptor, '5');
  104.         stringize_file_path_key(&descriptor, generate_file_path_key(34961, 15, x), 3);
  105.         return descriptor.path;
  106.     }
  107.     x -= 32768;
  108.     if (x < 1048576) {
  109.         generate_file_path_prefix(&descriptor, '9');
  110.         stringize_file_path_key(&descriptor, generate_file_path_key(1120393, 20, x), 4);
  111.         return descriptor.path;
  112.     }
  113.     if (x - 1048576 < 33554432) {
  114.         generate_file_path_prefix(&descriptor, 'W');
  115.         stringize_file_path_key(&descriptor, generate_file_path_key(35922449, 25, x - 1048576), 5);
  116.         return descriptor.path;
  117.     }
  118.     if (x - 34603008 >= 0) {
  119.         generate_file_path_prefix(&descriptor, '4');
  120.         stringize_file_path_key(&descriptor, generate_file_path_key(2290684177, 31, x - 34603008), 6);
  121.         return descriptor.path;
  122.     }
  123.  
  124.     return nullptr;
  125. }
  126.  
  127. bool path_exists(const char* const path)
  128. {
  129.     DWORD attributes = GetFileAttributesA(path);
  130.     return attributes != INVALID_FILE_ATTRIBUTES;
  131. }
  132.  
  133. bool file_exists(const char* const path)
  134. {
  135.     DWORD attributes = GetFileAttributesA(path);
  136.     return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
  137. }
  138.  
  139. bool directory_exists(const char* const path)
  140. {
  141.     DWORD attributes = GetFileAttributesA(path);
  142.     return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  143. }
  144.  
  145. bool make_directory(const char* const path)
  146. {
  147.     return CreateDirectoryA(path, nullptr) != FALSE;
  148. }
  149.  
  150. bool make_directories(const char* const path)
  151. {
  152.     char directory[_MAX_PATH];
  153.  
  154.     const char* part = path;
  155.     while (*part != '\0') {
  156.         const char* const delimeter = path_get_delimeter(part);
  157.         if (*delimeter == '\0')
  158.             break;
  159.         const size_t part_length = delimeter - path;
  160.  
  161.         memset(directory, 0, sizeof(directory));
  162.         strncpy(directory, path, part_length);
  163.  
  164.         if (!directory_exists(directory)) {
  165.             if (!make_directory(directory))
  166.                 return false;
  167.         }
  168.  
  169.         part = path_skip_delimeter(delimeter);
  170.     }
  171.  
  172.     return true;
  173. }
  174.  
  175. const char* path_get_delimeter(const char* const path)
  176. {
  177.     if (*path == '\0' || *path == '/')
  178.         return path;
  179.  
  180.     const char* p = path;
  181.     do {
  182.         p++;
  183.     } while (*p != '\0' && *p != '/');
  184.  
  185.     return p;
  186. }
  187.  
  188. const char* path_skip_delimeter(const char* const path)
  189. {
  190.     if (*path != '/')
  191.         return path;
  192.  
  193.     const char* p = path;
  194.     do {
  195.         p++;
  196.     } while (*p == '/');
  197.  
  198.     return p;
  199. }
  200.