Cleanup
[carla.git] / source / modules / water / files / FileOutputStream.cpp
blobead60c07d1fec4891cf8f3d19f1b1c280417c88b
1 /*
2 ==============================================================================
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com>
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
23 ==============================================================================
26 #include "FileOutputStream.h"
28 namespace water {
30 int64 water_fileSetPosition (void* handle, int64 pos);
32 //==============================================================================
33 FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse)
34 : file (f),
35 fileHandle (nullptr),
36 status (Result::ok()),
37 currentPosition (0),
38 bufferSize (bufferSizeToUse),
39 bytesInBuffer (0)
41 if (buffer.malloc(jmax (bufferSizeToUse, (size_t) 16)))
42 openHandle();
43 else
44 status = Result::fail ("Allocation failure");
47 FileOutputStream::~FileOutputStream()
49 flushBuffer();
50 closeHandle();
53 int64 FileOutputStream::getPosition()
55 return currentPosition;
58 bool FileOutputStream::setPosition (int64 newPosition)
60 if (newPosition != currentPosition)
62 flushBuffer();
63 currentPosition = water_fileSetPosition (fileHandle, newPosition);
66 return newPosition == currentPosition;
69 bool FileOutputStream::flushBuffer()
71 bool ok = true;
73 if (bytesInBuffer > 0)
75 ok = (writeInternal (buffer, bytesInBuffer) == (ssize_t) bytesInBuffer);
76 bytesInBuffer = 0;
79 return ok;
82 void FileOutputStream::flush()
84 flushBuffer();
85 flushInternal();
88 bool FileOutputStream::write (const void* const src, const size_t numBytes)
90 wassert (src != nullptr && ((ssize_t) numBytes) >= 0);
92 if (bytesInBuffer + numBytes < bufferSize)
94 memcpy (buffer + bytesInBuffer, src, numBytes);
95 bytesInBuffer += numBytes;
96 currentPosition += (int64) numBytes;
98 else
100 if (! flushBuffer())
101 return false;
103 if (numBytes < bufferSize)
105 memcpy (buffer + bytesInBuffer, src, numBytes);
106 bytesInBuffer += numBytes;
107 currentPosition += (int64) numBytes;
109 else
111 const ssize_t bytesWritten = writeInternal (src, numBytes);
113 if (bytesWritten < 0)
114 return false;
116 currentPosition += (int64) bytesWritten;
117 return bytesWritten == (ssize_t) numBytes;
121 return true;
124 bool FileOutputStream::writeRepeatedByte (uint8 byte, size_t numBytes)
126 wassert (((ssize_t) numBytes) >= 0);
128 if (bytesInBuffer + numBytes < bufferSize)
130 memset (buffer + bytesInBuffer, byte, numBytes);
131 bytesInBuffer += numBytes;
132 currentPosition += (int64) numBytes;
133 return true;
136 return OutputStream::writeRepeatedByte (byte, numBytes);
139 #ifdef CARLA_OS_WIN
140 void FileOutputStream::openHandle()
142 HANDLE h = CreateFileA (file.getFullPathName().toUTF8(), GENERIC_WRITE, FILE_SHARE_READ, 0,
143 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
145 if (h != INVALID_HANDLE_VALUE)
147 LARGE_INTEGER li;
148 li.QuadPart = 0;
149 li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_END);
151 if (li.LowPart != INVALID_SET_FILE_POINTER)
153 fileHandle = (void*) h;
154 currentPosition = li.QuadPart;
155 return;
159 status = getResultForLastError();
162 void FileOutputStream::closeHandle()
164 CloseHandle ((HANDLE) fileHandle);
167 ssize_t FileOutputStream::writeInternal (const void* bufferToWrite, size_t numBytes)
169 if (fileHandle != nullptr)
171 DWORD actualNum = 0;
172 if (! WriteFile ((HANDLE) fileHandle, bufferToWrite, (DWORD) numBytes, &actualNum, 0))
173 status = getResultForLastError();
175 return (ssize_t) actualNum;
178 return 0;
181 void FileOutputStream::flushInternal()
183 if (fileHandle != nullptr)
184 if (! FlushFileBuffers ((HANDLE) fileHandle))
185 status = getResultForLastError();
187 #else
188 void FileOutputStream::openHandle()
190 if (file.exists())
192 const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644);
194 if (f != -1)
196 currentPosition = lseek (f, 0, SEEK_END);
198 if (currentPosition >= 0)
200 fileHandle = fdToVoidPointer (f);
202 else
204 status = getResultForErrno();
205 close (f);
208 else
210 status = getResultForErrno();
213 else
215 const int f = open (file.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644);
217 if (f != -1)
218 fileHandle = fdToVoidPointer (f);
219 else
220 status = getResultForErrno();
224 void FileOutputStream::closeHandle()
226 if (fileHandle != 0)
228 close (getFD (fileHandle));
229 fileHandle = 0;
233 ssize_t FileOutputStream::writeInternal (const void* const data, const size_t numBytes)
235 ssize_t result = 0;
237 if (fileHandle != 0)
239 result = ::write (getFD (fileHandle), data, numBytes);
241 if (result == -1)
242 status = getResultForErrno();
245 return result;
248 void FileOutputStream::flushInternal()
250 if (fileHandle != 0)
252 if (fsync (getFD (fileHandle)) == -1)
253 status = getResultForErrno();
256 #endif