@@ -227,20 +227,6 @@ case class Bin(child: Expression)
227227 }
228228}
229229
230- object Hex {
231- val hexDigits = Array [Char ](
232- '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F'
233- ).map(_.toByte)
234-
235- // lookup table to translate '0' -> 0 ... 'F'/'f' -> 15
236- val unhexDigits = {
237- val array = Array .fill[Byte ](128 )(- 1 )
238- (0 to 9 ).foreach(i => array('0' + i) = i.toByte)
239- (0 to 5 ).foreach(i => array('A' + i) = (i + 10 ).toByte)
240- (0 to 5 ).foreach(i => array('a' + i) = (i + 10 ).toByte)
241- array
242- }
243- }
244230
245231/**
246232 * If the argument is an INT or binary, hex returns the number as a STRING in hexadecimal format.
@@ -272,18 +258,30 @@ case class Hex(child: Expression) extends UnaryExpression with Serializable {
272258 case LongType => hex(num.asInstanceOf [Long ])
273259 case IntegerType => hex(num.asInstanceOf [Integer ].toLong)
274260 case BinaryType => hex(num.asInstanceOf [Array [Byte ]])
275- case StringType => hex(num.asInstanceOf [UTF8String ].getBytes )
261+ case StringType => hex(num.asInstanceOf [UTF8String ])
276262 }
277263 }
278264 }
279265
280- private [this ] def hex (bytes : Array [Byte ]): UTF8String = {
281- val length = bytes.length
266+ /**
267+ * Converts every character in s to two hex digits.
268+ */
269+ private def hex (str : UTF8String ): UTF8String = {
270+ hex(str.getBytes)
271+ }
272+
273+ private def hex (bytes : Array [Byte ]): UTF8String = {
274+ doHex(bytes, bytes.length)
275+ }
276+
277+ private def doHex (bytes : Array [Byte ], length : Int ): UTF8String = {
282278 val value = new Array [Byte ](length * 2 )
283279 var i = 0
284280 while (i < length) {
285- value(i * 2 ) = Hex .hexDigits((bytes(i) & 0xF0 ) >> 4 )
286- value(i * 2 + 1 ) = Hex .hexDigits(bytes(i) & 0x0F )
281+ value(i * 2 ) = Character .toUpperCase(Character .forDigit(
282+ (bytes(i) & 0xF0 ) >>> 4 , 16 )).toByte
283+ value(i * 2 + 1 ) = Character .toUpperCase(Character .forDigit(
284+ bytes(i) & 0x0F , 16 )).toByte
287285 i += 1
288286 }
289287 UTF8String .fromBytes(value)
@@ -296,64 +294,14 @@ case class Hex(child: Expression) extends UnaryExpression with Serializable {
296294 var len = 0
297295 do {
298296 len += 1
299- value(value.length - len) = Hex .hexDigits((numBuf & 0xF ).toInt)
297+ value(value.length - len) = Character .toUpperCase(Character
298+ .forDigit((numBuf & 0xF ).toInt, 16 )).toByte
300299 numBuf >>>= 4
301300 } while (numBuf != 0 )
302301 UTF8String .fromBytes(Arrays .copyOfRange(value, value.length - len, value.length))
303302 }
304303}
305304
306- /**
307- * Performs the inverse operation of HEX.
308- * Resulting characters are returned as a byte array.
309- */
310- case class Unhex (child : Expression )
311- extends UnaryExpression with ExpectsInputTypes with Serializable {
312-
313- override def nullable : Boolean = true
314- override def dataType : DataType = BinaryType
315- override def inputTypes : Seq [DataType ] = Seq (BinaryType )
316-
317- override def eval (input : InternalRow ): Any = {
318- val num = child.eval(input)
319- if (num == null ) {
320- null
321- } else {
322- unhex(num.asInstanceOf [UTF8String ].getBytes)
323- }
324- }
325-
326- private [this ] def unhex (bytes : Array [Byte ]): Array [Byte ] = {
327- val out = new Array [Byte ]((bytes.length + 1 ) >> 1 )
328- var i = 0
329- if ((bytes.length & 0x01 ) != 0 ) {
330- // padding with '0'
331- if (bytes(0 ) < 0 ) {
332- return null
333- }
334- val v = Hex .unhexDigits(bytes(0 ))
335- if (v == - 1 ) {
336- return null
337- }
338- out(0 ) = v
339- i += 1
340- }
341- // two characters form the hex value.
342- while (i < bytes.length) {
343- if (bytes(i) < 0 || bytes(i + 1 ) < 0 ) {
344- return null
345- }
346- val first = Hex .unhexDigits(bytes(i))
347- val second = Hex .unhexDigits(bytes(i + 1 ))
348- if (first == - 1 || second == - 1 ) {
349- return null
350- }
351- out(i / 2 ) = (((first << 4 ) | second) & 0xFF ).toByte
352- i += 2
353- }
354- out
355- }
356- }
357305
358306// //////////////////////////////////////////////////////////////////////////////////////////////////
359307// //////////////////////////////////////////////////////////////////////////////////////////////////
@@ -500,6 +448,58 @@ case class ShiftRight(left: Expression, right: Expression) extends BinaryExpress
500448 }
501449}
502450
451+ /**
452+ * Performs the inverse operation of HEX.
453+ * Resulting characters are returned as a byte array.
454+ */
455+ case class UnHex (child : Expression ) extends UnaryExpression with Serializable {
456+
457+ override def dataType : DataType = BinaryType
458+
459+ override def checkInputDataTypes (): TypeCheckResult = {
460+ if (child.dataType.isInstanceOf [StringType ] || child.dataType == NullType ) {
461+ TypeCheckResult .TypeCheckSuccess
462+ } else {
463+ TypeCheckResult .TypeCheckFailure (s " unHex accepts String type, not ${child.dataType}" )
464+ }
465+ }
466+
467+ override def eval (input : InternalRow ): Any = {
468+ val num = child.eval(input)
469+ if (num == null ) {
470+ null
471+ } else {
472+ unhex(num.asInstanceOf [UTF8String ].getBytes)
473+ }
474+ }
475+
476+ private val unhexDigits = {
477+ val array = Array .fill[Byte ](128 )(- 1 )
478+ (0 to 9 ).foreach(i => array('0' + i) = i.toByte)
479+ (0 to 5 ).foreach(i => array('A' + i) = (i + 10 ).toByte)
480+ (0 to 5 ).foreach(i => array('a' + i) = (i + 10 ).toByte)
481+ array
482+ }
483+
484+ private def unhex (inputBytes : Array [Byte ]): Array [Byte ] = {
485+ var bytes = inputBytes
486+ if ((bytes.length & 0x01 ) != 0 ) {
487+ bytes = '0' .toByte +: bytes
488+ }
489+ val out = new Array [Byte ](bytes.length >> 1 )
490+ // two characters form the hex value.
491+ var i = 0
492+ while (i < bytes.length) {
493+ val first = unhexDigits(bytes(i))
494+ val second = unhexDigits(bytes(i + 1 ))
495+ if (first == - 1 || second == - 1 ) { return null }
496+ out(i / 2 ) = (((first << 4 ) | second) & 0xFF ).toByte
497+ i += 2
498+ }
499+ out
500+ }
501+ }
502+
503503case class Hypot (left : Expression , right : Expression )
504504 extends BinaryMathExpression (math.hypot, " HYPOT" )
505505
0 commit comments