Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added unchecked casts; fixes bug #441. Code and original patches supp…

…lied by @stuarthalloway

Signed-off-by: Rich Hickey <richhickey@gmail.com>
  • Loading branch information...
commit cbd789d1a5b472d92b91f2fe0e273f48c2583483 1 parent 8225407
Aaron Bedra abedra authored richhickey committed
54 src/clj/clojure/core.clj
@@ -3031,6 +3031,49 @@
3031 3031 :added "1.0"}
3032 3032 [x] (clojure.lang.RT/booleanCast x))
3033 3033
  3034 +(defn unchecked-byte
  3035 + "Coerce to byte. Subject to rounding or truncation."
  3036 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedByteCast ~x)))
  3037 + :added "1.3"}
  3038 + [^Number x] (clojure.lang.RT/uncheckedByteCast x))
  3039 +
  3040 +(defn unchecked-short
  3041 + "Coerce to short. Subject to rounding or truncation."
  3042 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedShortCast ~x)))
  3043 + :added "1.3"}
  3044 + [^Number x] (clojure.lang.RT/uncheckedShortCast x))
  3045 +
  3046 +(defn unchecked-char
  3047 + "Coerce to char. Subject to rounding or truncation."
  3048 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedCharCast ~x)))
  3049 + :added "1.3"}
  3050 + [x] (. clojure.lang.RT (uncheckedCharCast x)))
  3051 +
  3052 +(defn unchecked-int
  3053 + "Coerce to int. Subject to rounding or truncation."
  3054 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedIntCast ~x)))
  3055 + :added "1.3"}
  3056 + [^Number x] (clojure.lang.RT/uncheckedIntCast x))
  3057 +
  3058 +(defn unchecked-long
  3059 + "Coerce to long. Subject to rounding or truncation."
  3060 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedLongCast ~x)))
  3061 + :added "1.3"}
  3062 + [^Number x] (clojure.lang.RT/uncheckedLongCast x))
  3063 +
  3064 +(defn unchecked-float
  3065 + "Coerce to float. Subject to rounding."
  3066 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedFloatCast ~x)))
  3067 + :added "1.3"}
  3068 + [^Number x] (clojure.lang.RT/uncheckedFloatCast x))
  3069 +
  3070 +(defn unchecked-double
  3071 + "Coerce to double. Subject to rounding."
  3072 + {:inline (fn [x] `(. clojure.lang.RT (uncheckedDoubleCast ~x)))
  3073 + :added "1.3"}
  3074 + [^Number x] (clojure.lang.RT/uncheckedDoubleCast x))
  3075 +
  3076 +
3034 3077 (defn number?
3035 3078 "Returns true if x is a Number"
3036 3079 {:added "1.0"
@@ -5832,14 +5875,11 @@
5832 5875 {:added "1.0"}
5833 5876 ([f & opts]
5834 5877 (let [opts (normalize-slurp-opts opts)
5835   - sb (StringBuilder.)]
  5878 + sb (StringBuilder.)
  5879 + sw (java.io.StringWriter.)]
5836 5880 (with-open [#^java.io.Reader r (apply jio/reader f opts)]
5837   - (loop [c (.read r)]
5838   - (if (neg? c)
5839   - (str sb)
5840   - (do
5841   - (.append sb (char c))
5842   - (recur (.read r)))))))))
  5881 + (jio/copy r sw)
  5882 + (str sw)))))
5843 5883
5844 5884 (defn spit
5845 5885 "Opposite of slurp. Opens f with writer, writes content, then
208 src/jvm/clojure/lang/RT.java
@@ -1055,6 +1055,214 @@ static public double doubleCast(double x){
1055 1055 return x;
1056 1056 }
1057 1057
  1058 +static public byte uncheckedByteCast(Object x){
  1059 + return ((Number) x).byteValue();
  1060 +}
  1061 +
  1062 +static public byte uncheckedByteCast(byte x){
  1063 + return x;
  1064 +}
  1065 +
  1066 +static public byte uncheckedByteCast(short x){
  1067 + return (byte) x;
  1068 +}
  1069 +
  1070 +static public byte uncheckedByteCast(int x){
  1071 + return (byte) x;
  1072 +}
  1073 +
  1074 +static public byte uncheckedByteCast(long x){
  1075 + return (byte) x;
  1076 +}
  1077 +
  1078 +static public byte uncheckedByteCast(float x){
  1079 + return (byte) x;
  1080 +}
  1081 +
  1082 +static public byte uncheckedByteCast(double x){
  1083 + return (byte) x;
  1084 +}
  1085 +
  1086 +static public short uncheckedShortCast(Object x){
  1087 + return ((Number) x).shortValue();
  1088 +}
  1089 +
  1090 +static public short uncheckedShortCast(byte x){
  1091 + return x;
  1092 +}
  1093 +
  1094 +static public short uncheckedShortCast(short x){
  1095 + return x;
  1096 +}
  1097 +
  1098 +static public short uncheckedShortCast(int x){
  1099 + return (short) x;
  1100 +}
  1101 +
  1102 +static public short uncheckedShortCast(long x){
  1103 + return (short) x;
  1104 +}
  1105 +
  1106 +static public short uncheckedShortCast(float x){
  1107 + return (short) x;
  1108 +}
  1109 +
  1110 +static public short uncheckedShortCast(double x){
  1111 + return (short) x;
  1112 +}
  1113 +
  1114 +static public char uncheckedCharCast(Object x){
  1115 + if(x instanceof Character)
  1116 + return ((Character) x).charValue();
  1117 + return (char) ((Number) x).longValue();
  1118 +}
  1119 +
  1120 +static public char uncheckedCharCast(byte x){
  1121 + return (char) x;
  1122 +}
  1123 +
  1124 +static public char uncheckedCharCast(short x){
  1125 + return (char) x;
  1126 +}
  1127 +
  1128 +static public char uncheckedCharCast(char x){
  1129 + return x;
  1130 +}
  1131 +
  1132 +static public char uncheckedCharCast(int x){
  1133 + return (char) x;
  1134 +}
  1135 +
  1136 +static public char uncheckedCharCast(long x){
  1137 + return (char) x;
  1138 +}
  1139 +
  1140 +static public char uncheckedCharCast(float x){
  1141 + return (char) x;
  1142 +}
  1143 +
  1144 +static public char uncheckedCharCast(double x){
  1145 + return (char) x;
  1146 +}
  1147 +
  1148 +static public int uncheckedIntCast(Object x){
  1149 + if(x instanceof Number)
  1150 + return ((Number)x).intValue();
  1151 + return ((Character) x).charValue();
  1152 +}
  1153 +
  1154 +static public int uncheckedIntCast(byte x){
  1155 + return x;
  1156 +}
  1157 +
  1158 +static public int uncheckedIntCast(short x){
  1159 + return x;
  1160 +}
  1161 +
  1162 +static public int uncheckedIntCast(char x){
  1163 + return x;
  1164 +}
  1165 +
  1166 +static public int uncheckedIntCast(int x){
  1167 + return x;
  1168 +}
  1169 +
  1170 +static public int uncheckedIntCast(long x){
  1171 + return (int) x;
  1172 +}
  1173 +
  1174 +static public int uncheckedIntCast(float x){
  1175 + return (int) x;
  1176 +}
  1177 +
  1178 +static public int uncheckedIntCast(double x){
  1179 + return (int) x;
  1180 +}
  1181 +
  1182 +static public long uncheckedLongCast(Object x){
  1183 + return ((Number) x).longValue();
  1184 +}
  1185 +
  1186 +static public long uncheckedLongCast(byte x){
  1187 + return x;
  1188 +}
  1189 +
  1190 +static public long uncheckedLongCast(short x){
  1191 + return x;
  1192 +}
  1193 +
  1194 +static public long uncheckedLongCast(int x){
  1195 + return x;
  1196 +}
  1197 +
  1198 +static public long uncheckedLongCast(long x){
  1199 + return x;
  1200 +}
  1201 +
  1202 +static public long uncheckedLongCast(float x){
  1203 + return (long) x;
  1204 +}
  1205 +
  1206 +static public long uncheckedLongCast(double x){
  1207 + return (long) x;
  1208 +}
  1209 +
  1210 +static public float uncheckedFloatCast(Object x){
  1211 + return ((Number) x).floatValue();
  1212 +}
  1213 +
  1214 +static public float uncheckedFloatCast(byte x){
  1215 + return x;
  1216 +}
  1217 +
  1218 +static public float uncheckedFloatCast(short x){
  1219 + return x;
  1220 +}
  1221 +
  1222 +static public float uncheckedFloatCast(int x){
  1223 + return x;
  1224 +}
  1225 +
  1226 +static public float uncheckedFloatCast(long x){
  1227 + return x;
  1228 +}
  1229 +
  1230 +static public float uncheckedFloatCast(float x){
  1231 + return x;
  1232 +}
  1233 +
  1234 +static public float uncheckedFloatCast(double x){
  1235 + return (float) x;
  1236 +}
  1237 +
  1238 +static public double uncheckedDoubleCast(Object x){
  1239 + return ((Number) x).doubleValue();
  1240 +}
  1241 +
  1242 +static public double uncheckedDoubleCast(byte x){
  1243 + return x;
  1244 +}
  1245 +
  1246 +static public double uncheckedDoubleCast(short x){
  1247 + return x;
  1248 +}
  1249 +
  1250 +static public double uncheckedDoubleCast(int x){
  1251 + return x;
  1252 +}
  1253 +
  1254 +static public double uncheckedDoubleCast(long x){
  1255 + return x;
  1256 +}
  1257 +
  1258 +static public double uncheckedDoubleCast(float x){
  1259 + return x;
  1260 +}
  1261 +
  1262 +static public double uncheckedDoubleCast(double x){
  1263 + return x;
  1264 +}
  1265 +
1058 1266 static public IPersistentMap map(Object... init){
1059 1267 if(init == null)
1060 1268 return PersistentArrayMap.EMPTY;
89 test/clojure/test_clojure/numbers.clj
@@ -12,7 +12,8 @@
12 12 ;;
13 13
14 14 (ns clojure.test-clojure.numbers
15   - (:use clojure.test))
  15 + (:use clojure.test
  16 + clojure.template))
16 17
17 18
18 19 ; TODO:
@@ -37,6 +38,91 @@
37 38 13178456923875639284562345789M
38 39 13178456923875639284562345789N))
39 40
  41 +(deftest unchecked-cast-num-obj
  42 + (do-template [prim-array cast]
  43 + (are [n]
  44 + (let [a (prim-array 1)]
  45 + (aset a 0 (cast n)))
  46 + (Byte. Byte/MAX_VALUE)
  47 + (Short. Short/MAX_VALUE)
  48 + (Integer. Integer/MAX_VALUE)
  49 + (Long. Long/MAX_VALUE)
  50 + (Float. Float/MAX_VALUE)
  51 + (Double. Double/MAX_VALUE))
  52 + byte-array
  53 + unchecked-byte
  54 + short-array
  55 + unchecked-short
  56 + char-array
  57 + unchecked-char
  58 + int-array
  59 + unchecked-int
  60 + long-array
  61 + unchecked-long
  62 + float-array
  63 + unchecked-float
  64 + double-array
  65 + unchecked-double))
  66 +
  67 +(deftest unchecked-cast-num-prim
  68 + (do-template [prim-array cast]
  69 + (are [n]
  70 + (let [a (prim-array 1)]
  71 + (aset a 0 (cast n)))
  72 + Byte/MAX_VALUE
  73 + Short/MAX_VALUE
  74 + Integer/MAX_VALUE
  75 + Long/MAX_VALUE
  76 + Float/MAX_VALUE
  77 + Double/MAX_VALUE)
  78 + byte-array
  79 + unchecked-byte
  80 + short-array
  81 + unchecked-short
  82 + char-array
  83 + unchecked-char
  84 + int-array
  85 + unchecked-int
  86 + long-array
  87 + unchecked-long
  88 + float-array
  89 + unchecked-float
  90 + double-array
  91 + unchecked-double))
  92 +
  93 +(deftest unchecked-cast-char
  94 + ; in keeping with the checked cast functions, char and Character can only be cast to int
  95 + (is (unchecked-int (char 0xFFFF)))
  96 + (is (let [c (char 0xFFFF)] (unchecked-int c)))) ; force primitive char
  97 +
  98 +(def expected-casts
  99 + [
  100 + [:input [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE Integer/MAX_VALUE Long/MAX_VALUE Float/MAX_VALUE Double/MAX_VALUE]]
  101 + [char [:error (char 0) (char 1) (char 127) (char 32767) :error :error :error :error]]
  102 + [unchecked-char [(char 65535) (char 0) (char 1) (char 127) (char 32767) (char 65535) (char 65535) (char 65535) (char 65535)]]
  103 + [byte [-1 0 1 Byte/MAX_VALUE :error :error :error :error :error]]
  104 + [unchecked-byte [-1 0 1 Byte/MAX_VALUE -1 -1 -1 -1 -1]]
  105 + [short [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE :error :error :error :error]]
  106 + [unchecked-short [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE -1 -1 -1 -1]]
  107 + [int [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE Integer/MAX_VALUE :error :error :error]]
  108 + [unchecked-int [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE Integer/MAX_VALUE -1 Integer/MAX_VALUE Integer/MAX_VALUE]]
  109 + [long [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE Integer/MAX_VALUE Long/MAX_VALUE Long/MAX_VALUE Long/MAX_VALUE]]
  110 + [unchecked-long [-1 0 1 Byte/MAX_VALUE Short/MAX_VALUE Integer/MAX_VALUE Long/MAX_VALUE Long/MAX_VALUE Long/MAX_VALUE]]
  111 + ;; 2.14748365E9 if when float/double conversion is avoided...
  112 + [float [-1.0 0.0 1.0 127.0 32767.0 2.147483648E9 9.223372036854776E18 Float/MAX_VALUE :error]]
  113 + [unchecked-float [-1.0 0.0 1.0 127.0 32767.0 2.147483648E9 9.223372036854776E18 Float/MAX_VALUE Float/POSITIVE_INFINITY]]
  114 + [double [-1.0 0.0 1.0 127.0 32767.0 2.147483647E9 9.223372036854776E18 Float/MAX_VALUE Double/MAX_VALUE]]
  115 + [unchecked-double [-1.0 0.0 1.0 127.0 32767.0 2.147483647E9 9.223372036854776E18 Float/MAX_VALUE Double/MAX_VALUE]]])
  116 +
  117 +(deftest test-expected-casts
  118 + (let [[[_ inputs] & expectations] expected-casts]
  119 + (doseq [[f vals] expectations]
  120 + (let [wrapped (fn [x]
  121 + (try
  122 + (f x)
  123 + (catch IllegalArgumentException e :error)))]
  124 + (is (= vals (map wrapped inputs)))))))
  125 +
40 126 ;; *** Functions ***
41 127
42 128 (defonce DELTA 1e-12)
@@ -394,3 +480,4 @@ Math/pow overflows to Infinity."
394 480 (is (== (numerator 1/2) 1))
395 481 (is (= (bigint (/ 100000000000000000000 3)) 33333333333333333333))
396 482 (is (= (long 10000000000000000000/3) 3333333333333333333)))
  483 +

0 comments on commit cbd789d

Please sign in to comment.
Something went wrong with that request. Please try again.