{-# OPTIONS_GHC -XNoImplicitPrelude #-}------------------------------------------------------------------------------- |-- Module : Foreign.C.String-- Copyright : (c) The FFI task force 2001-- License : BSD-style (see the file libraries/base/LICENSE)-- -- Maintainer : ffi@haskell.org-- Stability : provisional-- Portability : portable---- Utilities for primitive marshalling of C strings.---- The marshalling converts each Haskell character, representing a Unicode-- code point, to one or more bytes in a manner that, by default, is-- determined by the current locale. As a consequence, no guarantees-- can be made about the relative length of a Haskell string and its-- corresponding C string, and therefore all the marshalling routines-- include memory allocation. The translation between Unicode and the-- encoding of the current locale may be lossy.-------------------------------------------------------------------------------moduleForeign.C.String(-- representation of strings in C-- * C stringsCString,-- = Ptr CCharCStringLen,-- = (Ptr CChar, Int)-- ** Using a locale-dependent encoding-- | Currently these functions are identical to their @CAString@ counterparts;-- eventually they will use an encoding determined by the current locale.-- conversion of C strings into Haskell strings--peekCString,-- :: CString -> IO StringpeekCStringLen,-- :: CStringLen -> IO String-- conversion of Haskell strings into C strings--newCString,-- :: String -> IO CStringnewCStringLen,-- :: String -> IO CStringLen-- conversion of Haskell strings into C strings using temporary storage--withCString,-- :: String -> (CString -> IO a) -> IO awithCStringLen,-- :: String -> (CStringLen -> IO a) -> IO acharIsRepresentable,-- :: Char -> IO Bool-- ** Using 8-bit characters-- | These variants of the above functions are for use with C libraries-- that are ignorant of Unicode. These functions should be used with-- care, as a loss of information can occur.castCharToCChar,-- :: Char -> CCharcastCCharToChar,-- :: CChar -> CharcastCharToCUChar,-- :: Char -> CUCharcastCUCharToChar,-- :: CUChar -> CharcastCharToCSChar,-- :: Char -> CSCharcastCSCharToChar,-- :: CSChar -> CharpeekCAString,-- :: CString -> IO StringpeekCAStringLen,-- :: CStringLen -> IO StringnewCAString,-- :: String -> IO CStringnewCAStringLen,-- :: String -> IO CStringLenwithCAString,-- :: String -> (CString -> IO a) -> IO awithCAStringLen,-- :: String -> (CStringLen -> IO a) -> IO a-- * C wide strings-- | These variants of the above functions are for use with C libraries-- that encode Unicode using the C @wchar_t@ type in a system-dependent-- way. The only encodings supported are---- * UTF-32 (the C compiler defines @__STDC_ISO_10646__@), or---- * UTF-16 (as used on Windows systems).CWString,-- = Ptr CWcharCWStringLen,-- = (Ptr CWchar, Int)peekCWString,-- :: CWString -> IO StringpeekCWStringLen,-- :: CWStringLen -> IO StringnewCWString,-- :: String -> IO CWStringnewCWStringLen,-- :: String -> IO CWStringLenwithCWString,-- :: String -> (CWString -> IO a) -> IO awithCWStringLen,-- :: String -> (CWStringLen -> IO a) -> IO a)whereimportForeign.Marshal.ArrayimportForeign.C.TypesimportForeign.PtrimportForeign.StorableimportData.Word#ifdef __GLASGOW_HASKELL__importGHC.ListimportGHC.RealimportGHC.NumimportGHC.Base#elseimportData.Char(chr,ord)#define unsafeChr chr#endif------------------------------------------------------------------------------- Strings-- representation of strings in C-- -------------------------------- | A C string is a reference to an array of C characters terminated by NUL.typeCString=PtrCChar-- | A string with explicit length information in bytes instead of a-- terminating NUL (allowing NUL characters in the middle of the string).typeCStringLen=(PtrCChar,Int)-- exported functions-- ---------------------- * the following routines apply the default conversion when converting the-- C-land character encoding into the Haskell-land character encoding-- | Marshal a NUL terminated C string into a Haskell string.--peekCString::CString->IOStringpeekCString=peekCAString-- | Marshal a C string with explicit length into a Haskell string.--peekCStringLen::CStringLen->IOStringpeekCStringLen=peekCAStringLen-- | Marshal a Haskell string into a NUL terminated C string.---- * the Haskell string may /not/ contain any NUL characters---- * new storage is allocated for the C string and must be-- explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCString::String->IOCStringnewCString=newCAString-- | Marshal a Haskell string into a C string (ie, character array) with-- explicit length information.---- * new storage is allocated for the C string and must be-- explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCStringLen::String->IOCStringLennewCStringLen=newCAStringLen-- | Marshal a Haskell string into a NUL terminated C string using temporary-- storage.---- * the Haskell string may /not/ contain any NUL characters---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCString::String->(CString->IOa)->IOawithCString=withCAString-- | Marshal a Haskell string into a C string (ie, character array)-- in temporary storage, with explicit length information.---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCStringLen::String->(CStringLen->IOa)->IOawithCStringLen=withCAStringLen-- | Determines whether a character can be accurately encoded in a 'CString'.-- Unrepresentable characters are converted to @\'?\'@.---- Currently only Latin-1 characters are representable.charIsRepresentable::Char->IOBoolcharIsRepresentablec=return(ordc<256)-- single byte characters-- -------------------------- ** NOTE: These routines don't handle conversions! **-- | Convert a C byte, representing a Latin-1 character, to the corresponding-- Haskell character.castCCharToChar::CChar->CharcastCCharToCharch=unsafeChr(fromIntegral(fromIntegralch::Word8))-- | Convert a Haskell character to a C character.-- This function is only safe on the first 256 characters.castCharToCChar::Char->CCharcastCharToCCharch=fromIntegral(ordch)-- | Convert a C @unsigned char@, representing a Latin-1 character, to-- the corresponding Haskell character.castCUCharToChar::CUChar->CharcastCUCharToCharch=unsafeChr(fromIntegral(fromIntegralch::Word8))-- | Convert a Haskell character to a C @unsigned char@.-- This function is only safe on the first 256 characters.castCharToCUChar::Char->CUCharcastCharToCUCharch=fromIntegral(ordch)-- | Convert a C @signed char@, representing a Latin-1 character, to the-- corresponding Haskell character.castCSCharToChar::CSChar->CharcastCSCharToCharch=unsafeChr(fromIntegral(fromIntegralch::Word8))-- | Convert a Haskell character to a C @signed char@.-- This function is only safe on the first 256 characters.castCharToCSChar::Char->CSCharcastCharToCSCharch=fromIntegral(ordch)-- | Marshal a NUL terminated C string into a Haskell string.--peekCAString::CString->IOString#ifndef __GLASGOW_HASKELL__peekCAStringcp=docs<-peekArray0nULcpreturn(cCharsToCharscs)#elsepeekCAStringcp=dol<-lengthArray0nULcpifl<=0thenreturn""elseloop""(l-1)whereloopsi=doxval<-peekElemOffcpiletval=castCCharToCharxvalval`seq`ifi<=0thenreturn(val:s)elseloop(val:s)(i-1)#endif-- | Marshal a C string with explicit length into a Haskell string.--peekCAStringLen::CStringLen->IOString#ifndef __GLASGOW_HASKELL__peekCAStringLen(cp,len)=docs<-peekArraylencpreturn(cCharsToCharscs)#elsepeekCAStringLen(cp,len)|len<=0=return""-- being (too?) nice.|otherwise=loop[](len-1)whereloopacci=doxval<-peekElemOffcpiletval=castCCharToCharxval-- blow away the coercion ASAP.if(val`seq`(i==0))thenreturn(val:acc)elseloop(val:acc)(i-1)#endif-- | Marshal a Haskell string into a NUL terminated C string.---- * the Haskell string may /not/ contain any NUL characters---- * new storage is allocated for the C string and must be-- explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCAString::String->IOCString#ifndef __GLASGOW_HASKELL__newCAString=newArray0nUL.charsToCChars#elsenewCAStringstr=doptr<-mallocArray0(lengthstr)letgo[]n=pokeElemOffptrnnULgo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)gostr0returnptr#endif-- | Marshal a Haskell string into a C string (ie, character array) with-- explicit length information.---- * new storage is allocated for the C string and must be-- explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCAStringLen::String->IOCStringLen#ifndef __GLASGOW_HASKELL__newCAStringLenstr=newArrayLen(charsToCCharsstr)#elsenewCAStringLenstr=doptr<-mallocArray0lenletgo[]n=n`seq`return()-- make it strict in ngo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)gostr0return(ptr,len)wherelen=lengthstr#endif-- | Marshal a Haskell string into a NUL terminated C string using temporary-- storage.---- * the Haskell string may /not/ contain any NUL characters---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCAString::String->(CString->IOa)->IOa#ifndef __GLASGOW_HASKELL__withCAString=withArray0nUL.charsToCChars#elsewithCAStringstrf=allocaArray0(lengthstr)$\ptr->letgo[]n=pokeElemOffptrnnULgo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)indogostr0fptr#endif-- | Marshal a Haskell string into a C string (ie, character array)-- in temporary storage, with explicit length information.---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCAStringLen::String->(CStringLen->IOa)->IOawithCAStringLenstrf=#ifndef __GLASGOW_HASKELL__withArrayLen(charsToCCharsstr)$\lenptr->f(ptr,len)#elseallocaArraylen$\ptr->letgo[]n=n`seq`return()-- make it strict in ngo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)indogostr0f(ptr,len)wherelen=lengthstr#endif-- auxiliary definitions-- ------------------------ C's end of string character--nUL::CCharnUL=0-- allocate an array to hold the list and pair it with the number of elementsnewArrayLen::Storablea=>[a]->IO(Ptra,Int)newArrayLenxs=doa<-newArrayxsreturn(a,lengthxs)#ifndef __GLASGOW_HASKELL__-- cast [CChar] to [Char]--cCharsToChars::[CChar]->[Char]cCharsToCharsxs=mapcastCCharToCharxs-- cast [Char] to [CChar]--charsToCChars::[Char]->[CChar]charsToCCharsxs=mapcastCharToCCharxs#endif------------------------------------------------------------------------------- Wide strings-- representation of wide strings in C-- ------------------------------------- | A C wide string is a reference to an array of C wide characters-- terminated by NUL.typeCWString=PtrCWchar-- | A wide character string with explicit length information in 'CWchar's-- instead of a terminating NUL (allowing NUL characters in the middle-- of the string).typeCWStringLen=(PtrCWchar,Int)-- | Marshal a NUL terminated C wide string into a Haskell string.--peekCWString::CWString->IOStringpeekCWStringcp=docs<-peekArray0wNULcpreturn(cWcharsToCharscs)-- | Marshal a C wide string with explicit length into a Haskell string.--peekCWStringLen::CWStringLen->IOStringpeekCWStringLen(cp,len)=docs<-peekArraylencpreturn(cWcharsToCharscs)-- | Marshal a Haskell string into a NUL terminated C wide string.---- * the Haskell string may /not/ contain any NUL characters---- * new storage is allocated for the C wide string and must-- be explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCWString::String->IOCWStringnewCWString=newArray0wNUL.charsToCWchars-- | Marshal a Haskell string into a C wide string (ie, wide character array)-- with explicit length information.---- * new storage is allocated for the C wide string and must-- be explicitly freed using 'Foreign.Marshal.Alloc.free' or-- 'Foreign.Marshal.Alloc.finalizerFree'.--newCWStringLen::String->IOCWStringLennewCWStringLenstr=newArrayLen(charsToCWcharsstr)-- | Marshal a Haskell string into a NUL terminated C wide string using-- temporary storage.---- * the Haskell string may /not/ contain any NUL characters---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCWString::String->(CWString->IOa)->IOawithCWString=withArray0wNUL.charsToCWchars-- | Marshal a Haskell string into a NUL terminated C wide string using-- temporary storage.---- * the Haskell string may /not/ contain any NUL characters---- * the memory is freed when the subcomputation terminates (either-- normally or via an exception), so the pointer to the temporary-- storage must /not/ be used after this.--withCWStringLen::String->(CWStringLen->IOa)->IOawithCWStringLenstrf=withArrayLen(charsToCWcharsstr)$\lenptr->f(ptr,len)-- auxiliary definitions-- ----------------------wNUL::CWcharwNUL=0cWcharsToChars::[CWchar]->[Char]charsToCWchars::[Char]->[CWchar]#ifdef mingw32_HOST_OS-- On Windows, wchar_t is 16 bits wide and CWString uses the UTF-16 encoding.-- coding errors generate Chars in the surrogate rangecWcharsToChars=mapchr.fromUTF16.mapfromIntegralwherefromUTF16(c1:c2:wcs)|0xd800<=c1&&c1<=0xdbff&&0xdc00<=c2&&c2<=0xdfff=((c1-0xd800)*0x400+(c2-0xdc00)+0x10000):fromUTF16wcsfromUTF16(c:wcs)=c:fromUTF16wcsfromUTF16[]=[]charsToCWchars=foldrutf16Char[].mapordwhereutf16Charcwcs|c<0x10000=fromIntegralc:wcs|otherwise=letc'=c-0x10000infromIntegral(c'`div`0x400+0xd800):fromIntegral(c'`mod`0x400+0xdc00):wcs#else /* !mingw32_HOST_OS */cWcharsToCharsxs=mapcastCWcharToCharxscharsToCWcharsxs=mapcastCharToCWcharxs-- These conversions only make sense if __STDC_ISO_10646__ is defined-- (meaning that wchar_t is ISO 10646, aka Unicode)castCWcharToChar::CWchar->CharcastCWcharToCharch=chr(fromIntegralch)castCharToCWchar::Char->CWcharcastCharToCWcharch=fromIntegral(ordch)#endif /* !mingw32_HOST_OS */