2 進から 16 進への変換関数

以下のサンプル・プログラムでは、bintohex および hextobin という 2 つの UDF を定義しています。これらは、一般的な 2 進と 16 進のデータ変換を行います。

/*
Copyright (c) 2007-2009 Netezza Corporation, an IBM Company
All rights reserved.

Functions bintohex and hextobin allow packing and unpacking of binary 
data into varchar fields.

This file must be placed in the /home/nz/osf/ directory.

create or replace function bintohex(varchar(16000)) returns 
varchar(32000)
language cpp parameter style npsgeneric
EXTERNAL CLASS NAME 'CBinToHex'
EXTERNAL HOST OBJECT '/home/nz/osf/hexbin.o_x86'
EXTERNAL SPU OBJECT '/home/nz/osf/hexbin.o_spu10';

create or replace function hextobin(varchar(32000)) returns 
varchar(16000)
language cpp parameter style npsgeneric
EXTERNAL CLASS NAME 'CHexToBin'
EXTERNAL HOST OBJECT '/home/nz/osf/hexbin.o_x86'
EXTERNAL SPU OBJECT '/home/nz/osf/hexbin.o_spu10';

(SIMPLE USAGE)
select bintohex(field) from a;
select bintohex('abcd') from a;

select hextobin(field) from b;
select hextobin('3A3B0F1141') from b;

(COMPLEX USAGE)
create table bintest (a varchar(100), b varchar(50));
insert into bintest values ('000102030405060708090A0B0C0D0E0F','');
update bintest set B = hextobin(A);
select bintohex(B) from bintest;

Note: select * from bintest will not properly display column B.
*/

#include "udxinc.h"
#include <string.h>

using namespace nz::udx;
class CHexToBin : public Udf
{
     char convert(char inp)
     {
        if (inp >= '0' && inp <= '9')
            return inp - '0';
        if (inp >= 'a' && inp <= 'f')
            return inp - 'a' + 10;
        if (inp >= 'A' && inp <= 'F')
            return inp - 'A' + 10;
        throwUdxException("Bad Hex");
        return 0;
     }

public:
     char *m_pBuf;
     CHexToBin()
       {
          m_pBuf = new char[16000];
       }
     ~CHexToBin()
       {
          delete m_pBuf;
       }
     static Udf* instantiate();
     virtual ReturnValue evaluate()
     {
       StringReturn* ret = stringReturnInfo();
       StringArg *input = stringArg(0);
       int numbytes = input->length / 2;

          if ((input->length%2) != 0)
            throwUdxException("Bad Hex (Dangling)");

          for (int i = 0; i < numbytes; i++)
            {
             char b1 = input->data[i*2];
             char b2 = input->data[i*2+1];
           m_pBuf[i] = convert(b1) * 16 + convert(b2);
          }
       ret->size = numbytes;
       memcpy(ret->data, m_pBuf, numbytes);

       NZ_UDX_RETURN_STRING(ret);
     }
};

Udf* CHexToBin::instantiate()
{
  return new CHexToBin;
}
class CBinToHex : public Udf
{
     char unconvert(char inp)
     {
        if (inp <= 9)
               return inp + '0';
        return inp + 'A' - 10;
     }

public:
     char *m_pBuf;
     CBinToHex()
       {
         m_pBuf = new char[32000];
       }
     ~CBinToHex()
       {
         delete m_pBuf;
       }
     static Udf* instantiate();
     virtual ReturnValue evaluate()
     {

       StringReturn* ret = stringReturnInfo();
       StringArg *input = stringArg(0);
       int numbytes = input->length * 2;
       for (int i=0; i < input->length; i++)
         {
           m_pBuf[i*2] = unconvert(((unsigned char)(input->data[i]) & 
0xF0) >> 4);

           m_pBuf[i*2+1] = unconvert((unsigned char)(input->data[i]) & 
0x0F);
         }
       ret->size = numbytes;
       memcpy(ret->data, m_pBuf, numbytes);

       NZ_UDX_RETURN_STRING(ret);
       }
};

Udf* CBinToHex::instantiate()
{
       return new CBinToHex;
}