Click here to Skip to main content
15,880,469 members
Articles / High Performance Computing / Vectorization

A C++ String Class

Rate me:
Please Sign up or sign in to vote.
4.96/5 (29 votes)
3 Jan 2015CPOL13 min read 120.5K   2.6K   93  
A fast, reference counted, copy-on-write string class
#pragma once
#ifndef __HWINDATETIME_H__
#define __HWINDATETIME_H__

#include <iostream>
#include <iomanip>
#include "hwinDef.h"
#include "hwinString.h"


#ifdef _MANAGED
#pragma managed(push,off) 
#endif

#pragma pack(push,8)
namespace harlinn
{
    namespace windows
    {

        namespace globalization
        {
            class Calendar;
        };

        class BinaryReader;
        class BinaryWriter;

        enum class DateTimeKind
        {
            Unspecified = 0,
            Utc = 1,
            Local = 2
        };

        enum class DayOfWeek
        {
            Sunday = 0,
            Monday = 1,
            Tuesday = 2,
            Wednesday = 3,
            Thursday = 4,
            Friday = 5,
            Saturday = 6
        };

        enum class DatePart
        {
            Year = 0,
            DayOfYear = 1,
            Month = 2,
            Day = 3
        };

        class TimeBase
        {
        public:
            static const long long TicksPerMillisecond = 10000;
            static const long long TicksPerSecond = TicksPerMillisecond * 1000;
            static const long long TicksPerMinute = TicksPerSecond * 60;
            static const long long TicksPerHour = TicksPerMinute * 60;
            static const long long TicksPerDay = TicksPerHour * 24;

            HWIN_EXPORT static const double MillisecondsPerTick;
            HWIN_EXPORT static const double SecondsPerTick;
            HWIN_EXPORT static const double MinutesPerTick;
            HWIN_EXPORT static const double HoursPerTick;
            HWIN_EXPORT static const double DaysPerTick;
            HWIN_EXPORT static const double OADateMinAsDouble;
            HWIN_EXPORT static const double OADateMaxAsDouble;

            HWIN_EXPORT static const int DaysToMonth365[13];
            HWIN_EXPORT static const int DaysToMonth366[13];

            static const int MillisPerSecond = 1000;
            static const int MillisPerMinute = MillisPerSecond * 60;
            static const int MillisPerHour = MillisPerMinute * 60;
            static const int MillisPerDay = MillisPerHour * 24;


            static const long long MaxSeconds = MaxInt64 / TicksPerSecond;
            static const long long MinSeconds = MinInt64 / TicksPerSecond;

            static const long long MaxMilliSeconds = MaxInt64 / TicksPerMillisecond;
            static const long long MinMilliSeconds = MinInt64 / TicksPerMillisecond;

            static const long long TicksPerTenthSecond = TicksPerMillisecond * 100;

            static const long long UnixEpoch = 621355968000000000LL;

            static const int DaysPerYear = 365;
            static const int DaysPer4Years = DaysPerYear * 4 + 1;
            static const int DaysPer100Years = DaysPer4Years * 25 - 1;
            static const int DaysPer400Years = DaysPer100Years * 4 + 1;


            static const int DaysTo1601 = DaysPer400Years * 4;
            static const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367;
            static const int DaysTo10000 = DaysPer400Years * 25 - 366;

            static const long long MinTicks = 0;
            static const long long MaxTicks = DaysTo10000 * TicksPerDay - 1;
            static const long long MaxMillis = ( long long )DaysTo10000 * MillisPerDay;

            static const long long FileTimeOffset = DaysTo1601 * TicksPerDay;
            static const long long DoubleDateOffset = DaysTo1899 * TicksPerDay;


            static const long long OADateMinAsTicks = ( DaysPer100Years - DaysPerYear ) * TicksPerDay;

        };


        class DateTime;
        class TimeSpan : public TimeBase
        {
            friend class DateTime;
        public:


            HWIN_EXPORT static const TimeSpan Zero;
            HWIN_EXPORT static const TimeSpan MaxValue;
            HWIN_EXPORT static const TimeSpan MinValue;

        private:




            long long ticks;

            HWIN_EXPORT static TimeSpan Interval( double theValue, int theScale );
        public:
            HWIN_EXPORT static long long TimeToTicks( int theDays, int theHours = 0, int theMinutes = 0, int theSeconds = 0, int theMilliseconds = 0 );

