⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdcmutil.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      perror("in Get MAC Adress (internal) : sock");
      return -1;
   }
   memset(&parpreq, 0, sizeof(struct arpreq));
   psa = (struct sockaddr_in *) &parpreq.arp_pa;

   memset(psa, 0, sizeof(struct sockaddr_in));
   psa->sin_family = AF_INET;
   memcpy(&psa->sin_addr, *paddrs, sizeof(struct in_addr));

   status = ioctl(sock, SIOCGARP, &parpreq);
   if (status == -1 )
   {
      perror("in Get MAC Adress (internal) : SIOCGARP");
      return -1;
   }
   memcpy(addr, parpreq.arp_ha.sa_data, 6);

   return 0;
#else
#ifdef CMAKE_HAVE_NET_IF_H
   int       sd;
   struct ifreq    ifr, *ifrp;
   struct ifconf    ifc;
   char buf[1024];
   int      n, i;
   unsigned char    *a;
#if defined(AF_LINK) && (!defined(SIOCGIFHWADDR) && !defined(SIOCGENADDR))
   struct sockaddr_dl *sdlp;
#endif

//
// BSD 4.4 defines the size of an ifreq to be
// max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
// However, under earlier systems, sa_len isn't present, so the size is 
// just sizeof(struct ifreq)
// We should investigate the use of SIZEOF_ADDR_IFREQ
//
#ifdef HAVE_SA_LEN
   #ifndef max
      #define max(a,b) ((a) > (b) ? (a) : (b))
   #endif
   #define ifreq_size(i) max(sizeof(struct ifreq),\
        sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
#else
   #define ifreq_size(i) sizeof(struct ifreq)
#endif // HAVE_SA_LEN

   if ( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0 )
   {
      return -1;
   }
   memset(buf, 0, sizeof(buf));
   ifc.ifc_len = sizeof(buf);
   ifc.ifc_buf = buf;
   if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
   {
      close(sd);
      return -1;
   }
   n = ifc.ifc_len;
   for (i = 0; i < n; i+= ifreq_size(*ifrp) )
   {
      ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
      strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
#ifdef SIOCGIFHWADDR
      if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
         continue;
      a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
#else
#ifdef SIOCGENADDR
      // In theory this call should also work on Sun Solaris, but apparently
      // SIOCGENADDR is not implemented properly thus the call 
      // ioctl(sd, SIOCGENADDR, &ifr) always returns errno=2 
      // (No such file or directory)
      // Furthermore the DLAPI seems to require full root access
      if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
         continue;
      a = (unsigned char *) ifr.ifr_enaddr;
#else
#ifdef AF_LINK
      sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
      if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
         continue;
      a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
#else
      perror("in Get MAC Adress (internal) : No way to access hardware");
      close(sd);
      return -1;
#endif // AF_LINK
#endif // SIOCGENADDR
#endif // SIOCGIFHWADDR
      if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) continue;

      if (addr) 
      {
         memcpy(addr, a, 6);
         close(sd);
         return 0;
      }
   }
   close(sd);
#endif
   // Not implemented platforms (or no cable !)
   perror("in Get MAC Adress (internal) : There was a configuration problem (or no cable !) on your platform");
   memset(addr,0,6);
   return -1;
#endif //__sun
}

/**
 * \brief Mini function to return the last digit from a number express in base 256
 *        pre condition data contain an array of 6 unsigned char
 *        post condition carry contain the last digit
 */
inline int getlastdigit(unsigned char *data, unsigned int size = 6)
{
  int extended, carry = 0;
  for(unsigned int i=0;i<size;i++)
    {
    extended = (carry << 8) + data[i];
    data[i] = extended / 10;
    carry = extended % 10;
    }
  return carry;
}


size_t Util::EncodeBytes(char *out, const unsigned char *data, int size)
{
  bool zero = false;
  int res;
  std::string sres;
  unsigned char buffer[32];
  unsigned char *addr = buffer;
  memcpy(addr, data, size);
  while(!zero)
    {
    res = getlastdigit(addr, size);
    sres.insert(sres.begin(), '0' + res);
    zero = true;
    for(int i = 0; i < size; ++i)
      {
      zero = zero && (addr[i] == 0);
      }
    }

  //return sres;
  strcpy(out, sres.c_str()); //, sres.size() );
  return sres.size();
}


/**
 * \brief Encode the mac address on a fixed length string of 15 characters.
 * we save space this way.
 */
std::string Util::GetMACAddress()
{
   // This code is the result of a long internet search to find something
   // as compact as possible (not OS independant). We only have to separate
   // 3 OS: Win32, SunOS and 'real' POSIX
   // http://groups-beta.google.com/group/comp.unix.solaris/msg/ad36929d783d63be
   // http://bdn.borland.com/article/0,1410,26040,00.html
   unsigned char addr[6];

   int stat = GetMacAddrSys(addr);
   if (stat == 0)
   {
      // We need to convert a 6 digit number from base 256 to base 10, using integer
      // would requires a 48bits one. To avoid this we have to reimplement the div + modulo 
      // with string only
      bool zero = false;
      int res;
      std::string sres;
      while(!zero)
      {
         res = getlastdigit(addr);
         sres.insert(sres.begin(), '0' + res);
         zero = (addr[0] == 0) && (addr[1] == 0) && (addr[2] == 0) 
             && (addr[3] == 0) && (addr[4] == 0) && (addr[5] == 0);
      }

      return sres;
   }
   else
   {
      gdcmWarningMacro("Problem in finding the MAC Address");
      return "";
   }
}

