-
Notifications
You must be signed in to change notification settings - Fork 585
/
Copy pathqvalue.h
176 lines (148 loc) · 4 KB
/
qvalue.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
* Handling of the q value
*
* Copyright (C) 2004 FhG FOKUS
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief Functions related to the SIP q value
*/
#ifndef _QVALUE_H
#define _QVALUE_H 1
#include <string.h>
/*! \page QvalueHandling Q Value Handling
*
* The q value expresses the priority of a URI within a set of URIs
* (Contact header field in the same SIP message or dset array in
* ser. The higher is the q value of a URI the higher is the priority
* of the URI.
*
* The q value is usually expressed as a floating point number with
* limited number of decimal digits, for example 0.346. RFC3261 allows
* 0-3 decimal digits.
*
* To speed things up we represent the q value as integer number, it
* is then easier to handle/print the value. To convert float into
* integer we multiply the q value by 1000, i.e.
* (float)0.567 == (int)567. In the opposite direction, values
* higher or equal to 1000 are converted to 1.0 and values below or
* equal to 0 are converted to 0.
*
* Value Q_UNSPECIFIED (which is in fact -1) has a special meaning, it
* means that the q value is not known and the parameter should not be
* printed when printing Contacts, implementations will then use
* implementation specific pre-defined values.
*/
typedef int qvalue_t;
/*! \brief
* Use this if the value of q is not specified
*/
#define Q_UNSPECIFIED ((qvalue_t)-1)
#define MAX_Q ((qvalue_t)1000)
#define MIN_Q ((qvalue_t)0)
#define MAX_Q_STR "1"
#define MAX_Q_STR_LEN (sizeof(MAX_Q_STR) - 1)
#define MIN_Q_STR "0"
#define MIN_Q_STR_LEN (sizeof(MIN_Q_STR) - 1)
#define Q_PREFIX "0."
#define Q_PREFIX_LEN (sizeof(Q_PREFIX) - 1)
#define qverr2str(rc) \
(rc == E_Q_INV_CHAR ? "bad characters" : \
rc == E_Q_EMPTY ? "empty value" : \
rc == E_Q_TOO_BIG ? "max value is 1.0" : "bad qvalue")
/*! \brief
* Calculate the length of printed q
*/
static inline size_t len_q(qvalue_t q)
{
if (q == Q_UNSPECIFIED) {
return 0;
} else if (q >= MAX_Q) {
return MAX_Q_STR_LEN;
} else if (q <= MIN_Q) {
return MIN_Q_STR_LEN;
} else if (q % 100 == 0) {
return Q_PREFIX_LEN + 1;
} else if (q % 10 == 0) {
return Q_PREFIX_LEN + 2;
} else {
return Q_PREFIX_LEN + 3;
}
}
/*! \brief
* Convert qvalue_t to double
*/
static inline double q2double(qvalue_t q)
{
if (q == Q_UNSPECIFIED) {
return -1;
} else {
return (double)((double)q / (double)1000);
}
}
/*! \brief
* Convert double to qvalue_t
*/
static inline qvalue_t double2q(double q)
{
if (q == -1) {
return Q_UNSPECIFIED;
} else {
return q * 1000;
}
}
/*! \brief
* Convert q value to string
*/
static inline char* q2str(qvalue_t q, unsigned int* len)
{
static char buf[sizeof("0.123")];
char* p;
p = buf;
if (q == Q_UNSPECIFIED) {
/* Do nothing */
} else if (q >= MAX_Q) {
memcpy(p, MAX_Q_STR, MAX_Q_STR_LEN);
p += MAX_Q_STR_LEN;
} else if (q <= MIN_Q) {
memcpy(p, MIN_Q_STR, MIN_Q_STR_LEN);
p += MIN_Q_STR_LEN;
} else {
memcpy(p, Q_PREFIX, Q_PREFIX_LEN);
p += Q_PREFIX_LEN;
*p++ = q / 100 + '0';
q %= 100;
if (!q) goto end;
*p++ = q / 10 + '0';
q %= 10;
if (!q) goto end;
*p++ = q + '0';
}
end:
*p = '\0';
if (len) {
*len = p - buf;
}
return buf;
}
/*! \brief
* Convert string representation of q parameter in qvalue_t
*/
int str2q(qvalue_t* q, char* s, int len);
#endif /* _QVALUE_H */