IOFunctions.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012 SCHUNK GmbH & Co. KG
3  * Copyright (c) 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "IOFunctions.h"
19 #include <string.h>
20 
21 int util_ignore(int iSize, char cDelimiter, FILE* hFileHandle)
22 {
23  char cChar;
24  for(int i = 0; i < iSize; i++)
25  {
26  cChar = fgetc(hFileHandle);
27  if(cChar == EOF)
28  return -1;
29  if(cChar == cDelimiter)
30  return 0;
31  }
32  return 0;
33 }
34 
35 int util_skipWhiteSpace(FILE* hFileHandle)
36 {
37  char cChar;
38  do
39  {
40  cChar = fgetc(hFileHandle);
41  if(cChar == EOF)
42  return -1;
43  if(cChar != ' ' && cChar != '"' && cChar != '\t')
44  {
45  ungetc(cChar, hFileHandle);
46  return 0;
47  }
48  }while(1);
49  return 0;
50 }
51 
52 int util_getStringCutWhiteSpace(char* acReturnString, int iSize, FILE* hFileHandle)
53 {
54  char cChar;
55  fgets(acReturnString, iSize, hFileHandle);
56  for(int i = 0; i < iSize; i++)
57  {
58  cChar = acReturnString[i];
59  if(cChar == ' ' || cChar == '"' || cChar == '#' || cChar == ';' || cChar == '\t' || cChar == '\r' || cChar == '\n' || cChar == '\0')
60  {
61  acReturnString[i] = '\0';
62  break;
63  }
64  }
65  return 0;
66 }
67 
68 int util_searchSection(const char* acSectionName, FILE* hFileHandle)
69 {
70  int iRetVal = 1;
71  int iSectionLength;
72  char cChar;
73  char acBuffer[512];
74  iSectionLength = strlen(acSectionName);
75  do
76  {
77  cChar = fgetc(hFileHandle);
78  if(cChar == EOF) // check for end of file
79  iRetVal = -1;
80  else if(cChar == '#' || cChar == ';') // check for comment
81  {
82  iRetVal = util_ignore(0x7FFF,'\n', hFileHandle); // skip all characters up to '\n'
83  if(iRetVal == 0)
84  iRetVal = 1;
85  }
86  else if(cChar == '[') // no comment so parse it
87  {
88  fgets(acBuffer, iSectionLength+1, hFileHandle);
89 
90  if(strncmp(acBuffer, acSectionName, iSectionLength) == 0)
91  {
92  cChar = fgetc(hFileHandle);
93  if(cChar == ']')
94  iRetVal = util_ignore(0x7FFF,'\n', hFileHandle); // skip all characters up to '\n'
95  else
96  iRetVal = -1;
97  }
98  }
99  }
100  while(iRetVal > 0);
101  return iRetVal;
102 }
103 
104 int util_searchKey(const char* acKeyName, FILE* hFileHandle)
105 {
106  int iRetVal = 1;
107  int iKeyLength, iBufferLength;
108  char cChar;
109  char acBuffer[512];
110  iKeyLength = strlen(acKeyName);
111  do
112  {
113  cChar = fgetc(hFileHandle);
114  if(cChar == EOF) // check for end of file
115  iRetVal = -1;
116  else if(cChar == '[') // check for new section
117  {
118  ungetc(cChar, hFileHandle);
119  iRetVal = -1;
120  }
121  else if(cChar == '#' || cChar == ';') // check for comment
122  {
123  iRetVal = util_ignore(0x7FFF,'\n', hFileHandle); // skip all characters up to '\n'
124  if(iRetVal == 0)
125  iRetVal = 1;
126  }
127  else if(cChar != ' ' && cChar != '\t' && cChar != '\r' && cChar != '\n') // no comment or whitespace so parse it
128  {
129  acBuffer[0] = cChar;
130  if (iKeyLength > 1)
131  fgets(acBuffer + 1, iKeyLength, hFileHandle);
132 
133  iBufferLength = strlen(acBuffer);
134  if(iBufferLength > iKeyLength || (iBufferLength == iKeyLength && acBuffer[iBufferLength - 1] != '\n'))
135  {
136  if(strncmp(acBuffer, acKeyName, iKeyLength) == 0)
137  {
138  iRetVal = util_skipWhiteSpace(hFileHandle);
139  cChar = fgetc(hFileHandle);
140  if(cChar == '=') // check for delimiter
141  iRetVal = util_skipWhiteSpace(hFileHandle);
142  else
143  return -1;
144  }
145  else
146  {
147  iRetVal = util_ignore(0x7FFF,'\n', hFileHandle); // skip all characters up to '\n'
148  if(iRetVal == 0)
149  iRetVal = 1;
150  }
151  }
152  }
153  }
154  while(iRetVal > 0);
155  return iRetVal;
156 }
157 
158 int util_searchString(const char* acSectionName, const char* acKeyName, const char* acDefaultString, char* acReturnString, int iSize, const char* acFileName)
159 {
160  FILE* hFileHandle = fopen( acFileName, "r" );
161  if(hFileHandle <= 0)
162  {
163  strncpy(acReturnString, acDefaultString, iSize);
164  return -1;
165  }
166 
167  if(util_searchSection(acSectionName, hFileHandle) < 0)
168  {
169  strncpy(acReturnString, acDefaultString, iSize);
170  fclose(hFileHandle);
171  return 0;
172  }
173  if(util_searchKey(acKeyName, hFileHandle) < 0)
174  {
175  strncpy(acReturnString, acDefaultString, iSize);
176  fclose(hFileHandle);
177  return 0;
178  }
179  util_getStringCutWhiteSpace(acReturnString, iSize, hFileHandle);
180  fclose(hFileHandle);
181  return strlen(acReturnString);
182 }
183 
184 int util_setSection(const char* acSectionName, FILE* hFileHandle)
185 {
186  int iRetVal = fseek(hFileHandle,0,SEEK_CUR);
187  if(iRetVal < 0)
188  {
189 // std::cout << "Section set error" << std::endl;
190  return -1;
191  }
192  iRetVal = fprintf(hFileHandle, "\n\n[%s]", acSectionName);
193  if(iRetVal == strlen(acSectionName) + 4)
194  {
195 // std::cout << "Section set" << std::endl;
196  fseek(hFileHandle,0,SEEK_CUR);
197  return 0;
198  }
199  else
200  {
201 // std::cout << "Section set error" << std::endl;
202  return -1;
203  }
204 }
205 
206 int util_setKey(const char* acKeyName, FILE* hFileHandle)
207 {
208  int iRetVal = fseek(hFileHandle,0,SEEK_CUR);
209  if(iRetVal < 0)
210  {
211 // std::cout << "Section set error" << std::endl;
212  return -1;
213  }
214  iRetVal = fprintf(hFileHandle, "\n%s = ", acKeyName);
215  if(iRetVal == strlen(acKeyName) + 4)
216  {
217 // std::cout << "Key set" << std::endl;
218  fseek(hFileHandle,0,SEEK_CUR);
219  return 0;
220  }
221  else
222  {
223 // std::cout << "Key set error" << std::endl;
224  return -1;
225  }
226 }
227 
228 int util_setString(const char* acSectionName, const char* acKeyName, const char* acString, const char* acFileName)
229 {
230  int iRetVal = 0;
231  int iLength = 0;
232  char* acBuffer = NULL;
233  FILE* hFileHandle = fopen( acFileName, "r+" );
234  if(hFileHandle <= 0)
235  {
236  hFileHandle = fopen( acFileName, "w+" );
237  if(hFileHandle <= 0)
238  {
239 // std::cout << "File open error" << std::endl;
240  return -1;
241  }
242  }
243 // std::cout << "File open" << std::endl;
244  if(util_searchSection(acSectionName, hFileHandle) < 0)
245  {
246 // std::cout << "Section not found" << std::endl;
247  iRetVal = util_setSection(acSectionName, hFileHandle);
248  if(iRetVal < 0)
249  {
250  fclose(hFileHandle);
251  return -1;
252  }
253  }
254 // else
255 // std::cout << "Section found" << std::endl;
256  if(util_searchKey(acKeyName, hFileHandle) < 0)
257  {
258 // std::cout << "Key not found" << std::endl;
259  fpos_t fposRest;
260  iRetVal = fgetpos(hFileHandle, &fposRest);
261  if(iRetVal < 0)
262  {
263 // std::cout << "get Rest pos error" << std::endl;
264  fclose(hFileHandle);
265  return -1;
266  }
267  char cChar;
268  do
269  {
270 #if defined(__LINUX__)
271  fposRest.__pos--;
272 #else
273  fposRest--;
274 #endif
275  iRetVal = fsetpos(hFileHandle, &fposRest);
276  if(iRetVal < 0)
277  {
278 // std::cout << "set Rest pos error" << std::endl;
279  fclose(hFileHandle);
280  return -1;
281  }
282  cChar = fgetc(hFileHandle);
283  if(cChar != '\n')
284  {
285 #if defined(__LINUX__)
286  fposRest.__pos++;
287 #else
288  fposRest++;
289 #endif
290  iRetVal = fsetpos(hFileHandle, &fposRest);
291  if(iRetVal < 0)
292  {
293 // std::cout << "set Rest pos error" << std::endl;
294  fclose(hFileHandle);
295  return -1;
296  }
297  break;
298  }
299  }while(1);
300 
301  do
302  {
303  cChar = fgetc(hFileHandle);
304  if(cChar == EOF)
305  break;
306  }while(1);
307  fpos_t fposEnd;
308  iRetVal = fgetpos(hFileHandle, &fposEnd);
309  if(iRetVal < 0)
310  {
311 // std::cout << "get End pos error" << std::endl;
312  fclose(hFileHandle);
313  return -1;
314  }
315 #if defined(__LINUX__)
316  iLength = fposEnd.__pos - fposRest.__pos;
317 #else
318  iLength = fposEnd - fposRest;
319 #endif
320  if(iLength > 0)
321  {
322  acBuffer = new char[iLength];
323  // std::cout << "Rest length: " << iLength << std::endl;
324 
325  iRetVal = fsetpos(hFileHandle, &fposRest);
326  if(iRetVal < 0)
327  {
328  // std::cout << "set Rest pos error" << std::endl;
329  fclose(hFileHandle);
330  if(acBuffer != NULL)
331  delete[] acBuffer;
332  return -1;
333  }
334 
335  iLength = fread(acBuffer, sizeof(char), iLength, hFileHandle);
336  if(iLength < 0)
337  {
338  // std::cout << "read Rest error" << std::endl;
339  fclose(hFileHandle);
340  if(acBuffer != NULL)
341  delete[] acBuffer;
342  return -1;
343  }
344  acBuffer[iLength] = '\0';
345  }
346 // std::cout << "read Rest:" << acBuffer << std::endl;
347  iRetVal = fsetpos(hFileHandle, &fposRest);
348  if(iRetVal < 0)
349  {
350 // std::cout << "set String pos error" << std::endl;
351  fclose(hFileHandle);
352  if(acBuffer != NULL)
353  delete[] acBuffer;
354  return -1;
355  }
356  iRetVal = util_setKey(acKeyName, hFileHandle);
357  if(iRetVal < 0)
358  {
359  fclose(hFileHandle);
360  if(acBuffer != NULL)
361  delete[] acBuffer;
362  return -1;
363  }
364  iRetVal = fprintf(hFileHandle, "%s", acString);
365  if(iRetVal != strlen(acString))
366  {
367 // std::cout << "String set error" << std::endl;
368  fclose(hFileHandle);
369  if(acBuffer != NULL)
370  delete[] acBuffer;
371  return -1;
372  }
373 // else
374 // std::cout << "String set" << std::endl;
375  if(iLength > 0)
376  {
377  iLength = fwrite(acBuffer, sizeof(char), iLength, hFileHandle);
378  if(iLength != iLength)
379  {
380  // std::cout << "write Rest error" << std::endl;
381  fclose(hFileHandle);
382  if(acBuffer != NULL)
383  delete[] acBuffer;
384  return -1;
385  }
386  if(acBuffer != NULL)
387  delete[] acBuffer;
388  }
389  }
390  else
391  {
392 // std::cout << "Key found" << std::endl;
393  fpos_t fposString;
394  iRetVal = fgetpos(hFileHandle, &fposString);
395  if(iRetVal < 0)
396  {
397 // std::cout << "get String pos error" << std::endl;
398  fclose(hFileHandle);
399  return -1;
400  }
401 
402  char cChar;
403  int iErase = 0;
404  do
405  {
406  cChar = fgetc(hFileHandle);
407  if(cChar == EOF || cChar == '\n' || cChar == ';' || cChar == '#')
408  {
409  ungetc(cChar, hFileHandle);
410  break;
411  }
412  iErase++;
413  }while(1);
414  fpos_t fposRest;
415  iRetVal = fgetpos(hFileHandle, &fposRest);
416  if(iRetVal < 0)
417  {
418 // std::cout << "get Rest pos error" << std::endl;
419  fclose(hFileHandle);
420  return -1;
421  }
422 
423  do
424  {
425  cChar = fgetc(hFileHandle);
426  if(cChar == EOF)
427  break;
428  }while(1);
429  fpos_t fposEnd;
430  iRetVal = fgetpos(hFileHandle, &fposEnd);
431  if(iRetVal < 0)
432  {
433  std::cout << "get End pos error" << std::endl;
434  fclose(hFileHandle);
435  return -1;
436  }
437 #if defined(__LINUX__)
438  iLength = fposEnd.__pos - fposRest.__pos;
439 #else
440  iLength = fposEnd - fposRest;
441 #endif
442  if(iLength > 0)
443  {
444  acBuffer = new char[iLength];
445  // std::cout << "Rest length: " << iLength << std::endl;
446 
447  iRetVal = fsetpos(hFileHandle, &fposRest);
448  if(iRetVal < 0)
449  {
450  // std::cout << "set Rest pos error" << std::endl;
451  fclose(hFileHandle);
452  if(acBuffer != NULL)
453  delete[] acBuffer;
454  return -1;
455  }
456 
457  iLength = fread(acBuffer, sizeof(char), iLength, hFileHandle);
458  if(iLength < 0)
459  {
460  // std::cout << "read Rest error" << std::endl;
461  fclose(hFileHandle);
462  if(acBuffer != NULL)
463  delete[] acBuffer;
464  return -1;
465  }
466  acBuffer[iLength] = '\0';
467  }
468 // std::cout << "read Rest:" << acBuffer << std::endl;
469  iRetVal = fsetpos(hFileHandle, &fposString);
470  if(iRetVal < 0)
471  {
472 // std::cout << "set String pos error" << std::endl;
473  fclose(hFileHandle);
474  if(acBuffer != NULL)
475  delete[] acBuffer;
476  return -1;
477  }
478 
479  iRetVal = fprintf(hFileHandle, "%s ", acString);
480  iErase -= strlen(acString) + 1;
481  if(iRetVal != strlen(acString) + 1)
482  {
483 // std::cout << "String set error" << std::endl;
484  fclose(hFileHandle);
485  if(acBuffer != NULL)
486  delete[] acBuffer;
487  return -1;
488  }
489 // else
490 // std::cout << "String set" << std::endl;
491 
492  if(iLength > 0)
493  {
494  iLength = fwrite(acBuffer, sizeof(char), iLength, hFileHandle);
495  if(iLength != iLength)
496  {
497  // std::cout << "write Rest error" << std::endl;
498  fclose(hFileHandle);
499  if(acBuffer != NULL)
500  delete[] acBuffer;
501  return -1;
502  }
503  // std::cout << "erase " << iErase << std::endl;
504  for(int i = 0; i < iErase; i++)
505  {
506  cChar = fputc('\0', hFileHandle);
507  if(cChar == EOF)
508  break;
509  }
510  if(acBuffer != NULL)
511  delete[] acBuffer;
512  }
513  }
514  fclose(hFileHandle);
515  return 0;
516 }
517 
518 // -------------------------------------------------------------------------- ;
519 
520 //\fdd{ This function helps to read input formatted as keyword (or phrase),
521 // number (optional), delimiter, followed by an argument, which will be
522 // read by some other function. Leading white space and comments
523 // (everything from a '#' or ';' sign until the end of that line) will be
524 // skipped. The next std::string (including any white space) will be compared
525 // against the keyword. If this does not match the function returns
526 // imediately and indicates the error. If the number is positive
527 // (including zero) the next std::string after skipping white space will be
528 // read in as an integral number. If the numbers are not equal the
529 // function returns and indicates the error. Otherwise white space will
530 // be skipped and the next character will be compared with the delimiter.
531 // In case of mismatch the function returns an error code, otherwise it
532 // skips white space a last time. Now the stream should be positioned at
533 // the argument, which could be read by an adequate read function. }
534 //\xmp{ The following examples could be processed by this function:
535 // \begin{itemize}
536 // \item \verb|count of events = 5|
537 // \item \verb|item 001: first item|
538 // \item \verb|position = [ 12, 34 ]|
539 // \item \verb|circle:|\newline
540 // \verb|center = [ 43, 21]|\newline
541 // \verb|radius = 7|
542 // \end{itemize}
543 // In the last example \texttt{circle} is the keyword, no number is used
544 // and the delimiter is a colon. Therefore the corresponding call to this
545 // function would look as follows:\newline
546 // \begin{quote}
547 // \verb|error = posArgForKey(inL, "circle", -1, ':');|\newline
548 // \end{quote}
549 // This function will check for "circle" and the colon. Then it positions
550 // the stream just ahead of the std::string "center". Given a class
551 // \texttt{circle} with a method read able to process this format, we
552 // could just call:\newline
553 // \begin{quote}
554 // \verb|circle::read(inL);|\newline
555 // \end{quote}
556 // in order to read the circle from the input stream. }
557 //\arg{ in: a reference to an input stream }
558 //\arg{ key: the keyword (or phrase) to look for }
559 //\arg{ number: an optional number following the keyword }
560 //\arg{ delim: the sign preceeding the argument for the given keyword }
561 //\ret{ The constant \texttt{OKAY} indicates successful operation. In case of
562 // an error the following cases are distinguished:
563 // \begin{itemize}
564 // \item \texttt{NO\_KEY} the keyword did not match
565 // \item \texttt{KEY\_BUT\_WRONG\_NUMBER} the number did not match
566 // \item \texttt{KEY\_BUT\_NO\_EQUAL} the delimiter did not match
567 // \item \texttt{FOUND\_EOF} EOF reached
568 // \end{itemize}. }
569 
570 #ifdef WITHSTREAMS
571 int util_posArgForKey(
572  std::istream& in,
573  const char* key,
574  int number,
575  char delim)
576 {
577  static char buf[BUFFER_LENGTH];
578  char cL;
579  int count;
580 
581  while( !in.eof() )
582  {
583  in >> cL;
584 
585  if(cL == '#' || cL == ';') // check for comment
586  in.ignore(0x7FFF,'\n'); // skip all characters up to '\n'
587  else // no comment so parse it
588  {
589  buf[0] = cL;
590 
591  if (strlen(key) > 1) // Workaround for bug in WATCOM's std::istream::get
592  in.get(buf+1, strlen(key), '\n');
593 
594  if(strncmp(buf, key, strlen(key)) == 0)
595  {
596  if (number >= 0)
597  {
598  in >> count;
599 
600  if (count != number)
601  return KEY_BUT_WRONG_NUMBER;
602  };
603 
604  in >> std::ws; // skip whitespace
605  in >> cL;
606  if(cL == delim) // check for delimiter
607  {
608  // skip whitespace
609 
610  in >> std::ws;
611 
612  // the argument should follow now
613 
614  return OKAY;
615  }
616  else
617  return KEY_BUT_NO_EQUAL;
618  }
619  else
620  return NO_KEY;
621  };
622  };
623 
624  return FOUND_EOF;
625 };
626 
627 // -------------------------------------------------------------------------- ;
628 /* \fdd{Generates error messsages according to an error status for example generated
629 by posArgForKey(..)}
630 */
631 void util_parseError(
632  int status,
633  const char* key,
634  int number)
635 {
636  switch(status)
637  {
638  case OKAY:
639  break;
640  case KEY_BUT_NO_EQUAL:
641  std::cerr << "\nread(in) parse error : '=' expected behind";
642  std::cerr << key;
643  if (number >= 0)
644  std::cerr << " " << number;
645  std::cerr << " !";
646  break;
647  case NO_KEY:
648  std::cerr << "\nread(in) parse error : '";
649  std::cerr << key;
650  if (number >= 0)
651  std::cerr << " " << number;
652  std::cerr << "' expected !";
653  break;
654  case FOUND_EOF:
655  std::cerr << "\nread(in) parse error : premature EOF '";
656  std::cerr << key;
657  if (number >= 0)
658  std::cerr << " " << number;
659  std::cerr << "' expected !";
660  break;
661  case NO_OPEN_BRACKET:
662  std::cerr << "\nread(in) parse error : '[' expected before";
663  std::cerr << key;
664  if (number >= 0)
665  std::cerr << " " << number;
666  std::cerr << " argument !";
667  break;
668  case NO_SEPERATOR:
669  std::cerr << "\nread(in) parse error : ', ' expected ";
670  std::cerr << " between components of " << key;
671  if (number >= 0)
672  std::cerr << " " << number;
673  std::cerr << " argument !";
674  break;
675  case NO_CLOSED_BRACKET:
676  std::cerr << "\nread(in) parse error : ']' expected behind";
677  std::cerr << key;
678  if (number >= 0)
679  std::cerr << " " << number;
680  std::cerr << " argument !";
681  break;
682  default:
683  std::cerr << "\nread(in) : unknown error !?!?!?!?!?!?!?!?!";
684  break;
685  };
686 };
687 
688 // -------------------------------------------------------------------------- ;
689 /*
690 \fdd{combines posArgForKey(..) and parseError(..) to one function call.}
691 \arg{std::istream& inA}
692 \arg{const char* const keyA}
693 \arg{int numberA}
694 \arg{char delimA}
695 \ret{{\tt const int} is returned. If eof occured before anything else than
696  FOUND\_EOF is returned. If no key was found NO\_KEY is returned.
697  If a key was found but the wrong number followed KEY\_BUT\_WRONG\_NUMBER is returned.
698  If a key was found, the number was negativ and no equal sign followed KEY\_BUT\_NO\_EQUAL
699  is returned. }
700 */
701 void util_posArgForKeyWithCheck(
702  std::istream& in,
703  const char* key,
704  int number,
705  char delim )
706 {
707  int status;
708 
709  status = util_posArgForKey(in, key, number, delim);
710 
711  if(status != OKAY)
712  util_parseError(status, key);
713 };
714 
715 #endif
const int KEY_BUT_NO_EQUAL
Definition: IOFunctions.h:37
const int NO_CLOSED_BRACKET
Definition: IOFunctions.h:42
int util_getStringCutWhiteSpace(char *acReturnString, int iSize, FILE *hFileHandle)
Definition: IOFunctions.cpp:52
int util_skipWhiteSpace(FILE *hFileHandle)
Definition: IOFunctions.cpp:35
const int NO_SEPERATOR
Definition: IOFunctions.h:41
int util_searchKey(const char *acKeyName, FILE *hFileHandle)
const int FOUND_EOF
Definition: IOFunctions.h:39
const int KEY_BUT_WRONG_NUMBER
Definition: IOFunctions.h:43
int util_setString(const char *acSectionName, const char *acKeyName, const char *acString, const char *acFileName)
int util_searchSection(const char *acSectionName, FILE *hFileHandle)
Definition: IOFunctions.cpp:68
int util_searchString(const char *acSectionName, const char *acKeyName, const char *acDefaultString, char *acReturnString, int iSize, const char *acFileName)
int util_setSection(const char *acSectionName, FILE *hFileHandle)
const int OKAY
Definition: IOFunctions.h:36
int util_setKey(const char *acKeyName, FILE *hFileHandle)
const int BUFFER_LENGTH
Definition: IOFunctions.h:34
int util_ignore(int iSize, char cDelimiter, FILE *hFileHandle)
Definition: IOFunctions.cpp:21
const int NO_OPEN_BRACKET
Definition: IOFunctions.h:40
const int NO_KEY
Definition: IOFunctions.h:38


schunk_libm5api
Author(s): Florian Weisshardt
autogenerated on Mon Nov 25 2019 03:48:19