Modifying the return value of cfg_set* functions, in order to make
[sip-router] / qvalue.c
1 /*
2  * $Id$
3  *
4  * Handling of the q value
5  *
6  * Copyright (C) 2004 FhG FOKUS
7  *
8  * This file is part of ser, a free SIP server.
9  *
10  * ser is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * For a license to use the ser software under conditions
16  * other than those described here, or to purchase support for this
17  * software, please contact iptel.org by e-mail at the following addresses:
18  *    info@iptel.org
19  *
20  * ser is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License 
26  * along with this program; if not, write to the Free Software 
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  *
29  * History
30  * ------
31  * 2004-04-25 created (janakj)
32  */
33
34 #include "error.h"
35 #include "qvalue.h"
36
37
38 /*
39  * Convert string representation of q parameter in qvalue_t
40  */
41 int str2q(qvalue_t* q, char* s, int len)
42 {
43         int i, digits, order;
44
45              /* States and equivalent regular expressions of input */
46         enum {
47                 ST_START,   /* (SPC|TAB)* */
48                 ST_0,       /* 0+ */
49                 ST_1,       /* 1 */
50                 ST_0_PT,    /* 0*\. */
51                 ST_1_PT,    /* 1\. */
52                 ST_1_PT_0,  /* 1\.0+ */
53                 ST_0_PT_N   /* 0*\.[0-9]+ */
54         } state = ST_START;
55
56         if (!q || !s) {
57                 return E_INVALID_PARAMS;
58         }
59
60         digits = 1;
61         order = 100;
62         for(i = 0; i < len; i++) {
63                 switch(state) {
64                 case ST_START:
65                         switch(s[i]) {
66                         case ' ':
67                         case '\t':
68                                 break;
69
70                         case '0':
71                                 *q = 0;
72                                 state = ST_0;
73                                 break;
74
75                         case '1':
76                                 *q = 1000;
77                                 state = ST_1;
78                                 break;
79
80                         case '.':
81                                 state = ST_0_PT;
82                                 break;
83
84                         default:
85                                 return E_Q_INV_CHAR;
86                         }
87                         break;
88
89                 case ST_0:
90                         switch(s[i]) {
91                         case '0':
92                                 break;
93
94                         case '.':
95                                 state = ST_0_PT;
96                                 break;
97
98                         case '1':
99                                 *q = 1000;
100                                 state = ST_1;
101                                 break;
102
103                         default:
104                                 if (s[i] >= '2' && s[i] <= '9') {
105                                         return E_Q_TOO_BIG;
106                                 } else {
107                                         return E_Q_INV_CHAR;
108                                 }
109                         }
110                         break;
111
112                 case ST_1:
113                         if (s[i] == '.') {
114                                 state = ST_1_PT;
115                                 break;
116                         } else {
117                                 if (s[i] >= '0' && s[i] <= '9') {
118                                         return E_Q_TOO_BIG;
119                                 } else {
120                                         return E_Q_INV_CHAR;
121                                 }
122                         }
123                         break;
124
125                 case ST_0_PT:
126                         if (s[i] >= '0' && s[i] <= '9') {
127                                 *q =  (s[i] - '0') * order;
128                                 order /= 10;
129                                 state = ST_0_PT_N;
130                         } else {
131                                 return E_Q_INV_CHAR;
132                         }
133                         break;
134
135                 case ST_1_PT:
136                         if (s[i] == '0') {
137                                 state = ST_1_PT_0;
138                         } else {
139                                 if (s[i] >= '1' && s[i] <= '9') {
140                                         return E_Q_TOO_BIG;
141                                 } else {
142                                         return E_Q_INV_CHAR;
143                                 }
144                         }
145                         break;
146
147                 case ST_1_PT_0:
148                         if (s[i] == '0') {
149                                 break;
150                         } else {
151                                 if (s[i] >= '1' && s[i] <= '9') {
152                                         return E_Q_TOO_BIG;
153                                 } else {
154                                         return E_Q_INV_CHAR;
155                                 }
156                         }
157                         break;
158
159                 case ST_0_PT_N:
160                         if (s[i] >= '0' && s[i] <= '9') {
161                                 if (digits <= 3) {
162                                         *q += (s[i] - '0') * order;
163                                         order /= 10;
164                                         digits++;
165                                 }
166                         } else {
167                                 return E_Q_INV_CHAR;
168                         }
169                         break;
170                 }
171         }
172
173         switch(state) {
174         case ST_START:
175                 return E_Q_EMPTY;
176                 
177         case ST_0_PT:
178         case ST_1_PT:
179                 return E_Q_DEC_MISSING;
180                 
181         default:
182                 return 0;
183         }
184 }