X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmUtil.cxx;h=224c9d5d84df101fb044e01bb41a54569d4bbf02;hb=1114315a33a78a25b6cc40dbc188e6d982f32204;hp=8825cb97d9f3cab91337203be6c3e79d7eaa2d12;hpb=cdddc2757271f571a876ff9f402af0114c00228c;p=gdcm.git diff --git a/src/gdcmUtil.cxx b/src/gdcmUtil.cxx index 8825cb97..224c9d5d 100644 --- a/src/gdcmUtil.cxx +++ b/src/gdcmUtil.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmUtil.cxx,v $ Language: C++ - Date: $Date: 2005/02/11 20:48:49 $ - Version: $Revision: 1.139 $ + Date: $Date: 2005/08/31 16:24:19 $ + Version: $Revision: 1.162 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -34,15 +34,18 @@ #include //only included in implementation file #include //only included in implementation file -#if defined(_MSC_VER) || defined(__MINGW32__) - #include // for gethostname and gethostbyname +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) + #include // for gethostname and gethostbyname and GetTickCount... +// I haven't find a way to determine wether we need to under GetCurrentTime or not... +// I think the best solution would simply to get rid of this problematic function +// and use a 'less' common name... +#if !defined(__BORLANDC__) || (__BORLANDC__ >= 0x0560) #undef GetCurrentTime +#endif #else -#ifndef __BORLANDC__ #include // for gethostname #include // for gethostbyname #endif -#endif // For GetMACAddress #ifdef _WIN32 @@ -92,13 +95,17 @@ namespace gdcm //------------------------------------------------------------------------- const std::string Util::GDCM_UID = "1.2.826.0.1.3680043.2.1143"; std::string Util::RootUID = GDCM_UID; +const uint16_t Util::FMIV = 0x0001; +uint8_t *Util::FileMetaInformationVersion = (uint8_t *)&FMIV; +std::string Util::GDCM_MAC_ADRESS = GetMACAddress(); //------------------------------------------------------------------------- // Public /** * \brief Provide a better 'c++' approach for sprintf * For example c code is: - * sprintf(trash, "%04x|%04x", group , elem); + * char result[200]; // hope 200 is enough + * sprintf(result, "%04x|%04x", group , elem); * * c++ code is * std::ostringstream buf; @@ -108,7 +115,8 @@ std::string Util::RootUID = GDCM_UID; * buf.str(); * * gdcm style code is - * Format("%04x|%04x", group , elem); + * string result; + * result = gdcm::Util::Format("%04x|%04x", group , elem); */ std::string Util::Format(const char *format, ...) { @@ -125,6 +133,10 @@ std::string Util::Format(const char *format, ...) /** * \brief Because not available in C++ (?) + * @param str string to check + * @param tokens std::vector to receive the tokenized substrings + * @param delimiters string containing the character delimitors + */ void Util::Tokenize (const std::string &str, std::vector &tokens, @@ -143,32 +155,70 @@ void Util::Tokenize (const std::string &str, /** * \brief Because not available in C++ (?) * Counts the number of occurences of a substring within a string + * @param str string to check + * @param subStr substring to count */ int Util::CountSubstring (const std::string &str, const std::string &subStr) { - int count = 0; // counts how many times it appears - std::string::size_type x = 0; // The index position in the string + int count = 0; // counts how many times it appears + std::string::size_type x = 0; // The index position in the string do { - x = str.find(subStr,x); // Find the substring - if (x != std::string::npos) // If present + x = str.find(subStr,x); // Find the substring + if (x != std::string::npos) // If present { - count++; // increase the count - x += subStr.length(); // Skip this word + count++; // increase the count + x += subStr.length(); // Skip this word } } - while (x != std::string::npos); // Carry on until not present + while (x != std::string::npos);// Carry on until not present return count; } +/** + * \brief Checks whether a 'string' is printable or not (in order + * to avoid corrupting the terminal of invocation when printing) + * @param s string to check + */ +bool Util::IsCleanString(std::string const &s) +{ + std::cout<< std::endl << s << std::endl; + for(unsigned int i=0; i 0) + if (str.size() > 0 ) { - if(!isprint((unsigned char)s[str.size()-1])) + if (!isprint((unsigned char)s[str.size()-1]) ) { - if(s[str.size()-1] == 0) + if (s[str.size()-1] == 0 ) { str[str.size()-1] = ' '; } @@ -196,6 +246,31 @@ std::string Util::CreateCleanString(std::string const &s) return str; } +/** + * \brief Weed out a string from the non-printable characters (in order + * to avoid corrupting the terminal of invocation when printing) + * @param s area to process (uint8_t is just for prototyping. feel free to cast) + * @param l area length to check + */ +std::string Util::CreateCleanString(uint8_t *s, int l) +{ + std::string str; + + for( int i=0; i pos2) + if ( pos1 > pos2 ) { res.resize(pos1); } @@ -247,7 +322,7 @@ std::string Util::GetName(std::string const &fullName) std::string::size_type slash_pos = filename.rfind("/"); std::string::size_type backslash_pos = filename.rfind("\\"); slash_pos = slash_pos > backslash_pos ? slash_pos : backslash_pos; - if(slash_pos != std::string::npos) + if (slash_pos != std::string::npos ) { return filename.substr(slash_pos + 1); } @@ -283,7 +358,7 @@ std::string Util::GetCurrentTime() /** * \brief Get both the date and time at the same time to avoid problem - * around midnight where two call could be before and after midnight + * around midnight where the two calls could be before and after midnight */ std::string Util::GetCurrentDateTime() { @@ -310,10 +385,11 @@ std::string Util::GetCurrentDateTime() strftime (tmp, sizeof (tmp), "%Y%m%d%H%M%S", ptm); // Add milliseconds - std::string r = tmp; - r += Format("%03ld", milliseconds); + // Don't use Util::Format to accelerate execution of code + char tmpAll[80]; + sprintf(tmpAll,"%s%03ld",tmp,milliseconds); - return r; + return tmpAll; } unsigned int Util::GetCurrentThreadID() @@ -321,18 +397,20 @@ unsigned int Util::GetCurrentThreadID() // FIXME the implementation is far from complete #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) return (unsigned int)GetCurrentThreadId(); -#endif +#else #ifdef __linux__ return 0; // Doesn't work on fedora, but is in the man page... //return (unsigned int)gettid(); -#endif +#else #ifdef __sun return (unsigned int)thr_self(); #else //default implementation return 0; -#endif +#endif // __sun +#endif // __linux__ +#endif // Win32 } unsigned int Util::GetCurrentProcessID() @@ -347,7 +425,7 @@ unsigned int Util::GetCurrentProcessID() } /** - * \brief tells us if the processor we are working with is BigEndian or not + * \brief tells us whether the processor we are working with is BigEndian or not */ bool Util::IsCurrentProcessorBigEndian() { @@ -362,7 +440,7 @@ bool Util::IsCurrentProcessorBigEndian() * \brief Create a /DICOM/ string: * It should a of even length (no odd length ever) * It can contain as many (if you are reading this from your - * editor the following character is is backslash followed by zero + * editor the following character is backslash followed by zero * that needed to be escaped with an extra backslash for doxygen) \\0 * as you want. */ @@ -377,7 +455,7 @@ std::string Util::DicomString(const char *s, size_t l) * \brief Create a /DICOM/ string: * It should a of even length (no odd length ever) * It can contain as many (if you are reading this from your - * editor the following character is is backslash followed by zero + * editor the following character is backslash followed by zero * that needed to be escaped with an extra backslash for doxygen) \\0 * as you want. * This function is similar to DicomString(const char*), @@ -387,7 +465,7 @@ std::string Util::DicomString(const char *s, size_t l) std::string Util::DicomString(const char *s) { size_t l = strlen(s); - if( l%2 ) + if ( l%2 ) { l++; } @@ -397,23 +475,58 @@ std::string Util::DicomString(const char *s) } /** - * \brief Safely compare two Dicom String: - * - Both string should be of even length + * \brief Safely check the equality of two Dicom String: + * - Both strings should be of even length * - We allow padding of even length string by either a null * character of a space */ bool Util::DicomStringEqual(const std::string &s1, const char *s2) { - // s2 is the string from the DICOM reference: 'MONOCHROME1' + // s2 is the string from the DICOM reference e.g. : 'MONOCHROME1' std::string s1_even = s1; //Never change input parameter std::string s2_even = DicomString( s2 ); - if( s1_even[s1_even.size()-1] == ' ') + if ( s1_even[s1_even.size()-1] == ' ' ) { s1_even[s1_even.size()-1] = '\0'; //replace space character by null } return s1_even == s2_even; } +/** + * \brief Safely compare two Dicom String: + * - Both strings should be of even length + * - We allow padding of even length string by either a null + * character of a space + */ +bool Util::CompareDicomString(const std::string &s1, const char *s2, int op) +{ + // s2 is the string from the DICOM reference e.g. : 'MONOCHROME1' + std::string s1_even = s1; //Never change input parameter + std::string s2_even = DicomString( s2 ); + if ( s1_even[s1_even.size()-1] == ' ' ) + { + s1_even[s1_even.size()-1] = '\0'; //replace space character by null + } + switch (op) + { + case GDCM_EQUAL : + return s1_even == s2_even; + case GDCM_DIFFERENT : + return s1_even != s2_even; + case GDCM_GREATER : + return s1_even > s2_even; + case GDCM_GREATEROREQUAL : + return s1_even >= s2_even; + case GDCM_LESS : + return s1_even < s2_even; + case GDCM_LESSOREQUAL : + return s1_even <= s2_even; + default : + gdcmDebugMacro(" Wrong operator : " << op); + return false; + } +} + #ifdef _WIN32 typedef BOOL(WINAPI * pSnmpExtensionInit) ( IN DWORD dwTimeZeroReference, @@ -438,13 +551,15 @@ bool Util::DicomStringEqual(const std::string &s1, const char *s2) #endif //_WIN32 /// \brief gets current M.A.C adress (for internal use only) +int GetMacAddrSys ( unsigned char *addr ); int GetMacAddrSys ( unsigned char *addr ) { #ifdef _WIN32 WSADATA WinsockData; - if (WSAStartup(MAKEWORD(2, 0), &WinsockData) != 0) + if ( (WSAStartup(MAKEWORD(2, 0), &WinsockData)) != 0 ) { - std::cerr << "This program requires Winsock 2.x!" << std::endl; + std::cerr << "in Get MAC Adress (internal) : This program requires Winsock 2.x!" + << std::endl; return -1; } @@ -538,7 +653,8 @@ int GetMacAddrSys ( unsigned char *addr ) && (varBind[1].value.asnValue.address.stream[4] == 0x00) ) { // Ignore all dial-up networking adapters - std::cerr << "Interface #" << j << " is a DUN adapter\n"; + std::cerr << "in Get MAC Adress (internal) : Interface #" + << j << " is a DUN adapter\n"; continue; } if ( (varBind[1].value.asnValue.address.stream[0] == 0x00) @@ -550,7 +666,8 @@ int GetMacAddrSys ( unsigned char *addr ) { // Ignore NULL addresses returned by other network // interfaces - std::cerr << "Interface #" << j << " is a NULL address\n"; + std::cerr << "in Get MAC Adress (internal) : Interface #" + << j << " is a NULL address\n"; continue; } memcpy( addr, varBind[1].value.asnValue.address.stream, 6); @@ -567,7 +684,7 @@ int GetMacAddrSys ( unsigned char *addr ) // implementation for POSIX system -#ifdef __sun +#if defined(CMAKE_HAVE_NET_IF_ARP_H) && defined(__sun) //The POSIX version is broken anyway on Solaris, plus would require full //root power struct arpreq parpreq; @@ -577,18 +694,18 @@ int GetMacAddrSys ( unsigned char *addr ) char **paddrs; int sock, status=0; - if(gethostname(hostname, MAXHOSTNAMELEN) != 0) + if (gethostname(hostname, MAXHOSTNAMELEN) != 0 ) { - perror("gethostname"); + perror("in Get MAC Adress (internal) : gethostname"); return -1; } phost = gethostbyname(hostname); paddrs = phost->h_addr_list; sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(sock == -1) + if (sock == -1 ) { - perror("sock"); + perror("in Get MAC Adress (internal) : sock"); return -1; } memset(&parpreq, 0, sizeof(struct arpreq)); @@ -599,9 +716,9 @@ int GetMacAddrSys ( unsigned char *addr ) memcpy(&psa->sin_addr, *paddrs, sizeof(struct in_addr)); status = ioctl(sock, SIOCGARP, &parpreq); - if(status == -1) + if (status == -1 ) { - perror("SIOCGARP"); + perror("in Get MAC Adress (internal) : SIOCGARP"); return -1; } memcpy(addr, parpreq.arp_ha.sa_data, 6); @@ -624,7 +741,7 @@ int GetMacAddrSys ( unsigned char *addr ) // 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 investiage the use of SIZEOF_ADDR_IFREQ +// We should investigate the use of SIZEOF_ADDR_IFREQ // #ifdef HAVE_SA_LEN #ifndef max @@ -636,7 +753,7 @@ int GetMacAddrSys ( unsigned char *addr ) #define ifreq_size(i) sizeof(struct ifreq) #endif // HAVE_SA_LEN - if( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0 ) + if ( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0 ) { return -1; } @@ -674,7 +791,7 @@ int GetMacAddrSys ( unsigned char *addr ) continue; a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; #else - perror("No way to access hardware"); + perror("in Get MAC Adress (internal) : No way to access hardware"); close(sd); return -1; #endif // AF_LINK @@ -692,7 +809,7 @@ int GetMacAddrSys ( unsigned char *addr ) close(sd); #endif // Not implemented platforms - perror("There was a configuration problem on your plateform"); + perror("in Get MAC Adress (internal) : There was a configuration problem on your plateform"); memset(addr,0,6); return -1; #endif //__sun @@ -741,7 +858,8 @@ std::string Util::GetMACAddress() { 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); + zero = (addr[0] == 0) && (addr[1] == 0) && (addr[2] == 0) + && (addr[3] == 0) && (addr[4] == 0) && (addr[5] == 0); } return sres; @@ -763,7 +881,7 @@ std::string Util::CreateUniqueUID(const std::string &root) { std::string prefix; std::string append; - if( root.empty() ) + if ( root.empty() ) { // gdcm UID prefix, as supplied by http://www.medicalconnections.co.uk prefix = RootUID; @@ -775,16 +893,20 @@ std::string Util::CreateUniqueUID(const std::string &root) // A root was specified use it to forge our new UID: append += "."; - append += Util::GetMACAddress(); + //append += Util::GetMACAddress(); // to save CPU time + append += Util::GDCM_MAC_ADRESS; append += "."; append += Util::GetCurrentDateTime(); //Also add a mini random number just in case: + char tmp[10]; int r = (int) (100.0*rand()/RAND_MAX); - append += Format("%02d", r); + // 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 ) + if ( (prefix + append).size() > 64 ) { gdcmErrorMacro( "Size of UID is too long." ); // we need a hash function to truncate this number @@ -797,7 +919,7 @@ std::string Util::CreateUniqueUID(const std::string &root) void Util::SetRootUID(const std::string &root) { - if( root.empty() ) + if ( root.empty() ) RootUID = GDCM_UID; else RootUID = root; @@ -818,7 +940,10 @@ std::ostream &binary_write(std::ostream &os, const uint16_t &val) { #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION) uint16_t swap; - swap = ((( val << 8 ) & 0xff00 ) | (( val >> 8 ) & 0x00ff ) ); + //swap = ((( val << 8 ) & 0xff00 ) | (( val >> 8 ) & 0x00ff ) ); + //save CPU time + swap = ( val << 8 | val >> 8 ); + return os.write(reinterpret_cast(&swap), 2); #else return os.write(reinterpret_cast(&val), 2); @@ -834,8 +959,11 @@ std::ostream &binary_write(std::ostream &os, const uint32_t &val) { #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION) uint32_t swap; - swap = ( ((val<<24) & 0xff000000) | ((val<<8) & 0x00ff0000) | - ((val>>8) & 0x0000ff00) | ((val>>24) & 0x000000ff) ); +// swap = ( ((val<<24) & 0xff000000) | ((val<<8) & 0x00ff0000) | +// ((val>>8) & 0x0000ff00) | ((val>>24) & 0x000000ff) ); +// save CPU time + swap = ( (val<<24) | ((val<<8) & 0x00ff0000) | + ((val>>8) & 0x0000ff00) | (val>>24) ); return os.write(reinterpret_cast(&swap), 4); #else return os.write(reinterpret_cast(&val), 4); @@ -865,7 +993,8 @@ std::ostream &binary_write(std::ostream &os, std::string const &val) /** * \brief binary_write binary_write * @param os ostream to write to - * @param val val + * @param val value + * @param len length of the 'value' to be written */ std::ostream &binary_write(std::ostream &os, const uint8_t *val, size_t len) { @@ -877,16 +1006,18 @@ std::ostream &binary_write(std::ostream &os, const uint8_t *val, size_t len) * \brief binary_write binary_write * @param os ostream to write to * @param val val + * @param len length of the 'value' to be written */ std::ostream &binary_write(std::ostream &os, const uint16_t *val, size_t len) { -// This is tricky since we are writting two bytes buffer. Be carefull with little endian -// vs big endian. Also this other trick is to allocate a small (efficient) buffer that store -// intermidiate result before writting it. +// This is tricky since we are writting two bytes buffer. +// Be carefull with little endian vs big endian. +// Also this other trick is to allocate a small (efficient) buffer that store +// intermediate result before writting it. #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION) const int BUFFER_SIZE = 4096; - uint16_t *buffer = new uint16_t[BUFFER_SIZE/2]; - uint16_t *binArea16 = (uint16_t*)val; + static char buffer[BUFFER_SIZE]; + uint16_t *binArea16 = (uint16_t*)val; //for the const // how many BUFFER_SIZE long pieces in binArea ? int nbPieces = len/BUFFER_SIZE; //(16 bits = 2 Bytes) @@ -894,26 +1025,26 @@ std::ostream &binary_write(std::ostream &os, const uint16_t *val, size_t len) for (int j=0;j> 8) | (binArea16[i] << 8); - uint16_t val16 = binArea16[i]; - buffer[i] = ((( val16 << 8 ) & 0xff00 ) | (( val16 >> 8 ) & 0x00ff ) ); + *pbuffer = *binArea16 >> 8 | *binArea16 << 8; + pbuffer++; + binArea16++; } - os.write ( (char*)buffer, BUFFER_SIZE ); - binArea16 += BUFFER_SIZE/2; + os.write ( buffer, BUFFER_SIZE ); } if ( remainingSize > 0) { + uint16_t *pbuffer = (uint16_t*)buffer; //reinitialize pbuffer for (int i = 0; i < remainingSize/2; i++) { - //buffer[i] = (binArea16[i] >> 8) | (binArea16[i] << 8); - uint16_t val16 = binArea16[i]; - buffer[i] = ((( val16 << 8 ) & 0xff00 ) | (( val16 >> 8 ) & 0x00ff ) ); + *pbuffer = *binArea16 >> 8 | *binArea16 << 8; + pbuffer++; + binArea16++; } - os.write ( (char*)buffer, remainingSize ); + os.write ( buffer, remainingSize ); } - delete[] buffer; return os; #else return os.write(reinterpret_cast(val), len); @@ -959,7 +1090,7 @@ std::string Util::GetIPAddress() char szHostName[HOST_NAME_MAX+1]; int r = gethostname(szHostName, HOST_NAME_MAX); - if( r == 0 ) + if ( r == 0 ) { // Get host adresses struct hostent *pHost = gethostbyname(szHostName); @@ -968,7 +1099,7 @@ std::string Util::GetIPAddress() { for( int j = 0; jh_length; j++ ) { - if( j > 0 ) str += "."; + if ( j > 0 ) str += "."; str += Util::Format("%u", (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);