foam to Tecplot360 converter
[OpenFOAM-1.6.x.git] / applications / utilities / postProcessing / dataConversion / foamToTecplot360 / tecio / tecsrc / strutil.cpp
blob9611722224db84ca7d0600cb9c52b007f35a2897
1 /*
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.
17 * Tecplot, Inc.
18 * 3535 Factoria Blvd, Ste. 550
19 * Bellevue, WA 98006, USA
20 * Phone: +1 425 653 1200
21 * http://www.tecplot.com/
24 #include "stdafx.h"
25 #include "MASTER.h"
26 #define TECPLOTENGINEMODULE
29 ******************************************************************
30 ******************************************************************
31 ******* ********
32 ****** (C) 1988-2008 Tecplot, Inc. *******
33 ******* ********
34 ******************************************************************
35 ******************************************************************
38 #define STRUTILMODULE
39 #include "GLOBAL.h"
40 #include "TASSERT.h"
41 #include "Q_UNICODE.h"
42 #if defined TECPLOTKERNEL
43 /* CORE SOURCE CODE REMOVED */
44 #endif
45 #include "ARRLIST.h"
46 #include "STRLIST.h"
47 #include "STRUTIL.h"
48 #include "ALLOC.h"
50 #include "Q_MSG.h"
52 #include <algorithm>
53 #include <cctype> // ...needed to find std::tolower and std::toupper
54 #include <limits.h>
55 #include "TranslatedString.h"
56 #if defined TECPLOTKERNEL
57 /* CORE SOURCE CODE REMOVED */
58 #endif
60 using namespace std;
61 using namespace tecplot::strutil;
63 #ifdef MSWIN
64 # pragma warning (disable : 4786) /* STL warning about trucated identifiers */
65 #endif
67 /* END HEADER */
69 /**
71 #define INITIAL_FORMAT_BUFFER_SIZE 16384*3
72 #if defined TECPLOTKERNEL
73 /* CORE SOURCE CODE REMOVED */
74 #endif
75 static char *FormatStringBuffer = NULL;
76 static int FormatStringBufferSize = INITIAL_FORMAT_BUFFER_SIZE;
78 #if defined TECPLOTKERNEL
79 /* CORE SOURCE CODE REMOVED */
80 #if defined MSWIN
81 #else
82 #endif /* !MSWIN */
83 #endif
85 #if defined TECPLOTKERNEL
86 /* CORE SOURCE CODE REMOVED */
87 #endif
89 /**
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
97 * infinite recursion.
99 if (FormatStringBuffer != NULL)
100 free(FormatStringBuffer);
101 FormatStringBuffer = NULL;
106 char *vFormatString(const char *Format,
107 va_list Arguments)
109 char *Result = NULL;
111 REQUIRE(VALID_REF(Format));
113 #if defined TECPLOTKERNEL
114 /* CORE SOURCE CODE REMOVED */
115 #endif
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';
137 # if defined MSWIN
138 memset(FormatStringBuffer, 0, FormatStringBufferSize - 1);
140 TryAgain =
141 _vsnprintf(FormatStringBuffer,
142 FormatStringBufferSize,
143 Format,
144 Arguments) == -1;
145 # elif defined IRIX62
146 vsprintf(FormatStringBuffer,
147 Format,
148 Arguments);
149 CHECK(strlen(FormatStringBuffer) < FormatStringBufferSize);
150 # else
151 vsnprintf(FormatStringBuffer,
152 FormatStringBufferSize,
153 Format,
154 Arguments);
155 # endif
157 #ifndef MSWIN
158 TryAgain = (FormatStringBuffer[FormatStringBufferSize - 1] == '\0');
159 #endif
160 if (TryAgain)
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
168 * recursion.
170 free(FormatStringBuffer);
171 FormatStringBufferSize += MAX(1, FormatStringBufferSize / 2);
172 FormatStringBuffer = (char *)malloc(FormatStringBufferSize);
173 TryAgain = (FormatStringBuffer != NULL);
174 if (!TryAgain)
175 FormatStringBufferSize = INITIAL_FORMAT_BUFFER_SIZE;
178 while (TryAgain);
180 if (FormatStringBuffer != NULL)
181 Result = DupString(dontTranslate(FormatStringBuffer));
184 #if defined TECPLOTKERNEL
185 /* CORE SOURCE CODE REMOVED */
186 #endif
188 ENSURE(VALID_REF(Result) || Result == NULL);
189 return Result;
194 char *FormatString(TranslatedString Format,
195 ...) /* 0 or more variable arguments */
197 REQUIRE(!Format.isNull());
199 va_list Arguments;
200 va_start(Arguments, Format);
201 char *Result = vFormatString(Format.c_str(), Arguments);
202 va_end(Arguments);
204 ENSURE(VALID_REF(Result) || Result == NULL);
205 return Result;
210 int FormatString(string& Buffer,
211 TranslatedString Format
212 ...) /* 0 or more variable arguments */
214 REQUIRE(!Format.isNull());
216 va_list Arguments;
217 va_start(Arguments, Format);
218 char *FormattedString = vFormatString(Format.c_str(), Arguments);
219 va_end(Arguments);
221 int Result;
222 if (FormattedString != NULL)
224 Buffer.assign(FormattedString);
225 Result = (int)Buffer.size();
226 FREE_ARRAY(FormattedString, "FormattedString");
228 else
229 Result = -1;
232 ENSURE(Result == -1 || Result >= 0);
233 return Result;
237 * Returns a duplicate of the string or NULL if sufficient memory is not
238 * available.
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");
248 if (Result != NULL)
249 strcpy(Result, String.c_str());
251 ENSURE(Result == NULL || (VALID_REF(Result) && strcmp(Result, String.c_str()) == 0));
252 return Result;
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,
265 const char *Source,
266 int Index,
267 int Count)
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));
276 REQUIRE(Count >= 0);
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))
303 Start++;
304 if (Start != String)
305 memmove(String, Start, strlen(Start) + 1);
307 ENSURE(VALID_REF(Result) && Result == String);
308 return Result;
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;
319 char *End = NULL;
321 REQUIRE(VALID_REF(String));
323 for (End = EndOfString(String); End != String && isspace(End[-1]); End--)
324 End[-1] = '\0';
326 ENSURE(VALID_REF(Result) && Result == String);
327 return Result;
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));
342 if (String)
343 return (StringFlushLeft(StringFlushRight(String)));
344 else
345 return String;
350 * If the specified string is longer than the maximum specified length
351 * truncate it and return a reference to it.
353 * String
354 * String to truncate if necessary.
355 * MaxLength
356 * Length at which to truncate the specified string if exceeded.
358 * Return
359 * Reference to the input string.
362 // Okay for UTF-8
363 char *StringTruncate(char *String,
364 LgIndex_t MaxLength)
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);
374 return String;
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.
382 * String
383 * String to trim and truncate if necessary.
384 * MaxLength
385 * Length at which to truncate the trimmed string if exceeded.
387 * Return
388 * Reference to the input string.
390 char *StringTrimAndTruncate(char *String,
391 LgIndex_t MaxLength)
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);
401 return String;
407 #ifndef MSWIN
408 StringList_pa LineBreakString(const char *String,
409 UInt32_t WrapMargin)
411 REQUIRE(VALID_REF(String));
413 StringList_pa Result = StringListAlloc();
414 if (Result != NULL)
416 Boolean_t IsOk = TRUE;
417 if (strlen(String) > WrapMargin)
419 char *StringCopy = DupString(dontTranslate(String));
420 IsOk = (StringCopy != NULL);
421 if (IsOk)
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 */
431 if (*CPtr == '\n')
433 *CPtr = '\0'; /* replace the newline */
434 CPtr++;
435 break;
438 CPtr++;
439 SubStringLen++;
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 */
449 if (*CPtr != ' ')
451 while (CPtr != SubString && *CPtr != ' ')
452 CPtr--;
453 if (*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')
460 CPtr++;
461 while (*CPtr != '\0' && *CPtr == ' ')
462 CPtr++; /* skip over the white space */
466 if (*CPtr != '\0')
468 *CPtr = '\0';
469 CPtr++;
471 StringFlushRight(SubString);
474 IsOk = StringListAppendString(Result, SubString);
475 SubString = CPtr;
476 SubStringLen = 0;
479 FREE_ARRAY(StringCopy, "StringCopy");
482 else
483 IsOk = StringListAppendString(Result, String);
485 if (!IsOk)
486 StringListDealloc(&Result);
489 ENSURE(Result == NULL || VALID_REF(Result));
490 return Result;
492 #endif
495 #if defined TECPLOTKERNEL
496 /* CORE SOURCE CODE REMOVED */
497 #endif /* TECPLOTKERNEL */
501 * Lexicographically compares, at most, the first 'Len' characters of
502 * s1 and s2.
504 * param s1
505 * First string or NULL.
506 * param s2
507 * Second string or NULL.
508 * param Len
509 * Maximum number of characters to compare.
510 * return
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'.
516 // Okay for UTF-8
517 int ustrncmp(const char *s1,
518 const char *s2,
519 size_t Len)
521 REQUIRE((s1 == NULL) || VALID_REF(s1));
522 REQUIRE((s2 == NULL) || VALID_REF(s2));
523 REQUIRE(Len >= 0);
525 char *t1;
526 char *t2;
527 char ct1;
528 char ct2;
529 size_t I = 0;
530 if ((s1 == NULL) && (s2 == NULL))
531 return 0;
532 if (s1 == NULL)
533 return -1;
534 else if (s2 == NULL)
535 return 1;
537 t1 = (char*)s1;
538 t2 = (char*)s2;
540 while (*t1 && *t2 && (I < Len))
542 ct1 = CAPITAL(*t1);
543 ct2 = CAPITAL(*t2);
544 if (ct1 != ct2)
545 return (ct1 - ct2);
546 t1++;
547 t2++;
548 I++;
550 if ((I == Len) ||
551 ((*t1 == '\0') && (*t2 == '\0')))
552 return 0;
553 else
554 return CAPITAL(*t1) - CAPITAL(*t2);
561 * Lexicographically compares the characters of s1 and s2.
563 * param s1
564 * First string or NULL.
565 * param s2
566 * Second string or NULL.
567 * return
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
570 * than 's2'.
572 int ustrcmp(const char *s1,
573 const char *s2)
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
586 #endif
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)
595 // Okay for UTF-8
597 #if !defined NO_ASSERTS
598 Boolean_t InternalResetString(char **SBase,
599 const char *NewString,
600 Boolean_t IssueErrMsg,
601 const char *FileName,
602 int LineNumber)
603 #else
604 Boolean_t InternalResetString(char **SBase,
605 const char *NewString,
606 Boolean_t IssueErrMsg)
607 #endif
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);
617 if (*SBase)
619 #if !defined NO_ASSERTS && defined DEBUG_ALLOC
620 char S[80+1];
621 MakeDebugRecord(FileName, LineNumber, "releasing", *SBase, S, 80);
622 FREE_ARRAY(*SBase, S);
623 #else
624 FREE_ARRAY(*SBase, "");
625 #endif
627 if (NewString == NULL)
629 *SBase = NULL;
630 return (TRUE);
632 else
634 #if !defined NO_ASSERTS && defined DEBUG_ALLOC
635 char S[80+1];
636 MakeDebugRecord(FileName, LineNumber, "duplicating", NewString, S, 80);
637 *SBase = ALLOC_ARRAY(strlen(NewString) + 1, char, S);
638 #else
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. */
644 # undef new
645 *SBase = new(FileName, LineNumber) char[strlen(NewString)+1];
646 # define new DEBUG_NEW
647 # else
648 *SBase = ALLOC_ARRAY(strlen(NewString) + 1, char, "");
649 # endif
650 #endif
651 if (*SBase)
653 strcpy(*SBase, NewString);
654 return (TRUE);
656 else
658 if (IssueErrMsg)
659 ErrMsg(translate("Out of memory"));
660 return (FALSE);
666 #if defined TECPLOTKERNEL
667 /* CORE SOURCE CODE REMOVED */
668 #endif
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)
684 size_t CurLen;
685 size_t NewLen;
686 int NumNewlines = 0;
687 char *NewString;
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'))
699 if (StringToAdd &&
700 (*StringToAdd == '\0') &&
701 DeleteStringToAdd)
703 char *TMP = (char *)StringToAdd;
704 FREE_ARRAY(TMP, "empty string to add");
707 else
710 if (*SBase == NULL)
711 CurLen = 0;
712 else
713 CurLen = strlen(*SBase);
715 while (*CPtr)
716 if (*CPtr++ == '\n')
717 NumNewlines++;
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);
730 IsOk = FALSE;
732 else
734 if (*SBase)
736 strcpy(NewString, *SBase);
737 FREE_ARRAY(*SBase, (CurLen > 0 ? *SBase : "previous text"));
739 else
740 *NewString = '\0';
743 char *NPtr = EndOfString(NewString);
744 const char *APtr = StringToAdd;
745 while (*APtr)
747 if ((*APtr == '\n') && ConvertNewlinesToAscii)
749 *NPtr++ = '\\';
750 *NPtr++ = 'n';
752 else
753 *NPtr++ = *APtr; //UTF8_AssignAndIncrement(&NPtr,(char**)&APtr,TRUE,FALSE); //*NPtr++ = *APtr;
754 APtr++;
756 *NPtr = '\0';
759 if (DeleteStringToAdd)
761 char *TMP = (char *)StringToAdd;
762 FREE_ARRAY(TMP, StringToAdd);
765 *SBase = NewString;
769 ENSURE(VALID_BOOLEAN(IsOk));
770 return (IsOk);
775 * See TackOnString for discussion.
778 // Okay for UTF-8
779 Boolean_t TackOnConstString(char **SBase,
780 const char *StringToAdd,
781 Boolean_t ConvertNewlinesToAscii)
783 size_t CurLen;
784 size_t NewLen;
785 int NumNewlines = 0;
786 char *NewString;
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'))
797 if (*SBase == NULL)
798 CurLen = 0;
799 else
800 CurLen = strlen(*SBase);
802 while (*CPtr)
803 if (*CPtr++ == '\n')
804 NumNewlines++;
806 NewLen = CurLen + strlen(StringToAdd) + 1 + NumNewlines;
808 NewString = ALLOC_ARRAY(NewLen, char, StringToAdd);
810 if (NewString == NULL)
812 IsOk = FALSE;
814 else
816 if (*SBase)
818 strcpy(NewString, *SBase);
819 FREE_ARRAY(*SBase, (CurLen > 0 ? *SBase : "previous text"));
821 else
822 *NewString = '\0';
825 char *NPtr = EndOfString(NewString);
826 const char *APtr = StringToAdd;
827 while (*APtr)
829 if ((*APtr == '\n') && ConvertNewlinesToAscii)
831 *NPtr++ = '\\';
832 *NPtr++ = 'n';
834 else
835 *NPtr++ = *APtr; // UTF8_AssignAndIncrement(&NPtr,(char**)&APtr,TRUE,FALSE);
836 APtr++;
838 *NPtr = '\0';
840 *SBase = NewString;
844 ENSURE(VALID_BOOLEAN(IsOk));
845 return (IsOk);
849 // Okay for UTF-8
850 Boolean_t TackOnChar(char **SBase,
851 char CharToAdd)
853 REQUIRE(VALID_REF(SBase));
855 char S[2];
856 S[0] = CharToAdd;
857 S[1] = '\0';
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.
868 * param String
869 * String to scan and convert if necessary. Note that the string will
870 * be reallocated if any new line characters are discovered.
872 * return
873 * TRUE if the request was successfull, FALSE otherwise.
876 // Okay for UTF-8
877 Boolean_t ReplaceNewlineWithBackslashN(char **String)
879 size_t I;
880 LgIndex_t NewlineCount;
881 size_t Length;
882 char *Replacement;
884 REQUIRE(VALID_REF(String));
885 REQUIRE(VALID_REF(*String));
887 /* count how many new line character are present */
888 NewlineCount = 0;
889 Length = strlen(*String);
890 for (I = 0; I < Length; I++)
891 if ((*String)[I] == '\n')
892 NewlineCount++;
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)
901 size_t J;
902 for (I = J = 0; I < Length + 1; I++, J++)
904 if ((*String)[I] == '\n')
906 Replacement[J] = '\\';
907 J++;
908 Replacement[J] = 'n';
910 else
912 Replacement[J] = (*String)[I];
916 /* sanity check */
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*/
936 #endif