0022627: Change OCCT memory management defaults
[occt.git] / src / Message / Message_Msg.cxx
1 // File:      Message_Msg.cxx
2 // Created:   27.04.01 19:44:52
3 // Author:    OCC Team
4 // Copyright: Open CASCADE S.A. 2005
5
6 #include <Message_Msg.hxx>
7 #include <Message_MsgFile.hxx>
8 #include <TCollection_AsciiString.hxx>
9 #include <stdio.h>
10         
11 typedef enum
12 {
13   Msg_IntegerType,
14   Msg_RealType,
15   Msg_StringType,
16   Msg_IndefiniteType
17 } FormatType;
18
19 //=======================================================================
20 //function : Message_Msg()
21 //purpose  : Constructor
22 //=======================================================================
23
24 Message_Msg::Message_Msg ()
25 {}
26
27
28 //=======================================================================
29 //function : Message_Msg()
30 //purpose  : Constructor
31 //=======================================================================
32
33 Message_Msg::Message_Msg (const Message_Msg& theMsg)
34 {
35   myMessageBody = theMsg.myMessageBody;
36   myOriginal = theMsg.myOriginal;
37   for ( Standard_Integer i = 1, n = theMsg.mySeqOfFormats.Length(); i <=n; i++ )
38     mySeqOfFormats.Append ( theMsg.mySeqOfFormats.Value(i) );
39 }
40
41 //=======================================================================
42 //function : Message_Msg()
43 //purpose  : Constructor
44 //=======================================================================
45
46 Message_Msg::Message_Msg (const Standard_CString theMsgCode)
47 {
48   TCollection_AsciiString aKey((char*)theMsgCode);
49   Set ( Message_MsgFile::Msg(aKey) );
50 }
51
52 //=======================================================================
53 //function : Message_Msg()
54 //purpose  : Constructor
55 //=======================================================================
56
57 Message_Msg::Message_Msg (const TCollection_ExtendedString& theMsgCode)
58 {
59   Set ( Message_MsgFile::Msg(theMsgCode) );
60 }
61
62 //=======================================================================
63 //function : Set
64 //purpose  : 
65 //=======================================================================
66
67 void Message_Msg::Set (const Standard_CString theMsg)
68 {
69   TCollection_AsciiString aMsg((char*)theMsg);
70   Set ( aMsg );
71 }
72
73 //=======================================================================
74 //function : Set
75 //purpose  : 
76 //=======================================================================
77
78 void Message_Msg::Set (const TCollection_ExtendedString& theMsg)
79 {
80   myMessageBody = theMsg;
81
82   const Standard_ExtString anExtString = myMessageBody.ToExtString();
83         Standard_Integer   anMsgLength = myMessageBody.Length();
84   for (Standard_Integer i = 0; i < anMsgLength; i++)
85   {
86     //  Search for '%' character starting a format specification
87     if (ToCharacter (anExtString[i]) == '%')
88     {
89       Standard_Integer   aStart = i++;
90       Standard_Character aChar = ToCharacter (anExtString[i]);
91       //        Check for format '%%'
92       if (aChar == '%')
93       {
94         myMessageBody.Remove (i+1);
95         if (i >= --anMsgLength) break;
96         aChar = ToCharacter (anExtString[i]);
97       }
98       //        Skip flags, field width and precision
99       while (i < anMsgLength)
100       {
101         if (aChar == '-' || aChar == '+' || aChar == ' ' ||
102             aChar == '#' || (aChar >= '0' && aChar <= '9') || aChar == '.')
103           i++;
104         else break;
105         aChar = ToCharacter (anExtString[i]);
106       }
107       if (i >= anMsgLength) break;
108
109       FormatType aFormatType;
110       if (aChar == 'h' || aChar == 'l') aChar = ToCharacter (anExtString[++i]);
111       switch (aChar)                    // detect the type of format spec
112       {
113       case 'd':
114       case 'i':
115       case 'o':
116       case 'u':
117       case 'x':
118       case 'X':
119         aFormatType = Msg_IntegerType;
120         break;
121       case 'f':
122       case 'e':
123       case 'E':
124       case 'g':
125       case 'G':
126         aFormatType = Msg_RealType;
127         break;
128       case 's':
129         aFormatType = Msg_StringType;
130         break;
131       default:
132         aFormatType = Msg_IndefiniteType;
133         continue;
134       }
135       mySeqOfFormats.Append (Standard_Integer(aFormatType));  // type
136       mySeqOfFormats.Append (aStart);                         // beginning pos
137       mySeqOfFormats.Append (i + 1 - aStart);                 // length
138     }
139   }
140   myOriginal = myMessageBody;
141 }
142
143 //=======================================================================
144 //function : Arg (Standard_CString)
145 //purpose  : 
146 //=======================================================================
147
148 Message_Msg& Message_Msg::Arg (const Standard_CString theString)
149 {
150   // get location and format
151   TCollection_AsciiString aFormat;
152   Standard_Integer aFirst = getFormat ( Msg_StringType, aFormat );
153   if ( !aFirst )
154     return *this;
155
156   // print string according to format
157   char * sStringBuffer = new char [Max (strlen(theString)+1, 1024)];
158   sprintf (sStringBuffer, aFormat.ToCString(), theString);
159   TCollection_ExtendedString aStr ( sStringBuffer );
160   delete [] sStringBuffer;
161   sStringBuffer = 0;
162
163   // replace the format placeholder by the actual string
164   replaceText ( aFirst, aFormat.Length(), aStr );
165   
166   return *this;
167 }
168
169 //=======================================================================
170 //function : Arg (TCollection_ExtendedString)
171 //purpose  : 
172 //remark   : This type of string is inserted without conversion (i.e. like %s)
173 //=======================================================================
174
175 Message_Msg& Message_Msg::Arg (const TCollection_ExtendedString& theString)
176 {
177   // get location and format
178   TCollection_AsciiString aFormat;
179   Standard_Integer aFirst = getFormat ( Msg_StringType, aFormat );
180   if ( !aFirst )
181     return *this;
182   
183   // replace the format placeholder by the actual string
184   replaceText ( aFirst, aFormat.Length(), theString );
185   
186   return *this;
187 }
188
189 //=======================================================================
190 //function : Arg (Standard_Integer)
191 //purpose  : 
192 //=======================================================================
193
194 Message_Msg& Message_Msg::Arg (const Standard_Integer theValue)
195 {
196   // get location and format
197   TCollection_AsciiString aFormat;
198   Standard_Integer aFirst = getFormat ( Msg_IntegerType, aFormat );
199   if ( !aFirst )
200     return *this;
201
202   // print string according to format
203   char sStringBuffer [64];
204   sprintf (sStringBuffer, aFormat.ToCString(), theValue);
205   TCollection_ExtendedString aStr ( sStringBuffer );
206
207   // replace the format placeholder by the actual string
208   replaceText ( aFirst, aFormat.Length(), aStr );
209   
210   return *this;
211 }
212
213 //=======================================================================
214 //function : Arg (Standard_Real)
215 //purpose  : 
216 //=======================================================================
217
218 Message_Msg& Message_Msg::Arg (const Standard_Real theValue)
219 {
220   // get location and format
221   TCollection_AsciiString aFormat;
222   Standard_Integer aFirst = getFormat ( Msg_RealType, aFormat );
223   if ( !aFirst )
224     return *this;
225
226   // print string according to format
227   char sStringBuffer [64];
228   sprintf (sStringBuffer, aFormat.ToCString(), theValue);
229   TCollection_ExtendedString aStr ( sStringBuffer );
230
231   // replace the format placeholder by the actual string
232   replaceText ( aFirst, aFormat.Length(), aStr );
233   
234   return *this;
235 }
236
237 //=======================================================================
238 //function : Get
239 //purpose  : used when the message is dispatched in Message_Messenger
240 //=======================================================================
241
242 const TCollection_ExtendedString& Message_Msg::Get ()
243 {
244   // remove all non-initialised format specifications
245   Standard_Integer i, anIncrement = 0;
246   static const TCollection_ExtendedString anUnknown ("UNKNOWN");
247   for (i = 1; i < mySeqOfFormats.Length(); i += 3)
248   {
249     TCollection_ExtendedString aRightPart =
250       myMessageBody.Split(mySeqOfFormats(i+1) + anIncrement);
251     aRightPart.Remove(1, mySeqOfFormats(i+2));
252     myMessageBody += anUnknown;
253     myMessageBody += aRightPart;
254     anIncrement += (anUnknown.Length() - mySeqOfFormats(i+2));
255   }
256   return myMessageBody;
257 }
258
259 //=======================================================================
260 //function : getFormat
261 //purpose  : Find placeholder in the string where to put next value of 
262 //           specified type, return its starting position in the string 
263 //           and relevant format string (located at that position).
264 //           The information on returned placeholder is deleted immediately,
265 //           so it will not be found further
266 //           If failed (no placeholder with relevant type found), returns 0
267 //=======================================================================
268
269 Standard_Integer Message_Msg::getFormat (const Standard_Integer theType,
270                                          TCollection_AsciiString &theFormat)
271 {
272   for (Standard_Integer i = 1; i <= mySeqOfFormats.Length(); i += 3)
273     if (mySeqOfFormats(i) == theType)
274     {
275       // Extract format
276       Standard_Integer aFirst = mySeqOfFormats(i+1);
277       Standard_Integer aLen = mySeqOfFormats(i+2);
278       theFormat = TCollection_AsciiString ( aLen, ' ' );
279       for ( Standard_Integer j=1; j <= aLen; j++ )
280         if ( IsAnAscii ( myMessageBody.Value ( aFirst + j ) ) )
281           theFormat.SetValue ( j, (Standard_Character)myMessageBody.Value ( aFirst + j ) );
282       // delete information on this placeholder
283       mySeqOfFormats.Remove (i, i+2);
284       // return start position
285       return aFirst + 1;
286     }
287   return 0;
288 }
289
290 //=======================================================================
291 //function : replaceText
292 //purpose  : Replace format text in myMessageBody (theNb chars from theFirst)
293 //           by string theStr
294 //=======================================================================
295
296 void Message_Msg::replaceText (const Standard_Integer theFirst,
297                                const Standard_Integer theNb,
298                                const TCollection_ExtendedString &theStr)
299 {
300   myMessageBody.Remove ( theFirst, theNb );
301   myMessageBody.Insert ( theFirst, theStr );
302   
303   // update information on remaining format placeholders
304   Standard_Integer anIncrement = theStr.Length() - theNb;
305   if ( ! anIncrement ) return;
306   for ( Standard_Integer i = 1; i <= mySeqOfFormats.Length(); i += 3 )
307     if ( mySeqOfFormats(i+1) > theFirst )
308       mySeqOfFormats(i+1) += anIncrement;
309 }