]> Creatis software - gdcm.git/blob - src/gdcmUtil.cxx
ENH: Improve string manipulation. I now inforce the notion of 'DicomString'
[gdcm.git] / src / gdcmUtil.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmUtil.cxx,v $
5   Language:  C++
6   Date:      $Date: 2004/11/05 20:23:14 $
7   Version:   $Revision: 1.60 $
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 #include <stdarg.h>  //only included in implementation file
23 #include <stdio.h>   //only included in implementation file
24
25 namespace gdcm 
26 {
27
28 /**
29  * \ingroup Globals
30  * \brief Provide a better 'c++' approach for sprintf
31  * For example c code is:
32  * sprintf(trash, "%04x|%04x", group , element);
33  *
34  * c++ is 
35  * std::ostringstream buf;
36  * buf << std::right << std::setw(4) << std::setfill('0') << std::hex
37  *     << group << "|" << std::right << std::setw(4) << std::setfill('0') 
38  *     << std::hex <<  element;
39  * buf.str();
40  */
41
42 std::string Util::Format(const char* format, ...)
43 {
44    char buffer[2048];
45    va_list args;
46    va_start(args, format);
47    vsprintf(buffer, format, args);  //might be a security flaw
48    return buffer;
49 }
50
51
52 /**
53  * \ingroup Globals
54  * \brief Because not available in C++ (?)
55  */
56 void Util::Tokenize (const std::string& str,
57                      std::vector<std::string>& tokens,
58                      const std::string& delimiters)
59 {
60    std::string::size_type lastPos = str.find_first_not_of(delimiters,0);
61    std::string::size_type pos     = str.find_first_of    (delimiters,lastPos);
62    while (std::string::npos != pos || std::string::npos != lastPos)
63    {
64       tokens.push_back(str.substr(lastPos, pos - lastPos));
65       lastPos = str.find_first_not_of(delimiters, pos);
66       pos     = str.find_first_of    (delimiters, lastPos);
67    }
68 }
69
70 /**
71  * \ingroup Globals
72  * \brief Because not available in C++ (?)
73  *        Counts the number of occurences of a substring within a string
74  */
75  
76 int Util::CountSubstring (const std::string& str,
77                           const std::string& subStr)
78 {
79    int count = 0;   // counts how many times it appears
80    unsigned int x = 0;       // The index position in the string
81
82    do
83    {
84       x = str.find(subStr,x);       // Find the substring
85       if (x != std::string::npos)   // If present
86       {
87          count++;                  // increase the count
88          x += subStr.length();     // Skip this word
89       }
90    }
91    while (x != std::string::npos);  // Carry on until not present
92
93    return count;
94 }
95
96 /**
97  * \ingroup Globals
98  * \brief  Weed out a string from the non-printable characters (in order
99  *         to avoid corrupting the terminal of invocation when printing)
100  * @param s string to remove non printable characters from
101  */
102 std::string Util::CreateCleanString(std::string const & s)
103 {
104    std::string str = s;
105
106    for(unsigned int i=0;i<str.size();i++)
107    {
108       if(!isprint(str[i]))
109       {
110          str[i]='.';
111       }
112    }
113
114    if(str.size()>0)
115    {
116       if(!isprint(s[str.size()-1]))
117       {
118          if(s[str.size()-1]==0)
119          {
120             str[str.size()-1]=' ';
121          }
122       }
123    }
124
125    return str;
126 }
127
128 /**
129  * \ingroup Globals
130  * \brief   Add a SEPARATOR to the end of the name is necessary
131  * @param name file/directory name to normalize 
132  */
133 std::string Util::NormalizePath(std::string const & pathname)
134 {
135    const char SEPARATOR_X      = '/';
136    const char SEPARATOR_WIN    = '\\';
137    const std::string SEPARATOR = "/";
138    std::string name = pathname;
139    int size = name.size();
140
141    if( name[size-1] != SEPARATOR_X && name[size-1] != SEPARATOR_WIN )
142    {
143       name += SEPARATOR;
144    }
145    return name;
146 }
147
148 /**
149  * \ingroup Globals
150  * \brief   Get the (directory) path from a full path file name
151  * @param   fullName file/directory name to extract Path from
152  */
153 std::string Util::GetPath(std::string const & fullName)
154 {
155    std::string res = fullName;
156    int pos1 = res.rfind("/");
157    int pos2 = res.rfind("\\");
158    if( pos1 > pos2)
159    {
160       res.resize(pos1);
161    }
162    else
163    {
164       res.resize(pos2);
165    }
166
167    return res;
168 }
169
170 /**
171  * \ingroup Util
172  * \brief   Get the (last) name of a full path file name
173  * @param   fullName file/directory name to extract end name from
174  */
175 std::string Util::GetName(std::string const & fullName)
176 {   
177   std::string filename = fullName;
178
179   std::string::size_type slash_pos = filename.rfind("/");
180   std::string::size_type backslash_pos = filename.rfind("\\");
181   slash_pos = slash_pos > backslash_pos ? slash_pos : backslash_pos;
182   if(slash_pos != std::string::npos)
183     {
184     return filename.substr(slash_pos + 1);
185     }
186   else
187     {
188     return filename;
189     }
190
191
192 /**
193  * \ingroup Util
194  * \brief Create a /DICOM/ string:
195  * It should a of even lenght (no odd length ever)
196  * It can contains as many \0 as you want.
197  * This function is similar to DicomString(const char*), 
198  * except it doesn't take a lenght. 
199  * It only pad with a null character if length is odd
200  */
201 std::string Util::DicomString(const char* s)
202 {
203    size_t l = strlen(s);
204    if( l%2 )
205    {
206       l++;
207    }
208    std::string r(s, s+l);
209    assert( !(r.size() % 2) );
210    return r;
211 }
212
213 /**
214  * \ingroup Util
215  * \brief Create a /DICOM/ string:
216  * It should a of even length (no odd length ever)
217  * It can contains as many \0 as you want.
218  */
219 std::string Util::DicomString(const char* s, size_t l)
220 {
221    std::string r(s, s+l);
222    assert( !(r.size() % 2) );
223    return r;
224 }
225
226 template <class T>
227 std::ostream& binary_write(std::ostream& os, const T& val)
228 {
229     return os.write(reinterpret_cast<const char*>(&val), sizeof val);
230 }
231
232 std::ostream& binary_write(std::ostream& os, const uint16_t& val)
233 {
234 #ifdef GDCM_WORDS_BIGENDIAN
235     uint16_t swap;
236     swap = ((( val << 8 ) & 0x0ff00 ) | (( val >> 8 ) & 0x00ff ) );
237     return os.write(reinterpret_cast<const char*>(&swap), 2);
238 #else
239     return os.write(reinterpret_cast<const char*>(&val), 2);
240 #endif //GDCM_WORDS_BIGENDIAN
241 }
242
243 std::ostream& binary_write(std::ostream& os, const uint32_t& val)
244 {
245 #ifdef GDCM_WORDS_BIGENDIAN
246     uint32_t swap;
247     swap = ( ((val<<24) & 0xff000000) | ((val<<8)  & 0x00ff0000) | 
248              ((val>>8)  & 0x0000ff00) | ((val>>24) & 0x000000ff) );
249     return os.write(reinterpret_cast<const char*>(&swap), 4);
250 #else
251     return os.write(reinterpret_cast<const char*>(&val), 4);
252 #endif //GDCM_WORDS_BIGENDIAN
253 }
254
255 //template <>
256 std::ostream& binary_write(std::ostream& os, const char* val)
257 {
258     return os.write(val, strlen(val));
259 }
260
261 std::ostream& binary_write(std::ostream& os, std::string const & val)
262 {
263     return os.write(val.c_str(), val.size());
264 }
265
266
267 } // end namespace gdcm
268