windows-nt/Source/XPSP1/NT/net/tapi/skywalker/parser/sdptime.cpp
2020-09-26 16:20:57 +08:00

768 lines
14 KiB
C++

/*
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;
}