A History Class for Use in Reading Today Data Files


The following is a C++ class for use in decifering the Today data files. Here is the class definition which is contained in a header file called history.h.
/*
    History class for Today in History
*/

#ifndef HISTORY_H
#define HISTORY_H

class History
{
    public:
        enum types { COMMENT, BIRTHDAY, EVENT, REMINDER, SAYING };
        History(const char *);
        History();

        int Type() const { return type; }
        int Month() const { return month; }
        int Day() const { return day; }
        int Year() const { return year; }
        int EndMonth() const { return endmonth; }
        int EndDay() const { return endday; }
        int DayOfWeek() const { return dayofweek; }
        int Continuation() const { return continuation; }
        const char *Text() const { return text; }

		void Load(const char *);
        void Type(const char);
        //             year      month        day
        void Date(const int, const int, const int);
        void Year(const int);
        void Month(const int);
        void Day(const int);
        void EndMonth(const int);
        void EndDay(const int);
        void DayOfWeek(const int);
        void Continuation(const int);
        void Text(const char *);

    private:
        int type;
        int year;
        int month;
        int day;
        int endmonth;
        int endday;
        int dayofweek;
        int continuation;
        char text[255];
        
        void DefaultEvent();
};

#endif


The guts follow. They are in the history.cpp file.
/*
    Member functions of History class
*/
#include "stdafx.h"

#include "history.h"
#include 

History::History()
{
    DefaultEvent();
}

History::History(const char * s)
{
    Load(s);
}

void History::Load(const char * s)
{
    Type(*s);

    if (type == COMMENT)
    {
        // get text of comment
        Text(s + 1);
    }
    else
    {
        // temporary array to parse
        char string[255];
        strncpy(string, s, sizeof string);

		// temporary text buffer
		char temptext[255];
        strncpy(temptext, string + 10, sizeof temptext);

        continuation = (toupper(*(string + 9)) == 'C') ? 1 : 0;
        dayofweek = (isdigit(*(string + 9))) ? (*(string + 9) - '0') : 0;
        *(string + 9) = '\0';

        // decifer date
        if (type == REMINDER)
        {
            // reminder has end month and day
            // instead of a year
            Year(0);
            int ed = atoi(string + 7);
            *(string + 7) = '\0';
            int em = atoi(string + 5);
            EndMonth(em);
            EndDay(ed);
        }
        else
        {
            int y = atoi(string + 5);
            Year(y);
        }
        *(string + 5) = '\0';
        int d = atoi(string + 3);
        *(string + 3) = '\0';
        int m = atoi(string + 1);
        Month(m);
        Day(d);

		// now build text from data
		switch (type)
		{
		    case BIRTHDAY:
			case EVENT:
				 if (continuation)
				 {
					 sprintf(text,"         %s", temptext);
				 }
				 else
				 {
				     sprintf(text,"%4d %s", year, temptext);
				 }
				 break;
			case REMINDER:
			case SAYING:
				 sprintf(text,"        %s", temptext);
				 break;

		}
    }
}

void History::DefaultEvent()
{
    type = COMMENT;
    Year(0);
    Month(1);
    Day(1);
    EndMonth(0);
    EndDay(0);
    Continuation(0);
    Text("Comment");
    DayOfWeek(0);
}

void History::Type(const char t)
{
    switch (toupper(t))
    {
        case 'B': type = BIRTHDAY;
                  break;
        case 'S': type = EVENT;
                  break;
        case 'R': type = REMINDER;
                  break;
        case 'F': type = SAYING;
                  break;
        default:  type = COMMENT;
    }
}

void History::Date(const int y, const int m, const int d)
{
    Year(y);
    Month(m);
    // must set day last
    Day(d);
}

void History::Year(const int y)
{
    year = (y < 9000) ? y : year;
}

void History::Month(const int m)
{
    month = (m > 0 && m < 13) ? m : month;
}

void History::EndMonth(const int m)
{
    endmonth = (m > 0 && m < 13) ? m : month;
}

void History::Day(const int d)
{
    int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // leap year reset feb days in month
    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0))
        days[1] = 29;

    day = (d > 0 && d <= days[month - 1]) ? d : day;
}
void History::EndDay(const int d)
{
    int days[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    // Since there is no year to look at there is no leap year check

    endday = (d > 0 && d <= days[month - 1]) ? d : day;
}

void History::DayOfWeek(const int d)
{
    dayofweek = (d > 0 && d < 8) ? d : dayofweek;
}

void History::Continuation(const int c)
{
    continuation = (c > 0) ? 1 : 0;
}

void History::Text(const char * s)
{
    strncpy(text, s, sizeof text);
}

And there you have it. Note: To get your copy of these files you can get a disk from me or, using your browser, pick File | Save As... and save the html file to your disk. If you are using Internet Explorer you can pick View | Source and this html document will be loaded into Notepad. You can then edit it and save it to a file.