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.

198 lines
5.6 KiB

  1. /*
  2. * Copyright 1998 American Power Conversion, All Rights Reserved
  3. *
  4. * NAME: tokenstr.cxx
  5. *
  6. * PATH:
  7. *
  8. * REVISION:
  9. *
  10. * DESCRIPTION:
  11. * This file contains the class definition for the TokenString class. It
  12. * is designed to replace the strtok() function, because when using strtok
  13. * "if multiple or simultaneous calls are made ... a high potential for data
  14. * corruption and innacurate results exists." -- MSVC OnLine Help
  15. *
  16. * REFERENCES:
  17. * Initially created by Todd Giaquinto
  18. *
  19. * NOTES:
  20. * This function mimics the behavior of strtok in all aspects.
  21. * Examples:
  22. * String: ,,,,1,2,3 Sep: , Tokens: "1" "2" "3"
  23. * String: ,#1#2,3#4 Sep: ,# Tokens: "1" "2" "3" "4"
  24. *
  25. * Typical Usage:
  26. * TokenString token_str(string, sep);
  27. * PCHAR tok = token_str.GetCurrentToken();
  28. * while (tok) {
  29. * .....
  30. * tok = token_str.GetCurrentToken();
  31. * }
  32. *
  33. * The GetCurrentToken call will return a pointer to the current string token
  34. * and then move the internal pointer to the start of the next token. If
  35. * GetCurrentToken is called without an argument, the separator string passed
  36. * to the constructor is used to gather each token. However, GetCurrentToken
  37. * is overloaded so that one implementation can take a new separator string
  38. * as an argument. Once a new separator string is passed in, all subsequent
  39. * calls to the parameter-less GetCurrentToken will use the last passed in
  40. * separator.
  41. *
  42. * REVISIONS:
  43. * tjg19Jan98: Initial implementation
  44. * tjg29Jan98: Included formal code review comments
  45. *
  46. * v-stebe 29Jul2000 Fixed PREfix errors (bugs #46356, #46357)
  47. */
  48. #include "cdefine.h"
  49. #include "tokenstr.h"
  50. // Function: TokenString Constructor
  51. // Parameters: 1. Character pointer containing the string (ie "#str#str2#")
  52. // 2. Character pointer containing the separator (ie "#")
  53. // Ret Value: None
  54. // Purpose: Initializes all class member variables to defaults. Then
  55. // stores the argument values.
  56. TokenString::TokenString(PCHAR aString, PCHAR aSeparatorString) :
  57. theString(NULL),
  58. theSeparators(NULL),
  59. theCurrentLocation(NULL),
  60. theSeparatorLength(0)
  61. {
  62. if (aString) {
  63. theString = new CHAR[strlen(aString) + 1];
  64. if (theString != NULL) {
  65. strcpy(theString, aString);
  66. }
  67. theCurrentLocation = theString;
  68. }
  69. storeSeparatorString(aSeparatorString);
  70. }
  71. // Function: TokenString Destructor
  72. // Parameters: None
  73. // Ret Value: None
  74. // Purpose: Cleans up all allocated memory.
  75. TokenString::~TokenString()
  76. {
  77. delete [] theString;
  78. theString = NULL;
  79. delete [] theSeparators;
  80. theSeparators = NULL;
  81. }
  82. // Function: storeSeparatorString
  83. // Parameters: Character pointer to the new separator string
  84. // Ret Value: None
  85. // Purpose: Stores the parameter aString as theSeparators. This method is
  86. // optimized to allocate memory only if the current buffer is too
  87. // small.
  88. VOID TokenString::storeSeparatorString(PCHAR aString)
  89. {
  90. if (aString) {
  91. INT length = strlen(aString);
  92. if (length > theSeparatorLength) {
  93. delete [] theSeparators;
  94. theSeparatorLength = length;
  95. theSeparators = new CHAR[length + 1];
  96. }
  97. if (theSeparators != NULL) {
  98. strcpy(theSeparators, aString);
  99. }
  100. }
  101. }
  102. // Function: isSeparator
  103. // Parameters: A character to check against theSeparators
  104. // Ret Value: TRUE, if theSeparators contains aCharacter
  105. // FALSE, otherwise
  106. // Purpose: Searches through theSeparators string looking for an
  107. // occurrence of aCharacter
  108. BOOL TokenString::isSeparator(CHAR aCharacter)
  109. {
  110. BOOL is_separator = FALSE;
  111. PCHAR current_sep = theSeparators;
  112. // Run this loop while the pointer and contents are non-NULL, and
  113. // we have not determined that aCharacter is a separator.
  114. while ((current_sep != NULL) &&
  115. (*current_sep != NULL) &&
  116. (is_separator == FALSE)) {
  117. if (*current_sep == aCharacter) {
  118. is_separator = TRUE;
  119. }
  120. current_sep++;
  121. }
  122. return is_separator;
  123. }
  124. // Function: GetCurrentToken
  125. // Parameters: Character pointer to a new separator string
  126. // Ret Value: Pointer to the current string in the list
  127. // Purpose: Sets theSeparators to aSeparatorString and gets the next token
  128. // in the string (using the new separator string)
  129. PCHAR TokenString::GetCurrentToken(PCHAR aSeparatorString)
  130. {
  131. storeSeparatorString(aSeparatorString);
  132. return GetCurrentToken();
  133. }
  134. // Function: GetCurrentToken
  135. // Parameters: None
  136. // Ret Value: Pointer to the current string in the list
  137. // Purpose: Gets the next token in the string using theSeparators as
  138. // the separator string
  139. PCHAR TokenString::GetCurrentToken()
  140. {
  141. BOOL recording_token = FALSE;
  142. BOOL done = FALSE;
  143. PCHAR current_token = NULL;
  144. // While there is stuff in the list and the current token has not ended
  145. while (theCurrentLocation && *theCurrentLocation && !done) {
  146. // Check if the current character is a separator
  147. BOOL is_separator = isSeparator(*theCurrentLocation);
  148. // If we found a separator and we were recording a token,
  149. // change this separator to a NULL and reset flags
  150. if (is_separator && recording_token) {
  151. *theCurrentLocation = NULL;
  152. recording_token = FALSE;
  153. done = TRUE;
  154. }
  155. // If the character isn't a separator and not
  156. // already recording a token, mark the beginning of the token
  157. else if (!is_separator && !recording_token) {
  158. current_token = theCurrentLocation;
  159. recording_token = TRUE;
  160. }
  161. theCurrentLocation++;
  162. }
  163. return current_token;
  164. }