            TimeSpan( )
                : ticks( 0 )
            {

            }

            explicit TimeSpan( long long theTicks )
                : ticks( theTicks )
            {

            }

            TimeSpan( const TimeSpan& other )
                : ticks( other.ticks )
            {

            }

            TimeSpan( int hours, int minutes, int seconds )
                : ticks( TimeToTicks( 0, hours, minutes, seconds ) )
            {

            }

            TimeSpan( int days, int hours, int minutes, int seconds )
                : ticks( TimeToTicks( days, hours, minutes, seconds ) )
            {

            }

            TimeSpan( int days, int hours, int minutes, int seconds, int milliseconds )
                : ticks( TimeToTicks( days, hours, minutes, seconds, milliseconds ) )
            {

            }

            size_t hash( ) const
            {
                return std::_Hash_seq( ( const unsigned char * )&ticks, sizeof( ticks ) );
            }

            long long Ticks( ) const
            {
                return ticks;
            }

            int Days( ) const
            {
                return ( int )( ticks / TicksPerDay );
            }

            int Hours( ) const
            {
                return ( int )( ( ticks / TicksPerHour ) % 24 );
            }

            int Milliseconds( ) const
            {
                return ( int )( ( ticks / TicksPerMillisecond ) % 1000 );
            }

            int Minutes( ) const
            {
                return ( int )( ( ticks / TicksPerMinute ) % 60 );
            }

            int Seconds( ) const
            {
                return ( int )( ( ticks / TicksPerSecond ) % 60 );
            }

            HWIN_EXPORT double TotalDays( ) const;

            HWIN_EXPORT double TotalHours( ) const;

            HWIN_EXPORT double TotalMilliseconds( ) const;


            HWIN_EXPORT double TotalMinutes( ) const;

            HWIN_EXPORT double TotalSeconds( ) const;

            HWIN_EXPORT TimeSpan Add( const TimeSpan& other ) const;

            static int Compare( const TimeSpan& t1, const TimeSpan& t2 )
            {
                if ( t1.ticks > t2.ticks )
                {
                    return 1;
                }
                if ( t1.ticks < t2.ticks )
                {
                    return -1;
                }
                return 0;
            }

            int CompareTo( const TimeSpan& value ) const
            {
                if ( ticks > value.ticks )
                {
                    return 1;
                }
                if ( ticks < value.ticks )
                {
                    return -1;
                }
                return 0;
            }

            static TimeSpan FromDays( double value )
            {
                return Interval( value, MillisPerDay );
            }

            HWIN_EXPORT TimeSpan Duration( ) const;

            int HashCode( ) const
            {
                return ( int )ticks ^ ( int )( ticks >> 32 );
            }

            static TimeSpan FromHours( double value )
            {
                return Interval( value, MillisPerHour );
            }

            static TimeSpan FromMilliseconds( double value )
            {
                return Interval( value, 1 );
            }

            static TimeSpan FromMinutes( double value )
            {
                return Interval( value, MillisPerMinute );
            }

            HWIN_EXPORT TimeSpan Negate( ) const;

            static TimeSpan FromSeconds( double value )
            {
                return Interval( value, MillisPerSecond );
            }

            HWIN_EXPORT TimeSpan Subtract( const TimeSpan& theOther ) const;

            static TimeSpan FromTicks( long long value )
            {
                return TimeSpan( value );
            }

            TimeSpan operator + ( const TimeSpan& theValue ) const
            {
                return Add( theValue );
            }

            TimeSpan operator - ( const TimeSpan& theValue ) const
            {
                return Subtract( theValue );
            }

            template<typename T>
            typename std::enable_if<std::is_arithmetic<T>::value, TimeSpan>::type operator * ( const T& theValue ) const
            {
                return TimeSpan( Ticks( ) * static_cast< long long >( theValue ) );
            }

            template<typename T>
            friend typename std::enable_if<std::is_arithmetic<T>::value, TimeSpan>::type operator * ( const T& theValue, const TimeSpan& theTimeSpan )
            {
                return TimeSpan( static_cast< long long >( theValue )* theTimeSpan.Ticks( ) );
            }

