internal static byte[] CFGetData(SafeCFDataHandle cfData) { bool addedRef = false; try { cfData.DangerousAddRef(ref addedRef); byte[] bytes = new byte[CFDataGetLength(cfData).ToInt64()]; unsafe { byte *dataBytes = CFDataGetBytePtr(cfData); Marshal.Copy((IntPtr)dataBytes, bytes, 0, bytes.Length); } return(bytes); } finally { if (addedRef) { cfData.DangerousRelease(); } } }
internal static unsafe bool TryCFWriteData(SafeCFDataHandle cfData, Span <byte> destination, out int bytesWritten) { bool addedRef = false; try { cfData.DangerousAddRef(ref addedRef); long length = CFDataGetLength(cfData).ToInt64(); if (destination.Length < length) { bytesWritten = 0; return(false); } byte *dataBytes = CFDataGetBytePtr(cfData); fixed(byte *destinationPtr = &MemoryMarshal.GetReference(destination)) { Buffer.MemoryCopy(dataBytes, destinationPtr, destination.Length, length); } bytesWritten = (int)length; return(true); } finally { if (addedRef) { cfData.DangerousRelease(); } } }
internal static string CFStringToString(SafeCFStringHandle cfString) { Debug.Assert(cfString != null); Debug.Assert(!cfString.IsInvalid); Debug.Assert(!cfString.IsClosed); // If the string is already stored internally as UTF-8 we can (usually) // get the raw pointer to the data blob, then we can Marshal in the string // via pointer semantics, avoiding a copy. IntPtr interiorPointer = CFStringGetCStringPtr( cfString, CFStringBuiltInEncodings.kCFStringEncodingUTF8); if (interiorPointer != IntPtr.Zero) { return(Marshal.PtrToStringUTF8(interiorPointer) !); } SafeCFDataHandle cfData = CFStringCreateExternalRepresentation( IntPtr.Zero, cfString, CFStringBuiltInEncodings.kCFStringEncodingUTF8, 0); using (cfData) { bool addedRef = false; try { cfData.DangerousAddRef(ref addedRef); unsafe { // Note that CFDataGetLength(cfData).ToInt32() will throw on // too large of an input. Since a >2GB string is pretty unlikely, // that's considered a good thing here. return(Encoding.UTF8.GetString( CFDataGetBytePtr(cfData), CFDataGetLength(cfData).ToInt32())); } } finally { if (addedRef) { cfData.DangerousRelease(); } } } }
internal static string CFStringToString(SafeCFStringHandle cfString) { Debug.Assert(cfString != null); Debug.Assert(!cfString.IsInvalid); Debug.Assert(!cfString.IsClosed); #if HAVE_PTRTOSTRINGUTF8 IntPtr interiorPointer = CFStringGetCStringPtr( cfString, CFStringBuiltInEncodings.kCFStringEncodingUTF8); if (interiorPointer != IntPtr.Zero) { return(Marshal.PtrToStringUTF8(interiorPointer)); } #endif SafeCFDataHandle cfData = CFStringCreateExternalRepresentation( IntPtr.Zero, cfString, CFStringBuiltInEncodings.kCFStringEncodingUTF8, 0); using (cfData) { bool addedRef = false; try { cfData.DangerousAddRef(ref addedRef); unsafe { // Note that CFDataGetLength(cfData).ToInt32() will throw on // too large of an input. Since a >2GB string is pretty unlikely, // that's considered a good thing here. return(Encoding.UTF8.GetString( CFDataGetBytePtr(cfData), CFDataGetLength(cfData).ToInt32())); } } finally { if (addedRef) { cfData.DangerousRelease(); } } } }
internal static byte[] CFGetData(SafeCFDataHandle cfData) { bool addedRef = false; try { cfData.DangerousAddRef(ref addedRef); return(CFDataDangerousGetSpan(cfData).ToArray()); } finally { if (addedRef) { cfData.DangerousRelease(); } } }