Xmipp  v3.23.11-Nereus
xmipp_strings.cpp
Go to the documentation of this file.
1 /**************************************************************************
2  *
3  * Authors: J.R. Bilbao-Castro (jrbcast@ace.ual.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <regex.h>
30 #include <stdarg.h>
31 #include "xmipp_strings.h"
32 #include "xmipp_error.h"
33 #include "xmipp_macros.h"
34 #include "gcc_version.h"
35 
36 String removeChar( const String& str, char character )
37 {
38  String temp;
39 
40  for( unsigned int i = 0 ; i < str.length( ) ; i++ )
41  {
42  if ( str[ i ] != character )
43  temp += str[ i ];
44  }
45 
46  return temp;
47 }
48 
49 String unescape( const String& str )
50 {
51  String temp;
52 
53  for( unsigned int i = 0 ; i < str.length( ) ; i++ )
54  {
55  char current_char = str[ i ];
56 
57  if( current_char != '\n' && current_char != '\t' &&
58  current_char != '\v' && current_char != '\b' &&
59  current_char != '\r' && current_char != '\f' &&
60  current_char != '\a' )
61  {
62  temp += str[ i ];
63  }
64  }
65 
66  return temp;
67 }
68 
69 String simplify( const String& str )
70 {
71  String temp;
72 
73  // First, unescape string
74  String straux = unescape( str );
75 
76  // Remove spaces from the beginning
77  int pos = straux.find_first_not_of( ' ' );
78  straux.erase( 0, pos );
79 
80  // Trim the rest of spaces
81  for( unsigned int i = 0 ; i < straux.length( ) ; )
82  {
83  temp += straux[ i ];
84 
85  if ( straux[ i ] == ' ' )
86  {
87  while( straux[ i ] == ' ' )
88  {
89  i++;
90  }
91  }
92  else
93  {
94  i++;
95  }
96  }
97 
98  // Remove space left at the end of the string
99  // if needed
100  if( temp[ temp.size( ) - 1 ] == ' ' )
101  {
102  temp.resize( temp.size() - 1 );
103  }
104 
105  return temp;
106 }
107 
108 /* Trim all spaces from the beginning and the end */
109 void trim(String& str)
110 {
111  String::size_type pos = str.find_last_not_of(' ');
112 
113  if (pos != String::npos)
114  {
115  str.erase(pos + 1);
116  pos = str.find_first_not_of(' ');
117  if (pos != String::npos)
118  str.erase(0, pos);
119  }
120  else
121  str.clear();
122 }
123 
124 float textToFloat(const char* str)
125 {
126  if (str == NULL)
127  REPORT_ERROR(ERR_MEM_NULLPOINTER, "Cannot be converted into float");
128 
129  float retval;
130  int ok = sscanf(str, "%f", &retval);
131 
132  if (ok)
133  return retval;
134  REPORT_ERROR(ERR_VALUE_INCORRECT, "Conversion to float error");
135 }
136 
137 int textToInteger(const char* str)
138 {
139  if (str == NULL)
140  REPORT_ERROR(ERR_MEM_NULLPOINTER, "Cannot be converted into int");
141 
142  int retval;
143  int ok = sscanf(str, "%d", &retval);
144 
145  if (ok)
146  return retval;
147  REPORT_ERROR(ERR_VALUE_INCORRECT, "Conversion to int error");
148 }
149 
150 size_t textToSizeT(const char * str)
151 {
152  if (str == NULL)
153  REPORT_ERROR(ERR_MEM_NULLPOINTER, "Cannot be converted into int");
154 
155  long unsigned int retval;
156  int ok = sscanf(str, "%lu", &retval);
157 
158  if (ok)
159  return retval;
160  REPORT_ERROR(ERR_VALUE_INCORRECT, "Conversion to size_t error");
161 }
162 
163 long long textToLongLong(const char* str)
164 {
165  if (str == NULL)
166  REPORT_ERROR(ERR_MEM_NULLPOINTER, "Cannot be converted into long long int");
167 
168  long long int retval;
169  int ok = sscanf(str, "%lld", &retval);
170 
171  if (ok)
172  return retval;
173  REPORT_ERROR(ERR_VALUE_INCORRECT, "Conversion to long long int error");
174 }
175 
176 int bestPrecision(float F, int _width)
177 {
178  // If it is 0
179  if (F == 0)
180  return 1;
181 
182  // Otherwise
183  int exp = FLOOR(log10(ABS(F)));
184  int advised_prec;
185 
186  if (exp >= 0)
187  if (exp > _width - 3)
188  advised_prec = -1;
189  else
190  advised_prec = _width - 2;
191  else
192  {
193  advised_prec = _width + (exp - 1) - 3;
194  if (advised_prec <= 0)
195  advised_prec = -1;
196  }
197 
198  if (advised_prec < 0)
199  advised_prec = -1; // Choose exponential format
200 
201  return advised_prec;
202 }
203 
204 String floatToString(float F, int _width, int _prec)
205 {
206 #if GCC_VERSION < 30300
207  char aux[15];
208  std::ostrstream outs(aux, sizeof(aux));
209 #else
210 
211  std::ostringstream outs;
212 #endif
213 
214  outs.fill(' ');
215 
216  if (_width != 0)
217  outs.width(_width);
218 
219  if (_prec == 0)
220  _prec = bestPrecision(F, _width);
221 
222  if (_prec == -1 && _width > 7)
223  {
224  outs.precision(_width - 7);
225  outs.setf(std::ios::scientific);
226  }
227  else
228  outs.precision(_prec);
229 
230 #if GCC_VERSION < 30301
231 
232  outs << F << std::ends;
233 #else
234 
235  outs << F;
236 #endif
237 
238 #if GCC_VERSION < 30300
239 
240  return String(aux);
241 #else
242 
243  String retval = outs.str();
244  int i = retval.find('\0');
245 
246  if (i != -1)
247  retval = retval.substr(0, i);
248 
249  return retval;
250 #endif
251 }
252 
253 String integerToString(int I, int _width, char fill_with)
254 {
255  char aux[15];
256 
257  // Check width
258  int width = _width;
259  int Iaux = ABS(I);
260 
261  if (SGN(I) < 0)
262  width--;
263 
264  if (width == 0)
265  do
266  {
267  Iaux /= 10;
268  width++;
269  }
270  while (Iaux != 0);
271 
272  // Fill the number with the fill character
273  for (int i = 0; i < width; i++)
274  aux[i] = fill_with;
275 
276  // Start filling the array
277  aux[width--] = '\0';
278  Iaux = ABS(I);
279  do
280  {
281  int digit = Iaux % 10;
282  Iaux /= 10;
283  aux[width--] = '0' + digit;
284  }
285  while (Iaux != 0);
286 
287  if (SGN(I) < 0)
288  return static_cast< String >("-") + aux;
289  else
290  return static_cast< String >(aux);
291 }
292 
293 int charToInt(const char* str)
294 {
295  if (str == NULL)
296  REPORT_ERROR(ERR_MEM_NULLPOINTER, "Cannot convert NULL into int");
297 
298  char readval;
299  int ok = sscanf(str, "%c", &readval);
300 
301  if (ok)
302  return readval - 48;
303  REPORT_ERROR(ERR_VALUE_INCORRECT, "Conversion to int error");
304 
305  return 0;
306 }
307 
308 String stringToString(const String& str, size_t _width)
309 {
310  if (_width == 0)
311  return str;
312 
313  if (_width < str.length())
314  return str.substr(0, _width);
315 
316  String aux = str;
317  return aux.append(_width - str.length(), ' ');
318 }
319 
320 void checkAngle(const String& str)
321 {
322  if (str == "rot")
323  return;
324 
325  if (str == "tilt")
326  return;
327 
328  if (str == "psi")
329  return;
330 
332  static_cast< String >(
333  "checkAngle: Not recognized angle type: " + str));
334 }
335 
337 {
338  String retval;
339  int first = _str.find_first_not_of("\n \t");
340  int last = _str.find_last_not_of("\n \t");
341  bool after_blank = false;
342 
343  for (int i = first; i <= last; i++)
344  {
345  if (_str[i] == ' ' || _str[i] == '\n' || _str[i] == '\t')
346  {
347  if (!after_blank)
348  retval += _str[i];
349 
350  after_blank = true;
351  }
352  else
353  {
354  retval += _str[i];
355  after_blank = false;
356  }
357  }
358 
359  return retval;
360 }
361 
362 // Remove quotes ===========================================================
363 void removeQuotes(char **_str)
364 {
365  String retval = *_str;
366  if (retval.length() == 0)
367  return;
368  char c = retval[0];
369  if (c == '\"' || c == '\'')
370  retval = retval.substr(1, retval.length() - 1);
371  c = retval[retval.length()-1];
372  if (c == '\"' || c == '\'')
373  retval = retval.substr(0, retval.length() - 1);
374  free(*_str);
375  *_str = strdup(retval.c_str());
376 }
377 
378 // Split a string ==========================================================
379 int splitString(const String& input,
380  const String& delimiter,
381  StringVector & results,
382  bool includeEmpties)
383 {
384  results.clear();
385  size_t delimiterSize = delimiter.size();
386  if (input.size()== 0 || delimiterSize == 0)
387  return 0;
388 
389  size_t newPos, iPos = 0;
390  String emptyString;
391  while ((newPos = input.find(delimiter, iPos))!=String::npos)
392  {
393  if (newPos==iPos)
394  {
395  if (includeEmpties)
396  results.push_back(emptyString);
397  }
398  else
399  results.push_back(input.substr(iPos, newPos-iPos));
400  iPos = newPos+delimiterSize;
401  }
402  if (iPos>=input.size())
403  {
404  if (includeEmpties)
405  results.push_back(emptyString);
406  }
407  else
408  results.push_back(input.substr(iPos, String::npos));
409  return results.size();
410 }
411 
412 // To lower ================================================================
413 void toLower(char *_str)
414 {
415  int i = 0;
416  while (_str[i] != '\0')
417  {
418  if (_str[i] >= 'A' && _str[i] <= 'Z')
419  _str[i] += 'a' -'A';
420  i++;
421  }
422 }
423 
424 void toLower(String &_str)
425 {
426  int i = 0;
427  while (_str[i] != '\0')
428  {
429  if (_str[i] >= 'A' && _str[i] <= 'Z')
430  _str[i] += 'a' -'A';
431  i++;
432  }
433 }
434 
435 // Next token ==============================================================
436 String nextToken(const String &str, size_t &i)
437 {
438  String retval;
439  if (i >= str.length())
440  return retval;
441  int j = str.find_first_not_of(" \t\n", i);
442  if (j == -1)
443  return retval;
444  int k = str.find_first_of(" \t\n", j + 1);
445  if (k == -1)
446  k = str.length();
447  retval = str.substr(j, k - j + 1);
448  i = k + 1;
449  return retval;
450 }
451 
452 // Get word ================================================================
453 char *firstWord(char *str)
454 {
455  char *token;
456 
457  // Get token
458  if (str != NULL)
459  token = firstToken(str);
460  else
461  token = nextToken();
462 
463  // Check that there is something
464  if (token == NULL)
465  REPORT_ERROR(ERR_VALUE_EMPTY, "Empty token");
466 
467  return token;
468 }
469 
470 // Tokenize a C++ string ===================================================
471 void tokenize(const String& str, StringVector& tokens,
472  const String& delimiters)
473 {
474  tokens.clear();
475  // Skip delimiters at beginning.
476  String::size_type lastPos = str.find_first_not_of(delimiters, 0);
477  // Find first "non-delimiter".
478  String::size_type pos = str.find_first_of(delimiters, lastPos);
479 
480  while (String::npos != pos || String::npos != lastPos)
481  {
482  // Found a token, add it to the vector.
483  tokens.push_back(str.substr(lastPos, pos - lastPos));
484  // Skip delimiters. Note the "not_of"
485  lastPos = str.find_first_not_of(delimiters, pos);
486  // Find next "non-delimiter"
487  pos = str.find_first_of(delimiters, lastPos);
488  }
489 }
490 
491 // Find and replace =======================================================
492 String findAndReplace(const String& tInput, const String &tFind,
493  const String &tReplace)
494 {
495  size_t uFindLen = tFind.length();
496 
497  if( uFindLen == 0 )
498  return tInput;
499 
500  size_t uPos = 0;
501  size_t uReplaceLen = tReplace.length();
502  String tOut=tInput;
503  for( ;(uPos = tOut.find(tFind, uPos)) != String::npos; )
504  {
505  tOut=tOut.replace( uPos, uFindLen, tReplace );
506  uPos += uReplaceLen;
507  }
508  return tOut;
509 }
510 
511 #include <stdio.h>
512 #include <stdlib.h>
513 #include <string.h>
514 
515 
516 
517 /* Tokenizer for char arrays. It does NOT modify
518  * the input array
519  * src is a pointer to the array beginning.
520  * It may be modified to trim the token
521  * _end is a pointer to the end of the token
522  * sep is an array with the valid separator
523  */
524 
525 char *memtok(char **src, char **_end, const char *sep)
526 {
527  char *start = *src;
528  char *end;
529 
530  /*
531  * Skip over leading delimiters.
532  */
533  start += strspn(start, sep);
534  if (*start == 0)
535  {
536  *src = start;
537  return (0);
538  }
539 
540  /*
541  * Separate off one token.
542  */
543  end = start + strcspn(start, sep);
544  *src = start;
545  *_end=end;
546  return (start);
547 }
548 
549 
550 #undef _memmem
551 
552 /* Return the first occurrence of NEEDLE in HAYSTACK. Taken from GNU C Library */
553 void * _memmem ( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
554 {
555  if (needle_len == 0)
556  /* The first occurrence of the empty string is deemed to occur at
557  the beginning of the string. */
558  return (void *) haystack;
559 
560  /* Sanity check, otherwise the loop might search through the whole
561  memory. */
562  if (haystack_len < needle_len)
563  return NULL;
564 
565  // memchr
566  const char *pNeedle=(const char *) needle;
567 #ifdef NEVERDEFINED
568  const char *const last_possible = (const char *) haystack + haystack_len - needle_len;
569  for (const char *begin = (const char *) haystack; begin <= last_possible; ++begin)
570  if (begin[0] == pNeedle[0] &&
571  !memcmp (begin+1, pNeedle + 1, needle_len - 1))
572  return (void *) begin;
573 #else
574  const char *begin=(const char *) haystack;
575  const char *current=begin;
576  size_t remaining=haystack_len-needle_len+1;
577  int firstChar=(int)pNeedle[0];
578  while (remaining>0)
579  {
580  const char *found=(const char *) memchr(current, firstChar, remaining);
581  if (found==NULL)
582  break;
583  else
584  {
585  if (memcmp(found+1, pNeedle + 1, needle_len - 1)==0)
586  return (void *)found;
587  else
588  {
589  remaining-=found-current+1;
590  current=found+1;
591  }
592  }
593  }
594 #endif
595 
596  return NULL;
597 }
598 
599 /* Obtain an string from a format in the way of printf works
600  *
601  */
602 String formatString(const char * format, ...)
603 {
604  char formatBuffer[1024];
605  va_list args;
606  va_start(args, format);
607  vsprintf (formatBuffer, format, args);
608  String result(formatBuffer);
609  va_end (args);
610 
611  return result;
612 }
613 
614 /* Obtain an string from a format in the way of printf works
615  *
616  */
617 void formatStringFast(String &str, const char * format, ...)
618 {
619  char formatBuffer[1024];
620 
621  va_list args;
622  va_start(args, format);
623  vsprintf (formatBuffer, format, args);
624  str=formatBuffer;
625  va_end (args);
626 }
627 
628 /* Matches regular expression */
629 bool matchRegExp(const String &inputString, const String &pattern)
630 {
631  // Construct regular expression
632  regex_t re;
633  if (regcomp(&re, pattern.c_str(), REG_EXTENDED|REG_NOSUB) != 0)
634  REPORT_ERROR(ERR_ARG_INCORRECT,(String)"Pattern cannot be parsed:"+pattern);
635 
636  // Check if the string matches the pattern
637  int status = regexec(&re, inputString.c_str(), (size_t) 0, NULL, 0);
638  regfree(&re);
639  if (status != 0)
640  return false;
641  return true;
642 }
643 #include <sstream>
644 
645 String WordWrap(const String &inputString, size_t lineLength)
646 {
647 
648  if(inputString.size() <= lineLength)
649  return ((String)"# " + inputString + "\n");
650  std::istringstream iss(inputString);
651  std::ostringstream ss;
652  std::string line;
653 
654  line.clear();
655  do
656  {
657  std::string word;
658  iss >> word;
659 
660  if (line.length() + word.length() > lineLength)
661  {
662  ss << "# " << line << std::endl;
663  line.clear();
664  }
665  line += word + " ";
666 
667  }
668  while (iss);
669 
670  if (!line.empty())
671  {
672  ss << "# " << line << std::endl;
673  }
674  return ss.str();
675 }
676 
678 {
679  String aux;
680  aux=findAndReplace(str,"+","\\+");
681  return aux;
682 }
683 
684 bool endsWith(const char* str1, const char* str2)
685 {
686  int len1 = strlen(str1);
687  int len2 = strlen(str2);
688  return (len1 >= len2) && (0 == strcmp(str1 + len1 - len2, str2));
689 }
Empty value.
Definition: xmipp_error.h:194
char * firstWord(char *str)
bool endsWith(const char *str1, const char *str2)
String removeSpaces(const String &_str)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void trim(String &str)
doublereal * c
Null pointer passed as parameter.
Definition: xmipp_error.h:168
String WordWrap(const String &inputString, size_t lineLength)
int bestPrecision(float F, int _width)
String integerToString(int I, int _width, char fill_with)
std::vector< String > StringVector
Definition: xmipp_strings.h:35
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
char * memtok(char **src, char **_end, const char *sep)
glob_log first
void * _memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
#define FLOOR(x)
Definition: xmipp_macros.h:240
void checkAngle(const String &str)
float textToFloat(const char *str)
int splitString(const String &input, const String &delimiter, StringVector &results, bool includeEmpties)
Incorrect argument received.
Definition: xmipp_error.h:113
String simplify(const String &str)
String findAndReplace(const String &tInput, const String &tFind, const String &tReplace)
void removeQuotes(char **_str)
String removeChar(const String &str, char character)
void tokenize(const String &str, StringVector &tokens, const String &delimiters)
#define ABS(x)
Definition: xmipp_macros.h:142
free((char *) ob)
long long textToLongLong(const char *str)
void log10(Image< double > &op)
String stringToString(const String &str, size_t _width)
#define j
String escapeForRegularExpressions(const String &str)
bool matchRegExp(const String &inputString, const String &pattern)
std::string String
Definition: xmipp_strings.h:34
String formatString(const char *format,...)
int textToInteger(const char *str)
char * firstToken(const char *str)
int charToInt(const char *str)
String unescape(const String &str)
void toLower(char *_str)
String floatToString(float F, int _width, int _prec)
String nextToken(const String &str, size_t &i)
Incorrect value received.
Definition: xmipp_error.h:195
#define SGN(x)
Definition: xmipp_macros.h:155
size_t textToSizeT(const char *str)
void formatStringFast(String &str, const char *format,...)