2 |
* * |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003-2019 by Christian Schoenebeck * |
* Copyright (C) 2003-2021 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
* <cuse@users.sourceforge.net> * |
7 |
* * |
* * |
8 |
* This library is free software; you can redistribute it and/or modify * |
* This library is free software; you can redistribute it and/or modify * |
51 |
#include <vector> |
#include <vector> |
52 |
#include <iostream> |
#include <iostream> |
53 |
#include <stdarg.h> |
#include <stdarg.h> |
54 |
|
#include <thread> |
55 |
|
#include <mutex> |
56 |
|
|
57 |
#ifdef HAVE_CONFIG_H |
#ifdef HAVE_CONFIG_H |
58 |
# include <config.h> |
# include <config.h> |
240 |
List* GetParent() const { return pParent; } ///< Returns pointer to the chunk's parent list chunk. |
List* GetParent() const { return pParent; } ///< Returns pointer to the chunk's parent list chunk. |
241 |
file_offset_t GetSize() const { return ullCurrentChunkSize; } ///< Chunk size in bytes (without header, thus the chunk data body) |
file_offset_t GetSize() const { return ullCurrentChunkSize; } ///< Chunk size in bytes (without header, thus the chunk data body) |
242 |
file_offset_t GetNewSize() const { return ullNewChunkSize; } ///< New chunk size if it was modified with Resize(), otherwise value returned will be equal to GetSize(). |
file_offset_t GetNewSize() const { return ullNewChunkSize; } ///< New chunk size if it was modified with Resize(), otherwise value returned will be equal to GetSize(). |
243 |
file_offset_t GetPos() const { return ullPos; } ///< Position within the chunk data body (starting with 0). |
file_offset_t GetPos() const; |
244 |
file_offset_t GetFilePos() const { return ullStartPos + ullPos; } ///< Current, actual offset in file of current chunk data body read/write position. |
file_offset_t GetFilePos() const; |
245 |
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence = stream_start); |
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence = stream_start); |
246 |
file_offset_t RemainingBytes() const; |
file_offset_t RemainingBytes() const; |
247 |
stream_state_t GetState() const; |
stream_state_t GetState() const; |
277 |
List* pParent; |
List* pParent; |
278 |
File* pFile; |
File* pFile; |
279 |
file_offset_t ullStartPos; /* actual position in file where chunk data (without header) starts */ |
file_offset_t ullStartPos; /* actual position in file where chunk data (without header) starts */ |
|
file_offset_t ullPos; /* # of bytes from ulStartPos */ |
|
280 |
uint8_t* pChunkData; |
uint8_t* pChunkData; |
281 |
file_offset_t ullChunkDataSize; |
file_offset_t ullChunkDataSize; |
282 |
|
struct ChunkPos { /* current read/write position as # of bytes from ulStartPos */ |
283 |
|
file_offset_t ullPos; /* used if File::IsIOPerThread() is false (default) */ |
284 |
|
mutable std::map<std::thread::id,file_offset_t> byThread; /* used if File::IsIOPerThread() is true */ |
285 |
|
mutable std::mutex mutex; /* for protecting concurrent changes on byThread map itself */ |
286 |
|
} chunkPos; |
287 |
|
|
288 |
Chunk(File* pFile); |
Chunk(File* pFile); |
289 |
Chunk(File* pFile, List* pParent, uint32_t uiChunkID, file_offset_t ullBodySize); |
Chunk(File* pFile, List* pParent, uint32_t uiChunkID, file_offset_t ullBodySize); |
304 |
virtual void __resetPos(); ///< Sets Chunk's read/write position to zero. |
virtual void __resetPos(); ///< Sets Chunk's read/write position to zero. |
305 |
|
|
306 |
friend class List; |
friend class List; |
307 |
|
private: |
308 |
|
file_offset_t& GetPosUnsafeRef(); |
309 |
}; |
}; |
310 |
|
|
311 |
/** @brief RIFF List Chunk |
/** @brief RIFF List Chunk |
365 |
*/ |
*/ |
366 |
class File : public List { |
class File : public List { |
367 |
public: |
public: |
368 |
|
/** |
369 |
|
* OS dependent type serving as file handle / descriptor for OS |
370 |
|
* dependent file I/O operations. |
371 |
|
*/ |
372 |
|
#if POSIX |
373 |
|
typedef int Handle; |
374 |
|
#elif defined(WIN32) |
375 |
|
typedef HANDLE Handle; |
376 |
|
#else |
377 |
|
typedef FILE* Handle; |
378 |
|
#endif |
379 |
|
|
380 |
File(uint32_t FileType); |
File(uint32_t FileType); |
381 |
File(const String& path); |
File(const String& path); |
382 |
File(const String& path, uint32_t FileType, endian_t Endian, layout_t layout, offset_size_t fileOffsetSize = offset_size_auto); |
File(const String& path, uint32_t FileType, endian_t Endian, layout_t layout, offset_size_t fileOffsetSize = offset_size_auto); |
385 |
void SetByteOrder(endian_t Endian); |
void SetByteOrder(endian_t Endian); |
386 |
String GetFileName() const; |
String GetFileName() const; |
387 |
void SetFileName(const String& path); |
void SetFileName(const String& path); |
388 |
|
Handle FileHandle() const; |
389 |
bool IsNew() const; |
bool IsNew() const; |
390 |
layout_t GetLayout() const; |
layout_t GetLayout() const; |
391 |
file_offset_t GetCurrentFileSize() const; |
file_offset_t GetCurrentFileSize() const; |
393 |
file_offset_t GetRequiredFileSize(offset_size_t fileOffsetSize); |
file_offset_t GetRequiredFileSize(offset_size_t fileOffsetSize); |
394 |
int GetFileOffsetSize() const; |
int GetFileOffsetSize() const; |
395 |
int GetRequiredFileOffsetSize(); |
int GetRequiredFileOffsetSize(); |
396 |
|
bool IsIOPerThread() const; |
397 |
|
void SetIOPerThread(bool enable); |
398 |
|
|
399 |
virtual void Save(progress_t* pProgress = NULL); |
virtual void Save(progress_t* pProgress = NULL); |
400 |
virtual void Save(const String& path, progress_t* pProgress = NULL); |
virtual void Save(const String& path, progress_t* pProgress = NULL); |
401 |
virtual ~File(); |
virtual ~File(); |
402 |
protected: |
protected: |
403 |
#if POSIX |
struct HandlePair { |
404 |
int hFileRead; ///< handle / descriptor for reading from file |
Handle hRead; ///< handle / descriptor for reading from file |
405 |
int hFileWrite; ///< handle / descriptor for writing to (some) file |
Handle hWrite; ///< handle / descriptor for writing to (some) file |
406 |
#elif defined(WIN32) |
stream_mode_t Mode; ///< State of handles (ro, rw, closed). |
407 |
HANDLE hFileRead; ///< handle / descriptor for reading from file |
}; |
408 |
HANDLE hFileWrite; ///< handle / descriptor for writing to (some) file |
struct IO : HandlePair { |
409 |
#else |
mutable std::map<std::thread::id,HandlePair> byThread; ///< Optional: Individual file handle pair for each thread separately. |
410 |
FILE* hFileRead; ///< handle / descriptor for reading from file |
mutable std::mutex mutex; ///< For protecting concurrent changes on the @c byThread map itself and replacing handles. |
411 |
FILE* hFileWrite; ///< handle / descriptor for writing to (some) file |
} io; |
|
#endif // POSIX |
|
412 |
String Filename; |
String Filename; |
413 |
bool bEndianNative; |
bool bEndianNative; |
414 |
bool bIsNewFile; |
bool bIsNewFile; |
416 |
offset_size_t FileOffsetPreference; |
offset_size_t FileOffsetPreference; |
417 |
int FileOffsetSize; ///< Size of file offsets (in bytes) when this file was opened (or saved the last time). |
int FileOffsetSize; ///< Size of file offsets (in bytes) when this file was opened (or saved the last time). |
418 |
|
|
419 |
|
Handle FileWriteHandle() const; |
420 |
|
HandlePair FileHandlePair() const; |
421 |
|
|
422 |
friend class Chunk; |
friend class Chunk; |
423 |
friend class List; |
friend class List; |
424 |
private: |
private: |
|
stream_mode_t Mode; |
|
|
|
|
425 |
void __openExistingFile(const String& path, uint32_t* FileType = NULL); |
void __openExistingFile(const String& path, uint32_t* FileType = NULL); |
426 |
void ResizeFile(file_offset_t ullNewSize); |
void ResizeFile(file_offset_t ullNewSize); |
427 |
#if POSIX |
#if POSIX |
433 |
#endif |
#endif |
434 |
int FileOffsetSizeFor(file_offset_t fileSize) const; |
int FileOffsetSizeFor(file_offset_t fileSize) const; |
435 |
void Cleanup(); |
void Cleanup(); |
436 |
|
HandlePair& FileHandlePairUnsafeRef(); |
437 |
}; |
}; |
438 |
|
|
439 |
/** |
/** |