1 /***************************************************************************
2  *   copyright           : (C) 2004 by Hendrik Sattler                     *
3  *   mail                : post@hendrik-sattler.de                         *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  ***************************************************************************/
11 
12 #include <smspdu.h>
13 
14 #include <helper.h>
15 
16 #include <string.h>
17 #include <strings.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 
21 static
sms_pdu_sort_type(struct sms ** list,const char * sub_order)22 void sms_pdu_sort_type (struct sms** list, const char* sub_order) {
23   //4 lists for type sorting
24   struct sms** list_sub; //SMS-SUBMIT
25   unsigned int lssub = 0;
26   struct sms** list_del; //SMS-DELIVER
27   unsigned int lsdel = 0;
28   struct sms** list_sr; //SMS-STATUS-REPORT
29   unsigned int lssr = 0;
30   struct sms** list_uns; //unsupported types
31   unsigned int lsuns = 0;
32   unsigned int listsize = 0;
33 
34   if (list == NULL || list[0] == NULL) return;
35 
36   //count items in list;
37   while (list[listsize] != NULL) ++listsize;
38 
39   //splitting into type lists
40   list_sub = mem_alloc((listsize+1)*sizeof(struct sms*),0);
41   list_del = mem_alloc((listsize+1)*sizeof(struct sms*),0);
42   list_sr = mem_alloc((listsize+1)*sizeof(struct sms*),0);
43   list_uns = mem_alloc((listsize+1)*sizeof(struct sms*),0);
44   listsize = 0;
45   //do type sorting
46   while (list[listsize] != NULL) {
47     switch (list[listsize]->decoded->pdu->options.type) {
48     case SMS_TYPE_SUBMIT:
49       list_sub[lssub++] = list[listsize];
50       break;
51     case SMS_TYPE_DELIVER:
52       list_del[lsdel++] = list[listsize];
53       break;
54     case SMS_TYPE_STATUS_REPORT:
55       list_sr[lssr++] = list[listsize];
56       break;
57     default:
58       list_uns[lsuns++] = list[listsize];
59       break;
60     }
61     ++listsize;
62   }
63   list_sub[lssub] = NULL;
64   list_del[lsdel] = NULL;
65   list_sr[lssr] = NULL;
66   list_uns[lsuns] = NULL;
67 
68   //subsorting
69   sms_pdu_sort(list_sub,sub_order);
70   sms_pdu_sort(list_del,sub_order);
71   sms_pdu_sort(list_sr,sub_order);
72 
73   //merging to list
74   listsize = 0;
75   for (lsuns = 0; list_uns[lsuns] != NULL; ++lsuns) list[listsize++] = list_uns[lsuns];
76   for (lssub = 0; list_sub[lssub] != NULL; ++lssub) list[listsize++] = list_sub[lssub];
77   for (lssr = 0; list_sr[lssr] != NULL; ++lssr) list[listsize++] = list_sr[lssr];
78   for (lsdel = 0; list_del[lsdel] != NULL; ++lsdel) list[listsize++] = list_del[lsdel];
79   list[listsize] = NULL;
80   mem_realloc(list_uns,0);
81   mem_realloc(list_sub,0);
82   mem_realloc(list_sr,0);
83   mem_realloc(list_del,0);
84 }
85 
86 //as input for argument 4 of qsort
87 static
sms_pdu_sort_slot(const void * s1,const void * s2)88 int sms_pdu_sort_slot (const void* s1, const void* s2) {
89   const struct sms* sms1 = *((const struct sms**)s1);
90   const struct sms* sms2 = *((const struct sms**)s2);
91   int slot1 = sms1->encoded[sms1->decoded->pdu->partnum]->slot;
92   int slot2 = sms2->encoded[sms1->decoded->pdu->partnum]->slot;
93   return slot1-slot2;
94 }
95 
96 //as input for argument 4 of qsort
97 static
sms_pdu_sort_time(const void * s1,const void * s2)98 int sms_pdu_sort_time (const void* s1, const void* s2) {
99   const struct sms* sms1 = *((const struct sms**)s1);
100   const struct sms* sms2 = *((const struct sms**)s2);
101   struct sms_pdu_time* t1 = &sms1->decoded->pdu->timedata;
102   struct sms_pdu_time* t2 = &sms2->decoded->pdu->timedata;
103   if (t1->format != t2->format) return t1->format-t2->format;
104   else return t1->value-t2->value;
105 }
106 
sms_pdu_sort(struct sms ** list,const char * order)107 void sms_pdu_sort (struct sms** list, const char* order) {
108   char* new_order;
109   char* orders[] = { "type", "slot", "time" };
110   unsigned int listsize = 0;
111 
112   if (list == NULL || list[0] == NULL || str_len(order) == 0) return;
113 
114   //count items in list;
115   while (list[listsize] != NULL) ++listsize;
116 
117   //find next sorting item
118   new_order = strchr(order,',');
119   if (new_order != NULL) {
120     do {
121       ++new_order;
122     } while (isspace((int)*new_order) &&
123 	     *new_order != 0);
124   }
125 
126   if (strncasecmp(order,orders[0],strlen(orders[0])) == 0) {
127     /* type sorting */
128     sms_pdu_sort_type(list,new_order);
129   } else if (strncasecmp(order,orders[1],strlen(orders[1])) == 0) {
130     /* slot sorting */
131     qsort(list,listsize,sizeof(*list),sms_pdu_sort_slot);
132   } else if (strncasecmp(order,orders[2],strlen(orders[2])) == 0) {
133     /* time sorting */
134     qsort(list,listsize,sizeof(*list),sms_pdu_sort_time);
135   }
136 }
137