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.

443 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. strmap.c
  5. Abstract:
  6. Tests the string mapping mechanism for correctness and performance.
  7. Author:
  8. Jim Schmidt (jimschm) 19-Aug-1998
  9. Revision History:
  10. <full name> (<alias>) <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. HANDLE g_hHeap;
  14. HINSTANCE g_hInst;
  15. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  16. BOOL
  17. pTheFooFilter (
  18. IN OUT PREG_REPLACE_DATA Data
  19. );
  20. VOID
  21. pStandardSearchAndReplace (
  22. IN PGROWBUFFER Pairs,
  23. IN OUT PTSTR Buffer,
  24. IN UINT BufferSize
  25. );
  26. BOOL
  27. pCallEntryPoints (
  28. DWORD Reason
  29. )
  30. {
  31. HINSTANCE Instance;
  32. //
  33. // Simulate DllMain
  34. //
  35. Instance = g_hInst;
  36. //
  37. // Initialize the common libs
  38. //
  39. if (!MigUtil_Entry (Instance, Reason, NULL)) {
  40. return FALSE;
  41. }
  42. return TRUE;
  43. }
  44. BOOL
  45. Init (
  46. VOID
  47. )
  48. {
  49. g_hHeap = GetProcessHeap();
  50. g_hInst = GetModuleHandle (NULL);
  51. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  52. }
  53. VOID
  54. Terminate (
  55. VOID
  56. )
  57. {
  58. pCallEntryPoints (DLL_PROCESS_DETACH);
  59. }
  60. VOID
  61. HelpAndExit (
  62. VOID
  63. )
  64. {
  65. //
  66. // This routine is called whenever command line args are wrong
  67. //
  68. _ftprintf (
  69. stderr,
  70. TEXT("Command Line Syntax:\n\n")
  71. TEXT(" strmap [/D] [/N:<strings>] [/T[:<count>]] [/M|/S] [/F]\n")
  72. TEXT("\nDescription:\n\n")
  73. TEXT(" strmap tests CreateStringMapping and MappingSearchAndReplace.\n")
  74. TEXT("\nArguments:\n\n")
  75. TEXT(" /D Dump out string before and after test\n")
  76. TEXT(" /N Specifies the number of strings to map\n")
  77. TEXT(" /T Enables timing mode, <count> specifies number of tests to time\n")
  78. TEXT(" /M Times the mapping APIs\n")
  79. TEXT(" /S Times standard strnicmp and strcpy method\n")
  80. TEXT(" /F Enables the FOO filter function\n")
  81. );
  82. exit (1);
  83. }
  84. PCTSTR
  85. pGenerateRandomString (
  86. OUT PTSTR Ptr,
  87. IN INT MinLength,
  88. IN INT MaxLength
  89. )
  90. {
  91. INT Length;
  92. INT i;
  93. PTSTR p;
  94. Length = rand() * MaxLength / RAND_MAX;
  95. Length = max (MinLength, Length);
  96. p = Ptr;
  97. for (i = 0 ; i < Length ; i++) {
  98. //*p++ = rand() * 224 / RAND_MAX + 32;
  99. *p++ = rand() * 26 / RAND_MAX + 65;
  100. }
  101. *p = 0;
  102. return Ptr;
  103. }
  104. INT
  105. __cdecl
  106. _tmain (
  107. INT argc,
  108. PCTSTR argv[]
  109. )
  110. {
  111. INT i;
  112. PCTSTR NumberArg;
  113. INT Strings = 10;
  114. INT TestCount = 0;
  115. PMAPSTRUCT Map;
  116. TCHAR Old[256];
  117. TCHAR New[256];
  118. TCHAR Buffer[256];
  119. DWORD StartTick;
  120. GROWBUFFER Pairs = GROWBUF_INIT;
  121. BOOL TestMapApi = TRUE;
  122. BOOL Dump = FALSE;
  123. BOOL FooFilter = FALSE;
  124. for (i = 1 ; i < argc ; i++) {
  125. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  126. switch (_totlower ((CHARTYPE) _tcsnextc (&argv[i][1]))) {
  127. case TEXT('d'):
  128. //
  129. // /d (dump on)
  130. //
  131. Dump = TRUE;
  132. break;
  133. case TEXT('f'):
  134. //
  135. // /f (enable the FOO filter function)
  136. //
  137. FooFilter = TRUE;
  138. break;
  139. case TEXT('m'):
  140. //
  141. // /m (test map api)
  142. //
  143. TestMapApi = TRUE;
  144. break;
  145. case TEXT('s') :
  146. //
  147. // /s (test normal string apis)
  148. //
  149. TestMapApi = FALSE;
  150. break;
  151. case TEXT('n'):
  152. //
  153. // /n:<strings>
  154. //
  155. if (argv[i][2] == TEXT(':')) {
  156. NumberArg = &argv[i][3];
  157. } else if (i + 1 < argc) {
  158. NumberArg = argv[++i];
  159. } else {
  160. HelpAndExit();
  161. }
  162. Strings = _ttoi (NumberArg);
  163. if (Strings < 1) {
  164. HelpAndExit();
  165. }
  166. break;
  167. case TEXT('t'):
  168. //
  169. // /t[:<count>]
  170. //
  171. if (argv[i][2] == TEXT(':')) {
  172. NumberArg = &argv[i][3];
  173. TestCount = _ttoi (NumberArg);
  174. if (TestCount < 1) {
  175. HelpAndExit();
  176. }
  177. } else if (argv[i][2]) {
  178. HelpAndExit();
  179. } else {
  180. TestCount = 1000;
  181. }
  182. break;
  183. default:
  184. HelpAndExit();
  185. }
  186. } else {
  187. HelpAndExit();
  188. }
  189. }
  190. //
  191. // Begin processing
  192. //
  193. if (!Init()) {
  194. return 0;
  195. }
  196. //
  197. // Create mapping
  198. //
  199. Map = CreateStringMapping();
  200. //
  201. // Generate random mapping pairs
  202. //
  203. for (i = 0 ; i < Strings ; i++) {
  204. AddStringMappingPair (
  205. Map,
  206. pGenerateRandomString (Old, 1, 20),
  207. pGenerateRandomString (New, 0, 20)
  208. );
  209. _tprintf (TEXT("From: %s\nTo: %s\n\n"), Old, New);
  210. CharLower (Old);
  211. GrowBufAppendDword (&Pairs, ByteCount (Old));
  212. MultiSzAppend (&Pairs, Old);
  213. GrowBufAppendDword (&Pairs, ByteCount (New));
  214. MultiSzAppend (&Pairs, New);
  215. }
  216. if (FooFilter) {
  217. AddStringMappingPairEx (Map, TEXT("FOO"), TEXT("**BAR**"), pTheFooFilter);
  218. }
  219. StartTick = GetTickCount();
  220. if (TestMapApi) {
  221. for (i = 0 ; i < TestCount ; i++) {
  222. StringCopy (Buffer, pGenerateRandomString (Old, 10, sizeof (Buffer) / (4 * sizeof (TCHAR))));
  223. MappingSearchAndReplace (Map, Buffer, sizeof (Buffer));
  224. if (Dump) {
  225. _tprintf (TEXT("Old: %s\nNew: %s\n\n"), Old, Buffer);
  226. }
  227. }
  228. if (TestCount) {
  229. _tprintf (TEXT("\nMappingSearchAndReplace: Test of %i strings took %u ms\n"), TestCount, GetTickCount() - StartTick);
  230. }
  231. } else {
  232. StartTick = GetTickCount();
  233. for (i = 0 ; i < TestCount ; i++) {
  234. StringCopy (Buffer, pGenerateRandomString (Old, 10, sizeof (Buffer) / (4 * sizeof (TCHAR))));
  235. pStandardSearchAndReplace (&Pairs, Buffer, sizeof (Buffer));
  236. if (Dump) {
  237. _tprintf (TEXT("Old: %s\nNew: %s\n\n"), Old, Buffer);
  238. }
  239. }
  240. if (TestCount) {
  241. _tprintf (TEXT("\nStandard stricmp: Test of %i strings took %u ms\n"), TestCount, GetTickCount() - StartTick);
  242. }
  243. }
  244. //
  245. // Clean up mapping
  246. //
  247. DestroyStringMapping (Map);
  248. FreeGrowBuffer (&Pairs);
  249. //
  250. // End of processing
  251. //
  252. Terminate();
  253. return 0;
  254. }
  255. VOID
  256. pStandardSearchAndReplace (
  257. IN PGROWBUFFER Pairs,
  258. IN OUT PTSTR Buffer,
  259. IN UINT BufferSize
  260. )
  261. {
  262. TCHAR WorkBuffer[256];
  263. TCHAR LowerBuffer[256];
  264. PCTSTR Src;
  265. PCTSTR RealSrc;
  266. PTSTR Dest;
  267. PDWORD OldByteCount;
  268. PDWORD NewByteCount;
  269. PCTSTR Old;
  270. PCTSTR New;
  271. UINT u;
  272. UINT OutboundLen;
  273. UINT a, b;
  274. RealSrc = Buffer;
  275. Src = LowerBuffer;
  276. Dest = WorkBuffer;
  277. OutboundLen = ByteCount (Buffer);
  278. StringCopy (LowerBuffer, Buffer);
  279. CharLower (LowerBuffer);
  280. BufferSize -= sizeof (TCHAR);
  281. while (*Src) {
  282. u = 0;
  283. while (u < Pairs->End) {
  284. OldByteCount = (PDWORD) (Pairs->Buf + u);
  285. Old = (PCTSTR) (OldByteCount + 1);
  286. NewByteCount = (PDWORD) ((PBYTE) OldByteCount + *OldByteCount + sizeof (DWORD) + sizeof (TCHAR));
  287. New = (PCTSTR) (NewByteCount + 1);
  288. if (!_tcsncmp (Src, Old, *OldByteCount / sizeof (TCHAR))) {
  289. break;
  290. }
  291. u += *OldByteCount + *NewByteCount + sizeof (DWORD) * 2 + sizeof (TCHAR) * 2;
  292. }
  293. if (u < Pairs->End) {
  294. OutboundLen = OutboundLen - *OldByteCount + *NewByteCount;
  295. if (OutboundLen > BufferSize) {
  296. DEBUGMSG ((DBG_WHOOPS, "String got too long!"));
  297. OutboundLen = Dest - WorkBuffer;
  298. break;
  299. }
  300. CopyMemory (Dest, New, *NewByteCount);
  301. Dest = (PTSTR) ((PBYTE) Dest + *NewByteCount);
  302. Src = (PCTSTR) ((PBYTE) Src + *OldByteCount);
  303. RealSrc = (PCTSTR) ((PBYTE) RealSrc + *OldByteCount);
  304. } else {
  305. *Dest++ = *RealSrc++;
  306. Src++;
  307. }
  308. }
  309. *Dest = 0;
  310. StringCopy (Buffer, WorkBuffer);
  311. }
  312. BOOL
  313. pTheFooFilter (
  314. IN OUT PREG_REPLACE_DATA Data
  315. )
  316. {
  317. //
  318. // FOO was found in the string
  319. //
  320. _tprintf (TEXT("\"FOO\" was found in the string!!\n\n"));
  321. _tprintf (
  322. TEXT(" OriginalString: %s\n")
  323. TEXT(" CurrentString: %s\n")
  324. TEXT(" OldSubString: %s\n")
  325. TEXT(" NewSubString: %s\n")
  326. TEXT(" NewSubStringSizeInBytes: %u\n\n"),
  327. Data->Ansi.OriginalString,
  328. Data->Ansi.CurrentString,
  329. Data->Ansi.OldSubString,
  330. Data->Ansi.NewSubString,
  331. Data->Ansi.NewSubStringSizeInBytes
  332. );
  333. return TRUE;
  334. }