/**
 * \brief Creates a new UID. As stipulated in the DICOM ref
 *        each time a DICOM image is created it should have 
 *        a unique identifier (URI)
 * @param root is the DICOM prefix assigned by IOS group
 */
std::string Util::CreateUniqueUID(const std::string &root)
{
#if defined(HAVE_UUIDCREATE) || defined(HAVE_UUID_GENERATE) || defined(HAVE_UUID_CREATE)
   const char * s = Util::CreateUniqueUID2(root);
   return s;
#else
   std::string prefix;
   std::string append;
   if ( root.empty() )
   {
      // gdcm UID prefix, as supplied by http://www.medicalconnections.co.uk
      assert( !RootUID.empty() );
      prefix = RootUID; 
   }
   else
   {
      prefix = root;
   }

   // A root was specified use it to forge our new UID:
   append += ".";
   //append += Util::GetMACAddress(); // to save CPU time
   if( !Util::GDCM_MAC_ADDRESS.empty() )
     {
     append += Util::GDCM_MAC_ADDRESS;
     append += ".";
     }
   append += Util::GetCurrentDateTime();

   //Also add a mini random number just in case:
   char tmp[10];
   int r = (int) (100.0*rand()/RAND_MAX);
   // Don't use Util::Format to accelerate the execution
   sprintf(tmp,"%02d", r);
   append += tmp;

   // If append is too long we need to rehash it
   if ( (prefix + append).size() > 64 )
   {
      gdcmErrorMacro( "Size of UID is too long." );
      // we need a hash function to truncate this number
      // if only md5 was cross platform
      // MD5(append);
   }

   return prefix + append;
#endif
}

/* return true on success */
bool Util::GenerateUUID(unsigned char *uuid_data)
{
#if defined(HAVE_UUID_GENERATE)
  uuid_t g;
  uuid_generate(g);
  memcpy(uuid_data, g, sizeof(uuid_t));
  return true;
#elif defined(HAVE_UUID_CREATE)
  uint32_t rv;
  uuid_t g;
  uuid_create(&g, &rv);
  if (rv != uuid_s_ok)
    return false;
  memcpy(uuid_data, &g, sizeof(uuid_t));
  return true;
#elif defined(HAVE_UUIDCREATE)
  if (FAILED(UuidCreate((UUID *)uuid_data)))
    {
    return false;
    }
  return true;
#else
  uuid_data = 0;
  return false;
#endif
}

const char * Util::CreateUniqueUID2(const std::string &root)
{
   static std::string Unique;
   std::string prefix;
   //std::string append;
   if ( root.empty() )
   {
      // gdcm UID prefix, as supplied by http://www.medicalconnections.co.uk
      assert( !RootUID.empty() );
      prefix = RootUID; 
   }
   else
   {
      prefix = root;
   }

  //Unique = GetRoot();
  Unique = prefix;
  // We choose here a value of 26 so that we can still have 37 bytes free to 
  // set the suffix part which is sufficient to store a 2^(128-8+1)-1 number
  if( Unique.empty() || Unique.size() > 62 ) // 62 is simply the highest possible limit
    {
    // I cannot go any further...
    return NULL;
    }
  unsigned char uuid[16];
  bool r = GenerateUUID(uuid);
  // This should only happen in some obscure cases. Since the creation of UUID failed
  // I should try to go any further and make sure the user's computer crash and burn
  // right away
  if( !r ) return 0;
  char randbytesbuf[64];
  size_t len = Util::EncodeBytes(randbytesbuf, uuid, sizeof(uuid));
  assert( len < 64 ); // programmer error
  Unique += "."; // This dot is compulsary to separate root from suffix
  if( Unique.size() + len > 64 )
    {
    int idx = 0;
    bool found = false;
    std::bitset<8> x;
    while( !found && idx < 16 ) /* 16 is insane ... oh well */
      {
      // too bad ! randbytesbuf is too long, let's try to truncate the high bits a little
      x = uuid[idx];
      unsigned int i = 0;
      while( ( Unique.size() + len > 64 ) && i < 8 )
        {
        x[7-i] = 0;
        uuid[idx] = x.to_ulong();
        len = Util::EncodeBytes(randbytesbuf, uuid, sizeof(uuid));
        ++i;
        }
      if( ( Unique.size() + len > 64 ) && i == 8 ) 
        {
        // too bad only reducing the 8 bits from uuid[idx] was not enought,
        // let's set to zero the following bits...
        idx++;
        }
      else
        {
        // cool we found enough to stop
        found = true;
        }
      }
    if( !found )
      {
      // Technically this could only happen when root has a length >= 64 ... is it
      // even remotely possible ?
      gdcmWarningMacro( "Root is too long for current implementation" );
      return NULL;
      }
    }
  // can now safely use randbytesbuf as is, no need to truncate any more:
  Unique += randbytesbuf;

  assert( Util::IsValid( Unique.c_str() ) );

  return Unique.c_str();
}

void Util::SetRootUID(const std::string &root)
{
   if ( root.empty() )
      RootUID = GDCM_UID;
   else
      RootUID = root;
}

const std::string &Util::GetRootUID()
{
   return RootUID;
}

bool Util::IsValid(const char *uid_)
{
  /*
  9.1 UID ENCODING RULES
  The DICOM UID encoding rules are defined as follows:
  - Each component of a UID is a number and shall consist of one or more digits. The first digit of
  each component shall not be zero unless the component is a single digit.
  Note: Registration authorities may distribute components with non-significant leading zeroes. The leading
  zeroes should be ignored when being encoded (ie. 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -