File: OsPath.hs

package info (click to toggle)
git-annex 10.20250416-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 73,572 kB
  • sloc: haskell: 90,656; javascript: 9,103; sh: 1,469; makefile: 211; perl: 137; ansic: 44
file content (137 lines) | stat: -rw-r--r-- 3,723 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
{- OsPath utilities
 -
 - Copyright 2025 Joey Hess <id@joeyh.name>
 -
 - License: BSD-2-clause
 -}

{-# LANGUAGE CPP #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
{-# OPTIONS_GHC -fno-warn-tabs #-}

module Utility.OsPath (
	OsPath,
	OsString,
	literalOsPath,
	stringToOsPath,
	toOsPath,
	fromOsPath,
	module X,
	getSearchPath,
	unsafeFromChar,
) where

import Utility.FileSystemEncoding
import Data.ByteString.Short (ShortByteString)
import qualified Data.ByteString.Short as S
import qualified Data.ByteString.Lazy as L
#ifdef WITH_OSPATH
import System.OsPath as X hiding (OsPath, OsString, pack, unpack, unsafeFromChar)
import System.OsPath
import "os-string" System.OsString.Internal.Types
import qualified System.FilePath as PS
#if defined(mingw32_HOST_OS)
import GHC.IO (unsafePerformIO)
import System.OsString.Encoding.Internal (cWcharsToChars_UCS2)
import qualified System.OsString.Data.ByteString.Short.Word16 as BS16
#endif
#else
import System.FilePath.ByteString as X hiding (RawFilePath, getSearchPath)
import System.FilePath.ByteString (getSearchPath)
import Data.ByteString (ByteString)
import Data.Char
import Data.Word
#endif

class OsPathConv t where
	toOsPath :: t -> OsPath
	fromOsPath :: OsPath -> t

instance OsPathConv FilePath where
	toOsPath = toOsPath . toRawFilePath
	fromOsPath = fromRawFilePath . fromOsPath

#ifdef WITH_OSPATH
instance OsPathConv RawFilePath where
#if defined(mingw32_HOST_OS)
	toOsPath = bytesToOsPath
	fromOsPath = bytesFromOsPath
#else
	toOsPath = bytesToOsPath . S.toShort
	fromOsPath = S.fromShort . bytesFromOsPath
#endif

instance OsPathConv ShortByteString where
#if defined(mingw32_HOST_OS)
	toOsPath = bytesToOsPath . S.fromShort
	fromOsPath = S.toShort . bytesFromOsPath
#else
	toOsPath = bytesToOsPath
	fromOsPath = bytesFromOsPath
#endif

instance OsPathConv L.ByteString where
	toOsPath = toOsPath . L.toStrict
	fromOsPath = L.fromStrict . fromOsPath

#if defined(mingw32_HOST_OS)
-- On Windows, OsString contains a ShortByteString that is
-- utf-16 encoded. But the input RawFilePath is assumed to
-- be utf-8. So this is a relatively  expensive conversion.
bytesToOsPath :: RawFilePath -> OsPath
bytesToOsPath = unsafePerformIO . encodeFS . fromRawFilePath
#else
bytesToOsPath :: ShortByteString -> OsPath
bytesToOsPath = OsString . PosixString
#endif

#if defined(mingw32_HOST_OS)
bytesFromOsPath :: OsPath -> RawFilePath
-- On Windows, OsString contains a ShortByteString that is
-- utf-16 encoded, but RawFilePath is utf-8.
-- So this is relatively expensive conversion.
bytesFromOsPath = toRawFilePath . cWcharsToChars_UCS2 . BS16.unpack . getWindowsString . getOsString
#else
bytesFromOsPath :: OsPath -> ShortByteString
bytesFromOsPath = getPosixString . getOsString
#endif

{- For some reason not included in System.OsPath -}
getSearchPath :: IO [OsPath]
getSearchPath = map toOsPath <$> PS.getSearchPath

{- Used for string constants. Note that when using OverloadedStrings,
 - the IsString instance for ShortByteString only works properly with
 - ASCII characters. -}
literalOsPath :: ShortByteString -> OsPath
literalOsPath = toOsPath

#else
{- When not building with WITH_OSPATH, use RawFilePath.
 -}
type OsPath = RawFilePath

type OsString = ByteString

instance OsPathConv RawFilePath where
	toOsPath = id
	fromOsPath = id

instance OsPathConv ShortByteString where
	toOsPath = S.fromShort
	fromOsPath = S.toShort

instance OsPathConv L.ByteString where
	toOsPath = L.toStrict
	fromOsPath = L.fromStrict

unsafeFromChar :: Char -> Word8
unsafeFromChar = fromIntegral . ord

literalOsPath :: RawFilePath -> OsPath
literalOsPath = id
#endif

stringToOsPath :: String -> OsPath
stringToOsPath = toOsPath