Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

767 lines
14 KiB

  1. /*
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. */
  4. #include "sdppch.h"
  5. #include <strstrea.h>
  6. #include "sdptime.h"
  7. #include "sdpltran.h"
  8. // line transition states
  9. enum TIME_TRANSITION_STATES
  10. {
  11. TIME_START,
  12. TIME_START_TIME,
  13. TIME_STOP_TIME
  14. };
  15. // table for time line transitions
  16. const LINE_TRANSITION g_TimeStartTransitions[] = {
  17. {CHAR_BLANK, TIME_START_TIME}
  18. };
  19. const LINE_TRANSITION g_TimeStartTimeTransitions[] = {
  20. {CHAR_NEWLINE, TIME_STOP_TIME}
  21. };
  22. /* no transitions */
  23. const LINE_TRANSITION *g_TimeStopTimeTransitions = NULL;
  24. LINE_TRANSITION_INFO g_TimeTransitionInfo[] = {
  25. LINE_TRANSITION_ENTRY(TIME_START, g_TimeStartTransitions),
  26. LINE_TRANSITION_ENTRY(TIME_START_TIME, g_TimeStartTimeTransitions),
  27. LINE_TRANSITION_ENTRY(TIME_STOP_TIME, g_TimeStopTimeTransitions)
  28. };
  29. SDP_LINE_TRANSITION g_TimeTransition(
  30. g_TimeTransitionInfo,
  31. sizeof(g_TimeTransitionInfo)/sizeof(LINE_TRANSITION_INFO)
  32. );
  33. // line transition states
  34. enum REPEAT_TRANSITION_STATES
  35. {
  36. REPEAT_START,
  37. REPEAT_INTERVAL,
  38. REPEAT_DURATION,
  39. REPEAT_OFFSET,
  40. REPEAT_OFFSET_END
  41. };
  42. // table for repeat time line transitions
  43. const LINE_TRANSITION g_RepeatStartTransitions[] = {
  44. {CHAR_BLANK, REPEAT_INTERVAL}
  45. };
  46. const LINE_TRANSITION g_RepeatIntervalTransitions[] = {
  47. {CHAR_BLANK, REPEAT_DURATION}
  48. };
  49. const LINE_TRANSITION g_RepeatDurationTransitions[] = {
  50. {CHAR_BLANK, REPEAT_OFFSET},
  51. {CHAR_NEWLINE, REPEAT_OFFSET_END}
  52. };
  53. const LINE_TRANSITION g_RepeatOffsetTransitions[] = {
  54. {CHAR_BLANK, REPEAT_OFFSET},
  55. {CHAR_NEWLINE, REPEAT_OFFSET_END}
  56. };
  57. /* no transitions */
  58. const LINE_TRANSITION *g_RepeatOffsetEndTransitions = NULL;
  59. LINE_TRANSITION_INFO g_RepeatTransitionInfo[] = {
  60. LINE_TRANSITION_ENTRY(REPEAT_START, g_RepeatStartTransitions),
  61. LINE_TRANSITION_ENTRY(REPEAT_INTERVAL, g_RepeatIntervalTransitions),
  62. LINE_TRANSITION_ENTRY(REPEAT_DURATION, g_RepeatDurationTransitions),
  63. LINE_TRANSITION_ENTRY(REPEAT_OFFSET, g_RepeatOffsetTransitions),
  64. LINE_TRANSITION_ENTRY(REPEAT_OFFSET_END, g_RepeatOffsetEndTransitions)
  65. };
  66. SDP_LINE_TRANSITION g_RepeatTransition(
  67. g_RepeatTransitionInfo,
  68. sizeof(g_RepeatTransitionInfo)/sizeof(LINE_TRANSITION_INFO)
  69. );
  70. // line transition states
  71. enum ADJUSTMENT_TRANSITION_STATES
  72. {
  73. ADJUSTMENT_START,
  74. ADJUSTMENT_TIME,
  75. ADJUSTMENT_OFFSET,
  76. ADJUSTMENT_OFFSET_END
  77. };
  78. // table for adjustment time line transitions
  79. const LINE_TRANSITION g_AdjustmentStartTransitions[] = {
  80. {CHAR_BLANK, ADJUSTMENT_TIME}
  81. };
  82. const LINE_TRANSITION g_AdjustmentTimeTransitions[] = {
  83. {CHAR_BLANK, ADJUSTMENT_OFFSET},
  84. {CHAR_NEWLINE, ADJUSTMENT_OFFSET_END}
  85. };
  86. const LINE_TRANSITION g_AdjustmentOffsetTransitions[] = {
  87. {CHAR_BLANK, ADJUSTMENT_TIME},
  88. {CHAR_NEWLINE, ADJUSTMENT_OFFSET_END}
  89. };
  90. /* no transitions */
  91. const LINE_TRANSITION *g_AdjustmentOffsetEndTransitions = NULL;
  92. LINE_TRANSITION_INFO g_AdjustmentTransitionInfo[] = {
  93. LINE_TRANSITION_ENTRY(ADJUSTMENT_START, g_AdjustmentStartTransitions),
  94. LINE_TRANSITION_ENTRY(ADJUSTMENT_TIME, g_AdjustmentTimeTransitions),
  95. LINE_TRANSITION_ENTRY(ADJUSTMENT_OFFSET, g_AdjustmentOffsetTransitions),
  96. LINE_TRANSITION_ENTRY(ADJUSTMENT_OFFSET_END, g_AdjustmentOffsetEndTransitions)
  97. };
  98. SDP_LINE_TRANSITION g_AdjustmentTransition(
  99. g_AdjustmentTransitionInfo,
  100. sizeof(g_AdjustmentTransitionInfo)/sizeof(LINE_TRANSITION_INFO)
  101. );
  102. // time units
  103. const CHAR TIME_UNITS[] = {'d', 'h', 'm', 's', 'Y', 'M'};
  104. const BYTE NUM_TIME_UNITS = sizeof(TIME_UNITS)/sizeof(CHAR);
  105. BOOL
  106. SDP_TIME_PERIOD::PrintData(
  107. OUT ostrstream &OutputStream
  108. )
  109. {
  110. if ( m_IsCompact )
  111. {
  112. OutputStream << (LONG)m_CompactValue;
  113. if ( OutputStream.fail() )
  114. {
  115. SetLastError(SDP_OUTPUT_ERROR);
  116. return FALSE;
  117. }
  118. OutputStream << (CHAR)m_Unit;
  119. if ( OutputStream.fail() )
  120. {
  121. SetLastError(SDP_OUTPUT_ERROR);
  122. return FALSE;
  123. }
  124. }
  125. else
  126. {
  127. OutputStream << (LONG)m_PeriodValue;
  128. if ( OutputStream.fail() )
  129. {
  130. SetLastError(SDP_OUTPUT_ERROR);
  131. return FALSE;
  132. }
  133. }
  134. return TRUE;
  135. }
  136. // parse the time period field
  137. // of the form [-]LONG[time_unit]
  138. BOOL
  139. SDP_TIME_PERIOD::InternalParseToken(
  140. IN CHAR *Token
  141. )
  142. {
  143. // remove the white spaces
  144. RemoveWhiteSpaces(Token);
  145. // convert the leading characters to a long value
  146. CHAR *RestOfString = NULL;
  147. LONG LongValue = strtol(Token, &RestOfString, 10);
  148. // if not successful
  149. if ( (LONG_MAX == LongValue) || (LONG_MIN == LongValue) )
  150. {
  151. SetLastError(SDP_INVALID_TIME_PERIOD);
  152. return FALSE;
  153. }
  154. // if the next character is EOS, we are done as it is a non-compact representation
  155. if ( EOS == *RestOfString )
  156. {
  157. m_IsCompact = FALSE;
  158. m_PeriodValue = LongValue;
  159. return TRUE;
  160. }
  161. // it might be a compact representation
  162. for ( UINT i=0; i < NUM_TIME_UNITS; i++ )
  163. {
  164. // check if the time unit is acceptable
  165. if ( TIME_UNITS[i] == *RestOfString )
  166. {
  167. // check that the next character is EOS - the token should
  168. // only be of the form [-]LONG[time_unit]
  169. if ( EOS != *(RestOfString+1) )
  170. {
  171. SetLastError(SDP_INVALID_TIME_PERIOD);
  172. return FALSE;
  173. }
  174. // set the member variables
  175. m_IsCompact = TRUE;
  176. m_Unit = TIME_UNITS[i];
  177. m_CompactValue = LongValue;
  178. return TRUE;
  179. }
  180. }
  181. // not a valid time period
  182. SetLastError(SDP_INVALID_TIME_PERIOD);
  183. return FALSE;
  184. }
  185. SDP_FIELD *
  186. SDP_TIME_PERIOD_LIST::CreateElement(
  187. )
  188. {
  189. // create and return a new time period
  190. SDP_TIME_PERIOD *SdpTimePeriod;
  191. try
  192. {
  193. SdpTimePeriod = new SDP_TIME_PERIOD;
  194. }
  195. catch(...)
  196. {
  197. SdpTimePeriod = NULL;
  198. }
  199. return SdpTimePeriod;
  200. }
  201. SDP_REPEAT::SDP_REPEAT(
  202. )
  203. : SDP_VALUE(SDP_INVALID_REPEAT_FIELD, REPEAT_STRING, &g_RepeatTransition)
  204. {}
  205. void
  206. SDP_REPEAT::InternalReset(
  207. )
  208. {
  209. m_Interval.Reset();
  210. m_Duration.Reset();
  211. m_Offsets.Reset();
  212. }
  213. BOOL
  214. SDP_REPEAT::GetField(
  215. OUT SDP_FIELD *&Field,
  216. OUT BOOL &AddToArray
  217. )
  218. {
  219. // add in all cases by default
  220. AddToArray = TRUE;
  221. switch(m_LineState)
  222. {
  223. case REPEAT_INTERVAL:
  224. {
  225. Field = &m_Interval;
  226. }
  227. break;
  228. case REPEAT_DURATION:
  229. {
  230. Field = &m_Duration;
  231. }
  232. break;
  233. case REPEAT_OFFSET:
  234. case REPEAT_OFFSET_END:
  235. {
  236. if ( m_Offsets.GetSize() > 0 )
  237. {
  238. AddToArray = FALSE;
  239. }
  240. Field = &m_Offsets;
  241. }
  242. break;
  243. default:
  244. {
  245. SetLastError(m_ErrorCode);
  246. return FALSE;
  247. }
  248. break;
  249. };
  250. return TRUE;
  251. }
  252. // this is a workaround/hack for reusing the base class SDP_VALUE code for PrintValue().
  253. // it replaces the separator char for the last read field with a newline, so that when
  254. // PrintValue() executes and prints the time period list, it puts the newline character at
  255. // the end of the list (rather than CHAR_BLANK)
  256. BOOL
  257. SDP_REPEAT::InternalParseLine(
  258. IN OUT CHAR *&Line
  259. )
  260. {
  261. if ( !SDP_VALUE::InternalParseLine(Line) )
  262. {
  263. return FALSE;
  264. }
  265. m_SeparatorCharArray[m_SeparatorCharArray.GetSize()-1] = CHAR_NEWLINE;
  266. return TRUE;
  267. }
  268. SDP_VALUE *
  269. SDP_REPEAT_LIST::CreateElement(
  270. )
  271. {
  272. SDP_REPEAT *SdpRepeat;
  273. try
  274. {
  275. SdpRepeat = new SDP_REPEAT();
  276. }
  277. catch(...)
  278. {
  279. SdpRepeat = NULL;
  280. }
  281. return SdpRepeat;
  282. }
  283. SDP_ADJUSTMENT::SDP_ADJUSTMENT(
  284. )
  285. : SDP_VALUE(SDP_INVALID_ADJUSTMENT_FIELD, ADJUSTMENT_STRING, &g_AdjustmentTransition),
  286. SDP_ADJUSTMENT_SAFEARRAY(*this)
  287. {}
  288. void
  289. SDP_ADJUSTMENT::InternalReset(
  290. )
  291. {
  292. m_AdjustmentTimes.Reset();
  293. m_Offsets.Reset();
  294. }
  295. BOOL
  296. SDP_ADJUSTMENT::CalcIsModified(
  297. ) const
  298. {
  299. ASSERT(IsValid());
  300. return ( m_AdjustmentTimes.IsModified() || m_Offsets.IsModified() );
  301. }
  302. DWORD
  303. SDP_ADJUSTMENT::CalcCharacterStringSize(
  304. )
  305. {
  306. ASSERT(IsValid());
  307. if ( m_AdjustmentTimes.IsModified() || m_Offsets.IsModified() )
  308. {
  309. // this copy should not fail as the buffer size should be sufficient for
  310. // all forseeable situations
  311. ASSERT(NULL != m_PrintBuffer);
  312. ostrstream OutputStream(m_PrintBuffer, sizeof(m_PrintBuffer));
  313. BOOL Success = PrintData(OutputStream);
  314. ASSERT(Success);
  315. m_PrintLength = OutputStream.pcount();
  316. m_PrintBuffer[m_PrintLength] = EOS;
  317. }
  318. return m_PrintLength;
  319. }
  320. BOOL
  321. SDP_ADJUSTMENT::PrintElement(
  322. IN DWORD Index,
  323. OUT ostrstream &OutputStream
  324. )
  325. {
  326. ASSERT(IsValid());
  327. // this method must be called before PrintField is called
  328. m_AdjustmentTimes[Index]->GetCharacterStringSize();
  329. if ( !m_AdjustmentTimes[Index]->PrintField(OutputStream) )
  330. {
  331. return FALSE;
  332. }
  333. OutputStream << CHAR_BLANK;
  334. if ( OutputStream.fail() )
  335. {
  336. SetLastError(SDP_OUTPUT_ERROR);
  337. return FALSE;
  338. }
  339. // this method must be called before PrintField is called
  340. m_Offsets[Index]->GetCharacterStringSize();
  341. if ( !m_Offsets[Index]->PrintField(OutputStream) )
  342. {
  343. return FALSE;
  344. }
  345. return TRUE;
  346. }
  347. BOOL
  348. SDP_ADJUSTMENT::PrintData(
  349. OUT ostrstream &OutputStream
  350. )
  351. {
  352. ASSERT(m_AdjustmentTimes.GetSize() == m_Offsets.GetSize());
  353. // copy the prefix onto the output stream
  354. OutputStream << (CHAR *)m_TypePrefixString;
  355. if ( OutputStream.fail() )
  356. {
  357. SetLastError(SDP_OUTPUT_ERROR);
  358. return FALSE;
  359. }
  360. int NumElements = (int)m_AdjustmentTimes.GetSize();
  361. // write into the buffer as AdjustmentValue blank OffsetValue (blank AdjustmentValue blank OffsetValue)*
  362. // write the first element
  363. if ( !PrintElement(0, OutputStream) )
  364. {
  365. return FALSE;
  366. }
  367. for ( int i=1; i < NumElements; i++ )
  368. {
  369. OutputStream << CHAR_BLANK;
  370. if ( OutputStream.fail() )
  371. {
  372. SetLastError(SDP_OUTPUT_ERROR);
  373. return FALSE;
  374. }
  375. if ( !PrintElement(i, OutputStream) )
  376. {
  377. return FALSE;
  378. }
  379. }
  380. // copy the newline character onto the stream to terminate the type value line
  381. OutputStream << CHAR_NEWLINE;
  382. if ( OutputStream.fail() )
  383. {
  384. SetLastError(SDP_OUTPUT_ERROR);
  385. return FALSE;
  386. }
  387. return TRUE;
  388. }
  389. BOOL
  390. SDP_ADJUSTMENT::CopyValue(
  391. OUT ostrstream &OutputStream
  392. )
  393. {
  394. ASSERT(IsValid());
  395. ASSERT(NULL != m_PrintBuffer);
  396. OutputStream << (CHAR *)m_PrintBuffer;
  397. if ( OutputStream.fail() )
  398. {
  399. SetLastError(SDP_OUTPUT_ERROR);
  400. return FALSE;
  401. }
  402. return TRUE;
  403. }
  404. BOOL
  405. SDP_ADJUSTMENT::GetField(
  406. OUT SDP_FIELD *&Field,
  407. OUT BOOL &AddToArray
  408. )
  409. {
  410. // NOT added in all cases by default
  411. AddToArray = FALSE;
  412. switch(m_LineState)
  413. {
  414. case ADJUSTMENT_TIME:
  415. {
  416. // check that the number of adjustment times are same as the offset times
  417. ASSERT(m_AdjustmentTimes.GetSize() == m_Offsets.GetSize());
  418. if ( m_AdjustmentTimes.GetSize() != m_Offsets.GetSize() )
  419. {
  420. SetLastError(SDP_INTERNAL_ERROR);
  421. return FALSE;
  422. }
  423. Field = &m_AdjustmentTimes;
  424. }
  425. break;
  426. case ADJUSTMENT_OFFSET:
  427. case ADJUSTMENT_OFFSET_END:
  428. {
  429. Field = &m_Offsets;
  430. }
  431. break;
  432. default:
  433. {
  434. SetLastError(m_ErrorCode);
  435. return FALSE;
  436. }
  437. break;
  438. };
  439. return TRUE;
  440. }
  441. SDP_TIME::SDP_TIME(
  442. )
  443. : SDP_VALUE(SDP_INVALID_TIME_FIELD, TIME_STRING, &g_TimeTransition)
  444. {}
  445. void
  446. SDP_TIME::InternalReset(
  447. )
  448. {
  449. m_StartTime.Reset();
  450. m_StopTime.Reset();
  451. m_RepeatList.Reset();
  452. }
  453. BOOL
  454. SDP_TIME::CalcIsModified(
  455. ) const
  456. {
  457. ASSERT(IsValid());
  458. return
  459. SDP_VALUE::CalcIsModified() ||
  460. m_RepeatList.IsModified();
  461. }
  462. DWORD
  463. SDP_TIME::CalcCharacterStringSize(
  464. )
  465. {
  466. ASSERT(IsValid());
  467. return
  468. SDP_VALUE::CalcCharacterStringSize() +
  469. m_RepeatList.GetCharacterStringSize();
  470. }
  471. BOOL
  472. SDP_TIME::CopyValue(
  473. OUT ostrstream &OutputStream
  474. )
  475. {
  476. ASSERT(IsValid());
  477. return
  478. SDP_VALUE::CopyValue(OutputStream) &&
  479. m_RepeatList.PrintValue(OutputStream);
  480. }
  481. BOOL
  482. SDP_TIME::GetField(
  483. OUT SDP_FIELD *&Field,
  484. OUT BOOL &AddToArray
  485. )
  486. {
  487. // add in all cases by default
  488. AddToArray = TRUE;
  489. switch(m_LineState)
  490. {
  491. case TIME_START_TIME:
  492. {
  493. Field = &m_StartTime;
  494. }
  495. break;
  496. case TIME_STOP_TIME:
  497. {
  498. Field = &m_StopTime;
  499. }
  500. break;
  501. default:
  502. {
  503. SetLastError(m_ErrorCode);
  504. return FALSE;
  505. }
  506. break;
  507. };
  508. return TRUE;
  509. }
  510. BOOL
  511. SDP_TIME_LIST::IsModified(
  512. ) const
  513. {
  514. return
  515. m_Adjustment.IsModified() ||
  516. SDP_VALUE_LIST::IsModified();
  517. }
  518. DWORD
  519. SDP_TIME_LIST::GetCharacterStringSize(
  520. )
  521. {
  522. return
  523. m_Adjustment.GetCharacterStringSize() +
  524. SDP_VALUE_LIST::GetCharacterStringSize();
  525. }
  526. BOOL
  527. SDP_TIME_LIST::PrintValue(
  528. OUT ostrstream &OutputStream
  529. )
  530. {
  531. // the time list must be printed before the adjustment value line
  532. return
  533. SDP_VALUE_LIST::PrintValue(OutputStream) &&
  534. m_Adjustment.PrintValue(OutputStream);
  535. }
  536. void
  537. SDP_TIME_LIST::Reset(
  538. )
  539. {
  540. m_Adjustment.Reset();
  541. SDP_VALUE_LIST::Reset();
  542. }
  543. SDP_VALUE *
  544. SDP_TIME_LIST::CreateElement(
  545. )
  546. {
  547. SDP_TIME *SdpTime;
  548. try
  549. {
  550. SdpTime = new SDP_TIME();
  551. }
  552. catch(...)
  553. {
  554. SdpTime = NULL;
  555. }
  556. return SdpTime;
  557. }