FileInMemory FileInMemory_create (MelderFile file) { try { if (! MelderFile_readable (file)) { Melder_throw ("File not readable."); } long length = MelderFile_length (file); if (length <= 0) { Melder_throw ("File is empty."); } autoFileInMemory me = Thing_new (FileInMemory); my d_path = Melder_wcsdup (file -> path); my d_id = Melder_wcsdup (MelderFile_name (file)); my d_numberOfBytes = length; my d_data = NUMvector <char> (0, my d_numberOfBytes); // one extra for 0-byte at end if text MelderFile_open (file); for (long i = 0; i < my d_numberOfBytes; i++) { unsigned int number = bingetu1 (file -> filePointer); my d_data[i] = number; } my d_data[my d_numberOfBytes] = 0; // one extra MelderFile_close (file); return me.transfer(); } catch (MelderError) { Melder_throw ("FileInMemory not created from \"", Melder_fileToPath (file), "\"."); } }
autoFileInMemory FileInMemory_create (MelderFile file) { try { if (! MelderFile_readable (file)) { Melder_throw (U"File not readable."); } long length = MelderFile_length (file); if (length <= 0) { Melder_throw (U"File is empty."); } autoFileInMemory me = Thing_new (FileInMemory); my d_path = Melder_dup (file -> path); my d_id = Melder_dup (MelderFile_name (file)); my d_numberOfBytes = length; my ownData = true; my d_data = NUMvector <char> (0, my d_numberOfBytes); // includes room for a final null byte in case the file happens to contain text MelderFile_open (file); for (long i = 0; i < my d_numberOfBytes; i++) { unsigned int number = bingetu1 (file -> filePointer); my d_data[i] = number; } my d_data[my d_numberOfBytes] = 0; // one extra MelderFile_close (file); return me; } catch (MelderError) { Melder_throw (U"FileInMemory not created from \"", Melder_fileToPath (file), U"\"."); } }
/* BSD systems provide ftruncate, several others supply chsize, and a few may provide a (possibly undocumented) fcntl option F_FREESP. Under MS-DOS, you can sometimes use write(fd, "", 0). However, there is no portable solution, nor a way to delete blocks at the beginning. */ static void MelderFile_truncate (MelderFile me, long size) { #if defined(_WIN32) HANDLE hFile; DWORD fdwAccess = GENERIC_READ | GENERIC_WRITE, fPos; DWORD fdwShareMode = 0; /* File cannot be shared */ LPSECURITY_ATTRIBUTES lpsa = NULL; DWORD fdwCreate = OPEN_EXISTING; LARGE_INTEGER fileSize; MelderFile_close (me); hFile = CreateFileW (my path, fdwAccess, fdwShareMode, lpsa, fdwCreate, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { Melder_throw ("Can't open file ", MelderFile_messageName (me), "."); } // Set current file pointer to position 'size' fileSize.LowPart = size; fileSize.HighPart = 0; /* Limit the file size to 2^32 - 2 bytes */ fPos = SetFilePointer (hFile, fileSize.LowPart, &fileSize.HighPart, FILE_BEGIN); if (fPos == 0xFFFFFFFF) { Melder_throw ("Can't set the position at size ", size, "for file ", MelderFile_messageName (me), "."); } // Limit the file size as the current position of the file pointer. SetEndOfFile (hFile); CloseHandle (hFile); #elif defined(linux) || defined(macintosh) MelderFile_close (me); if (truncate (Melder_peekWcsToUtf8 (my path), size) == -1) Melder_throw ("Truncating failed for file ", MelderFile_messageName (me), " (", Melder_peekUtf8ToWcs (strerror (errno)), ")."); #else Melder_throw ("Don't know what to do."); #endif }