            bool operator == ( const TimeSpan& other ) const
            {
                return CompareTo( other ) == 0;
            }
            bool operator != ( const TimeSpan& other ) const
            {
                return CompareTo( other ) != 0;
            }
            bool operator <  ( const TimeSpan& other ) const
            {
                return CompareTo( other ) < 0;
            }
            bool operator <= ( const TimeSpan& other ) const
            {
                return CompareTo( other ) <= 0;
            }
            bool operator >  ( const TimeSpan& other ) const
            {
                return CompareTo( other ) > 0;
            }
            bool operator >= ( const TimeSpan& other ) const
            {
                return CompareTo( other ) >= 0;
            }
            HWIN_EXPORT WideString ToString( ) const;
        };


        namespace globalization
        {
            class GregorianCalendar;
        }
        class DateTime : public TimeBase
        {
        public:
            static const int KindShift = 62;
            static const unsigned long long KindUnspecified = 0x0000000000000000;
            static const unsigned long long KindUtc = 0x4000000000000000;
            static const unsigned long long KindLocal = 0x8000000000000000;
            static const unsigned long long TicksMask = 0x3FFFFFFFFFFFFFFF;
            static const unsigned long long FlagsMask = KindUtc | KindLocal;

        private:
            friend class globalization::GregorianCalendar;
            unsigned long long data;

            HWIN_EXPORT explicit DateTime( unsigned long long dateData );
        public:
            HWIN_EXPORT static long long ToLocalTicks( long long ticksInUtc );
            HWIN_EXPORT static long long ToUniversalTicks( long long ticksInLocalTime );
            HWIN_EXPORT static long long ToTicks( int year, int month, int day, const globalization::Calendar& calendar );
            HWIN_EXPORT static long long ToTicks( int year, int month, int day, int hour, int minute, int second, int millisecond );
            HWIN_EXPORT static long long ToTicks( int year, int month, int day, int hour, int minute, int second, int millisecond, const globalization::Calendar& calendar );
            HWIN_EXPORT static bool TryCreate( int year, int month, int day, int hour, int minute, int second, int millisecond, DateTime& result );

            HWIN_EXPORT static const DateTime MinValue;
            HWIN_EXPORT static const DateTime MaxValue;

            HWIN_EXPORT static long long DateToTicks( int year, int month, int day );
            HWIN_EXPORT static long long JulianDateToTicks( int year, int month, int day );
            HWIN_EXPORT static long long TimeToTicks( int hour, int minute, int second );
            HWIN_EXPORT static long long SystemTimeToTicks( const SYSTEMTIME& systemTime );

            explicit DateTime( ) : data( 0 )
            {
            }
            HWIN_EXPORT explicit DateTime( long long ticks );
            HWIN_EXPORT explicit DateTime( double days );
            HWIN_EXPORT DateTime( long long ticks, DateTimeKind kind );

