FreeCalypso > hg > tcs211-l1-reconst
comparison g23m/condat/ms/src/atb/ATBPb.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:509db1a7b7b8 |
---|---|
1 /******************************************************************************* | |
2 | |
3 CONDAT (UK) | |
4 | |
5 ******************************************************************************** | |
6 | |
7 This software product is the property of Condat (UK) Ltd and may not be | |
8 disclosed to any third party without the express permission of the owner. | |
9 | |
10 ******************************************************************************** | |
11 | |
12 $Project name: | |
13 $Project code: | |
14 $Module: | |
15 $File: ATBPb.c | |
16 $Revision: | |
17 | |
18 $Author: Condat(UK) | |
19 $Date: | |
20 | |
21 ******************************************************************************** | |
22 | |
23 Description: | |
24 | |
25 | |
26 ******************************************************************************** | |
27 | |
28 $History: ATBPb.c | |
29 | |
30 Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar | |
31 Description: Moving entries from Sim Card to phone memory fails. | |
32 Solution: When entries are moved, corresponding updations are done in cache as well. | |
33 | |
34 | |
35 $End | |
36 | |
37 *******************************************************************************/ | |
38 | |
39 #if defined (NEW_FRAME) | |
40 | |
41 #include "typedefs.h" | |
42 #include "vsi.h" | |
43 #include "pei.h" | |
44 #include "custom.h" | |
45 #include "gsm.h" | |
46 | |
47 #else | |
48 | |
49 #include "STDDEFS.H" | |
50 #include "custom.h" | |
51 #include "gsm.h" | |
52 #include "vsi.h" | |
53 | |
54 #endif | |
55 | |
56 #include <stdio.h> | |
57 #include <string.h> | |
58 | |
59 #include "mfw_mfw.h" | |
60 #include "mfw_sys.h" | |
61 | |
62 #include "cus_aci.h" | |
63 #include "prim.h" | |
64 #include "pcm.h" | |
65 | |
66 #include "ATBPb.h" | |
67 #include "ATBPb_i.h" | |
68 | |
69 /* Global data for phonebook */ | |
70 | |
71 static T_PB_DATA *phonebook[PB_PHONEBOOKS_MAX] = {0}; | |
72 | |
73 | |
74 /******************************************************************************* | |
75 | |
76 $Function: ATB_pb_GetPhonebook | |
77 | |
78 $Description: Checks to see which file system is selected | |
79 | |
80 $Returns: PB_OK Action completed OK. | |
81 PB_FILEWRITEFAIL File write encountered an error | |
82 | |
83 $Arguments: phonebook_id The phonebook identifier | |
84 current_type Place to store type of phonebook selected. | |
85 | |
86 *******************************************************************************/ | |
87 | |
88 PB_RET ATB_pb_GetPhonebook(SHORT phonebook_id, T_PB_TYPE *current_type) | |
89 { | |
90 PB_RET result; | |
91 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
92 | |
93 tracefunction("ATB_pb_GetPhonebook"); | |
94 | |
95 if (data) | |
96 { | |
97 *current_type = data->current_type; | |
98 return PB_OK; | |
99 } | |
100 | |
101 result = FS_pb_GetPhonebook(phonebook_id, current_type); | |
102 | |
103 return result; | |
104 } | |
105 | |
106 | |
107 /******************************************************************************* | |
108 | |
109 $Function: ATB_pb_SetPhonebook | |
110 | |
111 $Description: Select file system | |
112 | |
113 $Returns: PB_OK Action completed OK. | |
114 PB_FILEREADFAIL File read encountered an error | |
115 | |
116 $Arguments: phonebook_id The phonebook identifier | |
117 current_type Type of phonebook selected. | |
118 | |
119 *******************************************************************************/ | |
120 | |
121 PB_RET ATB_pb_SetPhonebook(SHORT phonebook_id, T_PB_TYPE current_type) | |
122 { | |
123 PB_RET result; | |
124 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
125 | |
126 tracefunction("ATB_pb_SetPhonebook"); | |
127 | |
128 if (data) | |
129 data->current_type = current_type; | |
130 | |
131 result = FS_pb_SetPhonebook(phonebook_id, current_type); | |
132 | |
133 return result; | |
134 } | |
135 | |
136 | |
137 /******************************************************************************* | |
138 | |
139 $Function: ATB_pb_Initialise | |
140 | |
141 $Description: Initialise an instance of phonebook. Dynamically allocates a record | |
142 cache in RAM. Creates the necessary file(s) if they do not already exist. | |
143 Sorts the phonebook by name and by number, creating the appropriate | |
144 index tables. | |
145 IMPORTANT: if the file reading is non-blocking - i.e. if a request to read | |
146 a file does not return with an answer straight away, but the system | |
147 awaits a callback - then "cache_max" must equal "records_max". This | |
148 ensures that all records are stored in RAM and can be retrieved without | |
149 waiting for a response. If the file reading is blocking, then cache_max | |
150 can be smaller than records_max. | |
151 | |
152 The memory allocated by this operation will not be freed until | |
153 ATB_pb_Exit() is called. | |
154 | |
155 $Returns: PB_OK Action completed OK. | |
156 PB_EXCT Action currently executing, callback awaited. | |
157 GI_pb_OK will be called if successful, | |
158 GI_pb_Error otherwise. | |
159 PB_BUSY Failed, phonebook is busy. | |
160 PB_FILEREADFAIL File read encountered an error | |
161 PB_FILEWRITEFAIL File write encountered an error | |
162 PB_BOOKALREADYEXISTS Tried to initialise a phonebook that already | |
163 exists | |
164 | |
165 $Arguments: phonebook_id The phonebook identifier | |
166 type Type of phonebook. | |
167 records_max Indicates the maximum number of entries the | |
168 phonebook can hold. | |
169 cache_max Indicates the maximum number of records that the | |
170 PB will store concurrently in RAM. | |
171 alpha_max Maximum size of unicode alpha tag in characters | |
172 number_max Maximum size of phone number in digits | |
173 ext_max Maximum size of extended data in bytes | |
174 | |
175 *******************************************************************************/ | |
176 | |
177 PB_RET ATB_pb_Initialise(SHORT phonebook_id, T_PB_TYPE type, SHORT records_max, SHORT cache_max, | |
178 SHORT alpha_max, SHORT number_max, SHORT ext_max) | |
179 { | |
180 T_PB_DATA *data; | |
181 | |
182 tracefunction("ATB_pb_Initialise()"); | |
183 | |
184 /* Check to see if this phonebook has already been allocated */ | |
185 | |
186 if (ATB_hnd_GetPbData(phonebook_id)!=NULL) | |
187 { | |
188 trace("* ERROR * - Phonebook already exists"); | |
189 GI_pb_Error(phonebook_id, PB_INITIALISE, PB_BOOKALREADYEXISTS); | |
190 return PB_BOOKALREADYEXISTS; | |
191 } | |
192 | |
193 /* Allocate memory for phonebook data */ | |
194 | |
195 data = (T_PB_DATA *)GI_pb_MemAlloc(sizeof(T_PB_DATA)); | |
196 ATB_hnd_SetPbData(phonebook_id, data); | |
197 | |
198 data->records_max = records_max; | |
199 data->records_used = 0; | |
200 data->search_results = 0; | |
201 | |
202 data->alpha_max = alpha_max; | |
203 data->number_max = number_max; | |
204 data->ext_max = ext_max; | |
205 | |
206 /* Allocate memory for index tables */ | |
207 | |
208 data->name_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT)); | |
209 memset(data->name_table, 0, records_max*sizeof(SHORT)); | |
210 data->number_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT)); | |
211 memset(data->number_table, 0, records_max*sizeof(SHORT)); | |
212 data->search_table = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT)); | |
213 memset(data->search_table, 0, records_max*sizeof(SHORT)); | |
214 data->in_memory = (SHORT *)GI_pb_MemAlloc(records_max*sizeof(SHORT)); | |
215 memset(data->in_memory, PB_EMPTY_RECORD, records_max*sizeof(SHORT)); | |
216 | |
217 /* Allocate memory for cache */ | |
218 | |
219 data->cache_max = cache_max; | |
220 data->cache_size = 0; | |
221 data->cache = (T_PB_RECORD **)GI_pb_MemAlloc(records_max*sizeof(T_PB_RECORD *)); | |
222 memset(data->cache, 0, records_max*sizeof(T_PB_RECORD *)); | |
223 | |
224 /* Set up command */ | |
225 | |
226 data->command_id = PB_INITIALISE; | |
227 data->status = PB_STATUS_INIT; | |
228 data->param.Initialise.type = type; | |
229 data->param.Initialise.records_max = records_max; | |
230 | |
231 return ATB_status_Initialise(phonebook_id); | |
232 } | |
233 | |
234 /* Status function for Initialise */ | |
235 | |
236 PB_RET ATB_status_Initialise(SHORT phonebook_id) | |
237 { | |
238 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
239 T_PB_INITIALISE *Initialise; | |
240 SHORT blocking; | |
241 PB_RET result; | |
242 | |
243 /* Ensure that phonebook exists */ | |
244 if (!data) | |
245 { | |
246 trace("**ERROR** Phonebook does not exist"); | |
247 return PB_BOOKDOESNOTEXIST; | |
248 } | |
249 | |
250 Initialise = &data->param.Initialise; | |
251 blocking = TRUE; | |
252 while (blocking) | |
253 { | |
254 switch(data->status) | |
255 { | |
256 case PB_STATUS_INIT: | |
257 trace("ATB_status_Initialise: INIT"); | |
258 result = FS_pb_Initialise(phonebook_id, Initialise->type, Initialise->records_max, | |
259 data->alpha_max, data->number_max, data->ext_max); | |
260 | |
261 /* Select next state */ | |
262 | |
263 data->status = PB_STATUS_EXEC; | |
264 Initialise->phys_index = 0; | |
265 Initialise->first_record = TRUE; | |
266 Initialise->record = ATB_pb_AllocRec(phonebook_id); | |
267 | |
268 /* Allow exit from function */ | |
269 | |
270 if (result!=PB_OK) | |
271 blocking = FALSE; | |
272 break; | |
273 | |
274 case PB_STATUS_EXEC: | |
275 trace("ATB_status_Initialise: EXEC"); | |
276 | |
277 /* Try to read in index tables from file system. If we can't find them, the | |
278 * records will be read in and sorted. */ | |
279 | |
280 if (Initialise->first_record) | |
281 { | |
282 result = FS_pb_ReadTables(phonebook_id, &data->records_used, data->name_table, data->number_table); | |
283 if (result==PB_OK) | |
284 { | |
285 /* Escape to PB_STATUS_COMPLETE */ | |
286 result = PB_OK; | |
287 data->status = PB_STATUS_COMPLETE; | |
288 break; | |
289 } | |
290 } | |
291 /* If we've already read a record, and it's an existing record, add it to the | |
292 * index tables and to the cache */ | |
293 | |
294 else | |
295 { | |
296 if (Initialise->record->alpha.data[0]!=(USHORT)0xFFFF) | |
297 { | |
298 ATB_mem_UpdateCache(phonebook_id, Initialise->phys_index, Initialise->record); | |
299 ATB_index_AddRec(phonebook_id, INDEX_NAME, Initialise->phys_index, Initialise->record, NULL); | |
300 ATB_index_AddRec(phonebook_id, INDEX_NUMBER, Initialise->phys_index, Initialise->record, NULL); | |
301 data->records_used++; | |
302 } | |
303 | |
304 Initialise->phys_index++; | |
305 } | |
306 | |
307 /* Start processing after first record is read */ | |
308 | |
309 Initialise->first_record = FALSE; | |
310 | |
311 /* If we haven't just read the last record, read the next one */ | |
312 | |
313 if (Initialise->phys_index<data->records_max) | |
314 { | |
315 result = FS_pb_ReadRec(phonebook_id, Initialise->phys_index, Initialise->record); | |
316 } | |
317 else | |
318 { | |
319 /* Set next state as finished */ | |
320 result = PB_OK; | |
321 data->status = PB_STATUS_COMPLETE; | |
322 } | |
323 | |
324 | |
325 /* Allow exit from function */ | |
326 | |
327 if (result!=PB_OK) | |
328 blocking = FALSE; | |
329 break; | |
330 | |
331 case PB_STATUS_COMPLETE: | |
332 trace("ATB_status_Initialise: COMPLETE"); | |
333 blocking = FALSE; | |
334 | |
335 /* Close file */ | |
336 | |
337 FS_pb_Finished(phonebook_id); | |
338 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table); | |
339 | |
340 /* Free the allocated record */ | |
341 | |
342 ATB_pb_FreeRec(phonebook_id, Initialise->record); | |
343 | |
344 /* Notify the GI of success */ | |
345 GI_pb_OK(phonebook_id, data->command_id, NULL); | |
346 result = PB_OK; | |
347 data->status = PB_STATUS_NONE; | |
348 break; | |
349 } | |
350 } | |
351 | |
352 return result; | |
353 } | |
354 | |
355 | |
356 /******************************************************************************* | |
357 | |
358 $Function: ATB_pb_Exit | |
359 | |
360 $Description: Frees memory associated with phonebook. To be called when the | |
361 phonebook is no longer required, or at shutdown. | |
362 | |
363 $Returns: PB_OK Action completed OK. | |
364 | |
365 $Arguments: phonebook_id The phonebook identifier | |
366 | |
367 *******************************************************************************/ | |
368 | |
369 PB_RET ATB_pb_Exit(SHORT phonebook_id) | |
370 { | |
371 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
372 SHORT phys_index; | |
373 | |
374 trace("ATB_pb_Exit"); | |
375 | |
376 /* Ensure that phonebook exists */ | |
377 if (!data) | |
378 { | |
379 trace("**ERROR** Phonebook does not exist"); | |
380 return PB_BOOKDOESNOTEXIST; | |
381 } | |
382 | |
383 for (phys_index = 0; phys_index<data->records_max; phys_index++) | |
384 { | |
385 if (data->cache[phys_index]!=NULL) | |
386 ATB_pb_FreeRec(phonebook_id, data->cache[phys_index]); | |
387 } | |
388 | |
389 GI_pb_MemFree((UBYTE *)data->cache, data->records_max*sizeof(T_PB_RECORD *)); | |
390 GI_pb_MemFree((UBYTE *)data->in_memory, data->records_max*sizeof(SHORT)); | |
391 GI_pb_MemFree((UBYTE *)data->search_table, data->records_max*sizeof(SHORT)); | |
392 GI_pb_MemFree((UBYTE *)data->number_table, data->records_max*sizeof(SHORT)); | |
393 GI_pb_MemFree((UBYTE *)data->name_table, data->records_max*sizeof(SHORT)); | |
394 | |
395 GI_pb_MemFree((UBYTE *)data, sizeof(T_PB_DATA)); | |
396 | |
397 ATB_hnd_SetPbData(phonebook_id, NULL); | |
398 return PB_OK; | |
399 } | |
400 | |
401 | |
402 /******************************************************************************* | |
403 | |
404 $Function: ATB_pb_Status | |
405 | |
406 $Description: Returns PB_OK if the phonebook is ready for a new command, | |
407 or PB_BUSY if the phonebook is busy. | |
408 | |
409 $Returns: PB_OK All tasks completed, phonebook ready. | |
410 PB_BUSY Commands currently executing. | |
411 | |
412 $Arguments: phonebook_id The phonebook identifier | |
413 | |
414 *******************************************************************************/ | |
415 | |
416 PB_RET ATB_pb_Status(SHORT phonebook_id) | |
417 { | |
418 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
419 PB_RET result; | |
420 | |
421 /* Ensure that phonebook exists */ | |
422 if (!data) | |
423 { | |
424 trace("**ERROR** Phonebook does not exist"); | |
425 return PB_BOOKDOESNOTEXIST; | |
426 } | |
427 | |
428 // Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar | |
429 // Description: Moving entries from Sim Card to phone memory fails. | |
430 // Solution: result should be set as PB_OK when PB_STATUS_COMPLETE is true also. | |
431 if ((data->status==PB_STATUS_NONE) ||(data->status==PB_STATUS_COMPLETE)) | |
432 result = PB_OK; | |
433 else | |
434 result = PB_BUSY; | |
435 | |
436 return result; | |
437 } | |
438 | |
439 | |
440 /******************************************************************************* | |
441 | |
442 $Function: ATB_pb_Info | |
443 | |
444 $Description: Returns information about the phonebook, which will be returned | |
445 in the data structure pointed to by phonebook_info. The caller must | |
446 allocate the T_PB_INFO structure. | |
447 | |
448 $Returns: PB_OK Action completed OK. | |
449 | |
450 $Arguments: phonebook_id The phonebook identifier | |
451 phonebook_info Pointer to data structure to contain phonebook | |
452 information (allocated by caller). | |
453 | |
454 *******************************************************************************/ | |
455 | |
456 PB_RET ATB_pb_Info(SHORT phonebook_id, T_PB_INFO *phonebook_info) | |
457 { | |
458 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
459 | |
460 /* Ensure that phonebook exists */ | |
461 if (!data) | |
462 { | |
463 trace("**ERROR** Phonebook does not exist"); | |
464 return PB_BOOKDOESNOTEXIST; | |
465 } | |
466 | |
467 phonebook_info->records_used = data->records_used; | |
468 phonebook_info->records_max = data->records_max; | |
469 phonebook_info->records_free = data->records_max - data->records_used; | |
470 phonebook_info->search_results = data->search_results; | |
471 | |
472 return PB_OK; | |
473 } | |
474 | |
475 | |
476 /******************************************************************************* | |
477 | |
478 $Function: ATB_pb_ReadRec | |
479 | |
480 $Description: Reads a record from the logical position index. The record information | |
481 will be returned in the data structure pointed to by record. The | |
482 T_PB_RECORD structure must be allocated by the user. | |
483 | |
484 This function calls the ATB_mem_ReadRec function, with an additional | |
485 check to make sure no other commands are currently executing. | |
486 | |
487 $Returns: PB_OK Action completed OK. | |
488 PB_BUSY Failed, phonebook is busy. | |
489 PB_FILEREADFAIL File read encountered an error | |
490 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
491 | |
492 $Arguments: phonebook_id The phonebook identifier | |
493 index_type The index list from which the record is to be read | |
494 log_index Logical index in the index list of the record to read | |
495 record Structure in which to store record data | |
496 | |
497 *******************************************************************************/ | |
498 | |
499 PB_RET ATB_pb_ReadRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, T_PB_RECORD *record) | |
500 { | |
501 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
502 PB_RET result; | |
503 | |
504 tracefunction("ATB_pb_ReadRec"); | |
505 | |
506 /* Ensure that phonebook exists */ | |
507 if (!data) | |
508 { | |
509 trace("**ERROR** Phonebook does not exist"); | |
510 return PB_BOOKDOESNOTEXIST; | |
511 } | |
512 | |
513 /* Make sure phonebook is not busy */ | |
514 | |
515 if (ATB_pb_Status(phonebook_id)==PB_BUSY) | |
516 { | |
517 trace("* ERROR * - Phonebook is busy"); | |
518 result = PB_BUSY; | |
519 } | |
520 else | |
521 { | |
522 /* Read the record from cache or from file */ | |
523 | |
524 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, record); | |
525 } | |
526 | |
527 /* Send success/failure info to the GI */ | |
528 | |
529 if (result==PB_OK) | |
530 GI_pb_OK(phonebook_id, PB_READREC, NULL); | |
531 else if (result!=PB_EXCT) | |
532 GI_pb_Error(phonebook_id, PB_READREC, result); | |
533 | |
534 /* Close any open file */ | |
535 | |
536 FS_pb_Finished(phonebook_id); | |
537 | |
538 return result; | |
539 } | |
540 | |
541 | |
542 /******************************************************************************* | |
543 | |
544 $Function: ATB_pb_WriteRec | |
545 | |
546 $Description: Writes a record to the logical position index. If the index is | |
547 PB_NEW_RECORD, a new record is added, otherwise the previous | |
548 record at that position is overwritten. The name and number index lists | |
549 will be updated with the new entry in the appropriate place in each. | |
550 GI_pb_OK will be called to confirm that the write completed successfully, | |
551 otherwise GI_pb_Error will be called with an error code. | |
552 Since the order of the records may change due to sorting, GI_pb_OK | |
553 will receive a pointer to an integer new_log_index, which will store the | |
554 new position of the record in the chosen index list. This is allocated | |
555 by and will be destroyed by the phonebook, so must be copied by the | |
556 GI before function return. | |
557 | |
558 $Returns: PB_OK Action completed OK. | |
559 PB_EXCT Action currently executing, callback awaited. | |
560 GI_pb_OK will be called if successful, | |
561 GI_pb_Error otherwise. | |
562 GI_pb_OK will receive a pointer to the following: | |
563 SHORT new_log_index - The new position of the | |
564 record in the chosen index list | |
565 PB_BUSY Failed, phonebook is busy. | |
566 PB_FILEWRITEFAIL File write encountered an error | |
567 PB_RECDOESNOTEXIST (Overwriting only) Tried to access a record that | |
568 does not exist | |
569 | |
570 $Arguments: phonebook_id The phonebook identifier | |
571 index_type The index list of the record to write | |
572 log_index Logical index in the index list of the record to write | |
573 record Pointer to record data to write to phonebook | |
574 (allocated by caller) | |
575 | |
576 *******************************************************************************/ | |
577 | |
578 PB_RET ATB_pb_WriteRec(SHORT phonebook_id, T_PB_TYPE index_type, SHORT log_index, T_PB_RECORD *record) | |
579 { | |
580 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
581 SHORT phys_index; | |
582 | |
583 tracefunction("ATB_pb_WriteRec"); | |
584 | |
585 /* Ensure that phonebook exists */ | |
586 if (!data) | |
587 { | |
588 trace("**ERROR** Phonebook does not exist"); | |
589 return PB_BOOKDOESNOTEXIST; | |
590 } | |
591 | |
592 /* Make sure phonebook is not busy */ | |
593 | |
594 if (ATB_pb_Status(phonebook_id)==PB_BUSY) | |
595 { | |
596 trace("* ERROR * - Phonebook is busy"); | |
597 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_BUSY); | |
598 return PB_BUSY; | |
599 } | |
600 | |
601 /* Are we adding a new record, or overwriting an old one? */ | |
602 | |
603 if (log_index==PB_NEW_RECORD) | |
604 { | |
605 /* Is phonebook full? */ | |
606 | |
607 if (data->records_used==data->records_max) | |
608 { | |
609 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_BOOKFULL); | |
610 return PB_BOOKFULL; | |
611 } | |
612 | |
613 /* Find an empty physical record */ | |
614 for (phys_index=0; phys_index<data->records_max; phys_index++) | |
615 { | |
616 if (data->in_memory[phys_index]==PB_EMPTY_RECORD) | |
617 break; | |
618 } | |
619 } | |
620 else | |
621 { | |
622 /* Check that record exists */ | |
623 | |
624 if (log_index<0 | |
625 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER)) | |
626 || (index_type==INDEX_SEARCH && log_index>data->search_results) | |
627 || (index_type==INDEX_PHYSICAL && log_index>data->records_max)) | |
628 { | |
629 GI_pb_Error(phonebook_id, PB_WRITEREC, PB_RECDOESNOTEXIST); | |
630 return PB_RECDOESNOTEXIST; | |
631 } | |
632 | |
633 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index); | |
634 } | |
635 | |
636 /* Set up command */ | |
637 | |
638 data->command_id = PB_WRITEREC; | |
639 data->status = PB_STATUS_INIT; | |
640 | |
641 data->param.WriteRec.log_index = log_index; | |
642 data->param.WriteRec.index_type = index_type; | |
643 data->param.WriteRec.phys_index = phys_index; | |
644 data->param.WriteRec.record = record; | |
645 | |
646 return ATB_status_WriteRec(phonebook_id); | |
647 } | |
648 | |
649 /* Status function for WriteRec */ | |
650 | |
651 PB_RET ATB_status_WriteRec(SHORT phonebook_id) | |
652 { | |
653 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
654 T_PB_WRITEREC *WriteRec = &data->param.WriteRec; | |
655 SHORT blocking; | |
656 PB_RET result; | |
657 SHORT name_log_index; | |
658 SHORT number_log_index; | |
659 SHORT *log_index_return; | |
660 | |
661 blocking = TRUE; | |
662 while (blocking) | |
663 { | |
664 switch(data->status) | |
665 { | |
666 case PB_STATUS_INIT: | |
667 result = FS_pb_WriteRec(phonebook_id, WriteRec->phys_index, WriteRec->record); | |
668 | |
669 /* Select next state */ | |
670 | |
671 data->status = PB_STATUS_COMPLETE; | |
672 | |
673 /* Allow exit from function */ | |
674 | |
675 if (result!=PB_OK) | |
676 blocking = FALSE; | |
677 break; | |
678 | |
679 case PB_STATUS_COMPLETE: | |
680 | |
681 if (WriteRec->log_index!=PB_NEW_RECORD) | |
682 { | |
683 name_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NAME, WriteRec->phys_index); | |
684 ATB_index_RemoveRec(phonebook_id, INDEX_NAME, name_log_index); | |
685 number_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NUMBER, WriteRec->phys_index); | |
686 ATB_index_RemoveRec(phonebook_id, INDEX_NUMBER, number_log_index); | |
687 data->records_used--; | |
688 } | |
689 | |
690 /* Indicate that record is new, then add to the cache */ | |
691 | |
692 data->in_memory[WriteRec->phys_index] = 0; | |
693 ATB_mem_UpdateCache(phonebook_id, WriteRec->phys_index, WriteRec->record); | |
694 | |
695 /* Add the record to the index lists */ | |
696 | |
697 ATB_index_AddRec(phonebook_id, INDEX_NAME, WriteRec->phys_index, WriteRec->record, &name_log_index); | |
698 ATB_index_AddRec(phonebook_id, INDEX_NUMBER, WriteRec->phys_index, WriteRec->record, &number_log_index); | |
699 data->records_used++; | |
700 | |
701 blocking = FALSE; | |
702 | |
703 /* Close any open file */ | |
704 | |
705 FS_pb_Finished(phonebook_id); | |
706 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table); | |
707 | |
708 /* Notify the GI of success */ | |
709 log_index_return = NULL; | |
710 if (WriteRec->index_type==INDEX_NAME) | |
711 log_index_return = &name_log_index; | |
712 if (WriteRec->index_type==INDEX_NUMBER) | |
713 log_index_return = &number_log_index; | |
714 | |
715 GI_pb_OK(phonebook_id, data->command_id, log_index_return); | |
716 result = PB_OK; | |
717 data->status = PB_STATUS_NONE; | |
718 break; | |
719 } | |
720 } | |
721 | |
722 /* Report any errors to the GI */ | |
723 | |
724 if (result!=PB_OK && result!=PB_EXCT) | |
725 { | |
726 GI_pb_Error(phonebook_id, PB_WRITEREC, result); | |
727 } | |
728 | |
729 return result; | |
730 } | |
731 | |
732 | |
733 /******************************************************************************* | |
734 | |
735 $Function: ATB_pb_DeleteRec | |
736 | |
737 $Description: Deletes a record at a logical position index. | |
738 GI_pb_OK will be called to confirm that the delete completed successfully, | |
739 otherwise GI_pb_Error will be called with an error code. | |
740 | |
741 $Returns: PB_OK Action completed OK. | |
742 PB_EXCT Action currently executing, callback awaited. | |
743 GI_pb_OK will be called if successful, | |
744 GI_pb_Error otherwise. | |
745 PB_BUSY Failed, phonebook is busy. | |
746 PB_FILEWRITEFAIL File write encountered an error | |
747 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
748 | |
749 $Arguments: phonebook_id The phonebook identifier | |
750 index_type The index list of the record to delete | |
751 log_index Logical index in the index list of the record to delete | |
752 | |
753 *******************************************************************************/ | |
754 | |
755 PB_RET ATB_pb_DeleteRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index) | |
756 { | |
757 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
758 | |
759 tracefunction("ATB_pb_DeleteRec"); | |
760 | |
761 /* Ensure that phonebook exists */ | |
762 if (!data) | |
763 { | |
764 trace("**ERROR** Phonebook does not exist"); | |
765 return PB_BOOKDOESNOTEXIST; | |
766 } | |
767 | |
768 /* Make sure phonebook is not busy */ | |
769 | |
770 if (ATB_pb_Status(phonebook_id)==PB_BUSY) | |
771 { | |
772 trace("* ERROR * - Phonebook is busy"); | |
773 GI_pb_Error(phonebook_id, PB_DELETEREC, PB_BUSY); | |
774 return PB_BUSY; | |
775 } | |
776 | |
777 /* Check that record exists */ | |
778 | |
779 if (log_index<0 | |
780 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER)) | |
781 || (index_type==INDEX_SEARCH && log_index>data->search_results) | |
782 || (index_type==INDEX_PHYSICAL && log_index>data->records_max)) | |
783 { | |
784 GI_pb_Error(phonebook_id, PB_DELETEREC, PB_RECDOESNOTEXIST); | |
785 return PB_RECDOESNOTEXIST; | |
786 } | |
787 | |
788 /* Set up the command */ | |
789 | |
790 data->command_id = PB_DELETEREC; | |
791 data->status = PB_STATUS_INIT; | |
792 | |
793 data->param.DeleteRec.log_index = log_index; | |
794 data->param.DeleteRec.index_type = index_type; | |
795 data->param.DeleteRec.phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index); | |
796 | |
797 return ATB_status_DeleteRec(phonebook_id); | |
798 } | |
799 | |
800 /* Status function for DeleteRec */ | |
801 | |
802 PB_RET ATB_status_DeleteRec(SHORT phonebook_id) | |
803 { | |
804 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
805 T_PB_DELETEREC *DeleteRec = &data->param.DeleteRec; | |
806 SHORT blocking; | |
807 PB_RET result; | |
808 SHORT name_log_index; | |
809 SHORT number_log_index; | |
810 | |
811 blocking = TRUE; | |
812 while (blocking) | |
813 { | |
814 switch(data->status) | |
815 { | |
816 case PB_STATUS_INIT: | |
817 result = FS_pb_DeleteRec(phonebook_id, DeleteRec->phys_index); | |
818 | |
819 /* Select next state */ | |
820 | |
821 data->status = PB_STATUS_COMPLETE; | |
822 | |
823 /* Allow exit from function */ | |
824 | |
825 if (result!=PB_OK) | |
826 blocking = FALSE; | |
827 break; | |
828 | |
829 case PB_STATUS_COMPLETE: | |
830 name_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NAME, DeleteRec->phys_index); | |
831 ATB_index_RemoveRec(phonebook_id, INDEX_NAME, name_log_index); | |
832 number_log_index = ATB_index_GetLogIndex(phonebook_id, INDEX_NUMBER, DeleteRec->phys_index); | |
833 ATB_index_RemoveRec(phonebook_id, INDEX_NUMBER, number_log_index); | |
834 data->records_used--; | |
835 data->in_memory[DeleteRec->phys_index] = -1; | |
836 | |
837 // Jan 18, 2004 REF: CRR MMI-SPR-25332 xnkulkar | |
838 // Description: Moving entries from Sim Card to phone memory fails. | |
839 // Solution: When entries are moved, corresponding updations are done in cache as well. | |
840 if(data->cache[DeleteRec->phys_index]!=NULL) | |
841 { | |
842 ATB_pb_FreeRec(phonebook_id, data->cache[DeleteRec->phys_index]); | |
843 data->cache[DeleteRec->phys_index]=NULL; | |
844 data->cache_size--; | |
845 } | |
846 | |
847 /* Close any open file */ | |
848 | |
849 FS_pb_Finished(phonebook_id); | |
850 FS_pb_WriteTables(phonebook_id, data->records_used, data->name_table, data->number_table); | |
851 | |
852 blocking = FALSE; | |
853 | |
854 /* Notify the GI of success */ | |
855 | |
856 GI_pb_OK(phonebook_id, data->command_id, NULL); | |
857 result = PB_OK; | |
858 data->status = PB_STATUS_NONE; | |
859 break; | |
860 } | |
861 } | |
862 | |
863 /* Report any errors to the GI */ | |
864 | |
865 if (result!=PB_OK && result!=PB_EXCT) | |
866 { | |
867 GI_pb_Error(phonebook_id, PB_DELETEREC, result); | |
868 } | |
869 | |
870 return result; | |
871 } | |
872 | |
873 | |
874 /******************************************************************************* | |
875 | |
876 $Function: ATB_pb_Find | |
877 | |
878 $Description: Find the nearest match to the supplied record. Only the index_type | |
879 specified will be considered: if the index_type is INDEX_NAME, then the | |
880 name only will be matched; if INDEX_NUMBER, then just the number. | |
881 The new_log_index parameter should be a pointer to a user allocated | |
882 integer. This will return the logical index of the closest match in the | |
883 index list specified. This index either corresponds to a perfect match, | |
884 or to the record that would appear just after the provided record in the | |
885 list. For example, if the list consisted of record 0, Alice and record 1, | |
886 Carol, then a search for Bob would return 1. A search for a record | |
887 that would occur before the first record always returns 0. A search for | |
888 a record that would occur after the last record returns the index of the | |
889 last record +1. | |
890 The "match" parameter should be a pointer to a user allocated variable | |
891 of type T_PB_MATCH. This returns information about how closely the | |
892 found entry matches the record. In the example above, a search for | |
893 Bob would return 1 and MATCH_NONE; a search for Ca would return 1 | |
894 and MATCH_START, and a search for Carol would return 1 and | |
895 MATCH_EXACT. Rarely, match may be MATCH_FRAGMENT: this can be | |
896 considered equivalent to MATCH_NONE in this context. | |
897 | |
898 $Returns: PB_OK Action completed OK. | |
899 PB_BUSY Failed, phonebook is busy. | |
900 PB_FILEREADFAIL File read encountered an error | |
901 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
902 (should never happen) | |
903 | |
904 $Arguments: phonebook_id The phonebook identifier | |
905 index_type The index_type of the provided record that is to be | |
906 searched for, and the index list that the resulting | |
907 new_log_index pertains to | |
908 record The record whose index_type is to be matched | |
909 new_log_index Returns with the logical index of the closest matching | |
910 record | |
911 match Specifies how good the resulting match was | |
912 (MATCH_NONE, MATCH_START, MATCH_FRAGMENT | |
913 or MATCH_EXACT). | |
914 | |
915 *******************************************************************************/ | |
916 | |
917 | |
918 PB_RET ATB_pb_Find (SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *new_log_index, T_PB_MATCH *match) | |
919 { | |
920 PB_RET result; | |
921 | |
922 tracefunction("ATB_pb_Find"); | |
923 | |
924 result = ATB_index_Find(phonebook_id, index_type, record, new_log_index, match); | |
925 | |
926 /* Close any open file */ | |
927 | |
928 FS_pb_Finished(phonebook_id); | |
929 | |
930 /* Send success/failure info to the GI */ | |
931 | |
932 if (result==PB_OK) | |
933 GI_pb_OK(phonebook_id, PB_FIND, NULL); | |
934 else if (result!=PB_EXCT) | |
935 GI_pb_Error(phonebook_id, PB_FIND, result); | |
936 | |
937 return result; | |
938 } | |
939 | |
940 | |
941 /******************************************************************************* | |
942 | |
943 $Function: ATB_pb_ReadRecList | |
944 | |
945 $Description: Fetches record information of sequential records in an index list, starting | |
946 at logical record start_log_index and fetching recs_count records in total. | |
947 The information will be stored in the caller allocated array of records | |
948 provided. | |
949 | |
950 $Returns: PB_OK Action completed OK. | |
951 PB_BUSY Failed, phonebook is busy. | |
952 PB_FILEREADFAIL File read encountered an error | |
953 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
954 | |
955 $Arguments: phonebook_id The phonebook identifier | |
956 index_type The index list to use | |
957 start_log_index Logical index in the index list of the first record to | |
958 read | |
959 recs_count Total number of sequential records to read. | |
960 record Array of entries in which to store the fetched records. | |
961 The array must be recs_count in size. (Caller allocated). | |
962 | |
963 *******************************************************************************/ | |
964 | |
965 PB_RET ATB_pb_ReadRecList(SHORT phonebook_id, T_PB_INDEX index_type, SHORT start_log_index, SHORT num_recs, T_PB_LIST *list) | |
966 { | |
967 PB_RET result; | |
968 SHORT log_index; | |
969 | |
970 tracefunction("ATB_pb_ReadRecList"); | |
971 | |
972 list->records_used = 0; | |
973 | |
974 /* Make sure phonebook is not busy */ | |
975 | |
976 if (ATB_pb_Status(phonebook_id)==PB_BUSY) | |
977 { | |
978 trace("* ERROR * - Phonebook is busy"); | |
979 /* Report any errors to the GI */ | |
980 GI_pb_Error(phonebook_id, PB_READRECLIST, PB_BUSY); | |
981 return PB_BUSY; | |
982 } | |
983 | |
984 /* Read in list of records */ | |
985 | |
986 for (log_index = start_log_index; log_index<start_log_index+num_recs && log_index<list->records_max; log_index++) | |
987 { | |
988 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, &list->record[log_index-start_log_index]); | |
989 if (result!=PB_OK) | |
990 break; | |
991 list->records_used++; | |
992 } | |
993 | |
994 /* Close any open file */ | |
995 | |
996 FS_pb_Finished(phonebook_id); | |
997 | |
998 /* Send success/failure info to the GI */ | |
999 | |
1000 if (result==PB_OK) | |
1001 GI_pb_OK(phonebook_id, PB_READRECLIST, NULL); | |
1002 else if (result!=PB_EXCT) | |
1003 GI_pb_Error(phonebook_id, PB_READRECLIST, result); | |
1004 | |
1005 return result; | |
1006 } | |
1007 | |
1008 | |
1009 /******************************************************************************* | |
1010 | |
1011 $Function: ATB_pb_Search | |
1012 | |
1013 $Description: Searches every record in the index list for a fragment. The index list | |
1014 must be either INDEX_NAME or INDEX_NUMBER. If it is INDEX_NAME, | |
1015 then a name fragment will be searched for; if it is INDEX_NUMBER, | |
1016 a number fragment will be searched for. | |
1017 | |
1018 The results are stored in an index list. They may be accessed by | |
1019 using the normal read and write functions, using the index type | |
1020 INDEX_SEARCH. The size of the search list is returned in the variable | |
1021 recs_count. | |
1022 | |
1023 $Returns: PB_OK Action completed OK. | |
1024 PB_BUSY Failed, phonebook is busy. | |
1025 PB_FILEREADFAIL File read encountered an error | |
1026 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
1027 (should never happen) | |
1028 | |
1029 $Arguments: phonebook_id The phonebook identifier | |
1030 index_type The index list to use | |
1031 record Record containing the fragment to search for | |
1032 recs_count Pointer to an int (user allocated) in which will be returned | |
1033 the number of search results. | |
1034 | |
1035 | |
1036 *******************************************************************************/ | |
1037 | |
1038 PB_RET ATB_pb_Search(SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *recs_count) | |
1039 { | |
1040 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1041 PB_RET result; | |
1042 SHORT count = 0; | |
1043 SHORT log_index; | |
1044 T_PB_MATCH match; | |
1045 T_PB_RECORD *cur_record; | |
1046 | |
1047 /* Ensure that phonebook exists */ | |
1048 if (!data) | |
1049 { | |
1050 trace("**ERROR** Phonebook does not exist"); | |
1051 return PB_BOOKDOESNOTEXIST; | |
1052 } | |
1053 | |
1054 /* Allocate record for temporary use */ | |
1055 | |
1056 cur_record = ATB_pb_AllocRec(phonebook_id); | |
1057 | |
1058 /* Make sure phonebook is not busy */ | |
1059 | |
1060 if (ATB_pb_Status(phonebook_id)==PB_BUSY) | |
1061 { | |
1062 trace("* ERROR * - Phonebook is busy"); | |
1063 GI_pb_Error(phonebook_id, PB_SEARCH, PB_BUSY); | |
1064 return PB_BUSY; | |
1065 } | |
1066 | |
1067 /* Make sure we're searching a valid index type */ | |
1068 | |
1069 if (index_type==INDEX_PHYSICAL || index_type==INDEX_SEARCH) | |
1070 { | |
1071 GI_pb_Error(phonebook_id, PB_SEARCH, PB_INDEXINVALID); | |
1072 return PB_INDEXINVALID; | |
1073 } | |
1074 | |
1075 for (log_index=0; log_index<data->records_used; log_index++) | |
1076 { | |
1077 result = ATB_mem_ReadRec(phonebook_id, index_type, log_index, cur_record); | |
1078 if (result!=PB_OK) | |
1079 break; | |
1080 | |
1081 match = ATB_index_Match(record, cur_record, index_type); | |
1082 | |
1083 if (match==MATCH_EXACT || match==MATCH_START || match==MATCH_FRAGMENT) | |
1084 { | |
1085 data->search_table[count] = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index); | |
1086 count++; | |
1087 } | |
1088 } | |
1089 | |
1090 data->search_results = count; | |
1091 *recs_count = count; | |
1092 | |
1093 /* Free allocated record */ | |
1094 | |
1095 ATB_pb_FreeRec(phonebook_id, cur_record); | |
1096 | |
1097 /* Close any open file */ | |
1098 | |
1099 FS_pb_Finished(phonebook_id); | |
1100 | |
1101 /* Send success/failure info to the GI */ | |
1102 | |
1103 if (result==PB_OK) | |
1104 GI_pb_OK(phonebook_id, PB_SEARCH, NULL); | |
1105 else if (result!=PB_EXCT) | |
1106 GI_pb_Error(phonebook_id, PB_SEARCH, result); | |
1107 | |
1108 return result; | |
1109 } | |
1110 | |
1111 | |
1112 /******************************************************************************* | |
1113 | |
1114 $Function: ATB_pb_ConvIndex | |
1115 | |
1116 $Description: Returns the index in table dest_index_type corresponding to the index | |
1117 in table src_index_type. | |
1118 | |
1119 $Returns: PB_OK Action completed OK. | |
1120 | |
1121 $Arguments: phonebook_id The phonebook identifier. | |
1122 index_type The index table of the original index. | |
1123 log_index The original logical index. | |
1124 new_index_type The index table required. | |
1125 new_log_index Pointer to where the new logical index will be stored | |
1126 | |
1127 *******************************************************************************/ | |
1128 | |
1129 PB_RET ATB_pb_ConvIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, | |
1130 T_PB_INDEX new_index_type, SHORT *new_log_index) | |
1131 { | |
1132 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1133 SHORT phys_index; | |
1134 | |
1135 /* Ensure that phonebook exists */ | |
1136 if (!data) | |
1137 { | |
1138 trace("**ERROR** Phonebook does not exist"); | |
1139 return PB_BOOKDOESNOTEXIST; | |
1140 } | |
1141 | |
1142 if (index_type==new_index_type) | |
1143 { | |
1144 *new_log_index = log_index; | |
1145 } | |
1146 else | |
1147 { | |
1148 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index); | |
1149 *new_log_index = ATB_index_GetLogIndex(phonebook_id, new_index_type, phys_index); | |
1150 } | |
1151 | |
1152 return PB_OK; | |
1153 } | |
1154 | |
1155 | |
1156 /******************************************************************************* | |
1157 | |
1158 $Function: ATB_pb_CharToBCD | |
1159 | |
1160 $Description: Converts an ascii string of digits into BCD form, with 4 bits representing | |
1161 each digit. | |
1162 | |
1163 $Returns: None | |
1164 | |
1165 $Arguments: src - source string (ascii) | |
1166 dest - destination string for BCD digits | |
1167 | |
1168 *******************************************************************************/ | |
1169 | |
1170 void ATB_pb_CharToBCD(UBYTE *dest, char *src, int max_len) | |
1171 { | |
1172 UBYTE srcIndex = 0; | |
1173 UBYTE destIndex = 0; | |
1174 BOOL leftbits = TRUE; /* Left or right nibble */ | |
1175 UBYTE digit = 0; | |
1176 | |
1177 while (digit!=0xF && srcIndex<max_len) | |
1178 { | |
1179 if (src[srcIndex]==NULL) | |
1180 digit = 0xF; /* 0xF terminates BCD */ | |
1181 else | |
1182 digit = src[srcIndex]-'0'; /* The digit, 0 to 9. */ | |
1183 | |
1184 if (leftbits) | |
1185 { | |
1186 dest[destIndex] = digit; | |
1187 leftbits = FALSE; | |
1188 } | |
1189 else | |
1190 { | |
1191 dest[destIndex] |= digit<<4; /* *16 shifts right 4 bits */ | |
1192 leftbits = TRUE; | |
1193 destIndex++; | |
1194 } | |
1195 srcIndex++; | |
1196 } | |
1197 | |
1198 return; | |
1199 } | |
1200 | |
1201 | |
1202 /******************************************************************************* | |
1203 | |
1204 $Function: ATB_pb_BCDToChar | |
1205 | |
1206 $Description: Converts a BCD string to ascii digits | |
1207 | |
1208 $Returns: None | |
1209 | |
1210 $Arguments: src - source string (BCD) | |
1211 dest - destination string for ascii digits | |
1212 | |
1213 *******************************************************************************/ | |
1214 | |
1215 void ATB_pb_BCDToChar(char *dest, UBYTE *src, int max_len) | |
1216 { | |
1217 SHORT numIndex = 0; | |
1218 UBYTE digit = 0xF; //dummy | |
1219 | |
1220 while (digit!=NULL && numIndex<max_len) | |
1221 { | |
1222 /*HELLO!*/ | |
1223 digit = ATB_num_Digit(src, numIndex); | |
1224 | |
1225 if (digit==0xF) | |
1226 digit = NULL; | |
1227 else | |
1228 digit+='0'; | |
1229 dest[numIndex] = digit; | |
1230 | |
1231 numIndex++; | |
1232 } | |
1233 | |
1234 return; | |
1235 } | |
1236 | |
1237 | |
1238 /******************************************************************************* | |
1239 | |
1240 $Function: ATB_pb_AllocRec | |
1241 | |
1242 $Description: Allocates memory for a record | |
1243 | |
1244 $Returns: | |
1245 | |
1246 $Arguments: phonebook_id The phonebook identifier | |
1247 | |
1248 *******************************************************************************/ | |
1249 | |
1250 T_PB_RECORD *ATB_pb_AllocRec(SHORT phonebook_id) | |
1251 { | |
1252 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1253 T_PB_RECORD *record; | |
1254 | |
1255 record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD)); | |
1256 | |
1257 record->alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT)); | |
1258 record->number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2); | |
1259 if (data->ext_max>0) | |
1260 { | |
1261 record->ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max); | |
1262 } | |
1263 else | |
1264 { | |
1265 record->ext_data = NULL; | |
1266 } | |
1267 record->ton_npi = 0; | |
1268 | |
1269 return record; | |
1270 } | |
1271 | |
1272 | |
1273 /******************************************************************************* | |
1274 | |
1275 $Function: ATB_pb_FreeRec | |
1276 | |
1277 $Description: Frees memory allocated for a record | |
1278 | |
1279 $Returns: | |
1280 | |
1281 $Arguments: phonebook_id The phonebook identifier | |
1282 record The record to destroy | |
1283 | |
1284 *******************************************************************************/ | |
1285 | |
1286 void ATB_pb_FreeRec(SHORT phonebook_id, T_PB_RECORD *record) | |
1287 { | |
1288 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1289 | |
1290 if (data->ext_max>0 && record->ext_data!=NULL) | |
1291 { | |
1292 GI_pb_MemFree((UBYTE *)record->ext_data, data->ext_max); | |
1293 } | |
1294 GI_pb_MemFree((UBYTE *)record->number, data->number_max/2); | |
1295 GI_pb_MemFree((UBYTE *)record->alpha.data, data->alpha_max*sizeof(USHORT)); | |
1296 | |
1297 GI_pb_MemFree((UBYTE *)record, sizeof(T_PB_RECORD)); | |
1298 | |
1299 return; | |
1300 } | |
1301 | |
1302 | |
1303 /******************************************************************************* | |
1304 | |
1305 $Function: ATB_pb_AllocRecList | |
1306 | |
1307 $Description: Allocates memory for a list of records | |
1308 | |
1309 $Returns: | |
1310 | |
1311 $Arguments: phonebook_id The phonebook identifier | |
1312 num_recs The number of records to allocate | |
1313 | |
1314 *******************************************************************************/ | |
1315 | |
1316 T_PB_LIST *ATB_pb_AllocRecList(SHORT phonebook_id, SHORT num_recs) | |
1317 { | |
1318 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1319 T_PB_LIST *list; | |
1320 SHORT rec_index; | |
1321 | |
1322 list = (T_PB_LIST *)GI_pb_MemAlloc(sizeof(T_PB_LIST)); | |
1323 list->records_max = num_recs; | |
1324 list->records_used = 0; | |
1325 list->record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD)*num_recs); | |
1326 | |
1327 for (rec_index=0; rec_index<num_recs; rec_index++) | |
1328 { | |
1329 list->record[rec_index].alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT)); | |
1330 list->record[rec_index].number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2); | |
1331 if (data->ext_max>0) | |
1332 { | |
1333 list->record[rec_index].ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max); | |
1334 } | |
1335 else | |
1336 { | |
1337 list->record[rec_index].ext_data = NULL; | |
1338 } | |
1339 } | |
1340 | |
1341 return list; | |
1342 } | |
1343 | |
1344 | |
1345 /******************************************************************************* | |
1346 | |
1347 $Function: ATB_pb_FreeRecList | |
1348 | |
1349 $Description: Frees memory allocated for a list of records | |
1350 | |
1351 $Returns: | |
1352 | |
1353 $Arguments: phonebook_id The phonebook identifier | |
1354 record The records to destroy | |
1355 num_recs Number of records in the list | |
1356 | |
1357 *******************************************************************************/ | |
1358 | |
1359 void ATB_pb_FreeRecList(SHORT phonebook_id, T_PB_LIST *list) | |
1360 { | |
1361 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1362 SHORT rec_index; | |
1363 | |
1364 for (rec_index=0; rec_index<list->records_max; rec_index++) | |
1365 { | |
1366 if (data->ext_max>0 && list->record[rec_index].ext_data!=NULL) | |
1367 { | |
1368 GI_pb_MemFree((UBYTE *)list->record[rec_index].ext_data, data->ext_max); | |
1369 } | |
1370 GI_pb_MemFree((UBYTE *)list->record[rec_index].number, data->number_max/2); | |
1371 GI_pb_MemFree((UBYTE *)list->record[rec_index].alpha.data, data->alpha_max*sizeof(USHORT)); | |
1372 } | |
1373 | |
1374 GI_pb_MemFree((UBYTE *)list->record, sizeof(T_PB_RECORD)*list->records_max); | |
1375 GI_pb_MemFree((UBYTE *)list, sizeof(T_PB_LIST)); | |
1376 | |
1377 return; | |
1378 } | |
1379 | |
1380 | |
1381 /******************************************************************************* | |
1382 | |
1383 $Function: ATB_mem_CopyRec | |
1384 | |
1385 $Description: Copies a record from one location to another. The destination should | |
1386 have memory allocated for its strings. | |
1387 | |
1388 $Returns: | |
1389 | |
1390 $Arguments: dest_record The destination record | |
1391 src_record The source record | |
1392 | |
1393 *******************************************************************************/ | |
1394 | |
1395 void ATB_pb_CopyRec(SHORT phonebook_id, T_PB_RECORD *dest_record, T_PB_RECORD *src_record) | |
1396 { | |
1397 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1398 | |
1399 dest_record->alpha.length = src_record->alpha.length; | |
1400 dest_record->alpha.dcs = src_record->alpha.dcs; | |
1401 memcpy((UBYTE *)dest_record->alpha.data, (UBYTE *)src_record->alpha.data, data->alpha_max*sizeof(USHORT)); | |
1402 memcpy(dest_record->number, src_record->number, data->number_max/2); | |
1403 if (data->ext_max>0) | |
1404 { | |
1405 memcpy(dest_record->ext_data, src_record->ext_data, data->ext_max); | |
1406 } | |
1407 dest_record->ton_npi = src_record->ton_npi; | |
1408 | |
1409 return; | |
1410 } | |
1411 | |
1412 | |
1413 /******************************************************************************* | |
1414 | |
1415 $Function: ATB_pb_OK | |
1416 | |
1417 $Description: This function is called if the requested FS command executed successfully. | |
1418 | |
1419 $Returns: None. | |
1420 | |
1421 $Arguments: phonebook_id The phonebook identifier | |
1422 | |
1423 *******************************************************************************/ | |
1424 | |
1425 | |
1426 PB_RET ATB_pb_OK(SHORT phonebook_id) | |
1427 { | |
1428 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1429 PB_RET result; | |
1430 | |
1431 switch(data->command_id) | |
1432 { | |
1433 case PB_INITIALISE: | |
1434 result = ATB_status_Initialise(phonebook_id); | |
1435 break; | |
1436 case PB_WRITEREC: | |
1437 result = ATB_status_WriteRec(phonebook_id); | |
1438 break; | |
1439 case PB_DELETEREC: | |
1440 result = ATB_status_DeleteRec(phonebook_id); | |
1441 break; | |
1442 } | |
1443 | |
1444 return result; | |
1445 } | |
1446 | |
1447 | |
1448 /******************************************************************************* | |
1449 | |
1450 $Function: ATB_pb_Error | |
1451 | |
1452 $Description: This function is called if an error was returned while executing the | |
1453 requested command. | |
1454 | |
1455 $Returns: None. | |
1456 | |
1457 $Arguments: phonebook_id The phonebook identifier | |
1458 error_id Identifies the error that occurred. | |
1459 | |
1460 *******************************************************************************/ | |
1461 | |
1462 void ATB_pb_Error(SHORT phonebook_id, SHORT error_id) | |
1463 { | |
1464 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1465 | |
1466 /* Forward the error report to the GI */ | |
1467 | |
1468 GI_pb_Error(phonebook_id, data->command_id, error_id); | |
1469 data->status = PB_STATUS_NONE; | |
1470 | |
1471 return; | |
1472 } | |
1473 | |
1474 /******************************************************************************* | |
1475 | |
1476 $Function: ATB_index_GetTable | |
1477 | |
1478 $Description: Returns a pointer to the index table specified by the index_type | |
1479 | |
1480 $Returns: None. | |
1481 | |
1482 $Arguments: phonebook_id The phonebook identifier | |
1483 index_type The index table required. | |
1484 | |
1485 *******************************************************************************/ | |
1486 | |
1487 SHORT * ATB_index_GetTable(SHORT phonebook_id, T_PB_INDEX index_type) | |
1488 { | |
1489 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1490 SHORT *table = NULL; | |
1491 | |
1492 switch(index_type) | |
1493 { | |
1494 case INDEX_NAME: | |
1495 table = data->name_table; | |
1496 break; | |
1497 case INDEX_NUMBER: | |
1498 table = data->number_table; | |
1499 break; | |
1500 case INDEX_SEARCH: | |
1501 table = data->search_table; | |
1502 break; | |
1503 default: | |
1504 table = GI_pb_GetTable(index_type); | |
1505 break; | |
1506 } | |
1507 | |
1508 return table; | |
1509 } | |
1510 | |
1511 | |
1512 /******************************************************************************* | |
1513 | |
1514 $Function: ATB_index_Find | |
1515 | |
1516 $Description: Find the nearest match to the supplied record. See ATB_pb_Find for | |
1517 more information. | |
1518 | |
1519 $Returns: PB_OK Action completed OK. | |
1520 PB_BUSY Failed, phonebook is busy. | |
1521 PB_FILEREADFAIL File read encountered an error | |
1522 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
1523 (should never happen) | |
1524 | |
1525 $Arguments: phonebook_id The phonebook identifier | |
1526 index_type The index_type of the provided record that is to be | |
1527 searched for, and the index list that the resulting | |
1528 new_log_index pertains to | |
1529 record The record whose index_type is to be matched | |
1530 new_log_index Returns with the logical index of the closest matching | |
1531 record | |
1532 match Specifies how good the resulting match was | |
1533 (MATCH_NONE, MATCH_START, MATCH_FRAGMENT | |
1534 or MATCH_EXACT). | |
1535 | |
1536 *******************************************************************************/ | |
1537 | |
1538 PB_RET ATB_index_Find (SHORT phonebook_id, T_PB_INDEX index_type, T_PB_RECORD *record, SHORT *new_log_index, T_PB_MATCH *match) | |
1539 { | |
1540 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1541 PB_RET result = PB_OK; | |
1542 SHORT *table; | |
1543 SHORT lower; | |
1544 SHORT upper; | |
1545 SHORT middle; | |
1546 T_PB_RECORD *comp_record; | |
1547 T_PB_COMPARE compare; | |
1548 UBYTE searching; | |
1549 | |
1550 /* Ensure that phonebook exists */ | |
1551 if (!data) | |
1552 { | |
1553 trace("**ERROR** Phonebook does not exist"); | |
1554 return PB_BOOKDOESNOTEXIST; | |
1555 } | |
1556 | |
1557 /* Allocate record for comparison */ | |
1558 | |
1559 comp_record = ATB_pb_AllocRec(phonebook_id); | |
1560 | |
1561 /* Make sure we're searching a valid index type */ | |
1562 | |
1563 if (index_type==INDEX_PHYSICAL || index_type==INDEX_SEARCH) | |
1564 { | |
1565 GI_pb_Error(phonebook_id, PB_FIND, PB_INDEXINVALID); | |
1566 return PB_INDEXINVALID; | |
1567 } | |
1568 | |
1569 table = ATB_index_GetTable(phonebook_id, index_type); | |
1570 | |
1571 /* The initial upper and lower bounds are the bounds of the array */ | |
1572 lower = 0; | |
1573 upper = data->records_used-1; | |
1574 | |
1575 searching = TRUE; | |
1576 | |
1577 /* If the list is empty, insert at 0 */ | |
1578 | |
1579 if (data->records_used==0) | |
1580 { | |
1581 middle = 0; | |
1582 searching = FALSE; | |
1583 } | |
1584 | |
1585 while (searching) | |
1586 { | |
1587 /* Compare our record with the middle element of the partition */ | |
1588 | |
1589 middle = (lower+upper)/2; | |
1590 | |
1591 result = ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record); | |
1592 | |
1593 if (result!=PB_OK) | |
1594 break; | |
1595 | |
1596 compare = ATB_index_Compare(record, comp_record, index_type); | |
1597 | |
1598 switch(compare) | |
1599 { | |
1600 case COMPARE_IDENTICAL: | |
1601 /* We've found a match; stop searching */ | |
1602 searching = FALSE; | |
1603 break; | |
1604 | |
1605 case COMPARE_FIRSTBEFORE: | |
1606 if (middle==lower) | |
1607 { | |
1608 /* The partition is a single element, so stop here. */ | |
1609 searching = FALSE; | |
1610 } | |
1611 else | |
1612 { | |
1613 /* Our record comes before the middle element; | |
1614 * redefine the partiton */ | |
1615 upper = middle - 1; | |
1616 } | |
1617 break; | |
1618 | |
1619 case COMPARE_FIRSTAFTER: | |
1620 if (middle==upper) | |
1621 { | |
1622 /* The partition is a single element, so stop here. The record | |
1623 * we need is the record after this one. */ | |
1624 middle++; | |
1625 searching = FALSE; | |
1626 } | |
1627 else | |
1628 { | |
1629 /* Our record comes after the middle element; | |
1630 * redefine the partiton */ | |
1631 lower = middle+1; | |
1632 } | |
1633 break; | |
1634 } | |
1635 } | |
1636 | |
1637 /* Store our results */ | |
1638 | |
1639 if (new_log_index) | |
1640 *new_log_index = middle; | |
1641 | |
1642 if (match) | |
1643 { | |
1644 ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record); | |
1645 *match = ATB_index_Match(record, comp_record, index_type); | |
1646 } | |
1647 | |
1648 /* Free allocated record */ | |
1649 | |
1650 ATB_pb_FreeRec(phonebook_id, comp_record); | |
1651 | |
1652 /* Send success/failure info to the GI */ | |
1653 | |
1654 if (result==PB_OK) | |
1655 GI_pb_OK(phonebook_id, PB_FIND, NULL); | |
1656 else if (result!=PB_EXCT) | |
1657 GI_pb_Error(phonebook_id, PB_FIND, result); | |
1658 | |
1659 return result; | |
1660 } | |
1661 | |
1662 | |
1663 /******************************************************************************* | |
1664 | |
1665 $Function: ATB_index_GetPhysIndex | |
1666 | |
1667 $Description: Returns the physical index corresponding to the given logical index, in | |
1668 the index table specified by the index_type. | |
1669 | |
1670 $Returns: None. | |
1671 | |
1672 $Arguments: phonebook_id The phonebook identifier. | |
1673 index_type The index table required. | |
1674 log_index The logical index. | |
1675 | |
1676 *******************************************************************************/ | |
1677 | |
1678 SHORT ATB_index_GetPhysIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index) | |
1679 { | |
1680 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1681 SHORT phys_index; | |
1682 SHORT *table; | |
1683 | |
1684 switch(index_type) | |
1685 { | |
1686 case INDEX_PHYSICAL: | |
1687 phys_index = log_index; | |
1688 break; | |
1689 case INDEX_NAME: | |
1690 case INDEX_NUMBER: | |
1691 case INDEX_SEARCH: | |
1692 table = ATB_index_GetTable(phonebook_id, index_type); | |
1693 phys_index = table[log_index]; | |
1694 break; | |
1695 } | |
1696 | |
1697 return phys_index; | |
1698 } | |
1699 | |
1700 | |
1701 /******************************************************************************* | |
1702 | |
1703 $Function: ATB_index_GetLogIndex | |
1704 | |
1705 $Description: Provided with the physical index, finds the logical index of the record | |
1706 in the index table specified. | |
1707 | |
1708 $Returns: None. | |
1709 | |
1710 $Arguments: phonebook_id The phonebook identifier | |
1711 index_type The index table required. | |
1712 phys_index The logical index of the record to find | |
1713 | |
1714 *******************************************************************************/ | |
1715 | |
1716 SHORT ATB_index_GetLogIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index) | |
1717 { | |
1718 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1719 SHORT *table = ATB_index_GetTable(phonebook_id, index_type); | |
1720 SHORT log_index; | |
1721 | |
1722 if (index_type==INDEX_PHYSICAL) | |
1723 { | |
1724 log_index = phys_index; | |
1725 } | |
1726 else | |
1727 { | |
1728 for (log_index=0; log_index<data->records_used; log_index++) | |
1729 { | |
1730 if (table[log_index]==phys_index) | |
1731 break; | |
1732 } | |
1733 } | |
1734 | |
1735 return log_index; | |
1736 } | |
1737 | |
1738 | |
1739 /******************************************************************************* | |
1740 | |
1741 $Function: ATB_index_AddRec | |
1742 | |
1743 $Description: Adds a record to an index list, sorting automatically as required. | |
1744 | |
1745 $Returns: None. | |
1746 | |
1747 $Arguments: phonebook_id The phonebook identifier | |
1748 index_type The index table required. | |
1749 phys_index The physical index of the record to add. | |
1750 record The record to add. | |
1751 new_log_index New logical index of record. | |
1752 | |
1753 *******************************************************************************/ | |
1754 | |
1755 void ATB_index_AddRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index, T_PB_RECORD *record, SHORT *new_log_index) | |
1756 { | |
1757 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1758 SHORT *table = ATB_index_GetTable(phonebook_id, index_type); | |
1759 SHORT log_index; | |
1760 SHORT found_log_index; | |
1761 | |
1762 ATB_index_Find(phonebook_id, index_type, record, &found_log_index, NULL); | |
1763 | |
1764 /* Shift end of index table down */ | |
1765 | |
1766 for (log_index=data->records_used; log_index>found_log_index; log_index--) | |
1767 { | |
1768 table[log_index] = table[log_index-1]; | |
1769 } | |
1770 | |
1771 table[found_log_index] = phys_index; | |
1772 | |
1773 if (new_log_index) | |
1774 *new_log_index = found_log_index; | |
1775 | |
1776 return; | |
1777 } | |
1778 | |
1779 /******************************************************************************* | |
1780 | |
1781 $Function: ATB_index_RemoveRec | |
1782 | |
1783 $Description: Removes a record reference from an index list, sorting the index list | |
1784 appropriately. | |
1785 | |
1786 $Returns: None. | |
1787 | |
1788 $Arguments: phonebook_id The phonebook identifier | |
1789 index_type The index table required. | |
1790 log_index The logical index of the record to remove | |
1791 | |
1792 *******************************************************************************/ | |
1793 | |
1794 void ATB_index_RemoveRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index) | |
1795 { | |
1796 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
1797 SHORT *table = ATB_index_GetTable(phonebook_id, index_type); | |
1798 SHORT table_index; | |
1799 | |
1800 for (table_index = log_index+1; table_index<data->records_used; table_index++) | |
1801 { | |
1802 table[table_index-1] = table[table_index]; | |
1803 } | |
1804 | |
1805 return; | |
1806 } | |
1807 | |
1808 | |
1809 /******************************************************************************* | |
1810 | |
1811 $Function: ATB_index_Match | |
1812 | |
1813 $Description: This function attempts a match between two records based on the | |
1814 index_type specified in index_type. It returns a value indicating | |
1815 whether there is no match (MATCH_NONE), a partial match | |
1816 (MAX_START), or an exact match (MATCH_EXACT). | |
1817 The function GI_pb_Match is called first, to check whether there is | |
1818 any user-specific matching required. If not, then ATB_alpha_Match | |
1819 is called for an alpha tag, or ATB_num_Match for a phone number. | |
1820 For any other index_type, MATCH_NONE is returned as default. | |
1821 | |
1822 $Returns: MATCH_EXACT, MATCH_START or MATCH_NONE | |
1823 | |
1824 $Arguments: record1 The first record to be compared | |
1825 record2 The second record to be compared | |
1826 index_type Indicator of the index_type which is to be matched | |
1827 | |
1828 *******************************************************************************/ | |
1829 | |
1830 T_PB_MATCH ATB_index_Match(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type) | |
1831 { | |
1832 T_PB_MATCH match; | |
1833 | |
1834 match = GI_pb_Match(record1, record2, index_type); | |
1835 | |
1836 if (match==MATCH_DEFAULT) | |
1837 { | |
1838 switch(index_type) | |
1839 { | |
1840 case INDEX_NAME: | |
1841 match = ATB_alpha_Match(&record1->alpha, &record2->alpha); | |
1842 break; | |
1843 case INDEX_NUMBER: | |
1844 match = ATB_num_Match(record1->number, record2->number); | |
1845 break; | |
1846 } | |
1847 } | |
1848 | |
1849 return match; | |
1850 } | |
1851 | |
1852 | |
1853 | |
1854 /******************************************************************************* | |
1855 | |
1856 $Function: ATB_index_Compare | |
1857 | |
1858 $Description: This function compares two records based on the index_type specified in | |
1859 index_type. It returns a value indicating whether the first record should | |
1860 come before or after the second. | |
1861 The function GI_pb_Compare is called first, to check whether there is | |
1862 any user-specific sorting required. If not, then ATB_alpha_Compare is | |
1863 called for an alpha tag, or ATB_num_Compare for a phone number. | |
1864 For any other index_type, COMPARE_FIRSTBEFORE is returned as default. | |
1865 | |
1866 $Returns: COMPARE_IDENTICAL The two records are identical | |
1867 COMPARE_FIRSTBEFORE The first record should come before the second record | |
1868 COMPARE_FIRSTAFTER The first record should come after the second record | |
1869 | |
1870 $Arguments: record1 The first record to be compared | |
1871 record2 The second record to be compared | |
1872 index_type Indicator of the index_type which is to be compared | |
1873 | |
1874 *******************************************************************************/ | |
1875 | |
1876 T_PB_COMPARE ATB_index_Compare(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type) | |
1877 { | |
1878 T_PB_COMPARE compare; | |
1879 | |
1880 compare = GI_pb_Compare(record1, record2, index_type); | |
1881 | |
1882 if (compare==COMPARE_DEFAULT) | |
1883 { | |
1884 switch(index_type) | |
1885 { | |
1886 case INDEX_NAME: | |
1887 compare = ATB_alpha_Compare(&record1->alpha, &record2->alpha); | |
1888 break; | |
1889 case INDEX_NUMBER: | |
1890 compare = ATB_num_Compare(record1->number, record2->number); | |
1891 break; | |
1892 } | |
1893 } | |
1894 | |
1895 return compare; | |
1896 } | |
1897 | |
1898 | |
1899 /******************************************************************************* | |
1900 | |
1901 $Function: ATB_alpha_Compare | |
1902 | |
1903 $Description: This function compares two alpha strings on the basis of an ascending | |
1904 alphanumeric latin list, and specifies which record would come first. | |
1905 | |
1906 | |
1907 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record | |
1908 COMPARE_FIRSTAFTER The first record should come after the second record | |
1909 | |
1910 $Arguments: alpha1 The first alpha tag | |
1911 alpha2 The second alpha tag | |
1912 | |
1913 *******************************************************************************/ | |
1914 | |
1915 T_PB_COMPARE ATB_alpha_Compare(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2) | |
1916 { | |
1917 T_PB_COMPARE compare; | |
1918 SHORT charIndex; | |
1919 USHORT length1 = alpha1->length; | |
1920 USHORT length2 = alpha2->length; | |
1921 USHORT char1; | |
1922 USHORT char2; | |
1923 | |
1924 compare = COMPARE_IDENTICAL; /* Default */ | |
1925 | |
1926 /* Special case, length of first string is 0 */ | |
1927 | |
1928 if (length1==0) | |
1929 compare = COMPARE_FIRSTBEFORE; | |
1930 | |
1931 for (charIndex = 0; charIndex < length1; charIndex++) | |
1932 { | |
1933 if (charIndex==length2) /* E.g. "Johnson" and "John" */ | |
1934 { | |
1935 compare = COMPARE_FIRSTAFTER; | |
1936 break; | |
1937 } | |
1938 | |
1939 char1 = alpha1->data[charIndex]; | |
1940 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z') | |
1941 char1 += (SHORT)('a'-'A'); | |
1942 char2 = alpha2->data[charIndex]; | |
1943 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z') | |
1944 char2 += (SHORT)('a'-'A'); | |
1945 | |
1946 if (char1 < char2) | |
1947 { | |
1948 compare = COMPARE_FIRSTBEFORE; | |
1949 break; | |
1950 } | |
1951 if (char1 > char2) | |
1952 { | |
1953 compare = COMPARE_FIRSTAFTER; | |
1954 break; | |
1955 } | |
1956 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */ | |
1957 { | |
1958 compare = COMPARE_FIRSTBEFORE; | |
1959 break; | |
1960 } | |
1961 } | |
1962 | |
1963 return compare; | |
1964 } | |
1965 | |
1966 | |
1967 /******************************************************************************* | |
1968 | |
1969 $Function: ATB_alpha_Match | |
1970 | |
1971 $Description: This function matches two alpha strings on the basis of a latin string | |
1972 matched from the start, and specifies how they match. | |
1973 | |
1974 $Returns: MATCH_NONE The strings do not match | |
1975 MATCH_START The first string matches the start of the second string | |
1976 MATCH_EXACT The two strings match exactly | |
1977 | |
1978 $Arguments: alpha1 The first alpha tag | |
1979 alpha2 The second alpha tag | |
1980 | |
1981 *******************************************************************************/ | |
1982 | |
1983 T_PB_COMPARE ATB_alpha_Match(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2) | |
1984 { | |
1985 T_PB_MATCH match; | |
1986 SHORT charIndex; | |
1987 USHORT length1 = alpha1->length; | |
1988 USHORT length2 = alpha2->length; | |
1989 SHORT offset; | |
1990 UBYTE searching; | |
1991 UBYTE some_match; | |
1992 USHORT char1, char2; | |
1993 | |
1994 match = MATCH_EXACT; /* Default */ | |
1995 searching = TRUE; | |
1996 some_match = FALSE; | |
1997 offset = 0; | |
1998 | |
1999 do | |
2000 { | |
2001 for (charIndex = 0; charIndex < length1; charIndex++) | |
2002 { | |
2003 | |
2004 if (charIndex==(length2-offset)) /* E.g. "Johnson" and "John" */ | |
2005 { | |
2006 searching = FALSE; | |
2007 break; /* No match, will exit do/while */ | |
2008 } | |
2009 | |
2010 char1 = alpha1->data[charIndex]; | |
2011 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z') | |
2012 char1 += (SHORT)('a'-'A'); | |
2013 char2 = alpha2->data[charIndex+offset]; | |
2014 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z') | |
2015 char2 += (SHORT)('a'-'A'); | |
2016 | |
2017 if (char1 != char2) | |
2018 { | |
2019 some_match = FALSE; /* Any fragment so far identified does not fit */ | |
2020 break; /* No match, keep looking */ | |
2021 } | |
2022 | |
2023 some_match = TRUE; | |
2024 | |
2025 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */ | |
2026 { | |
2027 if (offset==0) | |
2028 match = MATCH_START; | |
2029 else | |
2030 match = MATCH_FRAGMENT; | |
2031 break; | |
2032 } | |
2033 } | |
2034 | |
2035 if (some_match==TRUE) | |
2036 { | |
2037 searching = FALSE; | |
2038 } | |
2039 else | |
2040 { | |
2041 offset++; | |
2042 | |
2043 /* If the fragment won't fit, don't keep looking */ | |
2044 if ((offset+length1)>length2) | |
2045 { | |
2046 match=MATCH_NONE; | |
2047 searching = FALSE; | |
2048 } | |
2049 } | |
2050 }while (searching); | |
2051 | |
2052 return match; | |
2053 } | |
2054 | |
2055 | |
2056 /******************************************************************************* | |
2057 | |
2058 $Function: ATB_num_Digit | |
2059 | |
2060 $Description: Extracts the four-bit digit from a BCD number | |
2061 | |
2062 $Returns: The four bit digit | |
2063 | |
2064 $Arguments: num The BCD number | |
2065 numIndex The position in the BCD number to look | |
2066 | |
2067 *******************************************************************************/ | |
2068 | |
2069 UBYTE ATB_num_Digit(UBYTE *num, SHORT numIndex) | |
2070 { | |
2071 UBYTE digit; | |
2072 UBYTE shift = (numIndex&0x1)*0x4; | |
2073 | |
2074 digit = num[numIndex>>1]; /* Each BCD digit takes up half a byte */ | |
2075 digit &= (0xF<<shift); /* Isolate the digit */ | |
2076 digit >>= shift; /* Shift it so it has a value 0x0 - 0xF */ | |
2077 | |
2078 return digit; | |
2079 } | |
2080 | |
2081 | |
2082 /******************************************************************************* | |
2083 | |
2084 $Function: ATB_num_Length | |
2085 | |
2086 $Description: Returns the length of a BCD number in digits | |
2087 | |
2088 $Returns: Length of BCD number | |
2089 | |
2090 $Arguments: num The BCD number | |
2091 | |
2092 *******************************************************************************/ | |
2093 | |
2094 SHORT ATB_num_Length(UBYTE *num) | |
2095 { | |
2096 SHORT length; | |
2097 | |
2098 for (length = 0; ATB_num_Digit(num, length)!=0xF; length++) | |
2099 { | |
2100 } | |
2101 | |
2102 return length; | |
2103 } | |
2104 | |
2105 | |
2106 /******************************************************************************* | |
2107 | |
2108 $Function: ATB_num_Compare | |
2109 | |
2110 $Description: This function compares two phone numbers by the standard comparison | |
2111 method (ascending numeric, from the end of the number) and specifies | |
2112 which record would come first if sorted in this method. | |
2113 | |
2114 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record | |
2115 COMPARE_FIRSTAFTER The first record should come after the second record | |
2116 | |
2117 $Arguments: num1 The first number | |
2118 num2 The second number | |
2119 | |
2120 *******************************************************************************/ | |
2121 | |
2122 T_PB_COMPARE ATB_num_Compare(UBYTE *num1, UBYTE *num2) | |
2123 { | |
2124 T_PB_COMPARE compare; | |
2125 SHORT charIndex; | |
2126 SHORT length1 = ATB_num_Length(num1); | |
2127 SHORT length2 = ATB_num_Length(num2); | |
2128 UBYTE digit1; | |
2129 UBYTE digit2; | |
2130 | |
2131 compare = COMPARE_IDENTICAL; /* Default */ | |
2132 | |
2133 for (charIndex = 0; charIndex < length1; charIndex++) | |
2134 { | |
2135 if (charIndex==length2) /* E.g. "123456" and "1234" */ | |
2136 { | |
2137 compare = COMPARE_FIRSTAFTER; | |
2138 break; | |
2139 } | |
2140 | |
2141 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1)); | |
2142 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1)); | |
2143 | |
2144 if (digit1 < digit2) | |
2145 { | |
2146 compare = COMPARE_FIRSTBEFORE; | |
2147 break; | |
2148 } | |
2149 if (digit1 > digit2) | |
2150 { | |
2151 compare = COMPARE_FIRSTAFTER; | |
2152 break; | |
2153 } | |
2154 if (charIndex==length1-1 && length2>length1) /*E.g. "1234" and "123456" */ | |
2155 { | |
2156 compare = COMPARE_FIRSTBEFORE; | |
2157 break; | |
2158 } | |
2159 } | |
2160 | |
2161 return compare; | |
2162 } | |
2163 | |
2164 /******************************************************************************* | |
2165 | |
2166 $Function: ATB_num_Match | |
2167 | |
2168 $Description: This function matches phone numbers, from the end backwards, and | |
2169 specifies how they match. | |
2170 | |
2171 $Returns: MATCH_NONE The numbers do not match | |
2172 MATCH_START The first number matches the end of the second number | |
2173 MATCH_EXACT The two numbers match exactly | |
2174 | |
2175 $Arguments: num1 The first number | |
2176 num2 The second number | |
2177 | |
2178 *******************************************************************************/ | |
2179 | |
2180 T_PB_MATCH ATB_num_Match(UBYTE *num1, UBYTE *num2) | |
2181 { | |
2182 T_PB_MATCH match; | |
2183 SHORT charIndex; | |
2184 SHORT length1 = ATB_num_Length(num1); | |
2185 SHORT length2 = ATB_num_Length(num2); | |
2186 SHORT offset; | |
2187 UBYTE searching; | |
2188 UBYTE some_match; | |
2189 UBYTE digit1; | |
2190 UBYTE digit2; | |
2191 | |
2192 match = MATCH_EXACT; /* Default */ | |
2193 searching = TRUE; | |
2194 some_match = FALSE; | |
2195 offset = 0; | |
2196 | |
2197 do | |
2198 { | |
2199 for (charIndex = 0; charIndex < length1; charIndex++) | |
2200 { | |
2201 if (charIndex==(length2-offset)) /* E.g. "12345" and "123" */ | |
2202 { | |
2203 searching = FALSE; | |
2204 break; /* No match, will exit do/while */ | |
2205 } | |
2206 | |
2207 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1)); | |
2208 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1)); | |
2209 | |
2210 if (digit1 != digit2) | |
2211 { | |
2212 some_match = FALSE; /* Any fragment so far identified does not fit */ | |
2213 break; /* No match, keep looking */ | |
2214 } | |
2215 | |
2216 some_match = TRUE; | |
2217 | |
2218 if (charIndex==length1-1 && length2>length1) /*E.g. "123" and "12345" */ | |
2219 { | |
2220 if (offset==0) | |
2221 match = MATCH_START; | |
2222 else | |
2223 match = MATCH_FRAGMENT; | |
2224 break; | |
2225 } | |
2226 } | |
2227 | |
2228 if (some_match==TRUE) | |
2229 { | |
2230 searching = FALSE; | |
2231 } | |
2232 else | |
2233 { | |
2234 offset++; | |
2235 | |
2236 /* If the fragment won't fit, don't keep looking */ | |
2237 if ((offset+length1)>length2) | |
2238 { | |
2239 match=MATCH_NONE; | |
2240 searching = FALSE; | |
2241 } | |
2242 } | |
2243 } while (searching); | |
2244 | |
2245 return match; | |
2246 } | |
2247 | |
2248 | |
2249 /******************************************************************************* | |
2250 | |
2251 $Function: ATB_mem_UpdateCache | |
2252 | |
2253 $Description: Updates the cache with the record provided. If the cache is full, the | |
2254 least used record is overwritten. | |
2255 | |
2256 $Returns: None. | |
2257 | |
2258 $Arguments: phonebook_id The phonebook identifier | |
2259 index_type The index table required. | |
2260 phys_index The physical index of the record to add. | |
2261 record The record to add. | |
2262 | |
2263 *******************************************************************************/ | |
2264 | |
2265 void ATB_mem_UpdateCache(SHORT phonebook_id, SHORT phys_index, T_PB_RECORD *record) | |
2266 { | |
2267 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
2268 SHORT cacheIndex; | |
2269 SHORT leastUsed; | |
2270 SHORT leastIndex; | |
2271 | |
2272 /* First check if record is already in RAM */ | |
2273 | |
2274 if (data->cache[phys_index] != NULL) | |
2275 { | |
2276 /* Copy the record in case it has changed */ | |
2277 | |
2278 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record); | |
2279 | |
2280 if (data->in_memory[phys_index]<0xFFFF) | |
2281 data->in_memory[phys_index]++; | |
2282 return; | |
2283 } | |
2284 | |
2285 /* If the cache is full, find the least accessed record */ | |
2286 | |
2287 if (data->cache_size==data->cache_max) | |
2288 { | |
2289 leastIndex = 0; | |
2290 leastUsed = 255; | |
2291 | |
2292 for (cacheIndex=0; cacheIndex<data->records_max; cacheIndex++) | |
2293 { | |
2294 if (data->cache[cacheIndex]!=NULL && data->in_memory[cacheIndex] < leastUsed) | |
2295 { | |
2296 leastUsed = data->in_memory[cacheIndex]; | |
2297 leastIndex = cacheIndex; | |
2298 } | |
2299 } | |
2300 | |
2301 /* Give the new record the memory allocated for the least used record */ | |
2302 | |
2303 data->cache[phys_index] = data->cache[leastIndex]; | |
2304 data->cache[leastIndex] = NULL; | |
2305 data->in_memory[leastIndex] = 0; | |
2306 } | |
2307 | |
2308 /* If the cache is not full, allocate memory for record */ | |
2309 | |
2310 else | |
2311 { | |
2312 data->cache[phys_index] = ATB_pb_AllocRec(phonebook_id); | |
2313 data->cache_size++; | |
2314 } | |
2315 | |
2316 /* Copy the record into cache */ | |
2317 | |
2318 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record); | |
2319 data->in_memory[phys_index] = 1; | |
2320 | |
2321 return; | |
2322 } | |
2323 | |
2324 /******************************************************************************* | |
2325 | |
2326 $Function: ATB_mem_ReadRec | |
2327 | |
2328 $Description: Reads a record from the logical position index. Information is read from | |
2329 cache if it is present in memory, otherwise it will be read from file. | |
2330 | |
2331 The record information will be returned in the data structure pointed to | |
2332 by record. The T_PB_RECORD structure must be allocated by the caller. | |
2333 | |
2334 $Returns: PB_OK Action completed OK. | |
2335 PB_FILEREADFAIL File read encountered an error | |
2336 PB_RECDOESNOTEXIST Tried to access a record that does not exist | |
2337 | |
2338 $Arguments: phonebook_id The phonebook identifier | |
2339 index_type The index list from which the record is to be read | |
2340 log_index Logical index in the index list of the record to read | |
2341 record Structure in which to store record data | |
2342 | |
2343 *******************************************************************************/ | |
2344 | |
2345 PB_RET ATB_mem_ReadRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, T_PB_RECORD *record) | |
2346 { | |
2347 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id); | |
2348 SHORT phys_index; | |
2349 PB_RET result; | |
2350 | |
2351 /* Check that record exists */ | |
2352 | |
2353 if (log_index<0 | |
2354 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER)) | |
2355 || (index_type==INDEX_SEARCH && log_index>data->search_results) | |
2356 || (index_type==INDEX_PHYSICAL && log_index>data->records_max)) | |
2357 { | |
2358 trace("*** Error - record does not exist ***"); | |
2359 return PB_RECDOESNOTEXIST; | |
2360 } | |
2361 | |
2362 /* Get the corresponding physical record index */ | |
2363 | |
2364 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index); | |
2365 | |
2366 /* If the record is in the cache, simply copy it. Otherwise, call FS to read the record. */ | |
2367 | |
2368 if (data->in_memory[phys_index]>0) | |
2369 { | |
2370 ATB_pb_CopyRec(phonebook_id, record, data->cache[phys_index]); | |
2371 result = PB_OK; | |
2372 } | |
2373 else | |
2374 { | |
2375 /* NB - assumes blocking read operation. If the read operation is blocking, | |
2376 * the cache must be large enough to store all the phonebook entries. */ | |
2377 result = FS_pb_ReadRec(phonebook_id, phys_index, record); | |
2378 ATB_mem_UpdateCache(phonebook_id, phys_index, record); | |
2379 } | |
2380 | |
2381 return result; | |
2382 } | |
2383 | |
2384 | |
2385 /******************************************************************************* | |
2386 | |
2387 $Function: ATB_hnd_GetPbData | |
2388 | |
2389 $Description: Returns phonebook data handle | |
2390 | |
2391 $Returns: The phonebook data handle | |
2392 | |
2393 $Arguments: phonebook_id The phonebook identifier | |
2394 | |
2395 *******************************************************************************/ | |
2396 | |
2397 T_PB_DATA* ATB_hnd_GetPbData(SHORT phonebook_id) | |
2398 { | |
2399 return phonebook[phonebook_id]; | |
2400 } | |
2401 | |
2402 | |
2403 /******************************************************************************* | |
2404 | |
2405 $Function: ATB_hnd_SetPbData | |
2406 | |
2407 $Description: Sets phonebook data handle | |
2408 | |
2409 $Returns: None | |
2410 | |
2411 $Arguments: phonebook_id The phonebook identifier | |
2412 data The phonebook data | |
2413 | |
2414 *******************************************************************************/ | |
2415 | |
2416 void ATB_hnd_SetPbData(SHORT phonebook_id, T_PB_DATA *data) | |
2417 { | |
2418 phonebook[phonebook_id] = data; | |
2419 | |
2420 return; | |
2421 } | |
2422 |