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.

414 lines
9.8 KiB

  1. /*
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. */
  4. #include "sdppch.h"
  5. #include <strstrea.h>
  6. #include "sdpgen.h"
  7. #include "sdpfld.h"
  8. #include "sdpval.h"
  9. #include "sdpltran.h"
  10. // check if each of the fields in the field array is valid
  11. BOOL
  12. SDP_VALUE::IsValid(
  13. ) const
  14. {
  15. // if there are no members in the field array, then the instance is invalid
  16. int NumFields = (int)m_FieldArray.GetSize();
  17. if ( 0 >= NumFields )
  18. {
  19. return FALSE;
  20. }
  21. // check each of the members in the list for validity
  22. for (int i = 0; i < NumFields; i++)
  23. {
  24. SDP_FIELD *Field = m_FieldArray[i];
  25. // only the last field can be null
  26. ASSERT((i >= (NumFields-1)) || (NULL != Field));
  27. if ( NULL != Field )
  28. {
  29. // if even one member is invalid, return FALSE
  30. if ( !Field->IsValid() )
  31. {
  32. return FALSE;
  33. }
  34. }
  35. }
  36. // all members are valid
  37. return TRUE;
  38. }
  39. BOOL
  40. SDP_VALUE::CalcIsModified(
  41. ) const
  42. {
  43. ASSERT(IsValid());
  44. int NumFields = (int)m_FieldArray.GetSize();
  45. for (int i = 0; i < NumFields; i++)
  46. {
  47. SDP_FIELD *Field = m_FieldArray[i];
  48. // only the last field can be null
  49. ASSERT((i >= (NumFields-1)) || (NULL != Field));
  50. if ( (NULL != Field) && Field->IsModified() )
  51. {
  52. return TRUE;
  53. }
  54. }
  55. return FALSE;
  56. }
  57. DWORD
  58. SDP_VALUE::CalcCharacterStringSize(
  59. )
  60. {
  61. ASSERT(IsValid());
  62. // since the cost of checking if any of the constituent fields have
  63. // changed since last time is almost as much as actually computing the size,
  64. // the size is computed afresh each time this method is called
  65. DWORD m_CharacterStringSize = 0;
  66. int NumFields = (int)m_FieldArray.GetSize();
  67. for (int i = 0; i < NumFields; i++)
  68. {
  69. SDP_FIELD *Field = m_FieldArray[i];
  70. // only the last field can be null
  71. ASSERT((i >= (NumFields-1)) || (NULL != Field));
  72. if ( NULL != Field )
  73. {
  74. // add field string length
  75. m_CharacterStringSize += Field->GetCharacterStringSize();
  76. }
  77. // add separator character length
  78. m_CharacterStringSize++;
  79. }
  80. // if there is a line, add the prefix string length
  81. if ( 0 < NumFields )
  82. {
  83. m_CharacterStringSize += strlen( m_TypePrefixString );
  84. }
  85. return m_CharacterStringSize;
  86. }
  87. // this method should only be called after having called GetCharacterStringSize()
  88. // should only be called if valid
  89. BOOL
  90. SDP_VALUE::CopyValue(
  91. OUT ostrstream &OutputStream
  92. )
  93. {
  94. // should be valid
  95. ASSERT(IsValid());
  96. // copy the prefix onto the buffer ptr
  97. OutputStream << (CHAR *)m_TypePrefixString;
  98. if ( OutputStream.fail() )
  99. {
  100. SetLastError(SDP_OUTPUT_ERROR);
  101. return FALSE;
  102. }
  103. int NumFields = (int)m_FieldArray.GetSize();
  104. // the assumption here is that atleast one field must have been parsed in
  105. // if the value is valid
  106. ASSERT(0 != NumFields);
  107. for (int i = 0; i < NumFields; i++)
  108. {
  109. SDP_FIELD *Field = m_FieldArray[i];
  110. // only the last field can be null
  111. ASSERT((i >= (NumFields-1)) || (NULL != Field));
  112. if ( NULL != Field )
  113. {
  114. if ( !Field->PrintField(OutputStream) )
  115. {
  116. return FALSE;
  117. }
  118. }
  119. OutputStream << m_SeparatorCharArray[i];
  120. }
  121. // newline is presumably the last character parsed and entered into the array
  122. ASSERT(CHAR_NEWLINE == m_SeparatorCharArray[i-1]);
  123. return TRUE;
  124. }
  125. BOOL
  126. SDP_VALUE::InternalParseLine(
  127. IN OUT CHAR *&Line
  128. )
  129. {
  130. ASSERT(NULL != m_SdpLineTransition);
  131. BOOL Finished;
  132. // parse fields until there are no more fields to parse or an error occurs
  133. do
  134. {
  135. // check if the line state value is consistent with the corresponding entry
  136. const LINE_TRANSITION_INFO * const LineTransitionInfo =
  137. m_SdpLineTransition->GetAt(m_LineState);
  138. if ( NULL == LineTransitionInfo )
  139. {
  140. return FALSE;
  141. }
  142. CHAR SeparatorChar = '\0';
  143. SDP_FIELD *Field;
  144. CHAR *SeparatorString;
  145. // identify the token. if one of the the separator characters is found, replace
  146. // it by EOS and return the separator char. if none of the separator characters are
  147. // found, return NULL (ex. if EOS found first, return NULL)
  148. CHAR *Token = GetToken(
  149. Line,
  150. LineTransitionInfo->m_NumTransitions,
  151. LineTransitionInfo->m_SeparatorChars,
  152. SeparatorChar
  153. );
  154. //
  155. // Eliminate also the '\r'
  156. // from the token
  157. //
  158. if( Token )
  159. {
  160. int nStrLen = strlen( Token );
  161. for( int c = 0; c < nStrLen; c++)
  162. {
  163. CHAR& chElement = Token[c];
  164. if( chElement == '\r' )
  165. {
  166. chElement = '\0';
  167. }
  168. }
  169. }
  170. // when the block goes out of scope,
  171. // set the EOS character to the token separator character
  172. LINE_TERMINATOR LineTerminator(Token, SeparatorChar);
  173. // if there is no such token
  174. if ( !LineTerminator.IsLegal() )
  175. {
  176. SetLastError(m_ErrorCode);
  177. return FALSE;
  178. }
  179. // advance the line to the start of the next token
  180. Line += (LineTerminator.GetLength() + 1);
  181. BOOL AddToArray;
  182. // check if there was such a state transition
  183. // it returns a field if it needs to be parsed and a separate
  184. // finished flag to indicate end of line parsing
  185. if ( !GetFieldToParse(SeparatorChar, LineTransitionInfo, Field, Finished, AddToArray) )
  186. {
  187. return FALSE;
  188. }
  189. // add the separator character and the field to the array
  190. if ( AddToArray )
  191. {
  192. ASSERT(m_FieldArray.GetSize() == m_SeparatorCharArray.GetSize());
  193. INT_PTR Index;
  194. try
  195. {
  196. Index = m_SeparatorCharArray.Add(SeparatorChar);
  197. }
  198. catch(...)
  199. {
  200. SetLastError(ERROR_OUTOFMEMORY);
  201. return FALSE;
  202. }
  203. try
  204. {
  205. m_FieldArray.Add(Field);
  206. }
  207. catch(...)
  208. {
  209. m_SeparatorCharArray.RemoveAt(Index);
  210. SetLastError(ERROR_OUTOFMEMORY);
  211. return FALSE;
  212. }
  213. }
  214. // check if any more fields need to be parsed
  215. if ( NULL == Field )
  216. {
  217. ASSERT(TRUE == Finished);
  218. break;
  219. }
  220. // parse the field
  221. if ( !Field->ParseToken(Token) )
  222. {
  223. return FALSE;
  224. }
  225. }
  226. while (!Finished);
  227. return TRUE;
  228. }
  229. BOOL
  230. SDP_VALUE::GetFieldToParse(
  231. IN const CHAR SeparatorChar,
  232. IN const LINE_TRANSITION_INFO *LineTransitionInfo,
  233. OUT SDP_FIELD *&Field,
  234. OUT BOOL &Finished,
  235. OUT BOOL &AddToArray
  236. )
  237. {
  238. // no need for an if ( NULL != ...) because the caller ParseLine method must have verified
  239. // this before calling this method
  240. ASSERT(NULL != LineTransitionInfo);
  241. const LINE_TRANSITION * const LineTransitions = LineTransitionInfo->m_Transitions;
  242. if ( NULL == LineTransitions )
  243. {
  244. SetLastError(SDP_INTERNAL_ERROR);
  245. return FALSE;
  246. }
  247. // check if there is such a triggering separator
  248. for( UINT i=0; i < LineTransitionInfo->m_NumTransitions; i++ )
  249. {
  250. // check the separator for the transition
  251. if ( SeparatorChar == LineTransitions[i].m_SeparatorChar )
  252. {
  253. // perform the state transition - this is needed to determine the field to
  254. // parse. ideally the transition should occur after the action (ParseField),
  255. // but it doesn't matter here
  256. m_LineState = LineTransitions[i].m_NewLineState;
  257. // check if this transition was only meant to consume the separator character
  258. // and no fields need to be parsed
  259. if ( LINE_END == m_LineState )
  260. {
  261. // currently only a newline brings the state to LINE_END
  262. ASSERT(CHAR_NEWLINE == SeparatorChar);
  263. Field = NULL;
  264. Finished = TRUE;
  265. return TRUE;
  266. }
  267. // get the field to parse for the current state
  268. if ( !GetField(Field, AddToArray) )
  269. {
  270. ASSERT(FALSE);
  271. return FALSE;
  272. }
  273. // if the separator character was a newline, we are finished
  274. Finished = (CHAR_NEWLINE == SeparatorChar)? TRUE: FALSE;
  275. // success
  276. return TRUE;
  277. }
  278. }
  279. // no valid transition for the separator
  280. SetLastError(m_ErrorCode);
  281. return FALSE;
  282. }
  283. BOOL
  284. SDP_VALUE_LIST::IsModified(
  285. ) const
  286. {
  287. int NumElements = (int)GetSize();
  288. for ( int i = 0; i < NumElements; i++ )
  289. {
  290. if ( GetAt(i)->IsModified() )
  291. {
  292. return TRUE;
  293. }
  294. }
  295. return FALSE;
  296. }
  297. DWORD
  298. SDP_VALUE_LIST::GetCharacterStringSize(
  299. )
  300. {
  301. DWORD ReturnValue = 0;
  302. int NumElements = (int)GetSize();
  303. for ( int i = 0; i < NumElements; i++ )
  304. {
  305. ReturnValue += GetAt(i)->GetCharacterStringSize();
  306. }
  307. return ReturnValue;
  308. }
  309. BOOL
  310. SDP_VALUE_LIST::PrintValue(
  311. OUT ostrstream &OutputStream
  312. )
  313. {
  314. // should not be modified
  315. ASSERT(!IsModified());
  316. int NumElements = (int)GetSize();
  317. for ( int i = 0; i < NumElements; i++ )
  318. {
  319. if ( !GetAt(i)->PrintValue(OutputStream) )
  320. {
  321. return FALSE;
  322. }
  323. }
  324. return TRUE;
  325. }