            HWIN_EXPORT DateTime( int year, int month, int day );
            HWIN_EXPORT DateTime( int year, int month, int day, const globalization::Calendar& calendar );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, DateTimeKind kind );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, const globalization::Calendar& calendar );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, int millisecond );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, int millisecond, const globalization::Calendar& calendar );
            HWIN_EXPORT DateTime( int year, int month, int day, int hour, int minute, int second, int millisecond, const globalization::Calendar& calendar, DateTimeKind kind );


            size_t hash( ) const
            {
                return std::_Hash_seq( ( const unsigned char * )&data, sizeof( data ) );
            }

            long long Ticks( ) const
            {
                return data & TicksMask;
            }

            HWIN_EXPORT DateTime Add( const TimeSpan& value ) const;
            HWIN_EXPORT DateTime Add( double value, int scale ) const;
            HWIN_EXPORT DateTime AddDays( double value ) const;
            HWIN_EXPORT DateTime AddHours( double value ) const;
            HWIN_EXPORT DateTime AddMilliseconds( double value ) const;
            HWIN_EXPORT DateTime AddMinutes( double value ) const;
            HWIN_EXPORT DateTime AddMonths( int months ) const;
            HWIN_EXPORT DateTime AddSeconds( double value ) const;
            HWIN_EXPORT DateTime AddTicks( long long value ) const;
            HWIN_EXPORT DateTime AddYears( int value ) const;




            HWIN_EXPORT const DateTime& AssingTo( SYSTEMTIME& systemTime ) const;

            HWIN_EXPORT AnsiString DateToAnsiString( ) const;
            HWIN_EXPORT WideString DateToString( ) const;

            HWIN_EXPORT AnsiString TimeToAnsiString( ) const;
            HWIN_EXPORT WideString TimeToString( ) const;

            HWIN_EXPORT AnsiString ToAnsiString( ) const;
            HWIN_EXPORT WideString ToString( ) const;

            HWIN_EXPORT TimeSpan Subtract( const DateTime& value ) const;
            HWIN_EXPORT DateTime Subtract( const TimeSpan& value ) const;

            HWIN_EXPORT static int Compare( const DateTime& t1, const DateTime& t2 );
            HWIN_EXPORT int CompareTo( const DateTime& value ) const;

            bool operator == ( const DateTime& other ) const
            {
                return CompareTo( other ) == 0;
            }
            bool operator != ( const DateTime& other ) const
            {
                return CompareTo( other ) != 0;
            }
            bool operator <  ( const DateTime& other ) const
            {
                return CompareTo( other ) < 0;
            }
            bool operator <= ( const DateTime& other ) const
            {
                return CompareTo( other ) <= 0;
            }
            bool operator >  ( const DateTime& other ) const
            {
                return CompareTo( other ) > 0;
            }
            bool operator >= ( const DateTime& other ) const
            {
                return CompareTo( other ) >= 0;
            }

            DateTime operator + ( const TimeSpan& theValue ) const
            {
                return Add( theValue );
            }

            DateTime operator - ( const TimeSpan& theValue ) const
            {
                return Subtract( theValue );
            }

            TimeSpan operator - ( const DateTime& theValue ) const
            {
                return Subtract( theValue );
            }


            HWIN_EXPORT static int DaysInMonth( int year, int month );

            HWIN_EXPORT static long long DoubleDateToTicks( double value );

            HWIN_EXPORT static DateTime FromBinary( long long dateData );
            HWIN_EXPORT static DateTime FromFileTime( long long fileTime );
            HWIN_EXPORT static DateTime FromFileTimeUtc( long long fileTime );

            HWIN_EXPORT static DateTime FromOADate( double d );
            HWIN_EXPORT bool IsDaylightSavingTime( ) const;

            HWIN_EXPORT static DateTime SpecifyKind( const DateTime& value, DateTimeKind kind );

            HWIN_EXPORT long long ToBinary( ) const;

            HWIN_EXPORT int GetDatePart( DatePart datePart ) const;
            HWIN_EXPORT void GetYearMonthDay( int& year, int& month, int& day ) const;

            HWIN_EXPORT DateTime Date( ) const;

            HWIN_EXPORT int Year( ) const;
            HWIN_EXPORT int Month( ) const;
            HWIN_EXPORT int Day( ) const;
            HWIN_EXPORT DayOfWeek DayOfWeek( ) const;
            HWIN_EXPORT int DayOfYear( ) const;

            HWIN_EXPORT int Hour( ) const;


            HWIN_EXPORT int Minute( ) const;
            HWIN_EXPORT int Second( ) const;
            HWIN_EXPORT int Millisecond( ) const;


            HWIN_EXPORT TimeSpan TimeOfDay( ) const;

            HWIN_EXPORT DateTimeKind Kind( ) const;

            HWIN_EXPORT static DateTime Now( );
            HWIN_EXPORT static DateTime UtcNow( );
            HWIN_EXPORT static DateTime Today( );

            HWIN_EXPORT static bool IsLeapYear( int year );

            HWIN_EXPORT static double TicksToOADate( long long value );

            HWIN_EXPORT double ToOADate( ) const;

            HWIN_EXPORT long long ToFileTime( ) const;

            HWIN_EXPORT long long ToFileTimeUtc( ) const;

            HWIN_EXPORT DateTime ToLocalTime( ) const;

            HWIN_EXPORT DateTime ToUniversalTime( ) const;

            time_t ToTimeT( )
            {
                auto ticks = Ticks( );
                return time_t( ticks != ( -0x7FFFFFFFFFFFFFFFL - 1L ) ? ( ticks - UnixEpoch ) / TimeSpan::TicksPerSecond : ( -0x7FFFFFFFFFFFFFFFL - 1L ) );
            }

        };

        template<typename _Elem, typename _Traits >
        std::basic_ostream< _Elem, _Traits > & operator << ( std::basic_ostream< _Elem, _Traits> & stream, const DateTime& time )
        {
            if ( time < DateTime::MinValue )
            {
                stream << "Invalid - less than 0001-01-01";
            }
            else if ( time > DateTime::MaxValue )
            {
                stream << "Invalid - greater than 9999-12-31";
            }
            else
            {
                int year, month, day;
                time.GetYearMonthDay( year, month, day );
                auto hours = time.Hour( );
                auto minutes = time.Minute( );
                auto seconds = time.Second( );
                auto milliseconds = time.Millisecond( );

                auto fill = stream.fill( );
                auto width = stream.width( );
                auto zero = stream.widen( '0' );

                stream << std::setw( 4 ) << std::setfill( zero ) << year << '-'
                    << std::setw( 2 ) << std::setfill( zero ) << month << '-'
                    << std::setw( 2 ) << std::setfill( zero ) << day << ' '
                    << std::setw( 2 ) << std::setfill( zero ) << hours << ':'
                    << std::setw( 2 ) << std::setfill( zero ) << minutes << ':'
                    << std::setw( 2 ) << std::setfill( zero ) << seconds << '.'
                    << std::setw( 3 ) << std::setfill( zero ) << milliseconds << std::setw( width ) << std::setfill( fill );
            }
            return stream;
        }



        class Stopwatch
        {
            long long elapsedTicks;
            long long startedAt;
            bool isRunning;

            static long long frequency;
        public:

            HWIN_EXPORT static const bool IsHighResolution;
        private:
            static double tickFrequency;
            static bool InitializeStopwatch( );

            long long GetElapsedDateTimeTicks( ) const;

        public:
            HWIN_EXPORT static long long GetTimestamp( );
            HWIN_EXPORT static double GetTimestampInSeconds( );
            HWIN_EXPORT static double GetTimestampInMilliseconds( );
            HWIN_EXPORT static long long Frequency( );
            HWIN_EXPORT Stopwatch( );
            HWIN_EXPORT void Start( );
            HWIN_EXPORT Stopwatch StartNew( );

            HWIN_EXPORT void Stop( );
            HWIN_EXPORT void Reset( );
            HWIN_EXPORT void Restart( );
            HWIN_EXPORT bool IsRunning( ) const;

            HWIN_EXPORT TimeSpan Elapsed( ) const;
            HWIN_EXPORT long long ElapsedMilliseconds( ) const;
            HWIN_EXPORT long long ElapsedTicks( ) const;
        };

    }
}

