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