Movatterモバイル変換


[0]ホーム

URL:


{-# LANGUAGE Trustworthy #-}{-# LANGUAGE CPP, NoImplicitPrelude #-}------------------------------------------------------------------------------- |-- 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,CStringLen,-- ** Using a locale-dependent encoding-- | These functions are different from their @CAString@ counterparts-- in that they will use an encoding determined by the current locale,-- rather than always assuming ASCII.-- conversion of C strings into Haskell strings--peekCString,peekCStringLen,-- conversion of Haskell strings into C strings--newCString,newCStringLen,-- conversion of Haskell strings into C strings using temporary storage--withCString,withCStringLen,charIsRepresentable,-- ** 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,castCCharToChar,castCharToCUChar,castCUCharToChar,castCharToCSChar,castCSCharToChar,peekCAString,peekCAStringLen,newCAString,newCAStringLen,withCAString,withCAStringLen,-- * 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,CWStringLen,peekCWString,peekCWStringLen,newCWString,newCWStringLen,withCWString,withCWStringLen,)whereimportForeign.Marshal.ArrayimportForeign.C.TypesimportForeign.PtrimportForeign.StorableimportData.WordimportGHC.CharimportGHC.ListimportGHC.RealimportGHC.NumimportGHC.Baseimport{-# SOURCE#-}GHC.IO.EncodingimportqualifiedGHC.ForeignasGHC------------------------------------------------------------------------------- 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->IOStringpeekCStrings=getForeignEncoding>>=flipGHC.peekCStrings-- | Marshal a C string with explicit length into a Haskell string.--peekCStringLen::CStringLen->IOStringpeekCStringLens=getForeignEncoding>>=flipGHC.peekCStringLens-- | 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->IOCStringnewCStrings=getForeignEncoding>>=flipGHC.newCStrings-- | 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->IOCStringLennewCStringLens=getForeignEncoding>>=flipGHC.newCStringLens-- | 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)->IOawithCStringsf=getForeignEncoding>>=\enc->GHC.withCStringencsf-- | 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)->IOawithCStringLensf=getForeignEncoding>>=\enc->GHC.withCStringLenencsf-- -- | Determines whether a character can be accurately encoded in a 'CString'.-- -- Unrepresentable characters are converted to '?' or their nearest visual equivalent.charIsRepresentable::Char->IOBoolcharIsRepresentablec=getForeignEncoding>>=flipGHC.charIsRepresentablec-- 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->IOStringpeekCAStringcp=dol<-lengthArray0nULcpifl<=0thenreturn""elseloop""(l-1)whereloopsi=doxval<-peekElemOffcpiletval=castCCharToCharxvalval`seq`ifi<=0thenreturn(val:s)elseloop(val:s)(i-1)-- | Marshal a C string with explicit length into a Haskell string.--peekCAStringLen::CStringLen->IOStringpeekCAStringLen(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)-- | 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->IOCStringnewCAStringstr=doptr<-mallocArray0(lengthstr)letgo[]n=pokeElemOffptrnnULgo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)gostr0returnptr-- | 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->IOCStringLennewCAStringLenstr=doptr<-mallocArray0lenletgo[]n=n`seq`return()-- make it strict in ngo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)gostr0return(ptr,len)wherelen=lengthstr-- | 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)->IOawithCAStringstrf=allocaArray0(lengthstr)$\ptr->letgo[]n=pokeElemOffptrnnULgo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)indogostr0fptr-- | 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=allocaArraylen$\ptr->letgo[]n=n`seq`return()-- make it strict in ngo(c:cs)n=dopokeElemOffptrn(castCharToCCharc);gocs(n+1)indogostr0f(ptr,len)wherelen=lengthstr-- 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)------------------------------------------------------------------------------- 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 C wide string (i.e. wide-- 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.--withCWStringLen::String->(CWStringLen->IOa)->IOawithCWStringLenstrf=withArrayLen(charsToCWcharsstr)$\lenptr->f(ptr,len)-- auxiliary definitions-- ----------------------wNUL::CWcharwNUL=0cWcharsToChars::[CWchar]->[Char]charsToCWchars::[Char]->[CWchar]#if defined(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 */

[8]ページ先頭

©2009-2025 Movatter.jp