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.

85 lines
2.3 KiB

  1. // HEXTOSTR.CPP
  2. //
  3. // Utility functions to convert hexadecimal numbers into equivalent string
  4. // representations.
  5. //
  6. // Note: These functions are in their own file, rather than in STRUTIL.CPP,
  7. // because they use a const array. The current implementation of the linker
  8. // pulls this array into binaries if they use any function in the source file,
  9. // not just the functions which reference this array.
  10. #include "precomp.h"
  11. #include <strutil.h>
  12. const CHAR rgchHexNumMap[] =
  13. {
  14. '0', '1', '2', '3', '4', '5', '6', '7',
  15. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  16. };
  17. //
  18. // QWordToHexString()
  19. //
  20. // Converts a ULARGE_INTEGER to an ANSI string (not prefixed with 0x or 0X)
  21. //
  22. // NOTE: pszString must point to a buffer of at least CCHMAX_ULARGE_INTEGER chars
  23. //
  24. // Returns the number of characters written (not including the NULL terminator)
  25. int NMINTERNAL QWordToHexStringA(ULARGE_INTEGER qw, LPSTR pszString)
  26. {
  27. ASSERT(!IsBadWritePtr(pszString, sizeof(*pszString)*CCHMAX_HEX_ULARGE_INTEGER));
  28. LPSTR pszCurrent = pszString;
  29. DWORD dwQwParts[] = {qw.HighPart, qw.LowPart};
  30. int i;
  31. // Walk the QWORD four bits at a time, mapping them to the appropriate
  32. // char and storing them in the caller-supplied buffer.
  33. // We loop through the QWORD twice, working on each DWORD separately
  34. for (i = 0; i < ARRAY_ELEMENTS(dwQwParts); i++)
  35. {
  36. DWORD dwQwPart = dwQwParts[i];
  37. // Optimization: We only need to look at this DWORD part if it's
  38. // non-zero or we've already put chars in our buffer.
  39. if (dwQwPart || pszCurrent != pszString)
  40. {
  41. // <j> is the zero-based index of the low bit of the four-bit
  42. // range on which we're operating.
  43. int j;
  44. DWORD dwMask;
  45. for (j = BITS_PER_HEX_CHAR * (CCH_HEX_DWORD - 1),
  46. dwMask = 0xFL << j;
  47. j >= 0;
  48. j -= BITS_PER_HEX_CHAR,
  49. dwMask >>= BITS_PER_HEX_CHAR)
  50. {
  51. DWORD iDigit = (dwQwPart & dwMask) >> j;
  52. ASSERT(0xF >= iDigit);
  53. // We use this test to skip leading zeros
  54. if (pszCurrent != pszString || iDigit)
  55. {
  56. *pszCurrent++ = rgchHexNumMap[iDigit];
  57. }
  58. }
  59. }
  60. }
  61. // If the number was zero, we need to set it explicitly
  62. if (pszCurrent == pszString)
  63. {
  64. *pszCurrent++ = '0';
  65. }
  66. // Null terminate the string
  67. *pszCurrent = '\0';
  68. // Return the number of chars, not counting the null terminator
  69. return (int)(pszCurrent - pszString);
  70. }