Source: include/hp49calc.H


Annotated List
Files
Globals
Hierarchy
Index
/* -------------------------------------------------------------------------
   hp49.H - HP49 Calculator Specific Classes and Functions
   -------------------------------------------------------------------------
   Copyright (C) 2000-2001 Eric R. Schendel
 
   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.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               
   ------------------------------------------------------------------------- */

#ifndef HP49_H
#define HP49_H

#include<string>
#include<fstream>

#include "status.H"

namespace Hp49Calc {

using namespace StatusMsgs;

const long HPF_ERR_FILE_SIZE = -1;
const unsigned long HPF_DEFAULT_FILE_SIZE = (unsigned long) - 1;

const char HPF_HEADER[] = "HPHP49-X";
const char HPF_HEADER_REPLACE = 'X';
const int HPF_HEADER_SIZE = 8;

const unsigned long HPF_TYPE_STRING = 0x02A2C;

enum HpFileType {HPF_UNDEFINED = 0, HPF_STRING = 1, HPF_UNKNOWN = 2};

const unsigned short HPCRC_SEED = 0x1081;

/**
 * This is an abstract base class for all Hp49 files.
 * All classes which inherit this one must have an open() method.
 */
class Hp49File {

   public:

      /**
       * Constructor must be supplied with a file name
       *
       * @param name File name
       * @param lvl  Log level
       */
      Hp49File(string name, LogLevel lvl = NONE);
      virtual ~Hp49File();

      virtual Error open() = 0;
      virtual Error close();

      /**
       * For any reading or writing file activity, a stream must be created.
       *
       * @param mode same modes which would be passed to a fstream.open(...)
       */
      Error createStream(int mode);

      fstream& getStream() { return fs; }
      string getName() const { return fname; }
      HpFileType getType() const { return type; }

      /**
       * This is the size of the data portion of the Hp49 file. I know this
       * works properly for Hp49 string files but I have not tested it out with
       * any other other types of files, so I do not know if this is consistant
       * through out. Also the data part is the portion of bytes at the end of
       * the file, but this might change in the future.
       */
      unsigned long getDataSize() const;

   protected:
      void setType(HpFileType t) { type = t; }
      void setDataSize(unsigned long s) { size = s; }

   private:
      Log log;

      fstream fs;
      string fname;
      HpFileType type;
      long size;

      Hp49File();
};


class Hp49FileRead: public Hp49File {

   public:

      /**
       * Constructor must be supplied with a file name
       *
       * @param name File name
       * @param lvl  Log level
       */
      Hp49FileRead(string name, LogLevel lvl = NONE);

      /**
       * Checks to see if the file is a valid Hp49 file.
       *
       * @return Error: SUCCESS, MINOR (not valid Hp49 File), MAJOR (unable
       *                to physically read file).
       */
      Error check();

      Error open();

      /**
       * Trying to read past the end of file will be considered as an
       * error, especially since the data size of a file can be known
       * before hand.
       */
      bool readNibble(unsigned char&);

      /**
       * Basically two calls to readNibble
       */
      bool readByte(unsigned char&);

      /**
       * Reads nibbles from file to be recognized as a long integer.
       * Therefore the first read nibble is the least significant and
       * the last is the most significant.
       *
       * @param n    returned result of nibbles read
       * @param c_sz number of nibbles to read
       */
      Error readNibbles(unsigned long& n, const int c_sz);

      /**
       * Reads straight from the file, byte by byte, and places it in
       * a string.
       *
       * @param str returned result of bytes read
       * @param sz  number of bytes to read
       */
      Error readBytes(string&, const int sz);

      /**
       * Reads specified number of bytes of data from Hp49 file. After file is
       * read, pointer wil not be reseted and will not go beyond end-of-file.
       * This helps to have multiple reads for large files.
       *
       * @param data String to store data into
       * @param size Number of bytes to read. Default is all bytes
       */
      Error readData(string& data, unsigned long size = HPF_DEFAULT_FILE_SIZE);

   private:
      Log log;

      bool second_nib;
      char buffered_byte;

      Error process_header();
      Error get_file_type();
      Error get_data_size();
};


class Hp49FileWrite: public Hp49File {

   public:

      /**
       * Constructor must be supplied with a file name
       *
       * @param name File name
       * @param lvl  Log level
       */
      Hp49FileWrite(string name, LogLevel lvl = NONE);
      ~Hp49FileWrite();

      /**
       * The only supported file type to write to is a Hp49 String file,
       * therefore, open() defaults to openString(). The way this is handled
       * might change in the future.
       */
      Error open() { return openString(); }
      Error openString();

      /**
       * Very important that this is called or data bytes might be missing.
       */
      Error close();

      bool writeNibble(unsigned char&);
      bool writeByte(unsigned char&);

      /**
       * Writes specified number of nibbles from long integer to a Hp49 file.
       * Therefore the first written nibble is the least significant and
       * the last is the most significant.
       *
       * @param n    returned result of nibbles read
       * @param c_sz number of nibbles to read
       */
      Error writeNibbles(unsigned long n, const int c_sz);
      Error writeBytes(string);

      /**
       * Writes specified string of bytes of data to Hp49 file. This method
       * lacks the function to handle multiple writes! In an attempt to append
       * data will corrupt the Hp49 binary file. This will be fixed if I become
       * bored or find a real reason for it.
       *
       * @param data String to store data into.
       */
      Error writeData(string data);

   private:
      Log log;

      bool first_nib;
      char buffered_nib;

      Error create_header();
      Error set_string_type();
      Error set_data_size(unsigned long&);
};

class HpCRC {

   public:

      HpCRC(LogLevel = NONE);

      unsigned short calculate(string data);
      unsigned char low() { return crc & 0xFF; }
      unsigned char high() { return (crc >> 8) & 0xFF; }

      operator unsigned short() const { return crc; }

   private:
      Log log;

      unsigned short crc;
};

} //namespace Hp49Calc //

#endif

Generated on Fri Mar 9 02:04:42 2001, using kdoc 2.0a43.