/libphobos/libdruntime/core/internal/string.d

https://gitlab.com/4144/gcc · D · 213 lines · 173 code · 19 blank · 21 comment · 72 complexity · 1d11ebb93bf474099f1fd3590c94356b MD5 · raw file

  1. /**
  2. * String manipulation and comparison utilities.
  3. *
  4. * Copyright: Copyright Sean Kelly 2005 - 2009.
  5. * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
  6. * Authors: Sean Kelly, Walter Bright
  7. * Source: $(DRUNTIMESRC src/rt/util/_string.d)
  8. */
  9. module core.internal.string;
  10. pure:
  11. nothrow:
  12. @nogc:
  13. alias UnsignedStringBuf = char[20];
  14. char[] unsignedToTempString(ulong value, return char[] buf, uint radix = 10) @safe
  15. {
  16. size_t i = buf.length;
  17. do
  18. {
  19. ubyte x = cast(ubyte)(value % radix);
  20. value = value / radix;
  21. buf[--i] = cast(char)((x < 10) ? x + '0' : x - 10 + 'a');
  22. } while (value);
  23. return buf[i .. $];
  24. }
  25. private struct TempStringNoAlloc
  26. {
  27. // need to handle 65 bytes for radix of 2 with negative sign.
  28. private char[65] _buf;
  29. private ubyte _len;
  30. auto get() return
  31. {
  32. return _buf[$-_len..$];
  33. }
  34. alias get this;
  35. }
  36. auto unsignedToTempString(ulong value, uint radix) @safe
  37. {
  38. TempStringNoAlloc result = void;
  39. result._len = unsignedToTempString(value, result._buf, radix).length & 0xff;
  40. return result;
  41. }
  42. unittest
  43. {
  44. UnsignedStringBuf buf;
  45. assert(0.unsignedToTempString(buf, 10) == "0");
  46. assert(1.unsignedToTempString(buf, 10) == "1");
  47. assert(12.unsignedToTempString(buf, 10) == "12");
  48. assert(0x12ABCF .unsignedToTempString(buf, 16) == "12abcf");
  49. assert(long.sizeof.unsignedToTempString(buf, 10) == "8");
  50. assert(uint.max.unsignedToTempString(buf, 10) == "4294967295");
  51. assert(ulong.max.unsignedToTempString(buf, 10) == "18446744073709551615");
  52. // use stack allocated struct version
  53. assert(0.unsignedToTempString(10) == "0");
  54. assert(1.unsignedToTempString(10) == "1");
  55. assert(12.unsignedToTempString(10) == "12");
  56. assert(0x12ABCF .unsignedToTempString(16) == "12abcf");
  57. assert(long.sizeof.unsignedToTempString(10) == "8");
  58. assert(uint.max.unsignedToTempString(10) == "4294967295");
  59. assert(ulong.max.unsignedToTempString(10) == "18446744073709551615");
  60. }
  61. alias SignedStringBuf = char[20];
  62. char[] signedToTempString(long value, return char[] buf, uint radix) @safe
  63. {
  64. bool neg = value < 0;
  65. if (neg)
  66. value = cast(ulong)-value;
  67. auto r = unsignedToTempString(value, buf, radix);
  68. if (neg)
  69. {
  70. // about to do a slice without a bounds check
  71. auto trustedSlice(return char[] r) @trusted { assert(r.ptr > buf.ptr); return (r.ptr-1)[0..r.length+1]; }
  72. r = trustedSlice(r);
  73. r[0] = '-';
  74. }
  75. return r;
  76. }
  77. auto signedToTempString(long value, uint radix) @safe
  78. {
  79. bool neg = value < 0;
  80. if (neg)
  81. value = cast(ulong)-value;
  82. auto r = unsignedToTempString(value, radix);
  83. if (neg)
  84. {
  85. r._len++;
  86. r.get()[0] = '-';
  87. }
  88. return r;
  89. }
  90. unittest
  91. {
  92. SignedStringBuf buf;
  93. assert(0.signedToTempString(buf, 10) == "0");
  94. assert(1.signedToTempString(buf, 10) == "1");
  95. assert((-1).signedToTempString(buf, 10) == "-1");
  96. assert(12.signedToTempString(buf, 10) == "12");
  97. assert((-12).signedToTempString(buf, 10) == "-12");
  98. assert(0x12ABCF .signedToTempString(buf, 16) == "12abcf");
  99. assert((-0x12ABCF) .signedToTempString(buf, 16) == "-12abcf");
  100. assert(long.sizeof.signedToTempString(buf, 10) == "8");
  101. assert(int.max.signedToTempString(buf, 10) == "2147483647");
  102. assert(int.min.signedToTempString(buf, 10) == "-2147483648");
  103. assert(long.max.signedToTempString(buf, 10) == "9223372036854775807");
  104. assert(long.min.signedToTempString(buf, 10) == "-9223372036854775808");
  105. // use stack allocated struct version
  106. assert(0.signedToTempString(10) == "0");
  107. assert(1.signedToTempString(10) == "1");
  108. assert((-1).signedToTempString(10) == "-1");
  109. assert(12.signedToTempString(10) == "12");
  110. assert((-12).signedToTempString(10) == "-12");
  111. assert(0x12ABCF .signedToTempString(16) == "12abcf");
  112. assert((-0x12ABCF) .signedToTempString(16) == "-12abcf");
  113. assert(long.sizeof.signedToTempString(10) == "8");
  114. assert(int.max.signedToTempString(10) == "2147483647");
  115. assert(int.min.signedToTempString(10) == "-2147483648");
  116. assert(long.max.signedToTempString(10) == "9223372036854775807");
  117. assert(long.min.signedToTempString(10) == "-9223372036854775808");
  118. assert(long.max.signedToTempString(2) == "111111111111111111111111111111111111111111111111111111111111111");
  119. assert(long.min.signedToTempString(2) == "-1000000000000000000000000000000000000000000000000000000000000000");
  120. }
  121. /********************************
  122. * Determine number of digits that will result from a
  123. * conversion of value to a string.
  124. * Params:
  125. * value = number to convert
  126. * radix = radix
  127. * Returns:
  128. * number of digits
  129. */
  130. int numDigits(uint radix = 10)(ulong value) @safe
  131. {
  132. int n = 1;
  133. while (1)
  134. {
  135. if (value <= uint.max)
  136. {
  137. uint v = cast(uint)value;
  138. while (1)
  139. {
  140. if (v < radix)
  141. return n;
  142. if (v < radix * radix)
  143. return n + 1;
  144. if (v < radix * radix * radix)
  145. return n + 2;
  146. if (v < radix * radix * radix * radix)
  147. return n + 3;
  148. n += 4;
  149. v /= radix * radix * radix * radix;
  150. }
  151. }
  152. n += 4;
  153. value /= radix * radix * radix * radix;
  154. }
  155. }
  156. unittest
  157. {
  158. assert(0.numDigits == 1);
  159. assert(9.numDigits == 1);
  160. assert(10.numDigits == 2);
  161. assert(99.numDigits == 2);
  162. assert(100.numDigits == 3);
  163. assert(999.numDigits == 3);
  164. assert(1000.numDigits == 4);
  165. assert(9999.numDigits == 4);
  166. assert(10000.numDigits == 5);
  167. assert(99999.numDigits == 5);
  168. assert(uint.max.numDigits == 10);
  169. assert(ulong.max.numDigits == 20);
  170. assert(0.numDigits!2 == 1);
  171. assert(1.numDigits!2 == 1);
  172. assert(2.numDigits!2 == 2);
  173. assert(3.numDigits!2 == 2);
  174. }
  175. int dstrcmp( scope const char[] s1, scope const char[] s2 ) @trusted
  176. {
  177. immutable len = s1.length <= s2.length ? s1.length : s2.length;
  178. if (__ctfe)
  179. {
  180. foreach (const u; 0 .. len)
  181. {
  182. if (s1[u] != s2[u])
  183. return s1[u] > s2[u] ? 1 : -1;
  184. }
  185. }
  186. else
  187. {
  188. import core.stdc.string : memcmp;
  189. const ret = memcmp( s1.ptr, s2.ptr, len );
  190. if ( ret )
  191. return ret;
  192. }
  193. return s1.length < s2.length ? -1 : (s1.length > s2.length);
  194. }