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.

455 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. cnvint.c
  5. Abstract:
  6. Text to integer and integer to text converion routines.
  7. Author:
  8. Steve Wood (stevewo) 23-Aug-1990
  9. Revision History:
  10. --*/
  11. #include <ntrtlp.h>
  12. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  13. #pragma alloc_text(PAGE,RtlIntegerToChar)
  14. #pragma alloc_text(PAGE,RtlCharToInteger)
  15. #pragma alloc_text(PAGE,RtlUnicodeStringToInteger)
  16. #pragma alloc_text(PAGE,RtlIntegerToUnicodeString)
  17. #pragma alloc_text(PAGE,RtlLargeIntegerToChar)
  18. #endif
  19. CHAR RtlpIntegerChars[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  20. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  21. NTSTATUS
  22. RtlIntegerToChar (
  23. IN ULONG Value,
  24. IN ULONG Base OPTIONAL,
  25. IN LONG OutputLength,
  26. OUT PSZ String
  27. )
  28. /*++
  29. Routine Description:
  30. Arguments:
  31. Return Value:
  32. --*/
  33. {
  34. CHAR Result[ 33 ], *s;
  35. ULONG Shift, Mask, Digit, Length;
  36. Shift = 0;
  37. switch( Base ) {
  38. case 16: Shift = 4; break;
  39. case 8: Shift = 3; break;
  40. case 2: Shift = 1; break;
  41. case 0: Base = 10;
  42. case 10: Shift = 0; break;
  43. default: return( STATUS_INVALID_PARAMETER );
  44. }
  45. if (Shift != 0) {
  46. Mask = 0xF >> 4 - Shift;
  47. }
  48. s = &Result[ 32 ];
  49. *s = '\0';
  50. do {
  51. if (Shift != 0) {
  52. Digit = Value & Mask;
  53. Value >>= Shift;
  54. }
  55. else {
  56. Digit = Value % Base;
  57. Value = Value / Base;
  58. }
  59. *--s = RtlpIntegerChars[ Digit ];
  60. } while (Value != 0);
  61. Length = &Result[ 32 ] - s;
  62. if (OutputLength < 0) {
  63. OutputLength = -OutputLength;
  64. while ((LONG)Length < OutputLength) {
  65. *--s = '0';
  66. Length++;
  67. }
  68. }
  69. if ((LONG)Length > OutputLength) {
  70. return( STATUS_BUFFER_OVERFLOW );
  71. }
  72. else {
  73. try {
  74. RtlMoveMemory( String, s, Length );
  75. if ((LONG)Length < OutputLength) {
  76. String[ Length ] = '\0';
  77. }
  78. }
  79. except( EXCEPTION_EXECUTE_HANDLER ) {
  80. return( GetExceptionCode() );
  81. }
  82. return( STATUS_SUCCESS );
  83. }
  84. }
  85. NTSTATUS
  86. RtlCharToInteger (
  87. IN PCSZ String,
  88. IN ULONG Base OPTIONAL,
  89. OUT PULONG Value
  90. )
  91. {
  92. CHAR c, Sign;
  93. ULONG Result, Digit, Shift;
  94. while ((Sign = *String++) <= ' ') {
  95. if (!*String) {
  96. String--;
  97. break;
  98. }
  99. }
  100. c = Sign;
  101. if (c == '-' || c == '+') {
  102. c = *String++;
  103. }
  104. if (!ARGUMENT_PRESENT( Base )) {
  105. Base = 10;
  106. Shift = 0;
  107. if (c == '0') {
  108. c = *String++;
  109. if (c == 'x') {
  110. Base = 16;
  111. Shift = 4;
  112. }
  113. else
  114. if (c == 'o') {
  115. Base = 8;
  116. Shift = 3;
  117. }
  118. else
  119. if (c == 'b') {
  120. Base = 2;
  121. Shift = 1;
  122. }
  123. else {
  124. String--;
  125. }
  126. c = *String++;
  127. }
  128. }
  129. else {
  130. switch( Base ) {
  131. case 16: Shift = 4; break;
  132. case 8: Shift = 3; break;
  133. case 2: Shift = 1; break;
  134. case 10: Shift = 0; break;
  135. default: return( STATUS_INVALID_PARAMETER );
  136. }
  137. }
  138. Result = 0;
  139. while (c) {
  140. if (c >= '0' && c <= '9') {
  141. Digit = c - '0';
  142. }
  143. else
  144. if (c >= 'A' && c <= 'F') {
  145. Digit = c - 'A' + 10;
  146. }
  147. else
  148. if (c >= 'a' && c <= 'f') {
  149. Digit = c - 'a' + 10;
  150. }
  151. else {
  152. break;
  153. }
  154. if (Digit >= Base) {
  155. break;
  156. }
  157. if (Shift == 0) {
  158. Result = (Base * Result) + Digit;
  159. }
  160. else {
  161. Result = (Result << Shift) | Digit;
  162. }
  163. c = *String++;
  164. }
  165. if (Sign == '-') {
  166. Result = (ULONG)(-(LONG)Result);
  167. }
  168. try {
  169. *Value = Result;
  170. }
  171. except( EXCEPTION_EXECUTE_HANDLER ) {
  172. return( GetExceptionCode() );
  173. }
  174. return( STATUS_SUCCESS );
  175. }
  176. NTSTATUS
  177. RtlUnicodeStringToInteger (
  178. IN PUNICODE_STRING String,
  179. IN ULONG Base OPTIONAL,
  180. OUT PULONG Value
  181. )
  182. {
  183. PCWSTR s;
  184. WCHAR c, Sign;
  185. ULONG nChars, Result, Digit, Shift;
  186. s = String->Buffer;
  187. nChars = String->Length / sizeof( WCHAR );
  188. while (nChars-- && (Sign = *s++) <= ' ') {
  189. if (!nChars) {
  190. Sign = UNICODE_NULL;
  191. break;
  192. }
  193. }
  194. c = Sign;
  195. if (c == L'-' || c == L'+') {
  196. if (nChars) {
  197. nChars--;
  198. c = *s++;
  199. }
  200. else {
  201. c = UNICODE_NULL;
  202. }
  203. }
  204. if (!ARGUMENT_PRESENT( Base )) {
  205. Base = 10;
  206. Shift = 0;
  207. if (c == L'0') {
  208. if (nChars) {
  209. nChars--;
  210. c = *s++;
  211. if (c == L'x') {
  212. Base = 16;
  213. Shift = 4;
  214. }
  215. else
  216. if (c == L'o') {
  217. Base = 8;
  218. Shift = 3;
  219. }
  220. else
  221. if (c == L'b') {
  222. Base = 2;
  223. Shift = 1;
  224. }
  225. else {
  226. nChars++;
  227. s--;
  228. }
  229. }
  230. if (nChars) {
  231. nChars--;
  232. c = *s++;
  233. }
  234. else {
  235. c = UNICODE_NULL;
  236. }
  237. }
  238. }
  239. else {
  240. switch( Base ) {
  241. case 16: Shift = 4; break;
  242. case 8: Shift = 3; break;
  243. case 2: Shift = 1; break;
  244. case 10: Shift = 0; break;
  245. default: return( STATUS_INVALID_PARAMETER );
  246. }
  247. }
  248. Result = 0;
  249. while (c != UNICODE_NULL) {
  250. if (c >= L'0' && c <= L'9') {
  251. Digit = c - L'0';
  252. }
  253. else
  254. if (c >= L'A' && c <= L'F') {
  255. Digit = c - L'A' + 10;
  256. }
  257. else
  258. if (c >= L'a' && c <= L'f') {
  259. Digit = c - L'a' + 10;
  260. }
  261. else {
  262. break;
  263. }
  264. if (Digit >= Base) {
  265. break;
  266. }
  267. if (Shift == 0) {
  268. Result = (Base * Result) + Digit;
  269. }
  270. else {
  271. Result = (Result << Shift) | Digit;
  272. }
  273. if (!nChars) {
  274. break;
  275. }
  276. nChars--;
  277. c = *s++;
  278. }
  279. if (Sign == L'-') {
  280. Result = (ULONG)(-(LONG)Result);
  281. }
  282. try {
  283. *Value = Result;
  284. }
  285. except( EXCEPTION_EXECUTE_HANDLER ) {
  286. return( GetExceptionCode() );
  287. }
  288. return( STATUS_SUCCESS );
  289. }
  290. NTSTATUS
  291. RtlIntegerToUnicodeString (
  292. IN ULONG Value,
  293. IN ULONG Base OPTIONAL,
  294. IN OUT PUNICODE_STRING String
  295. )
  296. {
  297. NTSTATUS Status;
  298. UCHAR ResultBuffer[ 16 ];
  299. ANSI_STRING AnsiString;
  300. Status = RtlIntegerToChar( Value, Base, sizeof( ResultBuffer ), ResultBuffer );
  301. if (NT_SUCCESS( Status )) {
  302. AnsiString.Buffer = ResultBuffer;
  303. AnsiString.MaximumLength = sizeof( ResultBuffer );
  304. AnsiString.Length = (USHORT)strlen( ResultBuffer );
  305. Status = RtlAnsiStringToUnicodeString( String, &AnsiString, FALSE );
  306. }
  307. return( Status );
  308. }
  309. NTSTATUS
  310. RtlLargeIntegerToChar (
  311. IN PLARGE_INTEGER Value,
  312. IN ULONG Base OPTIONAL,
  313. IN LONG OutputLength,
  314. OUT PSZ String
  315. )
  316. /*++
  317. Routine Description:
  318. Arguments:
  319. Return Value:
  320. --*/
  321. {
  322. CHAR Result[ 100 ], *s;
  323. ULONG Shift, Mask, Digit, Length;
  324. Shift = 0;
  325. switch( Base ) {
  326. case 16: Shift = 4; break;
  327. case 8: Shift = 3; break;
  328. case 2: Shift = 1; break;
  329. case 0:
  330. case 10: Shift = 0; break;
  331. default: return( STATUS_INVALID_PARAMETER );
  332. }
  333. if (Shift != 0) {
  334. Mask = 0xF >> 4 - Shift;
  335. }
  336. s = &Result[ 99 ];
  337. *s = '\0';
  338. if (Shift != 0) {
  339. ULONG LowValue,HighValue,HighShift,HighMask;
  340. LowValue = Value->LowPart;
  341. HighValue = Value->HighPart;
  342. HighShift = Shift - (sizeof(ULONG) % Shift);
  343. HighMask = 0xF >> 4 - HighShift;
  344. do {
  345. Digit = LowValue & Mask;
  346. LowValue = (LowValue >> Shift) | ((HighValue & HighMask) << (sizeof(ULONG) - HighShift));
  347. HighValue = HighValue >> HighShift;
  348. *--s = RtlpIntegerChars[ Digit ];
  349. } while ((LowValue | HighValue) != 0);
  350. } else {
  351. LARGE_INTEGER TempValue=*Value;
  352. do {
  353. TempValue = RtlExtendedLargeIntegerDivide(TempValue,Base,&Digit);
  354. *--s = RtlpIntegerChars[ Digit ];
  355. } while (TempValue.HighPart != 0 || TempValue.LowPart != 0);
  356. }
  357. Length = &Result[ 99 ] - s;
  358. if (OutputLength < 0) {
  359. OutputLength = -OutputLength;
  360. while ((LONG)Length < OutputLength) {
  361. *--s = '0';
  362. Length++;
  363. }
  364. }
  365. if ((LONG)Length > OutputLength) {
  366. return( STATUS_BUFFER_OVERFLOW );
  367. }
  368. else {
  369. try {
  370. RtlMoveMemory( String, s, Length );
  371. if ((LONG)Length < OutputLength) {
  372. String[ Length ] = '\0';
  373. }
  374. }
  375. except( EXCEPTION_EXECUTE_HANDLER ) {
  376. return( GetExceptionCode() );
  377. }
  378. return( STATUS_SUCCESS );
  379. }
  380. }