diff options
Diffstat (limited to 'zen')
-rw-r--r-- | zen/crc.h | 101 | ||||
-rw-r--r-- | zen/file_access.cpp | 43 | ||||
-rw-r--r-- | zen/file_access.h | 8 | ||||
-rw-r--r-- | zen/json.h | 2 | ||||
-rw-r--r-- | zen/legacy_compiler.h | 1 | ||||
-rw-r--r-- | zen/open_ssl.cpp | 1 | ||||
-rw-r--r-- | zen/recycler.cpp | 2 | ||||
-rw-r--r-- | zen/scope_guard.h | 3 | ||||
-rw-r--r-- | zen/serialize.h | 11 | ||||
-rw-r--r-- | zen/stl_tools.h | 68 | ||||
-rw-r--r-- | zen/string_base.h | 2 | ||||
-rw-r--r-- | zen/string_tools.h | 8 | ||||
-rw-r--r-- | zen/zstring.cpp | 8 | ||||
-rw-r--r-- | zen/zstring.h | 12 |
14 files changed, 143 insertions, 127 deletions
@@ -28,31 +28,31 @@ inline uint32_t getCrc32(const std::string& str) { return getCrc32(str.begin(), template <class ByteIterator> inline uint16_t getCrc16(ByteIterator first, ByteIterator last) //http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html { - constexpr uint16_t crcTable[] = - { - 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, - 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, - 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, - 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, - 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, - 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, - 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, - 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, - 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, - 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, - 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, - 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, - 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, - 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, - 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, - 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 - }; - static_assert(arraySize(crcTable) == 256 && arrayAccumulate<uint32_t>(crcTable) == 8380544); static_assert(sizeof(typename std::iterator_traits<ByteIterator>::value_type) == 1); uint16_t crc = 0; std::for_each(first, last, [&](unsigned char b) { + constexpr uint16_t crcTable[] = + { + 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, + 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, + 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, + 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, + 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, + 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, + 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, + 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, + 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, + 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, + 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, + 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, + 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, + 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, + 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, + 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040 + }; + static_assert(arraySize(crcTable) == 256 && arrayAccumulate<uint32_t>(crcTable) == 8380544); crc = (crc >> 8) ^ crcTable[(crc ^ b) & 0xFF]; }); return crc; @@ -62,41 +62,42 @@ uint16_t getCrc16(ByteIterator first, ByteIterator last) //http://www.sunshine2k template <class ByteIterator> inline uint32_t getCrc32(ByteIterator first, ByteIterator last) //https://en.wikipedia.org/wiki/Cyclic_redundancy_check { - constexpr uint32_t crcTable[] = - { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - static_assert(arraySize(crcTable) == 256 && arrayAccumulate<uint64_t>(crcTable) == 549755813760); static_assert(sizeof(typename std::iterator_traits<ByteIterator>::value_type) == 1); uint32_t crc = 0xFFFFFFFF; std::for_each(first, last, [&](unsigned char b) { + constexpr uint32_t crcTable[] = + { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d + }; + static_assert(arraySize(crcTable) == 256 && arrayAccumulate<uint64_t>(crcTable) == 549755813760); + crc = (crc >> 8) ^ crcTable[(crc ^ b) & 0xFF]; }); return crc ^ 0xFFFFFFFF; diff --git a/zen/file_access.cpp b/zen/file_access.cpp index 9a49cd55..8f021843 100644 --- a/zen/file_access.cpp +++ b/zen/file_access.cpp @@ -101,10 +101,10 @@ ItemType zen::getItemType(const Zstring& itemPath) //throw FileError THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot read file attributes of %x."), L"%x", fmtPath(itemPath)), "lstat"); if (S_ISLNK(itemInfo.st_mode)) - return ItemType::SYMLINK; + return ItemType::symlink; if (S_ISDIR(itemInfo.st_mode)) - return ItemType::FOLDER; - return ItemType::FILE; //S_ISREG || S_ISCHR || S_ISBLK || S_ISFIFO || S_ISSOCK + return ItemType::folder; + return ItemType::file; //S_ISREG || S_ISCHR || S_ISBLK || S_ISFIFO || S_ISSOCK } @@ -128,13 +128,13 @@ std::optional<ItemType> zen::itemStillExists(const Zstring& itemPath) //throw Fi const std::optional<ItemType> parentType = itemStillExists(*parentPath); //throw FileError - if (parentType && *parentType != ItemType::FILE /*obscure, but possible (and not an error)*/) + if (parentType && *parentType != ItemType::file /*obscure, but possible (and not an error)*/) try { traverseFolder(*parentPath, - [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::FILE; }, - [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::FOLDER; }, - [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::SYMLINK; }, + [&](const FileInfo& fi) { if (fi.itemName == itemName) throw ItemType::file; }, + [&](const FolderInfo& fi) { if (fi.itemName == itemName) throw ItemType::folder; }, + [&](const SymlinkInfo& si) { if (si.itemName == itemName) throw ItemType::symlink; }, [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); } catch (const ItemType&) //finding the item after getItemType() previously failed is exceptional @@ -171,13 +171,13 @@ namespace } -uint64_t zen::getFreeDiskSpace(const Zstring& path) //throw FileError, returns 0 if not available +int64_t zen::getFreeDiskSpace(const Zstring& path) //throw FileError, returns < 0 if not available { struct ::statfs info = {}; if (::statfs(path.c_str(), &info) != 0) THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot determine free disk space for %x."), L"%x", fmtPath(path)), "statfs"); - - return static_cast<uint64_t>(info.f_bsize) * info.f_bavail; + + return static_cast<int64_t>(info.f_bsize) * info.f_bavail; } @@ -237,7 +237,7 @@ void zen::removeDirectoryPlain(const Zstring& dirPath) //throw FileError { ErrorCode ec = getLastError(); //copy before making other system calls! bool symlinkExists = false; - try { symlinkExists = getItemType(dirPath) == ItemType::SYMLINK; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant + try { symlinkExists = getItemType(dirPath) == ItemType::symlink; } /*throw FileError*/ catch (FileError&) {} //previous exception is more relevant if (symlinkExists) { @@ -288,7 +288,7 @@ void removeDirectoryImpl(const Zstring& folderPath) //throw FileError void zen::removeDirectoryPlainRecursion(const Zstring& dirPath) //throw FileError { - if (getItemType(dirPath) == ItemType::SYMLINK) //throw FileError + if (getItemType(dirPath) == ItemType::symlink) //throw FileError removeSymlinkPlain(dirPath); //throw FileError else removeDirectoryImpl(dirPath); //throw FileError @@ -503,7 +503,7 @@ void zen::copyItemPermissions(const Zstring& sourcePath, const Zstring& targetPa if (::lchown(targetPath.c_str(), fileInfo.st_uid, fileInfo.st_gid) != 0) // may require admin rights! THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(targetPath)), "lchown"); - const bool isSymlinkTarget = getItemType(targetPath) == ItemType::SYMLINK; //throw FileError + const bool isSymlinkTarget = getItemType(targetPath) == ItemType::symlink; //throw FileError if (!isSymlinkTarget && //setting access permissions doesn't make sense for symlinks on Linux: there is no lchmod() ::chmod(targetPath.c_str(), fileInfo.st_mode) != 0) THROW_LAST_FILE_ERROR(replaceCpy(_("Cannot write permissions of %x."), L"%x", fmtPath(targetPath)), "chmod"); @@ -516,10 +516,15 @@ void zen::createDirectory(const Zstring& dirPath) //throw FileError, ErrorTarget { auto getErrorMsg = [&] { return replaceCpy(_("Cannot create directory %x."), L"%x", fmtPath(dirPath)); }; - //deliberately don't support creating irregular folders like "...." https://social.technet.microsoft.com/Forums/windows/en-US/ffee2322-bb6b-4fdf-86f9-8f93cf1fa6cb/ - if (endsWith(dirPath, Zstr(' ')) || - endsWith(dirPath, Zstr('.'))) - throw FileError(getErrorMsg(), replaceCpy<std::wstring>(L"Invalid trailing character \"%x\".", L"%x", utfTo<std::wstring>(dirPath.end()[-1]))); + //don't allow creating irregular folders like "...." https://social.technet.microsoft.com/Forums/windows/en-US/ffee2322-bb6b-4fdf-86f9-8f93cf1fa6cb/ + const Zstring dirName = afterLast(dirPath, FILE_NAME_SEPARATOR, IF_MISSING_RETURN_ALL); + if (std::all_of(dirName.begin(), dirName.end(), [](Zchar c) { return c == Zstr('.'); })) + /**/throw FileError(getErrorMsg(), replaceCpy<std::wstring>(L"Invalid folder name %x.", L"%x", fmtPath(dirName))); + + //not critical, but will visually confuse user sooner or later: + if (startsWith(dirName, Zstr(' ')) || + endsWith (dirName, Zstr(' '))) + throw FileError(getErrorMsg(), replaceCpy<std::wstring>(L"Folder name %x starts/ends with space character.", L"%x", fmtPath(dirName))); const mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; //0777, default for newly created directories @@ -545,7 +550,7 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File try //generally we expect that path already exists (see: ffs_paths.cpp) => check first { - if (getItemType(dirPath) != ItemType::FILE) //throw FileError + if (getItemType(dirPath) != ItemType::file) //throw FileError return; } catch (FileError&) {} //not yet existing or access error? let's find out... @@ -560,7 +565,7 @@ void zen::createDirectoryIfMissingRecursion(const Zstring& dirPath) //throw File { try { - if (getItemType(dirPath) != ItemType::FILE) //throw FileError + if (getItemType(dirPath) != ItemType::file) //throw FileError return; //already existing => possible, if createDirectoryIfMissingRecursion() is run in parallel } catch (FileError&) {} //not yet existing or access error diff --git a/zen/file_access.h b/zen/file_access.h index 8fdbde68..66c41fbd 100644 --- a/zen/file_access.h +++ b/zen/file_access.h @@ -33,9 +33,9 @@ bool dirAvailable (const Zstring& dirPath ); // enum class ItemType { - FILE, - FOLDER, - SYMLINK, + file, + folder, + symlink, }; //(hopefully) fast: does not distinguish between error/not existing ItemType getItemType(const Zstring& itemPath); //throw FileError @@ -53,7 +53,7 @@ enum class ProcSymlink void setFileTime(const Zstring& filePath, time_t modTime, ProcSymlink procSl); //throw FileError //symlink handling: always follow: -uint64_t getFreeDiskSpace(const Zstring& path); //throw FileError, returns 0 if not available +int64_t getFreeDiskSpace(const Zstring& path); //throw FileError, returns < 0 if not available VolumeId getVolumeId(const Zstring& itemPath); //throw FileError uint64_t getFileSize(const Zstring& filePath); //throw FileError @@ -43,7 +43,7 @@ struct JsonValue std::string serializeJson(const JsonValue& jval, - const std::string& lineBreak = "\r\n", + const std::string& lineBreak = "\n", const std::string& indent = " "); //noexcept diff --git a/zen/legacy_compiler.h b/zen/legacy_compiler.h index b480aa6d..13cdd8d0 100644 --- a/zen/legacy_compiler.h +++ b/zen/legacy_compiler.h @@ -9,7 +9,6 @@ #include <numbers> //C++20 - #include <span> //requires C++20 diff --git a/zen/open_ssl.cpp b/zen/open_ssl.cpp index 64b20bb3..f436875b 100644 --- a/zen/open_ssl.cpp +++ b/zen/open_ssl.cpp @@ -5,6 +5,7 @@ // ***************************************************************************** #include "open_ssl.h" +#include <stdexcept> #include "base64.h" #include "build_info.h" #include <openssl/pem.h> diff --git a/zen/recycler.cpp b/zen/recycler.cpp index 4d6ea1fd..28b2d6c1 100644 --- a/zen/recycler.cpp +++ b/zen/recycler.cpp @@ -34,7 +34,7 @@ bool zen::recycleOrDeleteIfExists(const Zstring& itemPath) //throw FileError //implement same behavior as in Windows: if recycler is not existing, delete permanently if (error && error->code == G_IO_ERROR_NOT_SUPPORTED) { - if (*type == ItemType::FOLDER) + if (*type == ItemType::folder) removeDirectoryPlainRecursion(itemPath); //throw FileError else removeFilePlain(itemPath); //throw FileError diff --git a/zen/scope_guard.h b/zen/scope_guard.h index 5d3ac411..846d5663 100644 --- a/zen/scope_guard.h +++ b/zen/scope_guard.h @@ -60,8 +60,7 @@ template <typename F> inline void runScopeGuardDestructor(F& fun, bool failed, std::integral_constant<ScopeGuardRunMode, ScopeGuardRunMode::onFail>) noexcept { if (failed) - try { fun(); } - catch (...) { assert(false); } + try { fun(); } catch (...) { assert(false); } } diff --git a/zen/serialize.h b/zen/serialize.h index 1eabcdec..a34f91a7 100644 --- a/zen/serialize.h +++ b/zen/serialize.h @@ -183,6 +183,11 @@ BinContainer bufferedLoad(BufferedInputStream& streamIn) //throw X if (bytesRead < blockSize) //end of file { buffer.resize(buffer.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics + + //caveat: memory consumption of returned string! + if (buffer.capacity() > buffer.size() * 3 / 2) //reference: in worst case, std::vector with growth factor 1.5 "wastes" 50% of its size as unused capacity + buffer.shrink_to_fit(); //=> shrink if buffer is wasting more than that! + return buffer; } } @@ -199,7 +204,7 @@ void writeArray(BufferedOutputStream& stream, const void* buffer, size_t len) template <class N, class BufferedOutputStream> inline void writeNumber(BufferedOutputStream& stream, const N& num) { - static_assert(IsArithmetic<N>::value || std::is_same_v<N, bool>); + static_assert(IsArithmetic<N>::value || std::is_same_v<N, bool> || std::is_enum_v<N>); writeArray(stream, &num, sizeof(N)); } @@ -227,8 +232,8 @@ void readArray(BufferedInputStream& stream, void* buffer, size_t len) //throw Un template <class N, class BufferedInputStream> inline N readNumber(BufferedInputStream& stream) //throw UnexpectedEndOfStreamError { - static_assert(IsArithmetic<N>::value || std::is_same_v<N, bool>); - N num = 0; + static_assert(IsArithmetic<N>::value || std::is_same_v<N, bool> || std::is_enum_v<N>); + N num{}; readArray(stream, &num, sizeof(N)); //throw UnexpectedEndOfStreamError return num; } diff --git a/zen/stl_tools.h b/zen/stl_tools.h index 8856ce84..5fd29b6b 100644 --- a/zen/stl_tools.h +++ b/zen/stl_tools.h @@ -55,23 +55,6 @@ void mergeTraversal(Iterator first1, Iterator last1, Iterator first2, Iterator last2, FunctionLeftOnly lo, FunctionBoth bo, FunctionRightOnly ro); - -template <class Num, class ByteIterator> Num hashBytes (ByteIterator first, ByteIterator last); -template <class Num, class ByteIterator> Num hashBytesAppend(Num hashVal, ByteIterator first, ByteIterator last); - -//support for custom string classes in std::unordered_set/map -struct StringHash -{ - template <class String> - size_t operator()(const String& str) const - { - const auto* strFirst = strBegin(str); - return hashBytes<size_t>(reinterpret_cast<const char*>(strFirst), - reinterpret_cast<const char*>(strFirst + strLength(str))); - } -}; - - //why, oh why is there no std::optional<T>::get()??? template <class T> inline T* get( std::optional<T>& opt) { return opt ? &*opt : nullptr; } template <class T> inline const T* get(const std::optional<T>& opt) { return opt ? &*opt : nullptr; } @@ -255,30 +238,53 @@ void mergeTraversal(Iterator first1, Iterator last1, //FNV-1a: https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function -template <class Num, class ByteIterator> inline -Num hashBytes(ByteIterator first, ByteIterator last) +template <class Num> +class FNV1aHash { - static_assert(IsInteger<Num>::value); +public: + FNV1aHash() {} + + void add(Num n) + { + hashVal_ ^= n; + hashVal_ *= prime_; + } + + Num get() const { return hashVal_; } + +private: + static_assert(IsUnsignedInt<Num>::value); static_assert(sizeof(Num) == 4 || sizeof(Num) == 8); //macOS: size_t is "unsigned long" - constexpr Num base = sizeof(Num) == 4 ? 2166136261U : 14695981039346656037ULL; + static constexpr Num base_ = sizeof(Num) == 4 ? 2166136261U : 14695981039346656037ULL; + static constexpr Num prime_ = sizeof(Num) == 4 ? 16777619U : 1099511628211ULL; - return hashBytesAppend(base, first, last); -} + Num hashVal_ = base_; +}; template <class Num, class ByteIterator> inline -Num hashBytesAppend(Num hashVal, ByteIterator first, ByteIterator last) +Num hashArray(ByteIterator first, ByteIterator last) { - static_assert(sizeof(typename std::iterator_traits<ByteIterator>::value_type) == 1); - constexpr Num prime = sizeof(Num) == 4 ? 16777619U : 1099511628211ULL; + using ValType = typename std::iterator_traits<ByteIterator>::value_type; + static_assert(sizeof(ValType) <= sizeof(Num)); + static_assert(IsInteger<ValType>::value || std::is_same_v<ValType, char> || std::is_same_v<ValType, wchar_t>); + + FNV1aHash<Num> hash; + std::for_each(first, last, [&hash](ValType v) { hash.add(static_cast<Num>(v)); }); + return hash.get(); +} + - for (; first != last; ++first) +//support for custom string classes in std::unordered_set/map +struct StringHash +{ + template <class String> + size_t operator()(const String& str) const { - hashVal ^= static_cast<Num>(*first); - hashVal *= prime; + const auto* strFirst = strBegin(str); + return hashArray<size_t>(strFirst, strFirst + strLength(str)); } - return hashVal; -} +}; } #endif //STL_TOOLS_H_84567184321434 diff --git a/zen/string_base.h b/zen/string_base.h index 58e5d43a..615c7d2c 100644 --- a/zen/string_base.h +++ b/zen/string_base.h @@ -11,8 +11,8 @@ #include <cassert> #include <cstdint> #include <atomic> -#include "string_tools.h" #include <compare> +#include "string_tools.h" //Zbase - a policy based string class optimizing performance and flexibility diff --git a/zen/string_tools.h b/zen/string_tools.h index cd26f5fd..eaf1a700 100644 --- a/zen/string_tools.h +++ b/zen/string_tools.h @@ -256,8 +256,8 @@ int compareString(const S& lhs, const T& rhs) const size_t rhsLen = strLength(rhs); //length check *after* strcmpWithNulls(): we do care about natural ordering: e.g. for "compareString(makeUpperCopy(lhs), makeUpperCopy(rhs))" - const int rv = impl::strcmpWithNulls(strBegin(lhs), strBegin(rhs), std::min(lhsLen, rhsLen)); - if (rv != 0) + if (const int rv = impl::strcmpWithNulls(strBegin(lhs), strBegin(rhs), std::min(lhsLen, rhsLen)); + rv != 0) return rv; return static_cast<int>(lhsLen) - static_cast<int>(rhsLen); } @@ -269,8 +269,8 @@ int compareAsciiNoCase(const S& lhs, const T& rhs) const size_t lhsLen = strLength(lhs); const size_t rhsLen = strLength(rhs); - const int rv = impl::strcmpAsciiNoCase(strBegin(lhs), strBegin(rhs), std::min(lhsLen, rhsLen)); - if (rv != 0) + if (const int rv = impl::strcmpAsciiNoCase(strBegin(lhs), strBegin(rhs), std::min(lhsLen, rhsLen)); + rv != 0) return rv; return static_cast<int>(lhsLen) - static_cast<int>(rhsLen); } diff --git a/zen/zstring.cpp b/zen/zstring.cpp index 8b16e02d..690f004b 100644 --- a/zen/zstring.cpp +++ b/zen/zstring.cpp @@ -64,7 +64,7 @@ Zstring getUnicodeNormalForm(const Zstring& str) return outStr; } - catch (SysError&) + catch ([[maybe_unused]] const SysError& e) { assert(false); return str; @@ -177,8 +177,7 @@ int compareNatural(const Zstring& lhs, const Zstring& rhs) const char* const strEndL = strL + lhsNorm.size(); const char* const strEndR = strR + rhsNorm.size(); - /* - - compare strings after conceptually creating blocks of whitespace/numbers/text + /* - compare strings after conceptually creating blocks of whitespace/numbers/text - implement strict weak ordering! - don't follow broken "strnatcasecmp": https://github.com/php/php-src/blob/master/ext/standard/strnatcmp.c 1. incorrect non-ASCII CI-comparison @@ -186,8 +185,7 @@ int compareNatural(const Zstring& lhs, const Zstring& rhs) 3. incorrect trimming of *all* whitespace 4. arbitrary handling of leading 0 only at string begin 5. incorrect handling of whitespace following a number - 6. code is a mess - */ + 6. code is a mess */ for (;;) { if (strL == strEndL || strR == strEndR) diff --git a/zen/zstring.h b/zen/zstring.h index e34d14a3..e262603e 100644 --- a/zen/zstring.h +++ b/zen/zstring.h @@ -26,7 +26,7 @@ using Zstringc = zen::Zbase<char>; //Caveat: don't expect input/output string sizes to match: // - different UTF-8 encoding length of upper-case chars -// - different number of upper case chars (e.g. "ß" => "SS" on macOS) +// - different number of upper case chars (e.g. "ߢ => "SS" on macOS) // - output is Unicode-normalized Zstring makeUpperCopy(const Zstring& str); @@ -37,7 +37,7 @@ Zstring getUnicodeNormalForm(const Zstring& str); // and conformant software should not treat canonically equivalent sequences, whether composed or decomposed or something in between, as different." // https://www.win.tue.nl/~aeb/linux/uc/nfc_vs_nfd.html -struct LessUnicodeNormal { bool operator()(const Zstring& lhs, const Zstring& rhs) const { return getUnicodeNormalForm(lhs) < getUnicodeNormalForm(rhs);} }; +struct LessUnicodeNormal { bool operator()(const Zstring& lhs, const Zstring& rhs) const { return getUnicodeNormalForm(lhs) < getUnicodeNormalForm(rhs); } }; Zstring replaceCpyAsciiNoCase(const Zstring& str, const Zstring& oldTerm, const Zstring& newTerm); @@ -49,8 +49,10 @@ struct ZstringNoCase //use as STL container key: avoid needless upper-case conve { ZstringNoCase(const Zstring& str) : upperCase(makeUpperCopy(str)) {} Zstring upperCase; + + std::strong_ordering operator<=>(const ZstringNoCase& other) const = default; }; -inline bool operator<(const ZstringNoCase& lhs, const ZstringNoCase& rhs) { return lhs.upperCase < rhs.upperCase; } + //------------------------------------------------------------------------------------------ @@ -60,9 +62,9 @@ inline bool operator<(const ZstringNoCase& lhs, const ZstringNoCase& rhs) { retu // macOS: ignore case + Unicode normalization forms int compareNativePath(const Zstring& lhs, const Zstring& rhs); -inline bool equalNativePath(const Zstring& lhs, const Zstring& rhs) { return compareNativePath(lhs, rhs) == 0; } +inline bool equalNativePath(const Zstring& lhs, const Zstring& rhs) { return compareNativePath(lhs, rhs) == 0; } -struct LessNativePath { bool operator()(const Zstring& lhs, const Zstring& rhs) const { return compareNativePath(lhs, rhs) < 0; } }; +struct LessNativePath { bool operator()(const Zstring& lhs, const Zstring& rhs) const { return compareNativePath(lhs, rhs) < 0; } }; //------------------------------------------------------------------------------------------ int compareNatural(const Zstring& lhs, const Zstring& rhs); |