namespace std
{
    template<>
    struct hash<harlinn::windows::TimeSpan>
    {
        size_t operator()( const harlinn::windows::TimeSpan& theValue ) const
        {
            return theValue.hash( );
        }
    };

    template<>
    struct hash<harlinn::windows::DateTime>
    {
        size_t operator()( const harlinn::windows::DateTime& theValue ) const
        {
            return theValue.hash( );
        }
    };


}


#pragma pack(pop)

#ifdef _MANAGED
#pragma managed(pop) 
#endif



#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Sea Surveillance AS
Norway Norway
Chief Architect - Sea Surveillance AS.

Specializing in integrated operations and high performance computing solutions.

I’ve been fooling around with computers since the early eighties, I’ve even done work on CP/M and MP/M.

Wrote my first “real” program on a BBC micro model B based on a series in a magazine at that time. It was fun and I got hooked on this thing called programming ...

A few Highlights:

  • High performance application server development
  • Model Driven Architecture and Code generators
  • Real-Time Distributed Solutions
  • C, C++, C#, Java, TSQL, PL/SQL, Delphi, ActionScript, Perl, Rexx
  • Microsoft SQL Server, Oracle RDBMS, IBM DB2, PostGreSQL
  • AMQP, Apache qpid, RabbitMQ, Microsoft Message Queuing, IBM WebSphereMQ, Oracle TuxidoMQ
  • Oracle WebLogic, IBM WebSphere
  • Corba, COM, DCE, WCF
  • AspenTech InfoPlus.21(IP21), OsiSoft PI


More information about what I do for a living can be found at: harlinn.com or LinkedIn

You can contact me at espen@harlinn.no

Comments and Discussions