|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // This file implements the management of strings for matching between the chat buffer (also |
|
15 // called the history buffer) and the chat strings. The chat buffer is a single buffer that |
|
16 // contains information that has been written to the test harness from the tsy. The chat |
|
17 // strings are the expected strings specified in the scripting language (in the RxEvents). |
|
18 // The expected or chat strings must match the strings received from the TSY. |
|
19 // This file also includes the logic to support the use of buffer markers to be associated with |
|
20 // the history buffer and the Chat strings. Essentially, these buffer markers delimit the |
|
21 // range of addresses in the history buffer where data associated with a particular command |
|
22 // could be found. The buffer marker structure only contains one address and uses the current |
|
23 // last character address as it's other delimeter. |
|
24 // |
|
25 // |
|
26 |
|
27 /** |
|
28 @file |
|
29 */ |
|
30 |
|
31 #include "Te_LoopBackATSTD.H" |
|
32 #include "Te_LoopBackSCHAT.H" |
|
33 #include "Te_LoopBackSLOGGER.H" |
|
34 |
|
35 CCommChatString* CCommChatString::NewL(const TDesC8& aDes, TBool aIsFolded) |
|
36 /** |
|
37 * 2 Phase Constructor |
|
38 * |
|
39 * This method creates a CCommChatString instance. After newing the necessary, it |
|
40 * pushes the chat string pointer onto the stack. Then it calls it's second stage |
|
41 * constructor (in this case the CreateL method), passing the parameters passed to |
|
42 * this method. |
|
43 * |
|
44 * @param aDes references the descriptor that contains the string. |
|
45 * @param aIsFolded a boolean that indicates the "foldedness" of this string. |
|
46 * |
|
47 * @leave This function will leave if the system is out of memory or unable |
|
48 * to allocate the amount of memory requested. |
|
49 * |
|
50 * @return A pointer to the newly created CCommChatString |
|
51 */ |
|
52 { |
|
53 CCommChatString* cs = new (ELeave) CCommChatString; |
|
54 CleanupStack::PushL(cs); |
|
55 cs->CreateL(aDes, aIsFolded); |
|
56 CleanupStack::Pop(); |
|
57 return cs; |
|
58 } |
|
59 |
|
60 CCommChatString::CCommChatString() |
|
61 /** |
|
62 * This method is the standard constructor for the class CCommChatString. |
|
63 */ |
|
64 { |
|
65 __DECLARE_NAME(_S("CCommChatString")); |
|
66 } |
|
67 |
|
68 CCommChatString::~CCommChatString() |
|
69 /** |
|
70 * This method is the standard destructor. It frees the memory allocated in the CreateL |
|
71 * method during construction. |
|
72 * |
|
73 * @return None. |
|
74 */ |
|
75 { |
|
76 User::Free(iString); |
|
77 } |
|
78 |
|
79 void CCommChatString::CreateL(const TDesC8& aDes, TBool aIsFolded) |
|
80 /** |
|
81 * Second Phase of Constructor |
|
82 * |
|
83 * This method is used as the second phase of the constructor for the CComChatString |
|
84 * class. It allocates heap memory as specified by the passed in descriptor's length. |
|
85 * Then, the string located in the descriptor is copied into the newly allocated memory. |
|
86 * The member data iLastChar is initialized to point to the last byte copied. The member |
|
87 * data iIsFolded is initialized to the passed parameter. |
|
88 * |
|
89 * @param aDes The descriptor containing the string data specified by the caller. |
|
90 * @param aIsFolded A boolean indicating whether or not the string is folded. |
|
91 * |
|
92 * @leave Leaves via User::AllocL if memory can not be allocated. |
|
93 */ |
|
94 { |
|
95 iIsFolded = aIsFolded; |
|
96 iString = (TText8*) User::AllocL(aDes.Length()); |
|
97 iLastChar = (iString+aDes.Length())-1; |
|
98 Mem::Copy(iString, (TUint8*)aDes.Ptr(), aDes.Length()); |
|
99 } |
|
100 |
|
101 // |
|
102 // CCommChatter |
|
103 // |
|
104 CCommChatter::CCommChatter(MCommChatNotify* aNotify, TInt aPriority) |
|
105 : CTimer(aPriority), iNotify(aNotify) |
|
106 /** |
|
107 * The constructor for the CCommChatter class. It adds the active object to the active |
|
108 * scheduler of the current thread and initializes member data elements. |
|
109 * |
|
110 * @param aNotify A pointer to the mixin class object associated with this object. This |
|
111 * information is stored in the iNotify member. |
|
112 * @param aPriority The priority which is assigned to the timer this class derives from CTimer. |
|
113 */ |
|
114 { |
|
115 __DECLARE_NAME(_S("CCommChatter")); |
|
116 CActiveScheduler::Add(this); |
|
117 iList.SetOffset(_FOFF(CCommChatString,iLink)); |
|
118 iMarkWrapCnt=0; |
|
119 } |
|
120 |
|
121 CCommChatter::~CCommChatter() |
|
122 /** |
|
123 * The standard destructor associated with the CCommChatter class. This method uses the |
|
124 * DeleteAllAndStop method to free resources saved in the CCommChatter object. Then it frees |
|
125 * the buffer created with CCommChatter. |
|
126 * |
|
127 * @return None |
|
128 */ |
|
129 { |
|
130 DeleteAllAndStop(); |
|
131 User::Free(iBuffer); |
|
132 } |
|
133 |
|
134 void CCommChatter::CreateL(TInt aBufSize) |
|
135 /** |
|
136 * This method is really the second stage constructor for the CCommChatter class, though it is |
|
137 * not called by the typical CCommChatter::NewL() method. The CCommChatter class is typically |
|
138 * created by another method (in the regression test case harness it is created in the |
|
139 * CATIO::ConstructL() method), then this method is called. This method allocates a buffer and |
|
140 * constructs the timer derived from CTimer in this class. The member data iBuffer, iBufferEnd, |
|
141 * and iMarkWrapCnt are initialized. |
|
142 * |
|
143 * @param aBufSize The size of the buffer to be created with this object. |
|
144 * |
|
145 * @leave This method can Leave via User::AllocL if memory is not available. |
|
146 */ |
|
147 { |
|
148 CTimer::ConstructL(); |
|
149 iBuffer = (TText8*)User::AllocL(aBufSize); |
|
150 iBufferEnd = (iBuffer+aBufSize)-1; |
|
151 ClearHistory(); |
|
152 iMarkWrapCnt=0; |
|
153 } |
|
154 |
|
155 void CCommChatter::ClearHistory() |
|
156 // |
|
157 // Empty history |
|
158 // |
|
159 /** |
|
160 * This method resets the history of the CCommChatter buffer in the object. It simply clears |
|
161 * the iCount and initializes the iLastChar member to iBuffer (the beginning of the buffer). |
|
162 * |
|
163 * @return None. |
|
164 */ |
|
165 { |
|
166 iLastChar = iBuffer; |
|
167 iCount = 0; |
|
168 } |
|
169 |
|
170 void CCommChatter::AddCharL(TText8 aChar) |
|
171 // |
|
172 // Add a character to the history buffer |
|
173 // Scan all strings to find any matches that may |
|
174 // be completed. |
|
175 // |
|
176 /** |
|
177 * This method adds a single character to the history buffer and then scans all stored |
|
178 * strings to find any matches that may have been completed because this character has |
|
179 * been added. The function deals with folded characters during the search. Note that |
|
180 * the routine first checks to see if the last character in the stored string matches |
|
181 * the input character. This reduces the number of invocations of the string match |
|
182 * functions. |
|
183 * |
|
184 * @param aChar The character to add to the buffer. |
|
185 * @leave This method can leave via the ChatStringMatchL call. |
|
186 */ |
|
187 { |
|
188 // Add char to buffer |
|
189 if (++iLastChar>iBufferEnd) |
|
190 { |
|
191 iLastChar = iBuffer; |
|
192 iMarkWrapCnt++; |
|
193 } |
|
194 *iLastChar = aChar; |
|
195 ++iCount; |
|
196 |
|
197 TText8 fchar = (TText8)User::Fold(aChar); |
|
198 |
|
199 // Scan for matching last character |
|
200 CCommChatString* cs; |
|
201 TDblQueIter<CCommChatString> iter(iList); |
|
202 |
|
203 while (cs = iter++, cs!=NULL) |
|
204 { |
|
205 if (cs->IsFolded() |
|
206 ? (User::Fold(cs->LastChar())==fchar && MatchF(cs)) |
|
207 : (cs->LastChar()==aChar && Match(cs))) |
|
208 { |
|
209 iNotify->ChatStringMatchL(cs); |
|
210 cs = iter; // In case user removed cs; |
|
211 } |
|
212 } |
|
213 } |
|
214 |
|
215 TBool CCommChatter::Match(const CCommChatString* aString) const |
|
216 // |
|
217 // Match a chat sgring against the history buffer |
|
218 // (Case sensitive) |
|
219 // |
|
220 /** |
|
221 * This method matchs a chat string against the history buffer in a case sensitive (unfolded) |
|
222 * manner. First the length of the two strings is compared. Then the actual content of the |
|
223 * strings is compared. |
|
224 * |
|
225 * @param aString A constant pointer to the chat string. |
|
226 * |
|
227 * @return ETrue if strings match, EFalse if they do not. |
|
228 */ |
|
229 { |
|
230 const TText8* s = aString->Ptr(); |
|
231 const TText8* sp = aString->EndPtr(); |
|
232 const TText8* bp = iLastChar; |
|
233 |
|
234 if (iCount<aString->Length()) |
|
235 return EFalse; |
|
236 |
|
237 while (*bp==*sp && sp>=s) |
|
238 { |
|
239 --sp; |
|
240 if (--bp<iBuffer) |
|
241 bp = iBufferEnd; |
|
242 } |
|
243 |
|
244 return sp<s; |
|
245 } |
|
246 |
|
247 TBool CCommChatter::MatchF(const CCommChatString* aString) const |
|
248 // |
|
249 // Match a folded chat string against the history buffer. |
|
250 // (Case insensitive) |
|
251 // |
|
252 |
|
253 /** |
|
254 * This method matchs a chat string against the history buffer in a case insensitive or folded |
|
255 * manner. First the length of the two strings is compared. Then the actual content of the |
|
256 * strings is compared. |
|
257 * |
|
258 * @param aString A constant pointer to the chat string. |
|
259 * |
|
260 * @return ETrue if strings match, EFalse if they do not. |
|
261 */ |
|
262 { |
|
263 const TText8* s = aString->Ptr(); |
|
264 const TText8* sp = aString->EndPtr(); |
|
265 const TText8* bp = iLastChar; |
|
266 if (iCount<aString->Length()) |
|
267 return EFalse; |
|
268 |
|
269 while (User::Fold(*bp)==User::Fold(*sp) && sp>=s) |
|
270 { |
|
271 --sp; |
|
272 if (--bp<iBuffer) |
|
273 bp = iBufferEnd; |
|
274 } |
|
275 return sp<s; |
|
276 } |
|
277 |
|
278 void CCommChatter::GetChatBufferMarker(TInputBufferMark& aBufferMarker) |
|
279 /** |
|
280 * This method sets up a buffer marker structure. It saves the current last character |
|
281 * location and notes the wrap state of the buffer. |
|
282 * |
|
283 * @param aBufferMarker A reference to a buffer marker structure. |
|
284 * Is modified with the current location of iLastChar and a wrap flag. |
|
285 * @return None |
|
286 */ |
|
287 { |
|
288 aBufferMarker.iMarkChar=iLastChar; |
|
289 if(++aBufferMarker.iMarkChar>iBufferEnd) |
|
290 { |
|
291 aBufferMarker.iMarkWrap=iMarkWrapCnt+1; |
|
292 aBufferMarker.iMarkChar=iBuffer; |
|
293 } |
|
294 else |
|
295 aBufferMarker.iMarkWrap=iMarkWrapCnt; |
|
296 } |
|
297 |
|
298 TPtrC8 CCommChatter::GetChatBufferLC(TInputBufferMark& aBufferMarker) |
|
299 /** |
|
300 * This method deals with extracting data from the Chat or History Buffer and returning it |
|
301 * to the caller. The data that is extracted from the buffer marker to the current last |
|
302 * character in the buffer. This method creates a new HBufC8 object and returns a pointer |
|
303 * to that descriptor. This method deals properly with a wrapped history buffer. |
|
304 * |
|
305 * @param aBufferMarker is a reference to a buffer marker structure that has been |
|
306 * previously initialized. This buffer marker structure limits the range of the |
|
307 * history buffer which must be copied/examined to find the relevant data. |
|
308 * @leave Leaves if error processing buffer between the mark and the current |
|
309 * last character. |
|
310 * @return TPtrC8 pointer to a newly created HBufC8 which contains the iRxBuffer |
|
311 * contents between the marker and the current last character. Data that |
|
312 * is of interest to this completion has been copied from the general |
|
313 * receive buffer to this buffer. |
|
314 */ |
|
315 { |
|
316 TText8* markChar=aBufferMarker.iMarkChar; |
|
317 if(iMarkWrapCnt==aBufferMarker.iMarkWrap) |
|
318 { |
|
319 __ASSERT_ALWAYS(iLastChar>markChar,User::Leave(KErrGeneral)); // Internal Error |
|
320 HBufC8* buffer=HBufC8::NewLC(iLastChar-markChar+1); |
|
321 TPtr8 ptr(buffer->Des()); |
|
322 ptr.Copy(markChar,iLastChar-markChar+1); |
|
323 return ptr; |
|
324 } |
|
325 else |
|
326 { |
|
327 if((iLastChar>markChar)||(iMarkWrapCnt>aBufferMarker.iMarkWrap+1)) |
|
328 User::Leave(KErrGeneral); // Data Lost |
|
329 HBufC8* buffer=HBufC8::NewLC(KChatBufferSize-(markChar-iLastChar)+1); |
|
330 TPtr8 ptr(buffer->Des()); |
|
331 ptr.Copy(TPtrC8(markChar,iBufferEnd-markChar+1)); |
|
332 ptr.Append(TPtrC8(iBuffer,iLastChar-iBuffer+1)); |
|
333 return ptr; |
|
334 } |
|
335 } |
|
336 |
|
337 void CCommChatter::RunL() |
|
338 /** |
|
339 * This is the RunL associated with the CTimer inherited by the CCommChatter class. This |
|
340 * RunL simply processess a timeout. |
|
341 * |
|
342 * @return None |
|
343 */ |
|
344 { |
|
345 iNotify->ChatTimeout(); |
|
346 } |
|
347 |
|
348 CCommChatString* CCommChatter::AddString(const TDesC8& aString) |
|
349 /** |
|
350 * This method adds a string to the stored chat strings. It creates a new chat string object |
|
351 * and adds it to the list of outstanding chat strings. |
|
352 * |
|
353 * @param aString This is a constant TDesC8 reference that is used to create the new string. |
|
354 * @return A pointer to the newly created CCommChatString object. |
|
355 */ |
|
356 { |
|
357 CCommChatString* chatString=NULL; |
|
358 TRAP_IGNORE(chatString=CCommChatString::NewL(aString,ETrue)); // trap but ignore leaves |
|
359 iList.AddLast(*chatString); |
|
360 return chatString; |
|
361 } |
|
362 |
|
363 void CCommChatter::RemoveString(CCommChatString* aString) |
|
364 /** |
|
365 * This method removes a string from the stored chat strings. It dequeues the string from the |
|
366 * list of stored chat strings but does not delete the object. |
|
367 * |
|
368 * @param aString A pointer to a CCommChatString |
|
369 * @return None |
|
370 */ { |
|
371 aString->iLink.Deque(); |
|
372 } |
|
373 |
|
374 void CCommChatter::DeleteAllAndStop() |
|
375 /** |
|
376 * This method stops the outstanding CTimer and removes all of the outstanding chat strings |
|
377 * from the chat string list and deletes them. |
|
378 * |
|
379 * @return None. |
|
380 */ |
|
381 { |
|
382 StopTimer(); |
|
383 CCommChatString* cs; |
|
384 while (!iList.IsEmpty()) |
|
385 { |
|
386 cs = iList.First(); |
|
387 RemoveString(cs); |
|
388 delete cs; |
|
389 } |
|
390 } |
|
391 |
|
392 void CCommChatter::StartTimer(const TTimeIntervalMicroSeconds32 aTimeout) |
|
393 /** |
|
394 * This method starts the timer associated with the CCommChatter class. This timer |
|
395 * triggers after a specific interval of time. This is a one shot timer. |
|
396 * |
|
397 * @param aTimeout The interval in micro-seconds before the timer should trigger. |
|
398 * @return None |
|
399 */ |
|
400 { |
|
401 if (IsActive()) |
|
402 Cancel(); |
|
403 After(aTimeout); |
|
404 } |
|
405 |
|
406 void CCommChatter::StopTimer() |
|
407 /** |
|
408 * This method simply stops the outstanding timer for the CCommChatter class. This timer |
|
409 * is implemented via an active object by the CTimer class. |
|
410 * |
|
411 * @return None |
|
412 */ |
|
413 { |
|
414 Cancel(); |
|
415 } |