home *** CD-ROM | disk | FTP | other *** search
- #include "path.h"
-
- #include <windows.h>
-
- struct PathDescriptor
- {
- char* path;
- uint32_t max_length;
- uint32_t length;
- };
-
- void generate_file_path_prefix(PathDescriptor* const descriptor, const char prefix)
- {
- if (!descriptor->max_length) {
- return;
- } else if (descriptor->max_length == 1) {
- descriptor->path[0] = '\0';
- descriptor->length = 0;
- } else {
- descriptor->path[0] = prefix;
- descriptor->path[1] = '\0';
- descriptor->length = 1;
- }
- }
-
- uint32_t generate_file_path_key(const uint32_t c, const uint32_t key_length, const uint32_t id)
- {
- if (!key_length)
- return id;
-
- uint32_t mask = 1u << key_length;
- uint32_t key = id;
- for (unsigned int i = 0; i < key_length; ++i) {
- key <<= 1;
- if ((key & mask) != 0)
- key ^= c;
- }
-
- return key;
- }
-
- void append_to_file_path(PathDescriptor* const descriptor, char c)
- {
- if (descriptor->max_length - descriptor->length <= 1)
- return;
- descriptor->path[descriptor->length++] = c;
- descriptor->path[descriptor->length] = '\0';
- }
-
- void stringize_file_path_key(PathDescriptor* const descriptor, const uint32_t key, const uint32_t key_length)
- {
- if (!key_length)
- return;
-
- static const char kALPHABET[] = { "K59W4S6H7DOVJPERUQMT8BAIC2YLG30Z1FNX" };
- static const size_t kALPHABET_LENGTH = sizeof(kALPHABET) - 1;
-
- char key_string[16];
- memset(key_string, 0, sizeof(key_string));
-
- uint64_t x = key;
- for (uint32_t i = 0; i < key_length; ++i) {
- const uint64_t y = ((x * 954437177) >> 32) >> 3;
- const uint64_t z = x - (y * 4 + y * 32);
- assert(z >= 0 && z < kALPHABET_LENGTH);
- key_string[i] = kALPHABET[z];
- x = y;
- }
-
- uint32_t pos;
- if (key_length % 2 == 0) {
- append_to_file_path(descriptor, '/');
- append_to_file_path(descriptor, key_string[key_length - 1]);
- pos = key_length - 2;
- } else {
- pos = key_length - 1;
- }
-
- while (true) {
- append_to_file_path(descriptor, key_string[pos]);
- if (!pos)
- break;
- append_to_file_path(descriptor, '/');
- append_to_file_path(descriptor, key_string[pos - 1]);
- pos -= 2;
- }
- }
-
- char* generate_file_path(const uint32_t id, char* const path, const uint32_t max_length)
- {
- PathDescriptor descriptor;
- descriptor.path = path;
- descriptor.max_length = max_length;
-
- int32_t x = static_cast<int32_t>(id);
- if (x < 1024) {
- generate_file_path_prefix(&descriptor, 'K');
- stringize_file_path_key(&descriptor, generate_file_path_key(1177, 10, x), 2);
- return descriptor.path;
- }
- x -= 1024;
- if (x < 32768) {
- generate_file_path_prefix(&descriptor, '5');
- stringize_file_path_key(&descriptor, generate_file_path_key(34961, 15, x), 3);
- return descriptor.path;
- }
- x -= 32768;
- if (x < 1048576) {
- generate_file_path_prefix(&descriptor, '9');
- stringize_file_path_key(&descriptor, generate_file_path_key(1120393, 20, x), 4);
- return descriptor.path;
- }
- if (x - 1048576 < 33554432) {
- generate_file_path_prefix(&descriptor, 'W');
- stringize_file_path_key(&descriptor, generate_file_path_key(35922449, 25, x - 1048576), 5);
- return descriptor.path;
- }
- if (x - 34603008 >= 0) {
- generate_file_path_prefix(&descriptor, '4');
- stringize_file_path_key(&descriptor, generate_file_path_key(2290684177, 31, x - 34603008), 6);
- return descriptor.path;
- }
-
- return nullptr;
- }
-
- bool path_exists(const char* const path)
- {
- DWORD attributes = GetFileAttributesA(path);
- return attributes != INVALID_FILE_ATTRIBUTES;
- }
-
- bool file_exists(const char* const path)
- {
- DWORD attributes = GetFileAttributesA(path);
- return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
- }
-
- bool directory_exists(const char* const path)
- {
- DWORD attributes = GetFileAttributesA(path);
- return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
- }
-
- bool make_directory(const char* const path)
- {
- return CreateDirectoryA(path, nullptr) != FALSE;
- }
-
- bool make_directories(const char* const path)
- {
- char directory[_MAX_PATH];
-
- const char* part = path;
- while (*part != '\0') {
- const char* const delimeter = path_get_delimeter(part);
- if (*delimeter == '\0')
- break;
- const size_t part_length = delimeter - path;
-
- memset(directory, 0, sizeof(directory));
- strncpy(directory, path, part_length);
-
- if (!directory_exists(directory)) {
- if (!make_directory(directory))
- return false;
- }
-
- part = path_skip_delimeter(delimeter);
- }
-
- return true;
- }
-
- const char* path_get_delimeter(const char* const path)
- {
- if (*path == '\0' || *path == '/')
- return path;
-
- const char* p = path;
- do {
- p++;
- } while (*p != '\0' && *p != '/');
-
- return p;
- }
-
- const char* path_skip_delimeter(const char* const path)
- {
- if (*path != '/')
- return path;
-
- const char* p = path;
- do {
- p++;
- } while (*p == '/');
-
- return p;
- }
-