comparison src/ui3/atb/ATBPb.c @ 420:e8ddbb0837ed

src/ui3: initial import of TCS3/LoCosto BMI & MFW code
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Jan 2018 03:09:00 +0000
parents
children
comparison
equal deleted inserted replaced
419:59143cd42ec7 420:e8ddbb0837ed
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=PB_ERROR;
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 /*a0393213 warnings removal-second parameter type changed from T_PB_TYPE to T_PB_INDEX*/
578 PB_RET ATB_pb_WriteRec(SHORT phonebook_id, T_PB_INDEX 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=PB_ERROR;
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=PB_ERROR;
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 //add "*" "#" in number by Peng Hou on 19/06/2006 begin
1177 while (digit!=0xF && srcIndex<max_len)
1178 {
1179 if (src[srcIndex]==NULL)
1180 digit = 0xF; /* 0xF terminates BCD */
1181 else
1182 {
1183 switch ( src[srcIndex] )
1184 {
1185 case '0':
1186 case '1':
1187 case '2':
1188 case '3':
1189 case '4':
1190 case '5':
1191 case '6':
1192 case '7':
1193 case '8':
1194 case '9':
1195 digit = src[srcIndex]-'0';
1196 break;
1197
1198 case '*':
1199 digit = 0x0a;
1200 break;
1201
1202 case '#':
1203 digit = 0x0b;
1204 break;
1205
1206 case 'p':
1207 case 'P':
1208 digit = 0x0c;
1209 break;
1210
1211 case 'w':
1212 case 'W':
1213 digit = 0x0d;
1214 break;
1215
1216 case 'E':
1217 digit = 0x0e;
1218 break;
1219
1220 default:
1221 continue;
1222 }
1223 }
1224 //add "*" "#" in number by Peng Hou on 19/06/2006 end
1225
1226 // digit = src[srcIndex]-'0'; /* The digit, 0 to 9. */
1227
1228
1229 if (leftbits)
1230 {
1231 dest[destIndex] = digit;
1232 leftbits = FALSE;
1233 }
1234 else
1235 {
1236 dest[destIndex] |= digit<<4; /* *16 shifts right 4 bits */
1237 leftbits = TRUE;
1238 destIndex++;
1239 }
1240 srcIndex++;
1241 }
1242
1243 return;
1244 }
1245
1246
1247 /*******************************************************************************
1248
1249 $Function: ATB_pb_BCDToChar
1250
1251 $Description: Converts a BCD string to ascii digits
1252
1253 $Returns: None
1254
1255 $Arguments: src - source string (BCD)
1256 dest - destination string for ascii digits
1257
1258 *******************************************************************************/
1259
1260 void ATB_pb_BCDToChar(char *dest, UBYTE *src, int max_len)
1261 {
1262 SHORT numIndex = 0;
1263 UBYTE digit = 0xF; //dummy
1264 //add "*" "#" in number by Peng Hou on 19/06/2006 begin
1265 while (digit!=NULL && numIndex<max_len)
1266 {
1267 /*HELLO!*/
1268 digit = ATB_num_Digit(src, numIndex);
1269
1270 if (digit==0xF)
1271 digit = NULL;
1272 else
1273 {
1274 switch ( digit )
1275 {
1276 case 0:
1277 case 1:
1278 case 2:
1279 case 3:
1280 case 4:
1281 case 5:
1282 case 6:
1283 case 7:
1284 case 8:
1285 case 9:
1286 {
1287 digit+='0';
1288 dest[numIndex] = digit;
1289 }
1290 break;
1291
1292 case 0x0a:
1293 dest[numIndex]='*';
1294 break;
1295 case 0x0b:
1296 dest[numIndex]='#';
1297 break;
1298 case 0x0c:
1299 dest[numIndex]='P';
1300 break;
1301 case 0x0d:
1302 dest[numIndex]='W';
1303 break;
1304 case 0x0e:
1305 dest[numIndex] ='E';
1306 break;
1307 default:
1308 dest[numIndex] ='\0';
1309 }
1310
1311 }
1312
1313 // digit+='0';
1314 //add "*" "#" in number by Peng Hou on 19/06/2006 end
1315 numIndex++;
1316 }
1317
1318 return;
1319 }
1320
1321
1322 /*******************************************************************************
1323
1324 $Function: ATB_pb_AllocRec
1325
1326 $Description: Allocates memory for a record
1327
1328 $Returns:
1329
1330 $Arguments: phonebook_id The phonebook identifier
1331
1332 *******************************************************************************/
1333
1334 T_PB_RECORD *ATB_pb_AllocRec(SHORT phonebook_id)
1335 {
1336 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1337 T_PB_RECORD *record;
1338
1339 record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD));
1340
1341 record->alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT));
1342 record->number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2);
1343 if (data->ext_max>0)
1344 {
1345 record->ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max);
1346 }
1347 else
1348 {
1349 record->ext_data = NULL;
1350 }
1351 record->ton_npi = 0;
1352
1353 return record;
1354 }
1355
1356
1357 /*******************************************************************************
1358
1359 $Function: ATB_pb_FreeRec
1360
1361 $Description: Frees memory allocated for a record
1362
1363 $Returns:
1364
1365 $Arguments: phonebook_id The phonebook identifier
1366 record The record to destroy
1367
1368 *******************************************************************************/
1369
1370 void ATB_pb_FreeRec(SHORT phonebook_id, T_PB_RECORD *record)
1371 {
1372 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1373
1374 if (data->ext_max>0 && record->ext_data!=NULL)
1375 {
1376 GI_pb_MemFree((UBYTE *)record->ext_data, data->ext_max);
1377 }
1378 GI_pb_MemFree((UBYTE *)record->number, data->number_max/2);
1379 GI_pb_MemFree((UBYTE *)record->alpha.data, data->alpha_max*sizeof(USHORT));
1380
1381 GI_pb_MemFree((UBYTE *)record, sizeof(T_PB_RECORD));
1382
1383 return;
1384 }
1385
1386
1387 /*******************************************************************************
1388
1389 $Function: ATB_pb_AllocRecList
1390
1391 $Description: Allocates memory for a list of records
1392
1393 $Returns:
1394
1395 $Arguments: phonebook_id The phonebook identifier
1396 num_recs The number of records to allocate
1397
1398 *******************************************************************************/
1399
1400 T_PB_LIST *ATB_pb_AllocRecList(SHORT phonebook_id, SHORT num_recs)
1401 {
1402 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1403 T_PB_LIST *list;
1404 SHORT rec_index;
1405
1406 list = (T_PB_LIST *)GI_pb_MemAlloc(sizeof(T_PB_LIST));
1407 list->records_max = num_recs;
1408 list->records_used = 0;
1409 list->record = (T_PB_RECORD *)GI_pb_MemAlloc(sizeof(T_PB_RECORD)*num_recs);
1410
1411 for (rec_index=0; rec_index<num_recs; rec_index++)
1412 {
1413 list->record[rec_index].alpha.data = (USHORT *)GI_pb_MemAlloc(data->alpha_max*sizeof(USHORT));
1414 list->record[rec_index].number = (UBYTE *)GI_pb_MemAlloc(data->number_max/2);
1415 if (data->ext_max>0)
1416 {
1417 list->record[rec_index].ext_data = (UBYTE *)GI_pb_MemAlloc(data->ext_max);
1418 }
1419 else
1420 {
1421 list->record[rec_index].ext_data = NULL;
1422 }
1423 }
1424
1425 return list;
1426 }
1427
1428
1429 /*******************************************************************************
1430
1431 $Function: ATB_pb_FreeRecList
1432
1433 $Description: Frees memory allocated for a list of records
1434
1435 $Returns:
1436
1437 $Arguments: phonebook_id The phonebook identifier
1438 record The records to destroy
1439 num_recs Number of records in the list
1440
1441 *******************************************************************************/
1442
1443 void ATB_pb_FreeRecList(SHORT phonebook_id, T_PB_LIST *list)
1444 {
1445 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1446 SHORT rec_index;
1447
1448 for (rec_index=0; rec_index<list->records_max; rec_index++)
1449 {
1450 if (data->ext_max>0 && list->record[rec_index].ext_data!=NULL)
1451 {
1452 GI_pb_MemFree((UBYTE *)list->record[rec_index].ext_data, data->ext_max);
1453 }
1454 GI_pb_MemFree((UBYTE *)list->record[rec_index].number, data->number_max/2);
1455 GI_pb_MemFree((UBYTE *)list->record[rec_index].alpha.data, data->alpha_max*sizeof(USHORT));
1456 }
1457
1458 GI_pb_MemFree((UBYTE *)list->record, sizeof(T_PB_RECORD)*list->records_max);
1459 GI_pb_MemFree((UBYTE *)list, sizeof(T_PB_LIST));
1460
1461 return;
1462 }
1463
1464
1465 /*******************************************************************************
1466
1467 $Function: ATB_mem_CopyRec
1468
1469 $Description: Copies a record from one location to another. The destination should
1470 have memory allocated for its strings.
1471
1472 $Returns:
1473
1474 $Arguments: dest_record The destination record
1475 src_record The source record
1476
1477 *******************************************************************************/
1478
1479 void ATB_pb_CopyRec(SHORT phonebook_id, T_PB_RECORD *dest_record, T_PB_RECORD *src_record)
1480 {
1481 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1482
1483 dest_record->alpha.length = src_record->alpha.length;
1484 dest_record->alpha.dcs = src_record->alpha.dcs;
1485 memcpy((UBYTE *)dest_record->alpha.data, (UBYTE *)src_record->alpha.data, data->alpha_max*sizeof(USHORT));
1486 memcpy(dest_record->number, src_record->number, data->number_max/2);
1487 if (data->ext_max>0)
1488 {
1489 memcpy(dest_record->ext_data, src_record->ext_data, data->ext_max);
1490 }
1491 dest_record->ton_npi = src_record->ton_npi;
1492
1493 return;
1494 }
1495
1496
1497 /*******************************************************************************
1498
1499 $Function: ATB_pb_OK
1500
1501 $Description: This function is called if the requested FS command executed successfully.
1502
1503 $Returns: None.
1504
1505 $Arguments: phonebook_id The phonebook identifier
1506
1507 *******************************************************************************/
1508
1509
1510 PB_RET ATB_pb_OK(SHORT phonebook_id)
1511 {
1512 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1513 PB_RET result=PB_ERROR;
1514
1515 switch(data->command_id)
1516 {
1517 case PB_INITIALISE:
1518 result = ATB_status_Initialise(phonebook_id);
1519 break;
1520 case PB_WRITEREC:
1521 result = ATB_status_WriteRec(phonebook_id);
1522 break;
1523 case PB_DELETEREC:
1524 result = ATB_status_DeleteRec(phonebook_id);
1525 break;
1526 }
1527
1528 return result;
1529 }
1530
1531
1532 /*******************************************************************************
1533
1534 $Function: ATB_pb_Error
1535
1536 $Description: This function is called if an error was returned while executing the
1537 requested command.
1538
1539 $Returns: None.
1540
1541 $Arguments: phonebook_id The phonebook identifier
1542 error_id Identifies the error that occurred.
1543
1544 *******************************************************************************/
1545
1546 void ATB_pb_Error(SHORT phonebook_id, SHORT error_id)
1547 {
1548 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1549
1550 /* Forward the error report to the GI */
1551
1552 GI_pb_Error(phonebook_id, data->command_id, error_id);
1553 data->status = PB_STATUS_NONE;
1554
1555 return;
1556 }
1557
1558 /*******************************************************************************
1559
1560 $Function: ATB_index_GetTable
1561
1562 $Description: Returns a pointer to the index table specified by the index_type
1563
1564 $Returns: None.
1565
1566 $Arguments: phonebook_id The phonebook identifier
1567 index_type The index table required.
1568
1569 *******************************************************************************/
1570
1571 SHORT * ATB_index_GetTable(SHORT phonebook_id, T_PB_INDEX index_type)
1572 {
1573 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1574 SHORT *table = NULL;
1575
1576 switch(index_type)
1577 {
1578 case INDEX_NAME:
1579 table = data->name_table;
1580 break;
1581 case INDEX_NUMBER:
1582 table = data->number_table;
1583 break;
1584 case INDEX_SEARCH:
1585 table = data->search_table;
1586 break;
1587 default:
1588 table = GI_pb_GetTable(index_type);
1589 break;
1590 }
1591
1592 return table;
1593 }
1594
1595
1596 /*******************************************************************************
1597
1598 $Function: ATB_index_Find
1599
1600 $Description: Find the nearest match to the supplied record. See ATB_pb_Find for
1601 more information.
1602
1603 $Returns: PB_OK Action completed OK.
1604 PB_BUSY Failed, phonebook is busy.
1605 PB_FILEREADFAIL File read encountered an error
1606 PB_RECDOESNOTEXIST Tried to access a record that does not exist
1607 (should never happen)
1608
1609 $Arguments: phonebook_id The phonebook identifier
1610 index_type The index_type of the provided record that is to be
1611 searched for, and the index list that the resulting
1612 new_log_index pertains to
1613 record The record whose index_type is to be matched
1614 new_log_index Returns with the logical index of the closest matching
1615 record
1616 match Specifies how good the resulting match was
1617 (MATCH_NONE, MATCH_START, MATCH_FRAGMENT
1618 or MATCH_EXACT).
1619
1620 *******************************************************************************/
1621
1622 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)
1623 {
1624 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1625 PB_RET result = PB_OK;
1626 /*SHORT *table;*/ /*a0393213 warning removal-variable set but not used*/
1627 SHORT lower;
1628 SHORT upper;
1629 SHORT middle;
1630 T_PB_RECORD *comp_record;
1631 T_PB_COMPARE compare;
1632 UBYTE searching;
1633
1634 /* Ensure that phonebook exists */
1635 if (!data)
1636 {
1637 trace("**ERROR** Phonebook does not exist");
1638 return PB_BOOKDOESNOTEXIST;
1639 }
1640
1641 /* Allocate record for comparison */
1642
1643 comp_record = ATB_pb_AllocRec(phonebook_id);
1644
1645 /* Make sure we're searching a valid index type */
1646
1647 if (index_type==INDEX_PHYSICAL || index_type==INDEX_SEARCH)
1648 {
1649 GI_pb_Error(phonebook_id, PB_FIND, PB_INDEXINVALID);
1650 return PB_INDEXINVALID;
1651 }
1652
1653 /*table = ATB_index_GetTable(phonebook_id, index_type);*//*a0393213 warning removal-variable set but not used*/
1654
1655 /* The initial upper and lower bounds are the bounds of the array */
1656 lower = 0;
1657 upper = data->records_used-1;
1658
1659 searching = TRUE;
1660
1661 /* If the list is empty, insert at 0 */
1662
1663 if (data->records_used==0)
1664 {
1665 middle = 0;
1666 searching = FALSE;
1667 }
1668
1669 while (searching)
1670 {
1671 /* Compare our record with the middle element of the partition */
1672
1673 middle = (lower+upper)/2;
1674
1675 result = ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record);
1676
1677 if (result!=PB_OK)
1678 break;
1679
1680 compare = ATB_index_Compare(record, comp_record, index_type);
1681
1682 switch(compare)
1683 {
1684 case COMPARE_IDENTICAL:
1685 /* We've found a match; stop searching */
1686 searching = FALSE;
1687 break;
1688
1689 case COMPARE_FIRSTBEFORE:
1690 if (middle==lower)
1691 {
1692 /* The partition is a single element, so stop here. */
1693 searching = FALSE;
1694 }
1695 else
1696 {
1697 /* Our record comes before the middle element;
1698 * redefine the partiton */
1699 upper = middle - 1;
1700 }
1701 break;
1702
1703 case COMPARE_FIRSTAFTER:
1704 if (middle==upper)
1705 {
1706 /* The partition is a single element, so stop here. The record
1707 * we need is the record after this one. */
1708 middle++;
1709 searching = FALSE;
1710 }
1711 else
1712 {
1713 /* Our record comes after the middle element;
1714 * redefine the partiton */
1715 lower = middle+1;
1716 }
1717 break;
1718 }
1719 }
1720
1721 /* Store our results */
1722
1723 if (new_log_index)
1724 *new_log_index = middle;
1725
1726 if (match)
1727 {
1728 ATB_mem_ReadRec(phonebook_id, index_type, middle, comp_record);
1729 *match = ATB_index_Match(record, comp_record, index_type);
1730 }
1731
1732 /* Free allocated record */
1733
1734 ATB_pb_FreeRec(phonebook_id, comp_record);
1735
1736 /* Send success/failure info to the GI */
1737
1738 if (result==PB_OK)
1739 GI_pb_OK(phonebook_id, PB_FIND, NULL);
1740 else if (result!=PB_EXCT)
1741 GI_pb_Error(phonebook_id, PB_FIND, result);
1742
1743 return result;
1744 }
1745
1746
1747 /*******************************************************************************
1748
1749 $Function: ATB_index_GetPhysIndex
1750
1751 $Description: Returns the physical index corresponding to the given logical index, in
1752 the index table specified by the index_type.
1753
1754 $Returns: None.
1755
1756 $Arguments: phonebook_id The phonebook identifier.
1757 index_type The index table required.
1758 log_index The logical index.
1759
1760 *******************************************************************************/
1761
1762 SHORT ATB_index_GetPhysIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index)
1763 {
1764 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1765 SHORT phys_index=-1;
1766 SHORT *table;
1767
1768 switch(index_type)
1769 {
1770 case INDEX_PHYSICAL:
1771 phys_index = log_index;
1772 break;
1773 case INDEX_NAME:
1774 case INDEX_NUMBER:
1775 case INDEX_SEARCH:
1776 table = ATB_index_GetTable(phonebook_id, index_type);
1777 phys_index = table[log_index];
1778 break;
1779 default:
1780 TRACE_ERROR("ATB_index_GetPhysIndex():Unknown index");
1781 break;
1782 }
1783
1784 return phys_index;
1785 }
1786
1787
1788 /*******************************************************************************
1789
1790 $Function: ATB_index_GetLogIndex
1791
1792 $Description: Provided with the physical index, finds the logical index of the record
1793 in the index table specified.
1794
1795 $Returns: None.
1796
1797 $Arguments: phonebook_id The phonebook identifier
1798 index_type The index table required.
1799 phys_index The logical index of the record to find
1800
1801 *******************************************************************************/
1802
1803 SHORT ATB_index_GetLogIndex(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index)
1804 {
1805 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1806 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1807 SHORT log_index;
1808
1809 if (index_type==INDEX_PHYSICAL)
1810 {
1811 log_index = phys_index;
1812 }
1813 else
1814 {
1815 for (log_index=0; log_index<data->records_used; log_index++)
1816 {
1817 if (table[log_index]==phys_index)
1818 break;
1819 }
1820 }
1821
1822 return log_index;
1823 }
1824
1825
1826 /*******************************************************************************
1827
1828 $Function: ATB_index_AddRec
1829
1830 $Description: Adds a record to an index list, sorting automatically as required.
1831
1832 $Returns: None.
1833
1834 $Arguments: phonebook_id The phonebook identifier
1835 index_type The index table required.
1836 phys_index The physical index of the record to add.
1837 record The record to add.
1838 new_log_index New logical index of record.
1839
1840 *******************************************************************************/
1841
1842 void ATB_index_AddRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT phys_index, T_PB_RECORD *record, SHORT *new_log_index)
1843 {
1844 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1845 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1846 SHORT log_index;
1847 SHORT found_log_index;
1848
1849 ATB_index_Find(phonebook_id, index_type, record, &found_log_index, NULL);
1850
1851 /* Shift end of index table down */
1852
1853 for (log_index=data->records_used; log_index>found_log_index; log_index--)
1854 {
1855 table[log_index] = table[log_index-1];
1856 }
1857
1858 table[found_log_index] = phys_index;
1859
1860 if (new_log_index)
1861 *new_log_index = found_log_index;
1862
1863 return;
1864 }
1865
1866 /*******************************************************************************
1867
1868 $Function: ATB_index_RemoveRec
1869
1870 $Description: Removes a record reference from an index list, sorting the index list
1871 appropriately.
1872
1873 $Returns: None.
1874
1875 $Arguments: phonebook_id The phonebook identifier
1876 index_type The index table required.
1877 log_index The logical index of the record to remove
1878
1879 *******************************************************************************/
1880
1881 void ATB_index_RemoveRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index)
1882 {
1883 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
1884 SHORT *table = ATB_index_GetTable(phonebook_id, index_type);
1885 SHORT table_index;
1886
1887 for (table_index = log_index+1; table_index<data->records_used; table_index++)
1888 {
1889 table[table_index-1] = table[table_index];
1890 }
1891
1892 return;
1893 }
1894
1895
1896 /*******************************************************************************
1897
1898 $Function: ATB_index_Match
1899
1900 $Description: This function attempts a match between two records based on the
1901 index_type specified in index_type. It returns a value indicating
1902 whether there is no match (MATCH_NONE), a partial match
1903 (MAX_START), or an exact match (MATCH_EXACT).
1904 The function GI_pb_Match is called first, to check whether there is
1905 any user-specific matching required. If not, then ATB_alpha_Match
1906 is called for an alpha tag, or ATB_num_Match for a phone number.
1907 For any other index_type, MATCH_NONE is returned as default.
1908
1909 $Returns: MATCH_EXACT, MATCH_START or MATCH_NONE
1910
1911 $Arguments: record1 The first record to be compared
1912 record2 The second record to be compared
1913 index_type Indicator of the index_type which is to be matched
1914
1915 *******************************************************************************/
1916
1917 T_PB_MATCH ATB_index_Match(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type)
1918 {
1919 T_PB_MATCH match;
1920
1921 match = GI_pb_Match(record1, record2, index_type);
1922
1923 if (match==MATCH_DEFAULT)
1924 {
1925 switch(index_type)
1926 {
1927 case INDEX_NAME:
1928 match = ATB_alpha_Match(&record1->alpha, &record2->alpha);
1929 break;
1930 case INDEX_NUMBER:
1931 match = ATB_num_Match(record1->number, record2->number);
1932 break;
1933 }
1934 }
1935
1936 return match;
1937 }
1938
1939
1940
1941 /*******************************************************************************
1942
1943 $Function: ATB_index_Compare
1944
1945 $Description: This function compares two records based on the index_type specified in
1946 index_type. It returns a value indicating whether the first record should
1947 come before or after the second.
1948 The function GI_pb_Compare is called first, to check whether there is
1949 any user-specific sorting required. If not, then ATB_alpha_Compare is
1950 called for an alpha tag, or ATB_num_Compare for a phone number.
1951 For any other index_type, COMPARE_FIRSTBEFORE is returned as default.
1952
1953 $Returns: COMPARE_IDENTICAL The two records are identical
1954 COMPARE_FIRSTBEFORE The first record should come before the second record
1955 COMPARE_FIRSTAFTER The first record should come after the second record
1956
1957 $Arguments: record1 The first record to be compared
1958 record2 The second record to be compared
1959 index_type Indicator of the index_type which is to be compared
1960
1961 *******************************************************************************/
1962
1963 T_PB_COMPARE ATB_index_Compare(T_PB_RECORD *record1, T_PB_RECORD *record2, T_PB_INDEX index_type)
1964 {
1965 T_PB_COMPARE compare;
1966
1967 compare = GI_pb_Compare(record1, record2, index_type);
1968
1969 if (compare==COMPARE_DEFAULT)
1970 {
1971 switch(index_type)
1972 {
1973 case INDEX_NAME:
1974 compare = ATB_alpha_Compare(&record1->alpha, &record2->alpha);
1975 break;
1976 case INDEX_NUMBER:
1977 compare = ATB_num_Compare(record1->number, record2->number);
1978 break;
1979 }
1980 }
1981
1982 return compare;
1983 }
1984
1985
1986 /*******************************************************************************
1987
1988 $Function: ATB_alpha_Compare
1989
1990 $Description: This function compares two alpha strings on the basis of an ascending
1991 alphanumeric latin list, and specifies which record would come first.
1992
1993
1994 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record
1995 COMPARE_FIRSTAFTER The first record should come after the second record
1996
1997 $Arguments: alpha1 The first alpha tag
1998 alpha2 The second alpha tag
1999
2000 *******************************************************************************/
2001
2002 T_PB_COMPARE ATB_alpha_Compare(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2)
2003 {
2004 T_PB_COMPARE compare;
2005 SHORT charIndex;
2006 USHORT length1 = alpha1->length;
2007 USHORT length2 = alpha2->length;
2008 USHORT char1;
2009 USHORT char2;
2010
2011 compare = COMPARE_IDENTICAL; /* Default */
2012
2013 /* Special case, length of first string is 0 */
2014
2015 if (length1==0)
2016 compare = COMPARE_FIRSTBEFORE;
2017
2018 for (charIndex = 0; charIndex < length1; charIndex++)
2019 {
2020 if (charIndex==length2) /* E.g. "Johnson" and "John" */
2021 {
2022 compare = COMPARE_FIRSTAFTER;
2023 break;
2024 }
2025
2026 char1 = alpha1->data[charIndex];
2027 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z')
2028 char1 += (SHORT)('a'-'A');
2029 char2 = alpha2->data[charIndex];
2030 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z')
2031 char2 += (SHORT)('a'-'A');
2032
2033 if (char1 < char2)
2034 {
2035 compare = COMPARE_FIRSTBEFORE;
2036 break;
2037 }
2038 if (char1 > char2)
2039 {
2040 compare = COMPARE_FIRSTAFTER;
2041 break;
2042 }
2043 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */
2044 {
2045 compare = COMPARE_FIRSTBEFORE;
2046 break;
2047 }
2048 }
2049
2050 return compare;
2051 }
2052
2053
2054 /*******************************************************************************
2055
2056 $Function: ATB_alpha_Match
2057
2058 $Description: This function matches two alpha strings on the basis of a latin string
2059 matched from the start, and specifies how they match.
2060
2061 $Returns: MATCH_NONE The strings do not match
2062 MATCH_START The first string matches the start of the second string
2063 MATCH_EXACT The two strings match exactly
2064
2065 $Arguments: alpha1 The first alpha tag
2066 alpha2 The second alpha tag
2067
2068 *******************************************************************************/
2069
2070 T_PB_MATCH ATB_alpha_Match(T_PB_ALPHA *alpha1, T_PB_ALPHA *alpha2)
2071 {
2072 T_PB_MATCH match;
2073 SHORT charIndex;
2074 USHORT length1 = alpha1->length;
2075 USHORT length2 = alpha2->length;
2076 SHORT offset;
2077 UBYTE searching;
2078 UBYTE some_match;
2079 USHORT char1, char2;
2080
2081 match = MATCH_EXACT; /* Default */
2082 searching = TRUE;
2083 some_match = FALSE;
2084 offset = 0;
2085
2086 do
2087 {
2088 for (charIndex = 0; charIndex < length1; charIndex++)
2089 {
2090
2091 if (charIndex==(length2-offset)) /* E.g. "Johnson" and "John" */
2092 {
2093 searching = FALSE;
2094 break; /* No match, will exit do/while */
2095 }
2096
2097 char1 = alpha1->data[charIndex];
2098 if (char1>=(SHORT)'A' && char1<=(SHORT)'Z')
2099 char1 += (SHORT)('a'-'A');
2100 char2 = alpha2->data[charIndex+offset];
2101 if (char2>=(SHORT)'A' && char2<=(SHORT)'Z')
2102 char2 += (SHORT)('a'-'A');
2103
2104 if (char1 != char2)
2105 {
2106 some_match = FALSE; /* Any fragment so far identified does not fit */
2107 break; /* No match, keep looking */
2108 }
2109
2110 some_match = TRUE;
2111
2112 if (charIndex==length1-1 && length2>length1) /*E.g. "John" and "Johnson" */
2113 {
2114 if (offset==0)
2115 match = MATCH_START;
2116 else
2117 match = MATCH_FRAGMENT;
2118 break;
2119 }
2120 }
2121
2122 if (some_match==TRUE)
2123 {
2124 searching = FALSE;
2125 }
2126 else
2127 {
2128 offset++;
2129
2130 /* If the fragment won't fit, don't keep looking */
2131 if ((offset+length1)>length2)
2132 {
2133 match=MATCH_NONE;
2134 searching = FALSE;
2135 }
2136 }
2137 }while (searching);
2138
2139 return match;
2140 }
2141
2142
2143 /*******************************************************************************
2144
2145 $Function: ATB_num_Digit
2146
2147 $Description: Extracts the four-bit digit from a BCD number
2148
2149 $Returns: The four bit digit
2150
2151 $Arguments: num The BCD number
2152 numIndex The position in the BCD number to look
2153
2154 *******************************************************************************/
2155
2156 UBYTE ATB_num_Digit(UBYTE *num, SHORT numIndex)
2157 {
2158 UBYTE digit;
2159 UBYTE shift = (numIndex&0x1)*0x4;
2160
2161 digit = num[numIndex>>1]; /* Each BCD digit takes up half a byte */
2162 digit &= (0xF<<shift); /* Isolate the digit */
2163 digit >>= shift; /* Shift it so it has a value 0x0 - 0xF */
2164
2165 return digit;
2166 }
2167
2168
2169 /*******************************************************************************
2170
2171 $Function: ATB_num_Length
2172
2173 $Description: Returns the length of a BCD number in digits
2174
2175 $Returns: Length of BCD number
2176
2177 $Arguments: num The BCD number
2178
2179 *******************************************************************************/
2180
2181 SHORT ATB_num_Length(UBYTE *num)
2182 {
2183 SHORT length;
2184
2185 for (length = 0; ATB_num_Digit(num, length)!=0xF; length++)
2186 {
2187 }
2188
2189 return length;
2190 }
2191
2192
2193 /*******************************************************************************
2194
2195 $Function: ATB_num_Compare
2196
2197 $Description: This function compares two phone numbers by the standard comparison
2198 method (ascending numeric, from the end of the number) and specifies
2199 which record would come first if sorted in this method.
2200
2201 $Returns: COMPARE_FIRSTBEFORE The first record should come before the second record
2202 COMPARE_FIRSTAFTER The first record should come after the second record
2203
2204 $Arguments: num1 The first number
2205 num2 The second number
2206
2207 *******************************************************************************/
2208
2209 T_PB_COMPARE ATB_num_Compare(UBYTE *num1, UBYTE *num2)
2210 {
2211 T_PB_COMPARE compare;
2212 SHORT charIndex;
2213 SHORT length1 = ATB_num_Length(num1);
2214 SHORT length2 = ATB_num_Length(num2);
2215 UBYTE digit1;
2216 UBYTE digit2;
2217
2218 compare = COMPARE_IDENTICAL; /* Default */
2219
2220 for (charIndex = 0; charIndex < length1; charIndex++)
2221 {
2222 if (charIndex==length2) /* E.g. "123456" and "1234" */
2223 {
2224 compare = COMPARE_FIRSTAFTER;
2225 break;
2226 }
2227
2228 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1));
2229 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1));
2230
2231 if (digit1 < digit2)
2232 {
2233 compare = COMPARE_FIRSTBEFORE;
2234 break;
2235 }
2236 if (digit1 > digit2)
2237 {
2238 compare = COMPARE_FIRSTAFTER;
2239 break;
2240 }
2241 if (charIndex==length1-1 && length2>length1) /*E.g. "1234" and "123456" */
2242 {
2243 compare = COMPARE_FIRSTBEFORE;
2244 break;
2245 }
2246 }
2247
2248 return compare;
2249 }
2250
2251 /*******************************************************************************
2252
2253 $Function: ATB_num_Match
2254
2255 $Description: This function matches phone numbers, from the end backwards, and
2256 specifies how they match.
2257
2258 $Returns: MATCH_NONE The numbers do not match
2259 MATCH_START The first number matches the end of the second number
2260 MATCH_EXACT The two numbers match exactly
2261
2262 $Arguments: num1 The first number
2263 num2 The second number
2264
2265 *******************************************************************************/
2266
2267 T_PB_MATCH ATB_num_Match(UBYTE *num1, UBYTE *num2)
2268 {
2269 T_PB_MATCH match;
2270 SHORT charIndex;
2271 SHORT length1 = ATB_num_Length(num1);
2272 SHORT length2 = ATB_num_Length(num2);
2273 SHORT offset;
2274 UBYTE searching;
2275 UBYTE some_match;
2276 UBYTE digit1;
2277 UBYTE digit2;
2278
2279 match = MATCH_EXACT; /* Default */
2280 searching = TRUE;
2281 some_match = FALSE;
2282 offset = 0;
2283
2284 do
2285 {
2286 for (charIndex = 0; charIndex < length1; charIndex++)
2287 {
2288 if (charIndex==(length2-offset)) /* E.g. "12345" and "123" */
2289 {
2290 searching = FALSE;
2291 break; /* No match, will exit do/while */
2292 }
2293
2294 digit1 = ATB_num_Digit(num1, (SHORT)(length1-charIndex-1));
2295 digit2 = ATB_num_Digit(num2, (SHORT)(length2-charIndex-1));
2296
2297 if (digit1 != digit2)
2298 {
2299 some_match = FALSE; /* Any fragment so far identified does not fit */
2300 break; /* No match, keep looking */
2301 }
2302
2303 some_match = TRUE;
2304
2305 if (charIndex==length1-1 && length2>length1) /*E.g. "123" and "12345" */
2306 {
2307 if (offset==0)
2308 match = MATCH_START;
2309 else
2310 match = MATCH_FRAGMENT;
2311 break;
2312 }
2313 }
2314
2315 if (some_match==TRUE)
2316 {
2317 searching = FALSE;
2318 }
2319 else
2320 {
2321 offset++;
2322
2323 /* If the fragment won't fit, don't keep looking */
2324 if ((offset+length1)>length2)
2325 {
2326 match=MATCH_NONE;
2327 searching = FALSE;
2328 }
2329 }
2330 } while (searching);
2331
2332 return match;
2333 }
2334
2335
2336 /*******************************************************************************
2337
2338 $Function: ATB_mem_UpdateCache
2339
2340 $Description: Updates the cache with the record provided. If the cache is full, the
2341 least used record is overwritten.
2342
2343 $Returns: None.
2344
2345 $Arguments: phonebook_id The phonebook identifier
2346 index_type The index table required.
2347 phys_index The physical index of the record to add.
2348 record The record to add.
2349
2350 *******************************************************************************/
2351
2352 void ATB_mem_UpdateCache(SHORT phonebook_id, SHORT phys_index, T_PB_RECORD *record)
2353 {
2354 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
2355 SHORT cacheIndex;
2356 SHORT leastUsed;
2357 SHORT leastIndex;
2358
2359 /* First check if record is already in RAM */
2360
2361 if (data->cache[phys_index] != NULL)
2362 {
2363 /* Copy the record in case it has changed */
2364
2365 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record);
2366
2367 if (data->in_memory[phys_index]<0x7FFF)/*a0393213 lint WR:Constant out of range Soln:0xffff changed to 0x7fff*/
2368 data->in_memory[phys_index]++;
2369 return;
2370 }
2371
2372 /* If the cache is full, find the least accessed record */
2373
2374 if (data->cache_size==data->cache_max)
2375 {
2376 leastIndex = 0;
2377 leastUsed = 255;
2378
2379 for (cacheIndex=0; cacheIndex<data->records_max; cacheIndex++)
2380 {
2381 if (data->cache[cacheIndex]!=NULL && data->in_memory[cacheIndex] < leastUsed)
2382 {
2383 leastUsed = data->in_memory[cacheIndex];
2384 leastIndex = cacheIndex;
2385 }
2386 }
2387
2388 /* Give the new record the memory allocated for the least used record */
2389
2390 data->cache[phys_index] = data->cache[leastIndex];
2391 data->cache[leastIndex] = NULL;
2392 data->in_memory[leastIndex] = 0;
2393 }
2394
2395 /* If the cache is not full, allocate memory for record */
2396
2397 else
2398 {
2399 data->cache[phys_index] = ATB_pb_AllocRec(phonebook_id);
2400 data->cache_size++;
2401 }
2402
2403 /* Copy the record into cache */
2404
2405 ATB_pb_CopyRec(phonebook_id, data->cache[phys_index], record);
2406 data->in_memory[phys_index] = 1;
2407
2408 return;
2409 }
2410
2411 /*******************************************************************************
2412
2413 $Function: ATB_mem_ReadRec
2414
2415 $Description: Reads a record from the logical position index. Information is read from
2416 cache if it is present in memory, otherwise it will be read from file.
2417
2418 The record information will be returned in the data structure pointed to
2419 by record. The T_PB_RECORD structure must be allocated by the caller.
2420
2421 $Returns: PB_OK Action completed OK.
2422 PB_FILEREADFAIL File read encountered an error
2423 PB_RECDOESNOTEXIST Tried to access a record that does not exist
2424
2425 $Arguments: phonebook_id The phonebook identifier
2426 index_type The index list from which the record is to be read
2427 log_index Logical index in the index list of the record to read
2428 record Structure in which to store record data
2429
2430 *******************************************************************************/
2431
2432 PB_RET ATB_mem_ReadRec(SHORT phonebook_id, T_PB_INDEX index_type, SHORT log_index, T_PB_RECORD *record)
2433 {
2434 T_PB_DATA *data = ATB_hnd_GetPbData(phonebook_id);
2435 SHORT phys_index;
2436 PB_RET result;
2437
2438 /* Check that record exists */
2439
2440 if (log_index<0
2441 || (log_index>=data->records_used && (index_type==INDEX_NAME || index_type==INDEX_NUMBER))
2442 || (index_type==INDEX_SEARCH && log_index>data->search_results)
2443 || (index_type==INDEX_PHYSICAL && log_index>data->records_max))
2444 {
2445 trace("*** Error - record does not exist ***");
2446 return PB_RECDOESNOTEXIST;
2447 }
2448
2449 /* Get the corresponding physical record index */
2450
2451 phys_index = ATB_index_GetPhysIndex(phonebook_id, index_type, log_index);
2452
2453 /* If the record is in the cache, simply copy it. Otherwise, call FS to read the record. */
2454
2455 if (data->in_memory[phys_index]>0)
2456 {
2457 ATB_pb_CopyRec(phonebook_id, record, data->cache[phys_index]);
2458 result = PB_OK;
2459 }
2460 else
2461 {
2462 /* NB - assumes blocking read operation. If the read operation is blocking,
2463 * the cache must be large enough to store all the phonebook entries. */
2464 result = FS_pb_ReadRec(phonebook_id, phys_index, record);
2465 ATB_mem_UpdateCache(phonebook_id, phys_index, record);
2466 }
2467
2468 return result;
2469 }
2470
2471
2472 /*******************************************************************************
2473
2474 $Function: ATB_hnd_GetPbData
2475
2476 $Description: Returns phonebook data handle
2477
2478 $Returns: The phonebook data handle
2479
2480 $Arguments: phonebook_id The phonebook identifier
2481
2482 *******************************************************************************/
2483
2484 T_PB_DATA* ATB_hnd_GetPbData(SHORT phonebook_id)
2485 {
2486 return phonebook[phonebook_id];
2487 }
2488
2489
2490 /*******************************************************************************
2491
2492 $Function: ATB_hnd_SetPbData
2493
2494 $Description: Sets phonebook data handle
2495
2496 $Returns: None
2497
2498 $Arguments: phonebook_id The phonebook identifier
2499 data The phonebook data
2500
2501 *******************************************************************************/
2502
2503 void ATB_hnd_SetPbData(SHORT phonebook_id, T_PB_DATA *data)
2504 {
2505 phonebook[phonebook_id] = data;
2506
2507 return;
2508 }
2509