2 * NOTICE and LICENSE for Tecplot Input/Output Library (TecIO) - OpenFOAM
4 * Copyright (C) 1988-2009 Tecplot, Inc. All rights reserved worldwide.
6 * Tecplot hereby grants OpenCFD limited authority to distribute without
7 * alteration the source code to the Tecplot Input/Output library, known
8 * as TecIO, as part of its distribution of OpenFOAM and the
9 * OpenFOAM_to_Tecplot converter. Users of this converter are also hereby
10 * granted access to the TecIO source code, and may redistribute it for the
11 * purpose of maintaining the converter. However, no authority is granted
12 * to alter the TecIO source code in any form or manner.
14 * This limited grant of distribution does not supersede Tecplot, Inc.'s
15 * copyright in TecIO. Contact Tecplot, Inc. for further information.
18 * 3535 Factoria Blvd, Ste. 550
19 * Bellevue, WA 98006, USA
20 * Phone: +1 425 653 1200
21 * http://www.tecplot.com/
26 #define TECPLOTENGINEMODULE
29 ******************************************************************
30 ******************************************************************
32 ****** (C) 1988-2008 Tecplot, Inc. *******
34 ******************************************************************
35 ******************************************************************
41 #include "Q_UNICODE.h"
42 #if defined TECPLOTKERNEL
43 /* CORE SOURCE CODE REMOVED */
53 #include <cctype> // ...needed to find std::tolower and std::toupper
55 #include "TranslatedString.h"
56 #if defined TECPLOTKERNEL
57 /* CORE SOURCE CODE REMOVED */
61 using namespace tecplot::strutil
;
64 # pragma warning (disable : 4786) /* STL warning about trucated identifiers */
71 #define INITIAL_FORMAT_BUFFER_SIZE 16384*3
72 #if defined TECPLOTKERNEL
73 /* CORE SOURCE CODE REMOVED */
75 static char *FormatStringBuffer
= NULL
;
76 static int FormatStringBufferSize
= INITIAL_FORMAT_BUFFER_SIZE
;
78 #if defined TECPLOTKERNEL
79 /* CORE SOURCE CODE REMOVED */
85 #if defined TECPLOTKERNEL
86 /* CORE SOURCE CODE REMOVED */
90 * This should be one of the last functions called by Tecplot while mopping up.
92 void FormatStringBufferCleanup(void)
95 * NOTE: We use free instead of FREE_ARRAY for the scratch buffer because in
96 * debug mode FREE_ARRAY uses ErrMsg which uses vFormatString causing
99 if (FormatStringBuffer
!= NULL
)
100 free(FormatStringBuffer
);
101 FormatStringBuffer
= NULL
;
106 char *vFormatString(const char *Format
,
111 REQUIRE(VALID_REF(Format
));
113 #if defined TECPLOTKERNEL
114 /* CORE SOURCE CODE REMOVED */
118 * NOTE: We use malloc instead of ALLOC_ARRAY for the scratch buffer because
119 * in debug mode ALLOC_ARRAY uses ErrMsg which uses vFormatString
120 * causing infinite recursion.
122 if (FormatStringBuffer
== NULL
)
123 FormatStringBuffer
= (char *)malloc(FormatStringBufferSize
);
125 if (FormatStringBuffer
!= NULL
)
127 Boolean_t TryAgain
= FALSE
;
131 * Assign a value other than '\0' to the end of the buffer so that we
132 * can determine if the buffer needs to be expanded. If after we call
133 * vsnprintf the end of the buffer has a '\0' we need to expand it.
135 FormatStringBuffer
[FormatStringBufferSize
- 1] = (char)!'\0';
138 memset(FormatStringBuffer
, 0, FormatStringBufferSize
- 1);
141 _vsnprintf(FormatStringBuffer
,
142 FormatStringBufferSize
,
145 # elif defined IRIX62
146 vsprintf(FormatStringBuffer
,
149 CHECK(strlen(FormatStringBuffer
) < FormatStringBufferSize
);
151 vsnprintf(FormatStringBuffer
,
152 FormatStringBufferSize
,
158 TryAgain
= (FormatStringBuffer
[FormatStringBufferSize
- 1] == '\0');
163 * Reallocate the buffer and try again.
165 * NOTE: We use malloc/free instead of ALLOC/FREE_ARRAY for the
166 * scratch buffer because in debug mode ALLOC/FREE_ARRAY
167 * uses ErrMsg which uses vFormatString causing infinite
170 free(FormatStringBuffer
);
171 FormatStringBufferSize
+= MAX(1, FormatStringBufferSize
/ 2);
172 FormatStringBuffer
= (char *)malloc(FormatStringBufferSize
);
173 TryAgain
= (FormatStringBuffer
!= NULL
);
175 FormatStringBufferSize
= INITIAL_FORMAT_BUFFER_SIZE
;
180 if (FormatStringBuffer
!= NULL
)
181 Result
= DupString(dontTranslate(FormatStringBuffer
));
184 #if defined TECPLOTKERNEL
185 /* CORE SOURCE CODE REMOVED */
188 ENSURE(VALID_REF(Result
) || Result
== NULL
);
194 char *FormatString(TranslatedString Format
,
195 ...) /* 0 or more variable arguments */
197 REQUIRE(!Format
.isNull());
200 va_start(Arguments
, Format
);
201 char *Result
= vFormatString(Format
.c_str(), Arguments
);
204 ENSURE(VALID_REF(Result
) || Result
== NULL
);
210 int FormatString(string
& Buffer
,
211 TranslatedString Format
212 ...) /* 0 or more variable arguments */
214 REQUIRE(!Format
.isNull());
217 va_start(Arguments
, Format
);
218 char *FormattedString
= vFormatString(Format
.c_str(), Arguments
);
222 if (FormattedString
!= NULL
)
224 Buffer
.assign(FormattedString
);
225 Result
= (int)Buffer
.size();
226 FREE_ARRAY(FormattedString
, "FormattedString");
232 ENSURE(Result
== -1 || Result
>= 0);
237 * Returns a duplicate of the string or NULL if sufficient memory is not
240 * NOTE: This function was created because ResetString(...) does not
241 * duplicate zero length strings but returns NULL instead.
243 char *DupString(TranslatedString String
)
245 REQUIRE(VALID_TRANSLATED_STRING(String
));
247 char *Result
= ALLOC_ARRAY(strlen(String
.c_str()) + 1, char, "duplicate string");
249 strcpy(Result
, String
.c_str());
251 ENSURE(Result
== NULL
|| (VALID_REF(Result
) && strcmp(Result
, String
.c_str()) == 0));
257 * Copy up to 'Count' characters from the 'Source' string beginning at
258 * position 'Index' to the 'Target' string. The actual number of characters
259 * copied may be less than 'Count' if a '\0' was encountered in the
260 * 'Source' string before 'Count' characters were copied.
262 * NOTE: The 'Target' and 'Source' strings may overlap.
264 void CopySubString(char *Target
,
269 LgIndex_t Length
= 0;
271 REQUIRE(VALID_REF(Target
));
272 REQUIRE("Target string is sized to accommodate a string who's length "
273 "is at least MIN(strlen(&Source[Index]), Count) characters.");
274 REQUIRE(VALID_REF(Source
));
275 REQUIRE(0 <= Index
&& Index
<= (LgIndex_t
)strlen(Source
));
278 Length
= MIN((LgIndex_t
)strlen(&Source
[Index
]), Count
);
279 memmove(Target
, &Source
[Index
], Length
);
280 Target
[Length
] = '\0';
282 ENSURE(VALID_REF(Target
) && (LgIndex_t
)strlen(Target
) == Length
);
285 #if defined TECPLOTKERNEL
286 /* CORE SOURCE CODE REMOVED */
287 #endif /* TECPLOTKERNEL */
290 * Remove any leading white space from the string and return
291 * a reference to it. NOTE: The input string is modified.
293 char *StringFlushLeft(char *String
)
295 char *Result
= String
;
296 char *Start
= String
;
298 REQUIRE(VALID_REF(String
));
300 /* move the substring beginning at the first non-whitespace */
301 /* character to the head of the string */
302 while (isspace(*Start
))
305 memmove(String
, Start
, strlen(Start
) + 1);
307 ENSURE(VALID_REF(Result
) && Result
== String
);
313 * Remove any trailing white space from the string and return
314 * a reference to it. NOTE: The input string is modified.
316 static char *StringFlushRight(char *String
)
318 char *Result
= String
;
321 REQUIRE(VALID_REF(String
));
323 for (End
= EndOfString(String
); End
!= String
&& isspace(End
[-1]); End
--)
326 ENSURE(VALID_REF(Result
) && Result
== String
);
332 * Remove any leading and trailing white space from the string
333 * and return a reference to it. The return value is not
334 * absolutely necessary since the input string is modified
335 * but it is convenient sometimes.
336 * NOTE: The input string is modified but no memory is
337 * allocated nor deallocated.
339 char *TrimLeadAndTrailSpaces(char *String
)
341 REQUIRE((String
== NULL
) || VALID_REF(String
));
343 return (StringFlushLeft(StringFlushRight(String
)));
350 * If the specified string is longer than the maximum specified length
351 * truncate it and return a reference to it.
354 * String to truncate if necessary.
356 * Length at which to truncate the specified string if exceeded.
359 * Reference to the input string.
363 char *StringTruncate(char *String
,
366 REQUIRE(VALID_REF(String
));
367 REQUIRE(MaxLength
>= 0);
369 if ((LgIndex_t
)strlen(String
) > MaxLength
)
370 String
[MaxLength
] = '\0';/* UTF8_SetAt(String,'\0',MaxLength); */
372 ENSURE(VALID_REF(String
));
373 ENSURE((LgIndex_t
)strlen(String
) <= MaxLength
);
379 * Trim and truncate the specified string such that its trimmed length
380 * does not exceed the specified length and return a reference to it.
383 * String to trim and truncate if necessary.
385 * Length at which to truncate the trimmed string if exceeded.
388 * Reference to the input string.
390 char *StringTrimAndTruncate(char *String
,
393 REQUIRE(VALID_REF(String
));
394 REQUIRE(MaxLength
>= 0);
396 TrimLeadAndTrailSpaces(String
);
397 StringTruncate(String
, MaxLength
);
399 ENSURE(VALID_REF(String
));
400 ENSURE((LgIndex_t
)strlen(String
) <= MaxLength
);
408 StringList_pa
LineBreakString(const char *String
,
411 REQUIRE(VALID_REF(String
));
413 StringList_pa Result
= StringListAlloc();
416 Boolean_t IsOk
= TRUE
;
417 if (strlen(String
) > WrapMargin
)
419 char *StringCopy
= DupString(dontTranslate(String
));
420 IsOk
= (StringCopy
!= NULL
);
423 char *CPtr
= StringCopy
;
424 char *SubString
= StringCopy
;
425 UInt32_t SubStringLen
= 0;
426 while (*CPtr
!= '\0' && IsOk
)
428 while (*CPtr
!= '\0' && SubStringLen
< WrapMargin
)
430 /* look for a hard break */
433 *CPtr
= '\0'; /* replace the newline */
443 * If we didn't find a hard break or the end of the string
444 * then we need to back up and find the closest space.
446 if (*CPtr
!= '\0' && SubStringLen
== WrapMargin
)
448 /* find the closes space from the right */
451 while (CPtr
!= SubString
&& *CPtr
!= ' ')
456 * Bummer, this line will exceed the wrap margin.
457 * Search forward for the next space or newline.
459 while (*CPtr
!= '\0' && *CPtr
!= ' ' && *CPtr
!= '\n')
461 while (*CPtr
!= '\0' && *CPtr
== ' ')
462 CPtr
++; /* skip over the white space */
471 StringFlushRight(SubString
);
474 IsOk
= StringListAppendString(Result
, SubString
);
479 FREE_ARRAY(StringCopy
, "StringCopy");
483 IsOk
= StringListAppendString(Result
, String
);
486 StringListDealloc(&Result
);
489 ENSURE(Result
== NULL
|| VALID_REF(Result
));
495 #if defined TECPLOTKERNEL
496 /* CORE SOURCE CODE REMOVED */
497 #endif /* TECPLOTKERNEL */
501 * Lexicographically compares, at most, the first 'Len' characters of
505 * First string or NULL.
507 * Second string or NULL.
509 * Maximum number of characters to compare.
511 * Integer value greater than, equal to, or less than zero according
512 * to whether the first 'Len' characters of 's1' are greater than,
513 * equal to, or less than 's2'.
517 int ustrncmp(const char *s1
,
521 REQUIRE((s1
== NULL
) || VALID_REF(s1
));
522 REQUIRE((s2
== NULL
) || VALID_REF(s2
));
530 if ((s1
== NULL
) && (s2
== NULL
))
540 while (*t1
&& *t2
&& (I
< Len
))
551 ((*t1
== '\0') && (*t2
== '\0')))
554 return CAPITAL(*t1
) - CAPITAL(*t2
);
561 * Lexicographically compares the characters of s1 and s2.
564 * First string or NULL.
566 * Second string or NULL.
568 * Integer value greater than, equal to, or less than zero according to
569 * whether the characters of 's1' are greater than, equal to, or less
572 int ustrcmp(const char *s1
,
575 REQUIRE((s1
== NULL
) || VALID_REF(s1
));
576 REQUIRE((s2
== NULL
) || VALID_REF(s2
));
578 return (ustrncmp(s1
, s2
, INT_MAX
));
583 #if defined TECPLOTKERNEL
584 /* CORE SOURCE CODE REMOVED */
585 #if !defined NO_ASSERTS && defined DEBUG_ALLOC
587 #endif /* TECPLOTKERNEL */
591 * The problem with passing file names for release builds is that
592 * the full path name is used (i.e., c:\user\craig\v7.5\tecplot\alloc.c)
597 #if !defined NO_ASSERTS
598 Boolean_t
InternalResetString(char **SBase
,
599 const char *NewString
,
600 Boolean_t IssueErrMsg
,
601 const char *FileName
,
604 Boolean_t
InternalResetString(char **SBase
,
605 const char *NewString
,
606 Boolean_t IssueErrMsg
)
609 REQUIRE(VALID_REF(SBase
));
610 REQUIRE(*SBase
== NULL
|| VALID_REF(*SBase
));
611 REQUIRE(NewString
== NULL
|| VALID_REF(NewString
));
612 REQUIRE(IMPLICATION(VALID_REF(*SBase
), *SBase
!= NewString
)); /* Prevent calling with same string. */
613 REQUIRE(VALID_BOOLEAN(IssueErrMsg
));
614 REQUIRE(VALID_NON_ZERO_LEN_STR(FileName
));
615 REQUIRE(LineNumber
>= 1);
619 #if !defined NO_ASSERTS && defined DEBUG_ALLOC
621 MakeDebugRecord(FileName
, LineNumber
, "releasing", *SBase
, S
, 80);
622 FREE_ARRAY(*SBase
, S
);
624 FREE_ARRAY(*SBase
, "");
627 if (NewString
== NULL
)
634 #if !defined NO_ASSERTS && defined DEBUG_ALLOC
636 MakeDebugRecord(FileName
, LineNumber
, "duplicating", NewString
, S
, 80);
637 *SBase
= ALLOC_ARRAY(strlen(NewString
) + 1, char, S
);
639 # if defined MSWIN && defined _DEBUG && !defined(MAKEARCHIVE) && !defined(NO_ASSERTS)
640 /* Allow the MFC memory leak detection to report the leak at the
641 * calling programs location, and not here (which is fairly useless).
642 * But first, we have to turn off the preprocessor definition of new
643 * and get to the original. */
645 *SBase
= new(FileName
, LineNumber
) char[strlen(NewString
)+1];
646 # define new DEBUG_NEW
648 *SBase
= ALLOC_ARRAY(strlen(NewString
) + 1, char, "");
653 strcpy(*SBase
, NewString
);
659 ErrMsg(translate("Out of memory"));
666 #if defined TECPLOTKERNEL
667 /* CORE SOURCE CODE REMOVED */
673 * Unfortunately, this routine uses the interface of DeleteStringToAdd
674 * forcing StringToAdd to be non-const. Another copy of this routine
675 * for const char *'s is below. Eventually we should get rid of
676 * the two routines and DeleteStringToAdd, always using the const version
677 * and deleting the string if necessary in the code that calls TackOnString.
679 Boolean_t
TackOnString(char **SBase
,
680 const char *StringToAdd
,
681 Boolean_t DeleteStringToAdd
,
682 Boolean_t ConvertNewlinesToAscii
)
688 const char *CPtr
= StringToAdd
;
689 Boolean_t IsOk
= TRUE
;
691 REQUIRE(VALID_REF(SBase
));
692 REQUIRE((StringToAdd
== NULL
) || VALID_REF(StringToAdd
));
693 REQUIRE(VALID_BOOLEAN(DeleteStringToAdd
));
694 REQUIRE(VALID_BOOLEAN(ConvertNewlinesToAscii
));
696 if ((StringToAdd
== NULL
) ||
697 (*StringToAdd
== '\0'))
700 (*StringToAdd
== '\0') &&
703 char *TMP
= (char *)StringToAdd
;
704 FREE_ARRAY(TMP
, "empty string to add");
713 CurLen
= strlen(*SBase
);
719 NewLen
= CurLen
+ strlen(StringToAdd
) + 1 + NumNewlines
;
721 NewString
= ALLOC_ARRAY(NewLen
, char, StringToAdd
);
723 if (NewString
== NULL
)
725 if (DeleteStringToAdd
)
727 char *TMP
= (char *)StringToAdd
;
728 FREE_ARRAY(TMP
, StringToAdd
);
736 strcpy(NewString
, *SBase
);
737 FREE_ARRAY(*SBase
, (CurLen
> 0 ? *SBase
: "previous text"));
743 char *NPtr
= EndOfString(NewString
);
744 const char *APtr
= StringToAdd
;
747 if ((*APtr
== '\n') && ConvertNewlinesToAscii
)
753 *NPtr
++ = *APtr
; //UTF8_AssignAndIncrement(&NPtr,(char**)&APtr,TRUE,FALSE); //*NPtr++ = *APtr;
759 if (DeleteStringToAdd
)
761 char *TMP
= (char *)StringToAdd
;
762 FREE_ARRAY(TMP
, StringToAdd
);
769 ENSURE(VALID_BOOLEAN(IsOk
));
775 * See TackOnString for discussion.
779 Boolean_t
TackOnConstString(char **SBase
,
780 const char *StringToAdd
,
781 Boolean_t ConvertNewlinesToAscii
)
787 const char *CPtr
= StringToAdd
;
788 Boolean_t IsOk
= TRUE
;
790 REQUIRE(VALID_REF(SBase
));
791 REQUIRE((StringToAdd
== NULL
) || VALID_REF(StringToAdd
));
792 REQUIRE(VALID_BOOLEAN(ConvertNewlinesToAscii
));
794 if ((StringToAdd
!= NULL
) &&
795 (*StringToAdd
!= '\0'))
800 CurLen
= strlen(*SBase
);
806 NewLen
= CurLen
+ strlen(StringToAdd
) + 1 + NumNewlines
;
808 NewString
= ALLOC_ARRAY(NewLen
, char, StringToAdd
);
810 if (NewString
== NULL
)
818 strcpy(NewString
, *SBase
);
819 FREE_ARRAY(*SBase
, (CurLen
> 0 ? *SBase
: "previous text"));
825 char *NPtr
= EndOfString(NewString
);
826 const char *APtr
= StringToAdd
;
829 if ((*APtr
== '\n') && ConvertNewlinesToAscii
)
835 *NPtr
++ = *APtr
; // UTF8_AssignAndIncrement(&NPtr,(char**)&APtr,TRUE,FALSE);
844 ENSURE(VALID_BOOLEAN(IsOk
));
850 Boolean_t
TackOnChar(char **SBase
,
853 REQUIRE(VALID_REF(SBase
));
859 return (TackOnString(SBase
, S
, FALSE
, FALSE
));
865 * Converts all one character new line characters in the allocated string
866 * to a two character "\n" sequence.
869 * String to scan and convert if necessary. Note that the string will
870 * be reallocated if any new line characters are discovered.
873 * TRUE if the request was successfull, FALSE otherwise.
877 Boolean_t
ReplaceNewlineWithBackslashN(char **String
)
880 LgIndex_t NewlineCount
;
884 REQUIRE(VALID_REF(String
));
885 REQUIRE(VALID_REF(*String
));
887 /* count how many new line character are present */
889 Length
= strlen(*String
);
890 for (I
= 0; I
< Length
; I
++)
891 if ((*String
)[I
] == '\n')
894 if (NewlineCount
!= 0)
896 /* allocate a new string and convert */
897 Replacement
= ALLOC_ARRAY(Length
+ NewlineCount
+ 1, char,
898 "replacement string");
899 if (Replacement
!= NULL
)
902 for (I
= J
= 0; I
< Length
+ 1; I
++, J
++)
904 if ((*String
)[I
] == '\n')
906 Replacement
[J
] = '\\';
908 Replacement
[J
] = 'n';
912 Replacement
[J
] = (*String
)[I
];
917 CHECK(I
== Length
+ 1);
918 CHECK(J
== Length
+ NewlineCount
+ 1);
921 /* release the old string and record the new one */
922 FREE_ARRAY(*String
, "original string");
923 *String
= Replacement
;
926 ENSURE(*String
== NULL
|| VALID_REF(*String
));
927 return (*String
!= NULL
);
930 #if defined TECPLOTKERNEL
931 /* CORE SOURCE CODE REMOVED */
932 #if defined TECPLOTKERNEL
933 #if !defined NO_ASSERTS
934 #endif /* !NO_ASSERTS */
935 #endif /*TECPLOTKERNEL*/