140 lines
4.2 KiB
C
140 lines
4.2 KiB
C
|
/**
|
||
|
* PANDA 3D SOFTWARE
|
||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||
|
*
|
||
|
* All use of this software is subject to the terms of the revised BSD
|
||
|
* license. You should have received a copy of this license along
|
||
|
* with this source code in a file named "LICENSE."
|
||
|
*
|
||
|
* @file streamWrapper.h
|
||
|
* @author drose
|
||
|
* @date 2008-11-11
|
||
|
*/
|
||
|
|
||
|
#ifndef STREAMWRAPPER_H
|
||
|
#define STREAMWRAPPER_H
|
||
|
|
||
|
#include "dtoolbase.h"
|
||
|
#include "mutexImpl.h"
|
||
|
#include "atomicAdjust.h"
|
||
|
|
||
|
/**
|
||
|
* The base class for both IStreamWrapper and OStreamWrapper, this provides
|
||
|
* the common locking interface.
|
||
|
*/
|
||
|
class EXPCL_DTOOL_PRC StreamWrapperBase {
|
||
|
protected:
|
||
|
INLINE StreamWrapperBase();
|
||
|
INLINE StreamWrapperBase(const StreamWrapperBase ©) = delete;
|
||
|
|
||
|
PUBLISHED:
|
||
|
INLINE void acquire();
|
||
|
INLINE void release();
|
||
|
|
||
|
public:
|
||
|
INLINE void ref() const;
|
||
|
INLINE bool unref() const;
|
||
|
|
||
|
private:
|
||
|
MutexImpl _lock;
|
||
|
|
||
|
// This isn't really designed as a reference counted class, but it is useful
|
||
|
// to treat it as one when dealing with substreams created by Multifile.
|
||
|
mutable AtomicAdjust::Integer _ref_count = 1;
|
||
|
|
||
|
#ifdef SIMPLE_THREADS
|
||
|
// In the SIMPLE_THREADS case, we need to use a bool flag, because MutexImpl
|
||
|
// defines to nothing in this case--but we still need to achieve a form of
|
||
|
// locking, since IO operations can cause the thread to swap without
|
||
|
// warning.
|
||
|
bool _lock_flag;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* This class provides a locking wrapper around an arbitrary istream pointer.
|
||
|
* A thread may use this class to perform an atomic seek/read/gcount
|
||
|
* operation.
|
||
|
*/
|
||
|
class EXPCL_DTOOL_PRC IStreamWrapper : virtual public StreamWrapperBase {
|
||
|
public:
|
||
|
INLINE IStreamWrapper(std::istream *stream, bool owns_pointer);
|
||
|
PUBLISHED:
|
||
|
INLINE explicit IStreamWrapper(std::istream &stream);
|
||
|
~IStreamWrapper();
|
||
|
|
||
|
INLINE std::istream *get_istream() const;
|
||
|
MAKE_PROPERTY(std::istream, get_istream);
|
||
|
|
||
|
public:
|
||
|
void read(char *buffer, std::streamsize num_bytes);
|
||
|
void read(char *buffer, std::streamsize num_bytes, std::streamsize &read_bytes);
|
||
|
void read(char *buffer, std::streamsize num_bytes, std::streamsize &read_bytes, bool &eof);
|
||
|
void seek_read(std::streamsize pos, char *buffer, std::streamsize num_bytes, std::streamsize &read_bytes, bool &eof);
|
||
|
INLINE int get();
|
||
|
std::streamsize seek_gpos_eof();
|
||
|
|
||
|
private:
|
||
|
std::istream *_istream;
|
||
|
bool _owns_pointer;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* This class provides a locking wrapper around an arbitrary ostream pointer.
|
||
|
* A thread may use this class to perform an atomic seek/write operation.
|
||
|
*/
|
||
|
class EXPCL_DTOOL_PRC OStreamWrapper : virtual public StreamWrapperBase {
|
||
|
public:
|
||
|
INLINE OStreamWrapper(std::ostream *stream, bool owns_pointer, bool stringstream_hack = false);
|
||
|
PUBLISHED:
|
||
|
INLINE explicit OStreamWrapper(std::ostream &stream);
|
||
|
~OStreamWrapper();
|
||
|
|
||
|
INLINE std::ostream *get_ostream() const;
|
||
|
MAKE_PROPERTY(std::ostream, get_ostream);
|
||
|
|
||
|
public:
|
||
|
void write(const char *buffer, std::streamsize num_bytes);
|
||
|
void write(const char *buffer, std::streamsize num_bytes, bool &fail);
|
||
|
void seek_write(std::streamsize pos, const char *buffer, std::streamsize num_bytes, bool &fail);
|
||
|
void seek_eof_write(const char *buffer, std::streamsize num_bytes, bool &fail);
|
||
|
INLINE bool put(char c);
|
||
|
std::streamsize seek_ppos_eof();
|
||
|
|
||
|
private:
|
||
|
std::ostream *_ostream;
|
||
|
bool _owns_pointer;
|
||
|
|
||
|
// This flag is necessary to work around a weird quirk in the MSVS C++
|
||
|
// runtime library: an empty stringstream cannot successfully seekp(0),
|
||
|
// until some data has been written to the stream. When this flag is set
|
||
|
// true, we know we have a possibly-empty stringstream, so we allow seekp(0)
|
||
|
// to fail silently, knowing that there's no harm in this case.
|
||
|
#ifdef WIN32_VC
|
||
|
bool _stringstream_hack;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* This class provides a locking wrapper around a combination ostream/istream
|
||
|
* pointer.
|
||
|
*/
|
||
|
class EXPCL_DTOOL_PRC StreamWrapper : public IStreamWrapper, public OStreamWrapper {
|
||
|
public:
|
||
|
INLINE StreamWrapper(std::iostream *stream, bool owns_pointer, bool stringstream_hack = false);
|
||
|
PUBLISHED:
|
||
|
INLINE explicit StreamWrapper(std::iostream &stream);
|
||
|
~StreamWrapper();
|
||
|
|
||
|
INLINE std::iostream *get_iostream() const;
|
||
|
MAKE_PROPERTY(std::iostream, get_iostream);
|
||
|
|
||
|
private:
|
||
|
std::iostream *_iostream;
|
||
|
bool _owns_pointer;
|
||
|
};
|
||
|
|
||
|
#include "streamWrapper.I"
|
||
|
|
||
|
#endif
|