]> Creatis software - gdcm.git/blob - src/gdcmUtil.cxx
BUG: All va_start should be close by a va_end in the same function. Thanks to Dennis...
[gdcm.git] / src / gdcmUtil.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmUtil.cxx,v $
5   Language:  C++
6   Date:      $Date: 2004/11/14 00:53:10 $
7   Version:   $Revision: 1.62 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmUtil.h"
20 #include "gdcmDebug.h"
21
22 // For GetCurrentDate, GetCurrentTime
23 #include <time.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include <stdarg.h>  //only included in implementation file
28 #include <stdio.h>   //only included in implementation file
29
30 namespace gdcm 
31 {
32
33 /**
34  * \ingroup Globals
35  * \brief Provide a better 'c++' approach for sprintf
36  * For example c code is:
37  * sprintf(trash, "%04x|%04x", group , element);
38  *
39  * c++ is 
40  * std::ostringstream buf;
41  * buf << std::right << std::setw(4) << std::setfill('0') << std::hex
42  *     << group << "|" << std::right << std::setw(4) << std::setfill('0') 
43  *     << std::hex <<  element;
44  * buf.str();
45  */
46
47 std::string Util::Format(const char* format, ...)
48 {
49    char buffer[2048];
50    va_list args;
51    va_start(args, format);
52    vsprintf(buffer, format, args);  //might be a security flaw
53    va_end(args); // Each invocation of va_start should be matched 
54                  // by a corresponding invocation of va_end
55                  // args is then 'undefined'
56    return buffer;
57 }
58
59
60 /**
61  * \ingroup Globals
62  * \brief Because not available in C++ (?)
63  */
64 void Util::Tokenize (const std::string& str,
65                      std::vector<std::string>& tokens,
66                      const std::string& delimiters)
67 {
68    std::string::size_type lastPos = str.find_first_not_of(delimiters,0);
69    std::string::size_type pos     = str.find_first_of    (delimiters,lastPos);
70    while (std::string::npos != pos || std::string::npos != lastPos)
71    {
72       tokens.push_back(str.substr(lastPos, pos - lastPos));
73       lastPos = str.find_first_not_of(delimiters, pos);
74       pos     = str.find_first_of    (delimiters, lastPos);
75    }
76 }
77
78 /**
79  * \ingroup Globals
80  * \brief Because not available in C++ (?)
81  *        Counts the number of occurences of a substring within a string
82  */
83  
84 int Util::CountSubstring (const std::string& str,
85                           const std::string& subStr)
86 {
87    int count = 0;   // counts how many times it appears
88    unsigned int x = 0;       // The index position in the string
89
90    do
91    {
92       x = str.find(subStr,x);       // Find the substring
93       if (x != std::string::npos)   // If present
94       {
95          count++;                  // increase the count
96          x += subStr.length();     // Skip this word
97       }
98    }
99    while (x != std::string::npos);  // Carry on until not present
100
101    return count;
102 }
103
104 /**
105  * \ingroup Globals
106  * \brief  Weed out a string from the non-printable characters (in order
107  *         to avoid corrupting the terminal of invocation when printing)
108  * @param s string to remove non printable characters from
109  */
110 std::string Util::CreateCleanString(std::string const & s)
111 {
112    std::string str = s;
113
114    for(unsigned int i=0;i<str.size();i++)
115    {
116       if(!isprint(str[i]))
117       {
118          str[i]='.';
119       }
120    }
121
122    if(str.size()>0)
123    {
124       if(!isprint(s[str.size()-1]))
125       {
126          if(s[str.size()-1]==0)
127          {
128             str[str.size()-1]=' ';
129          }
130       }
131    }
132
133    return str;
134 }
135
136 /**
137  * \ingroup Globals
138  * \brief   Add a SEPARATOR to the end of the name is necessary
139  * @param name file/directory name to normalize 
140  */
141 std::string Util::NormalizePath(std::string const & pathname)
142 {
143    const char SEPARATOR_X      = '/';
144    const char SEPARATOR_WIN    = '\\';
145    const std::string SEPARATOR = "/";
146    std::string name = pathname;
147    int size = name.size();
148
149    if( name[size-1] != SEPARATOR_X && name[size-1] != SEPARATOR_WIN )
150    {
151       name += SEPARATOR;
152    }
153    return name;
154 }
155
156 /**
157  * \ingroup Globals
158  * \brief   Get the (directory) path from a full path file name
159  * @param   fullName file/directory name to extract Path from
160  */
161 std::string Util::GetPath(std::string const & fullName)
162 {
163    std::string res = fullName;
164    int pos1 = res.rfind("/");
165    int pos2 = res.rfind("\\");
166    if( pos1 > pos2)
167    {
168       res.resize(pos1);
169    }
170    else
171    {
172       res.resize(pos2);
173    }
174
175    return res;
176 }
177
178 /**
179  * \ingroup Util
180  * \brief   Get the (last) name of a full path file name
181  * @param   fullName file/directory name to extract end name from
182  */
183 std::string Util::GetName(std::string const & fullName)
184 {   
185   std::string filename = fullName;
186
187   std::string::size_type slash_pos = filename.rfind("/");
188   std::string::size_type backslash_pos = filename.rfind("\\");
189   slash_pos = slash_pos > backslash_pos ? slash_pos : backslash_pos;
190   if(slash_pos != std::string::npos)
191     {
192     return filename.substr(slash_pos + 1);
193     }
194   else
195     {
196     return filename;
197     }
198
199
200 /**
201  * \ingroup Util
202  * \brief Create a /DICOM/ string:
203  * It should a of even lenght (no odd length ever)
204  * It can contains as many \0 as you want.
205  * This function is similar to DicomString(const char*), 
206  * except it doesn't take a lenght. 
207  * It only pad with a null character if length is odd
208  */
209 std::string Util::DicomString(const char* s)
210 {
211    size_t l = strlen(s);
212    if( l%2 )
213    {
214       l++;
215    }
216    std::string r(s, s+l);
217    assert( !(r.size() % 2) );
218    return r;
219 }
220
221 /**
222  * \ingroup Util
223  * \brief   Get the current date of the system in a dicom string
224  */
225 std::string Util::GetCurrentDate()
226 {
227     char tmp[512];
228     time_t tloc;
229     time (&tloc);    
230     strftime(tmp,512,"%Y%m%d", localtime(&tloc) );
231     return tmp;
232 }
233
234 /**
235  * \ingroup Util
236  * \brief   Get the current time of the system in a dicom string
237  */
238 std::string Util::GetCurrentTime()
239 {
240     char tmp[512];
241     time_t tloc;
242     time (&tloc);
243     strftime(tmp,512,"%H%M%S", localtime(&tloc) );
244     return tmp;  
245 }
246
247 /**
248  * \ingroup Util
249  * \brief Create a /DICOM/ string:
250  * It should a of even length (no odd length ever)
251  * It can contains as many \0 as you want.
252  */
253 std::string Util::DicomString(const char* s, size_t l)
254 {
255    std::string r(s, s+l);
256    assert( !(r.size() % 2) );
257    return r;
258 }
259
260 template <class T>
261 std::ostream& binary_write(std::ostream& os, const T& val)
262 {
263     return os.write(reinterpret_cast<const char*>(&val), sizeof val);
264 }
265
266 std::ostream& binary_write(std::ostream& os, const uint16_t& val)
267 {
268 #ifdef GDCM_WORDS_BIGENDIAN
269     uint16_t swap;
270     swap = ((( val << 8 ) & 0x0ff00 ) | (( val >> 8 ) & 0x00ff ) );
271     return os.write(reinterpret_cast<const char*>(&swap), 2);
272 #else
273     return os.write(reinterpret_cast<const char*>(&val), 2);
274 #endif //GDCM_WORDS_BIGENDIAN
275 }
276
277 std::ostream& binary_write(std::ostream& os, const uint32_t& val)
278 {
279 #ifdef GDCM_WORDS_BIGENDIAN
280     uint32_t swap;
281     swap = ( ((val<<24) & 0xff000000) | ((val<<8)  & 0x00ff0000) | 
282              ((val>>8)  & 0x0000ff00) | ((val>>24) & 0x000000ff) );
283     return os.write(reinterpret_cast<const char*>(&swap), 4);
284 #else
285     return os.write(reinterpret_cast<const char*>(&val), 4);
286 #endif //GDCM_WORDS_BIGENDIAN
287 }
288
289 std::ostream& binary_write(std::ostream& os, const char* val)
290 {
291     return os.write(val, strlen(val));
292 }
293
294 std::ostream& binary_write(std::ostream& os, std::string const & val)
295 {
296     return os.write(val.c_str(), val.size());
297 }
298
299 } // end namespace gdcm
300