aboutsummaryrefslogtreecommitdiff
path: root/SrcShared/EmStreamFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SrcShared/EmStreamFile.cpp')
-rw-r--r--SrcShared/EmStreamFile.cpp595
1 files changed, 595 insertions, 0 deletions
diff --git a/SrcShared/EmStreamFile.cpp b/SrcShared/EmStreamFile.cpp
new file mode 100644
index 0000000..380750c
--- /dev/null
+++ b/SrcShared/EmStreamFile.cpp
@@ -0,0 +1,595 @@
+/* -*- mode: C++; tab-width: 4 -*- */
+/* ===================================================================== *\
+ Copyright (c) 2000-2001 Palm, Inc. or its subsidiaries.
+ All rights reserved.
+
+ This file is part of the Palm OS Emulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+\* ===================================================================== */
+
+#include "EmCommon.h"
+#include "EmStreamFile.h"
+
+#include "EmErrCodes.h" // ConvertFromStdCError
+#include "ErrorHandling.h" // Errors::ThrowIfStdCError
+
+#include <errno.h> // EBADF, errno
+
+
+// ===========================================================================
+// ¥ EmStreamFile
+//
+// A EmStreamFile is a lightweight reference to an open file. The class's
+// constructor attempts to open (or create) the file based on the input
+// parameters. The class's destructor closes the file.
+//
+// Once a file is open, member functions can be used to operate on the
+// file (read from it, write to it, etc.).
+//
+// FileHandles can be copied, but no reference counting is performed.
+// Thus, after the first EmStreamFile is deleted, copies of it will
+// contain invalid file references.
+//
+// ===========================================================================
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::EmStreamFile
+ *
+ * DESCRIPTION: EmStreamFile constructor. Opens and/or creates the
+ * file according to the input parameters.
+ *
+ * PARAMETERS: ref - reference to the file to create/open.
+ *
+ * openMode - flags describing how to open/create the file
+ *
+ * creator - creator value to assign to the file if it's
+ * created (only used on Mac).
+ *
+ * fileType - file type value to assign to the file if it's
+ * created (only used on the Mac).
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+EmStreamFile::EmStreamFile (const EmFileRef& ref,
+ long openMode,
+ EmFileCreator creator,
+ EmFileType fileType) :
+ EmStream (),
+ fFileRef (ref),
+#if USE_MAC_CALLS
+ fRefNum (0)
+#else
+ fStream (NULL)
+#endif
+{
+ this->Open (ref, openMode, creator, fileType);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::~EmStreamFile
+ *
+ * DESCRIPTION: EmStreamFile destructor. Closes the file.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+EmStreamFile::~EmStreamFile (void)
+{
+ this->Close ();
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetMarker
+ *
+ * DESCRIPTION: Set the read/write position within the file.
+ *
+ * PARAMETERS: inOffset - stdio-style offset value.
+ *
+ * inFromWhere - stdio-style mode value.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetMarker (int32 inOffset,
+ StreamFromType inFromWhere)
+{
+ EmStream::SetMarker (inOffset, inFromWhere);
+
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ int whence;
+
+ if (inFromWhere == kStreamFromStart)
+ {
+ whence = fsFromStart;
+ }
+ else if (inFromWhere == kStreamFromEnd)
+ {
+ whence = fsFromLEOF;
+ }
+ else
+ {
+ EmAssert (inFromWhere == kStreamFromMarker);
+ whence = fsFromMark;
+ }
+
+ OSErr err = ::SetFPos (fRefNum, whence, inOffset);
+ if (err)
+ {
+ Need to deal with this being a Mac error, not a Std C error.
+ this->Throw (err);
+ }
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ int whence;
+
+ if (inFromWhere == kStreamFromStart)
+ {
+ whence = SEEK_SET;
+ }
+ else if (inFromWhere == kStreamFromEnd)
+ {
+ whence = SEEK_END;
+ }
+ else
+ {
+ EmAssert (inFromWhere == kStreamFromMarker);
+ whence = SEEK_CUR;
+ }
+
+ int err = fseek (fStream, inOffset, whence);
+ if (err)
+ {
+ this->Throw (errno);
+ }
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetMarker
+ *
+ * DESCRIPTION: Set the read/write position within the file.
+ *
+ * PARAMETERS: inOffset - stdio-style offset value.
+ *
+ * inFromWhere - stdio-style mode value.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+int32
+EmStreamFile::GetMarker (void) const
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ long pos;
+ OSErr err = ::GetFPos (fRefNum, &pos);
+ return pos;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ return ftell (fStream);
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetLength
+ *
+ * DESCRIPTION: Set the length of the file.
+ *
+ * PARAMETERS: inLength - the desired file length.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetLength (int32 inLength)
+{
+ EmStream::SetLength (inLength);
+
+ // !!! Use BOOL SetEndOfFile (fHandle);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetLength
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: None.
+ *
+ * RETURNED: The length of the stream (file) in bytes.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+int32
+EmStreamFile::GetLength (void) const
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EBADF);
+ }
+
+ long eof;
+ OSErr err = ::GetEOF (fRefNum, &eof);
+ return eof;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EBADF);
+ }
+
+ long cur = ftell (fStream);
+ fseek (fStream, 0, SEEK_END);
+
+ long length = ftell (fStream);
+ fseek (fStream, cur, SEEK_SET);
+
+ return length;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::PutBytes
+ *
+ * DESCRIPTION: Write data to the file.
+ *
+ * PARAMETERS: length - amount of data to write.
+ *
+ * buffer - buffer from which data is retrieved
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+ErrCode
+EmStreamFile::PutBytes (const void* inBuffer,
+ int32 inByteCount)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ return EBADF;
+ }
+
+ if (!inBuffer)
+ {
+ return EINVAL;
+ }
+
+ long count = inByteCount;
+ OSErr err = ::FSWrite (fRefNum, &count, inBuffer);
+
+ return err;
+#else
+ if (fStream == NULL)
+ {
+ return EBADF;
+ }
+
+ if (!inBuffer)
+ {
+ return EINVAL;
+ }
+
+ fwrite (inBuffer, 1, inByteCount, fStream);
+ if (ferror (fStream))
+ {
+ return ::ConvertFromStdCError (errno);
+ }
+
+ return 0;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::GetBytes
+ *
+ * DESCRIPTION: Read data from the file.
+ *
+ * PARAMETERS: length - amount of data to read.
+ *
+ * buffer - buffer into which the data is place.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+ErrCode
+EmStreamFile::GetBytes (void* outBuffer,
+ int32 inByteCount)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ return EBADF;
+ }
+
+ if (!outBuffer)
+ {
+ return EINVAL;
+ }
+
+ long count = inByteCount;
+ OSErr err = ::FSRead (fRefNum, &count, outBuffer);
+
+ if (!err && fTextMode)
+ {
+ char* buffer = (char*) outBuffer;
+ while (inByteCount--)
+ {
+ if (*buffer == '/n')
+ *buffer = '/r';
+ else if (*buffer == '/r')
+ *buffer = '/n';
+
+ ++buffer;
+ }
+ }
+
+ return err;
+#else
+ if (fStream == NULL)
+ {
+ return EBADF;
+ }
+
+ if (!outBuffer)
+ {
+ return EINVAL;
+ }
+
+ if (fread (outBuffer, 1, inByteCount, fStream) == 0)
+ {
+ return 1; // !!! need better error code
+ }
+
+ if (ferror (fStream))
+ {
+ return ::ConvertFromStdCError (errno);
+ }
+
+ return 0;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Open [protected]
+ *
+ * DESCRIPTION: Opens and/or creates the given file based on the given
+ * parameters. This function is called from the ctor in
+ * order to do all the work.
+ *
+ * PARAMETERS: ref - reference to the file to create/open.
+ *
+ * openMode - flags describing how to open/create the file
+ *
+ * creator - creator value to assign to the file if it's
+ * created (only used on Mac).
+ *
+ * fileType - file type value to assign to the file if it's
+ * created (only used on the Mac).
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Open (const EmFileRef& ref, long openMode,
+ EmFileCreator creator, EmFileType fileType)
+{
+#if USE_MAC_CALLS
+
+ // Open/create the file.
+
+ string cName = ref.GetFullPath ();
+ LStr255 name (cName.c_str ());
+ OSErr err;
+
+ if ((openMode & kOpenTypeMask) == kCreateOrEraseForUpdate)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ if (err == fnfErr)
+ {
+ err = ::Create (name, 0, creator, fileType);
+
+ if (!err)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ }
+
+ if (!err)
+ {
+ err = ::SetEOF (fRefNum, 0);
+ }
+ }
+ }
+ else if ((openMode & kOpenTypeMask) == kOpenExistingForRead)
+ {
+ err = ::FSOpen (name, 0, &fRefNum);
+ }
+
+ // Check for errors.
+
+ if (err)
+ {
+ fRefNum = 0;
+ this->Throw (err);
+ }
+
+ fTextMode = (openMode & kOpenText) != 0;
+#else
+ char* kModes[] = { "r", "w", "a", "r+", "w+", "a+" };
+ string mode (kModes[openMode & kOpenTypeMask]);
+
+ if ((openMode & kOpenText) != 0)
+ mode += 't';
+ else
+ mode += 'b';
+
+ // Open/create the file.
+
+ fStream = fopen (ref.GetFullPath ().c_str (), mode.c_str ());
+
+ // Check for errors.
+
+ if (fStream == NULL)
+ {
+ this->Throw (errno);
+ }
+#endif
+
+ if (creator && fileType)
+ {
+ ref.SetCreatorAndType (creator, fileType);
+ }
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Close [protected]
+ *
+ * DESCRIPTION: Closes the file. Called from the dtor to do all the
+ * work.
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ * If the operation fails, an exception is thrown.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Close (void)
+{
+#if USE_MAC_CALLS
+ if (fRefNum == 0)
+ {
+ this->Throw (EINVAL);
+ }
+
+ ::FSClose (fRefNum);
+ fRefNum = 0;
+#else
+ if (fStream == NULL)
+ {
+ this->Throw (EINVAL);
+ }
+
+ if (fclose (fStream))
+ {
+ fStream = NULL;
+ this->Throw (errno);
+ }
+
+ fStream = NULL;
+#endif
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::Throw [protected]
+ *
+ * DESCRIPTION: Bottleneck function for throwing an exception. Makes
+ * sure that the file's name is installed as an error
+ * message parameter and then throws the exception.
+ *
+ * PARAMETERS: err - Std C error code to throw.
+ *
+ * RETURNED: never.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::Throw (int err) const
+{
+ this->SetFileNameParameter ();
+
+ Errors::ThrowIfStdCError (err);
+}
+
+
+/***********************************************************************
+ *
+ * FUNCTION: EmStreamFile::SetFileNameParameter [protected]
+ *
+ * DESCRIPTION: .
+ *
+ * PARAMETERS: none.
+ *
+ * RETURNED: nothing.
+ *
+ ***********************************************************************/
+
+void
+EmStreamFile::SetFileNameParameter (void) const
+{
+ string name = fFileRef.GetName ();
+ Errors::SetParameter ("%filename", name);
+}