|
|
/*
Copyright (c) 1997-1999 Microsoft Corporation
*/
#include "sdppch.h"
#include <strstrea.h>
#include "sdptime.h"
#include "sdpltran.h"
// line transition states
enum TIME_TRANSITION_STATES { TIME_START, TIME_START_TIME, TIME_STOP_TIME };
// table for time line transitions
const LINE_TRANSITION g_TimeStartTransitions[] = { {CHAR_BLANK, TIME_START_TIME} };
const LINE_TRANSITION g_TimeStartTimeTransitions[] = { {CHAR_NEWLINE, TIME_STOP_TIME} };
/* no transitions */ const LINE_TRANSITION *g_TimeStopTimeTransitions = NULL;
LINE_TRANSITION_INFO g_TimeTransitionInfo[] = { LINE_TRANSITION_ENTRY(TIME_START, g_TimeStartTransitions),
LINE_TRANSITION_ENTRY(TIME_START_TIME, g_TimeStartTimeTransitions),
LINE_TRANSITION_ENTRY(TIME_STOP_TIME, g_TimeStopTimeTransitions) };
SDP_LINE_TRANSITION g_TimeTransition( g_TimeTransitionInfo, sizeof(g_TimeTransitionInfo)/sizeof(LINE_TRANSITION_INFO) );
// line transition states
enum REPEAT_TRANSITION_STATES { REPEAT_START, REPEAT_INTERVAL, REPEAT_DURATION, REPEAT_OFFSET, REPEAT_OFFSET_END };
// table for repeat time line transitions
const LINE_TRANSITION g_RepeatStartTransitions[] = { {CHAR_BLANK, REPEAT_INTERVAL} };
const LINE_TRANSITION g_RepeatIntervalTransitions[] = { {CHAR_BLANK, REPEAT_DURATION} };
const LINE_TRANSITION g_RepeatDurationTransitions[] = { {CHAR_BLANK, REPEAT_OFFSET}, {CHAR_NEWLINE, REPEAT_OFFSET_END} };
const LINE_TRANSITION g_RepeatOffsetTransitions[] = { {CHAR_BLANK, REPEAT_OFFSET}, {CHAR_NEWLINE, REPEAT_OFFSET_END} };
/* no transitions */ const LINE_TRANSITION *g_RepeatOffsetEndTransitions = NULL;
LINE_TRANSITION_INFO g_RepeatTransitionInfo[] = { LINE_TRANSITION_ENTRY(REPEAT_START, g_RepeatStartTransitions),
LINE_TRANSITION_ENTRY(REPEAT_INTERVAL, g_RepeatIntervalTransitions),
LINE_TRANSITION_ENTRY(REPEAT_DURATION, g_RepeatDurationTransitions),
LINE_TRANSITION_ENTRY(REPEAT_OFFSET, g_RepeatOffsetTransitions),
LINE_TRANSITION_ENTRY(REPEAT_OFFSET_END, g_RepeatOffsetEndTransitions) };
SDP_LINE_TRANSITION g_RepeatTransition( g_RepeatTransitionInfo, sizeof(g_RepeatTransitionInfo)/sizeof(LINE_TRANSITION_INFO) );
// line transition states
enum ADJUSTMENT_TRANSITION_STATES { ADJUSTMENT_START, ADJUSTMENT_TIME, ADJUSTMENT_OFFSET, ADJUSTMENT_OFFSET_END };
// table for adjustment time line transitions
const LINE_TRANSITION g_AdjustmentStartTransitions[] = { {CHAR_BLANK, ADJUSTMENT_TIME} };
const LINE_TRANSITION g_AdjustmentTimeTransitions[] = { {CHAR_BLANK, ADJUSTMENT_OFFSET}, {CHAR_NEWLINE, ADJUSTMENT_OFFSET_END} };
const LINE_TRANSITION g_AdjustmentOffsetTransitions[] = { {CHAR_BLANK, ADJUSTMENT_TIME}, {CHAR_NEWLINE, ADJUSTMENT_OFFSET_END} };
/* no transitions */ const LINE_TRANSITION *g_AdjustmentOffsetEndTransitions = NULL;
LINE_TRANSITION_INFO g_AdjustmentTransitionInfo[] = { LINE_TRANSITION_ENTRY(ADJUSTMENT_START, g_AdjustmentStartTransitions),
LINE_TRANSITION_ENTRY(ADJUSTMENT_TIME, g_AdjustmentTimeTransitions),
LINE_TRANSITION_ENTRY(ADJUSTMENT_OFFSET, g_AdjustmentOffsetTransitions),
LINE_TRANSITION_ENTRY(ADJUSTMENT_OFFSET_END, g_AdjustmentOffsetEndTransitions) };
SDP_LINE_TRANSITION g_AdjustmentTransition( g_AdjustmentTransitionInfo, sizeof(g_AdjustmentTransitionInfo)/sizeof(LINE_TRANSITION_INFO) );
// time units
const CHAR TIME_UNITS[] = {'d', 'h', 'm', 's', 'Y', 'M'}; const BYTE NUM_TIME_UNITS = sizeof(TIME_UNITS)/sizeof(CHAR);
BOOL SDP_TIME_PERIOD::PrintData( OUT ostrstream &OutputStream ) { if ( m_IsCompact ) { OutputStream << (LONG)m_CompactValue; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
OutputStream << (CHAR)m_Unit; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; } } else { OutputStream << (LONG)m_PeriodValue; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; } }
return TRUE; }
// parse the time period field
// of the form [-]LONG[time_unit]
BOOL SDP_TIME_PERIOD::InternalParseToken( IN CHAR *Token ) { // remove the white spaces
RemoveWhiteSpaces(Token);
// convert the leading characters to a long value
CHAR *RestOfString = NULL; LONG LongValue = strtol(Token, &RestOfString, 10);
// if not successful
if ( (LONG_MAX == LongValue) || (LONG_MIN == LongValue) ) { SetLastError(SDP_INVALID_TIME_PERIOD); return FALSE; }
// if the next character is EOS, we are done as it is a non-compact representation
if ( EOS == *RestOfString ) { m_IsCompact = FALSE; m_PeriodValue = LongValue;
return TRUE; }
// it might be a compact representation
for ( UINT i=0; i < NUM_TIME_UNITS; i++ ) { // check if the time unit is acceptable
if ( TIME_UNITS[i] == *RestOfString ) { // check that the next character is EOS - the token should
// only be of the form [-]LONG[time_unit]
if ( EOS != *(RestOfString+1) ) { SetLastError(SDP_INVALID_TIME_PERIOD); return FALSE; }
// set the member variables
m_IsCompact = TRUE; m_Unit = TIME_UNITS[i]; m_CompactValue = LongValue;
return TRUE; } }
// not a valid time period
SetLastError(SDP_INVALID_TIME_PERIOD); return FALSE; }
SDP_FIELD * SDP_TIME_PERIOD_LIST::CreateElement( ) { // create and return a new time period
SDP_TIME_PERIOD *SdpTimePeriod;
try { SdpTimePeriod = new SDP_TIME_PERIOD; } catch(...) { SdpTimePeriod = NULL; }
return SdpTimePeriod; }
SDP_REPEAT::SDP_REPEAT( ) : SDP_VALUE(SDP_INVALID_REPEAT_FIELD, REPEAT_STRING, &g_RepeatTransition) {}
void SDP_REPEAT::InternalReset( ) { m_Interval.Reset(); m_Duration.Reset(); m_Offsets.Reset(); }
BOOL SDP_REPEAT::GetField( OUT SDP_FIELD *&Field, OUT BOOL &AddToArray ) { // add in all cases by default
AddToArray = TRUE;
switch(m_LineState) { case REPEAT_INTERVAL: { Field = &m_Interval; }
break;
case REPEAT_DURATION: { Field = &m_Duration; }
break;
case REPEAT_OFFSET: case REPEAT_OFFSET_END: { if ( m_Offsets.GetSize() > 0 ) { AddToArray = FALSE; }
Field = &m_Offsets; }
break;
default: { SetLastError(m_ErrorCode); return FALSE; }
break; };
return TRUE; }
// this is a workaround/hack for reusing the base class SDP_VALUE code for PrintValue().
// it replaces the separator char for the last read field with a newline, so that when
// PrintValue() executes and prints the time period list, it puts the newline character at
// the end of the list (rather than CHAR_BLANK)
BOOL SDP_REPEAT::InternalParseLine( IN OUT CHAR *&Line ) { if ( !SDP_VALUE::InternalParseLine(Line) ) { return FALSE; }
m_SeparatorCharArray[m_SeparatorCharArray.GetSize()-1] = CHAR_NEWLINE; return TRUE; }
SDP_VALUE * SDP_REPEAT_LIST::CreateElement( ) { SDP_REPEAT *SdpRepeat;
try { SdpRepeat = new SDP_REPEAT(); } catch(...) { SdpRepeat = NULL; }
return SdpRepeat; }
SDP_ADJUSTMENT::SDP_ADJUSTMENT( ) : SDP_VALUE(SDP_INVALID_ADJUSTMENT_FIELD, ADJUSTMENT_STRING, &g_AdjustmentTransition), SDP_ADJUSTMENT_SAFEARRAY(*this) {}
void SDP_ADJUSTMENT::InternalReset( ) { m_AdjustmentTimes.Reset(); m_Offsets.Reset(); }
BOOL SDP_ADJUSTMENT::CalcIsModified( ) const { ASSERT(IsValid()); return ( m_AdjustmentTimes.IsModified() || m_Offsets.IsModified() ); }
DWORD SDP_ADJUSTMENT::CalcCharacterStringSize( ) { ASSERT(IsValid());
if ( m_AdjustmentTimes.IsModified() || m_Offsets.IsModified() ) { // this copy should not fail as the buffer size should be sufficient for
// all forseeable situations
ASSERT(NULL != m_PrintBuffer); ostrstream OutputStream(m_PrintBuffer, sizeof(m_PrintBuffer));
BOOL Success = PrintData(OutputStream); ASSERT(Success);
m_PrintLength = OutputStream.pcount(); m_PrintBuffer[m_PrintLength] = EOS; }
return m_PrintLength; }
BOOL SDP_ADJUSTMENT::PrintElement( IN DWORD Index, OUT ostrstream &OutputStream ) { ASSERT(IsValid());
// this method must be called before PrintField is called
m_AdjustmentTimes[Index]->GetCharacterStringSize(); if ( !m_AdjustmentTimes[Index]->PrintField(OutputStream) ) { return FALSE; }
OutputStream << CHAR_BLANK; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
// this method must be called before PrintField is called
m_Offsets[Index]->GetCharacterStringSize(); if ( !m_Offsets[Index]->PrintField(OutputStream) ) { return FALSE; }
return TRUE; }
BOOL SDP_ADJUSTMENT::PrintData( OUT ostrstream &OutputStream ) { ASSERT(m_AdjustmentTimes.GetSize() == m_Offsets.GetSize());
// copy the prefix onto the output stream
OutputStream << (CHAR *)m_TypePrefixString; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
int NumElements = (int)m_AdjustmentTimes.GetSize();
// write into the buffer as AdjustmentValue blank OffsetValue (blank AdjustmentValue blank OffsetValue)*
// write the first element
if ( !PrintElement(0, OutputStream) ) { return FALSE; }
for ( int i=1; i < NumElements; i++ ) { OutputStream << CHAR_BLANK; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
if ( !PrintElement(i, OutputStream) ) { return FALSE; } }
// copy the newline character onto the stream to terminate the type value line
OutputStream << CHAR_NEWLINE; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
return TRUE; }
BOOL SDP_ADJUSTMENT::CopyValue( OUT ostrstream &OutputStream ) { ASSERT(IsValid());
ASSERT(NULL != m_PrintBuffer);
OutputStream << (CHAR *)m_PrintBuffer; if ( OutputStream.fail() ) { SetLastError(SDP_OUTPUT_ERROR); return FALSE; }
return TRUE; }
BOOL SDP_ADJUSTMENT::GetField( OUT SDP_FIELD *&Field, OUT BOOL &AddToArray ) { // NOT added in all cases by default
AddToArray = FALSE;
switch(m_LineState) { case ADJUSTMENT_TIME: { // check that the number of adjustment times are same as the offset times
ASSERT(m_AdjustmentTimes.GetSize() == m_Offsets.GetSize()); if ( m_AdjustmentTimes.GetSize() != m_Offsets.GetSize() ) { SetLastError(SDP_INTERNAL_ERROR); return FALSE; }
Field = &m_AdjustmentTimes; }
break;
case ADJUSTMENT_OFFSET: case ADJUSTMENT_OFFSET_END: { Field = &m_Offsets; }
break;
default: { SetLastError(m_ErrorCode); return FALSE; }
break; };
return TRUE; }
SDP_TIME::SDP_TIME( ) : SDP_VALUE(SDP_INVALID_TIME_FIELD, TIME_STRING, &g_TimeTransition) {}
void SDP_TIME::InternalReset( ) { m_StartTime.Reset(); m_StopTime.Reset(); m_RepeatList.Reset(); }
BOOL SDP_TIME::CalcIsModified( ) const { ASSERT(IsValid());
return SDP_VALUE::CalcIsModified() || m_RepeatList.IsModified(); }
DWORD SDP_TIME::CalcCharacterStringSize( ) { ASSERT(IsValid());
return SDP_VALUE::CalcCharacterStringSize() + m_RepeatList.GetCharacterStringSize(); }
BOOL SDP_TIME::CopyValue( OUT ostrstream &OutputStream ) { ASSERT(IsValid());
return SDP_VALUE::CopyValue(OutputStream) && m_RepeatList.PrintValue(OutputStream); }
BOOL SDP_TIME::GetField( OUT SDP_FIELD *&Field, OUT BOOL &AddToArray ) { // add in all cases by default
AddToArray = TRUE;
switch(m_LineState) { case TIME_START_TIME: { Field = &m_StartTime; }
break;
case TIME_STOP_TIME: { Field = &m_StopTime; }
break;
default: { SetLastError(m_ErrorCode); return FALSE; }
break; };
return TRUE; }
BOOL SDP_TIME_LIST::IsModified( ) const { return m_Adjustment.IsModified() || SDP_VALUE_LIST::IsModified(); }
DWORD SDP_TIME_LIST::GetCharacterStringSize( ) { return m_Adjustment.GetCharacterStringSize() + SDP_VALUE_LIST::GetCharacterStringSize(); }
BOOL SDP_TIME_LIST::PrintValue( OUT ostrstream &OutputStream ) { // the time list must be printed before the adjustment value line
return SDP_VALUE_LIST::PrintValue(OutputStream) && m_Adjustment.PrintValue(OutputStream); }
void SDP_TIME_LIST::Reset( ) { m_Adjustment.Reset(); SDP_VALUE_LIST::Reset(); }
SDP_VALUE * SDP_TIME_LIST::CreateElement( ) { SDP_TIME *SdpTime;
try { SdpTime = new SDP_TIME(); } catch(...) { SdpTime = NULL; }
return SdpTime; }
|