authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-12 11:33:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-12 11:33:26-04:00
log1caa48c2df63d61b8d2501b3e3ee7c85ee8d89cb
tree596273952517f58477d1aed2da85f2711448412c
parentff0b7fe29a49a5619b3c2f7fee0baccb979caf2d

windows os.cpp implementations


4 files changed, 203 insertions(+), 10 deletions(-)

src/error.cpp+2
...@@ -30,6 +30,8 @@ const char *err_str(int err) {...@@ -30,6 +30,8 @@ const char *err_str(int err) {
30 case ErrorEndOfFile: return "end of file";30 case ErrorEndOfFile: return "end of file";
31 case ErrorIsDir: return "is directory";31 case ErrorIsDir: return "is directory";
32 case ErrorUnsupportedOperatingSystem: return "unsupported operating system";32 case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
33 case ErrorSharingViolation: return "sharing violation";
34 case ErrorPipeBusy: return "pipe busy";
33 }35 }
34 return "(invalid error)";36 return "(invalid error)";
35}37}
src/error.hpp+2
...@@ -30,6 +30,8 @@ enum Error {...@@ -30,6 +30,8 @@ enum Error {
30 ErrorEndOfFile,30 ErrorEndOfFile,
31 ErrorIsDir,31 ErrorIsDir,
32 ErrorUnsupportedOperatingSystem,32 ErrorUnsupportedOperatingSystem,
33 ErrorSharingViolation,
34 ErrorPipeBusy,
33};35};
3436
35const char *err_str(int err);37const char *err_str(int err);
src/os.cpp+198-9
...@@ -24,6 +24,7 @@...@@ -24,6 +24,7 @@
24#endif24#endif
2525
26#include <windows.h>26#include <windows.h>
27#include <shlobj.h>
27#include <io.h>28#include <io.h>
28#include <fcntl.h>29#include <fcntl.h>
2930
...@@ -1393,7 +1394,7 @@ Error os_self_exe_path(Buf *out_path) {...@@ -1393,7 +1394,7 @@ Error os_self_exe_path(Buf *out_path) {
1393 }1394 }
1394 if (copied_amt < buf_len(out_path)) {1395 if (copied_amt < buf_len(out_path)) {
1395 buf_resize(out_path, copied_amt);1396 buf_resize(out_path, copied_amt);
1396 return 0;1397 return ErrorNone;
1397 }1398 }
1398 buf_resize(out_path, buf_len(out_path) * 2);1399 buf_resize(out_path, buf_len(out_path) * 2);
1399 }1400 }
...@@ -1616,10 +1617,118 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy...@@ -1616,10 +1617,118 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
1616#endif1617#endif
1617}1618}
16181619
1619// Ported from std/os/get_app_data_dir.zig1620#if defined(ZIG_OS_WINDOWS)
1621// Ported from std/unicode.zig
1622struct Utf16LeIterator {
1623 uint8_t *bytes;
1624 size_t i;
1625};
1626
1627// Ported from std/unicode.zig
1628static Utf16LeIterator Utf16LeIterator_init(WCHAR *ptr) {
1629 return {(uint8_t*)ptr, 0};
1630}
1631
1632// Ported from std/unicode.zig
1633static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
1634 if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
1635 return {};
1636 uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1637 if (c0 & ~((uint32_t)0x03ff) == 0xd800) {
1638 // surrogate pair
1639 it->i += 2;
1640 assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
1641 uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8);
1642 assert(c1 & ~((uint32_t)0x03ff) == 0xdc00);
1643 it->i += 2;
1644 return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
1645 } else {
1646 assert(c0 & ~((uint32_t)0x03ff) != 0xdc00);
1647 it->i += 2;
1648 return Optional<uint32_t>::some(c0);
1649 }
1650}
1651
1652// Ported from std/unicode.zig
1653static uint8_t utf8CodepointSequenceLength(uint32_t c) {
1654 if (c < 0x80) return 1;
1655 if (c < 0x800) return 2;
1656 if (c < 0x10000) return 3;
1657 if (c < 0x110000) return 4;
1658 zig_unreachable();
1659}
1660
1661// Ported from std/unicode.zig
1662static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
1663 size_t length = utf8CodepointSequenceLength(c);
1664 assert(out.len >= length);
1665 switch (length) {
1666 // The pattern for each is the same
1667 // - Increasing the initial shift by 6 each time
1668 // - Each time after the first shorten the shifted
1669 // value to a max of 0b111111 (63)
1670 case 1:
1671 out.ptr[0] = c; // Can just do 0 + codepoint for initial range
1672 break;
1673 case 2:
1674 out.ptr[0] = 0b11000000 | (c >> 6);
1675 out.ptr[1] = 0b10000000 | (c & 0b111111);
1676 break;
1677 case 3:
1678 assert(!(0xd800 <= c && c <= 0xdfff));
1679 out.ptr[0] = 0b11100000 | (c >> 12);
1680 out.ptr[1] = 0b10000000 | ((c >> 6) & 0b111111);
1681 out.ptr[2] = 0b10000000 | (c & 0b111111);
1682 break;
1683 case 4:
1684 out.ptr[0] = 0b11110000 | (c >> 18);
1685 out.ptr[1] = 0b10000000 | ((c >> 12) & 0b111111);
1686 out.ptr[2] = 0b10000000 | ((c >> 6) & 0b111111);
1687 out.ptr[3] = 0b10000000 | (c & 0b111111);
1688 break;
1689 default:
1690 zig_unreachable();
1691 }
1692 return length;
1693}
1694
1695// Ported from std.unicode.utf16leToUtf8Alloc
1696static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
1697 // optimistically guess that it will all be ascii.
1698 buf_resize(out, 0);
1699 size_t out_index = 0;
1700 Utf16LeIterator it = Utf16LeIterator_init(utf16le);
1701 for (;;) {
1702 Optional<uint32_t> opt_codepoint = Utf16LeIterator_nextCodepoint(&it);
1703 if (!opt_codepoint.is_some) break;
1704 uint32_t codepoint = opt_codepoint.value;
1705
1706 size_t utf8_len = utf8CodepointSequenceLength(codepoint);
1707 buf_resize(out, buf_len(out) + utf8_len);
1708 utf8Encode(codepoint, {(uint8_t*)buf_ptr(out)+out_index, buf_len(out)-out_index});
1709 out_index += utf8_len;
1710 }
1711}
1712#endif
1713
1714// Ported from std.os.getAppDataDir
1620Error os_get_app_data_dir(Buf *out_path, const char *appname) {1715Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1621#if defined(ZIG_OS_WINDOWS)1716#if defined(ZIG_OS_WINDOWS)
1622#error "Unimplemented"1717 Error err;
1718 WCHAR *dir_path_ptr;
1719 switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
1720 case S_OK:
1721 // defer os.windows.CoTaskMemFree(@ptrCast(*c_void, dir_path_ptr));
1722 utf16le_ptr_to_utf8(out_path, dir_path_ptr);
1723 CoTaskMemFree(dir_path_ptr);
1724 buf_appendf(out_path, "\\%s", appname);
1725 return ErrorNone;
1726 case E_OUTOFMEMORY:
1727 return ErrorNoMem;
1728 default:
1729 return ErrorUnexpected;
1730 }
1731 zig_unreachable();
1623#elif defined(ZIG_OS_DARWIN)1732#elif defined(ZIG_OS_DARWIN)
1624 const char *home_dir = getenv("HOME");1733 const char *home_dir = getenv("HOME");
1625 if (home_dir == nullptr) {1734 if (home_dir == nullptr) {
...@@ -1665,14 +1774,44 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {...@@ -1665,14 +1774,44 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
1665 paths.append(buf_create_from_str(name));1774 paths.append(buf_create_from_str(name));
1666 }1775 }
1667 return ErrorNone;1776 return ErrorNone;
1777#elif defined(ZIG_OS_WINDOWS)
1778 // zig is built statically on windows, so we can return an empty list
1779 paths.resize(0);
1780 return ErrorNone;
1668#else1781#else
1669#error "unimplemented"1782#error unimplemented
1670#endif1783#endif
1671}1784}
16721785
1673Error os_file_open_r(Buf *full_path, OsFile *out_file) {1786Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1674#if defined(ZIG_OS_WINDOWS)1787#if defined(ZIG_OS_WINDOWS)
1675#error "unimplemented"1788 // TODO use CreateFileW
1789 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
1790
1791 if (result == INVALID_HANDLE_VALUE) {
1792 DWORD err = GetLastError();
1793 switch (err) {
1794 case ERROR_SHARING_VIOLATION:
1795 return ErrorSharingViolation;
1796 case ERROR_ALREADY_EXISTS:
1797 return ErrorPathAlreadyExists;
1798 case ERROR_FILE_EXISTS:
1799 return ErrorPathAlreadyExists;
1800 case ERROR_FILE_NOT_FOUND:
1801 return ErrorFileNotFound;
1802 case ERROR_PATH_NOT_FOUND:
1803 return ErrorFileNotFound;
1804 case ERROR_ACCESS_DENIED:
1805 return ErrorAccess;
1806 case ERROR_PIPE_BUSY:
1807 return ErrorPipeBusy;
1808 default:
1809 return ErrorUnexpected;
1810 }
1811 }
1812
1813 *out_file = result;
1814 return ErrorNone;
1676#else1815#else
1677 for (;;) {1816 for (;;) {
1678 int fd = open(buf_ptr(full_path), O_RDONLY|O_CLOEXEC);1817 int fd = open(buf_ptr(full_path), O_RDONLY|O_CLOEXEC);
...@@ -1702,7 +1841,36 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {...@@ -1702,7 +1841,36 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
17021841
1703Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {1842Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
1704#if defined(ZIG_OS_WINDOWS)1843#if defined(ZIG_OS_WINDOWS)
1705#error "unimplemented"1844 for (;;) {
1845 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ | GENERIC_WRITE,
1846 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
1847
1848 if (result == INVALID_HANDLE_VALUE) {
1849 DWORD err = GetLastError();
1850 switch (err) {
1851 case ERROR_SHARING_VIOLATION:
1852 // TODO wait for the lock instead of sleeping
1853 Sleep(10);
1854 continue;
1855 case ERROR_ALREADY_EXISTS:
1856 return ErrorPathAlreadyExists;
1857 case ERROR_FILE_EXISTS:
1858 return ErrorPathAlreadyExists;
1859 case ERROR_FILE_NOT_FOUND:
1860 return ErrorFileNotFound;
1861 case ERROR_PATH_NOT_FOUND:
1862 return ErrorFileNotFound;
1863 case ERROR_ACCESS_DENIED:
1864 return ErrorAccess;
1865 case ERROR_PIPE_BUSY:
1866 return ErrorPipeBusy;
1867 default:
1868 return ErrorUnexpected;
1869 }
1870 }
1871 *out_file = result;
1872 return ErrorNone;
1873 }
1706#else1874#else
1707 int fd;1875 int fd;
1708 for (;;) {1876 for (;;) {
...@@ -1757,7 +1925,12 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {...@@ -1757,7 +1925,12 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
17571925
1758Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {1926Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1759#if defined(ZIG_OS_WINDOWS)1927#if defined(ZIG_OS_WINDOWS)
1760#error unimplemented1928 FILETIME last_write_time;
1929 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
1930 return ErrorUnexpected;
1931 mtime->sec = last_write_time.dwLowDateTime | (last_write_time.dwHighDateTime << 32);
1932 mtime->nsec = 0;
1933 return ErrorNone;
1761#elif defined(ZIG_OS_LINUX)1934#elif defined(ZIG_OS_LINUX)
1762 struct stat statbuf;1935 struct stat statbuf;
1763 if (fstat(file, &statbuf) == -1)1936 if (fstat(file, &statbuf) == -1)
...@@ -1781,7 +1954,11 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {...@@ -1781,7 +1954,11 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
17811954
1782Error os_file_read(OsFile file, void *ptr, size_t *len) {1955Error os_file_read(OsFile file, void *ptr, size_t *len) {
1783#if defined(ZIG_OS_WINDOWS)1956#if defined(ZIG_OS_WINDOWS)
1784#error unimplemented1957 DWORD amt_read;
1958 if (ReadFile(file, ptr, *len, &amt_read, nullptr) == 0)
1959 return ErrorUnexpected;
1960 *len = amt_read;
1961 return ErrorNone;
1785#else1962#else
1786 for (;;) {1963 for (;;) {
1787 ssize_t rc = read(file, ptr, *len);1964 ssize_t rc = read(file, ptr, *len);
...@@ -1830,10 +2007,18 @@ Error os_file_read_all(OsFile file, Buf *contents) {...@@ -1830,10 +2007,18 @@ Error os_file_read_all(OsFile file, Buf *contents) {
18302007
1831Error os_file_overwrite(OsFile file, Buf *contents) {2008Error os_file_overwrite(OsFile file, Buf *contents) {
1832#if defined(ZIG_OS_WINDOWS)2009#if defined(ZIG_OS_WINDOWS)
1833#error unimplemented2010 if (SetFilePointer(file, 0, nullptr, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
2011 return ErrorFileSystem;
2012 if (!SetEndOfFile(file))
2013 return ErrorFileSystem;
2014 if (!WriteFile(file, buf_ptr(contents), buf_len(contents), nullptr, nullptr))
2015 return ErrorFileSystem;
2016 return ErrorNone;
1834#else2017#else
1835 if (lseek(file, 0, SEEK_SET) == -1)2018 if (lseek(file, 0, SEEK_SET) == -1)
1836 return ErrorFileSystem;2019 return ErrorFileSystem;
2020 if (ftruncate(file, 0) == -1)
2021 return ErrorFileSystem;
1837 for (;;) {2022 for (;;) {
1838 if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {2023 if (write(file, buf_ptr(contents), buf_len(contents)) == -1) {
1839 switch (errno) {2024 switch (errno) {
...@@ -1853,5 +2038,9 @@ Error os_file_overwrite(OsFile file, Buf *contents) {...@@ -1853,5 +2038,9 @@ Error os_file_overwrite(OsFile file, Buf *contents) {
1853}2038}
18542039
1855void os_file_close(OsFile file) {2040void os_file_close(OsFile file) {
2041#if defined(ZIG_OS_WINDOWS)
2042 CloseHandle(file);
2043#else
1856 close(file);2044 close(file);
2045#endif
1857}2046}
src/os.hpp+1-1
...@@ -72,7 +72,7 @@ struct Termination {...@@ -72,7 +72,7 @@ struct Termination {
72};72};
7373
74#if defined(ZIG_OS_WINDOWS)74#if defined(ZIG_OS_WINDOWS)
75#define OsFile (void *)75#define OsFile void *
76#else76#else
77#define OsFile int77#define OsFile int
78#endif78#endif