1/* Copyright (c) 2000-2003, 2007 MySQL AB
2 Use is subject to license terms
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17#include <my_global.h>
18#include <mysql_com.h>
19#include <mysql.h>
20
21/* Get the length of next field. Change parameter to point at fieldstart */
22ulong net_field_length(uchar **packet)
23{
24 reg1 uchar *pos= (uchar *)*packet;
25 if (*pos < 251)
26 {
27 (*packet)++;
28 return (ulong) *pos;
29 }
30 if (*pos == 251)
31 {
32 (*packet)++;
33 return NULL_LENGTH;
34 }
35 if (*pos == 252)
36 {
37 (*packet)+=3;
38 return (ulong) uint2korr(pos+1);
39 }
40 if (*pos == 253)
41 {
42 (*packet)+=4;
43 return (ulong) uint3korr(pos+1);
44 }
45 (*packet)+=9; /* Must be 254 when here */
46 return (ulong) uint4korr(pos+1);
47}
48
49/* The same as above but returns longlong */
50my_ulonglong net_field_length_ll(uchar **packet)
51{
52 uchar *pos= *packet;
53 if (*pos < 251)
54 {
55 (*packet)++;
56 return (my_ulonglong) *pos;
57 }
58 if (*pos == 251)
59 {
60 (*packet)++;
61 return (my_ulonglong) NULL_LENGTH;
62 }
63 if (*pos == 252)
64 {
65 (*packet)+=3;
66 return (my_ulonglong) uint2korr(pos+1);
67 }
68 if (*pos == 253)
69 {
70 (*packet)+=4;
71 return (my_ulonglong) uint3korr(pos+1);
72 }
73 DBUG_ASSERT(*pos == 254);
74 (*packet)+=9; /* Must be 254 when here */
75 return (my_ulonglong) uint8korr(pos+1);
76}
77
78my_ulonglong safe_net_field_length_ll(uchar **packet, size_t packet_len)
79{
80 uchar *pos= *packet;
81 if (packet_len < 1)
82 goto err;
83 if (*pos < 251)
84 {
85 (*packet)++;
86 return (my_ulonglong) *pos;
87 }
88 if (*pos == 251)
89 {
90 (*packet)++;
91 return (my_ulonglong) NULL_LENGTH;
92 }
93 if (*pos == 252)
94 {
95 if (packet_len < 3)
96 goto err;
97 (*packet)+=3;
98 return (my_ulonglong) uint2korr(pos+1);
99 }
100 if (*pos == 253)
101 {
102 if (packet_len < 4)
103 goto err;
104 (*packet)+=4;
105 return (my_ulonglong) uint3korr(pos+1);
106 }
107 if (packet_len < 9 || *pos != 254)
108 goto err;
109 (*packet)+=9;
110 return (my_ulonglong) uint8korr(pos+1);
111err:
112 *packet = NULL;
113 return 0;
114}
115
116/*
117 Store an integer with simple packing into a output package
118
119 SYNOPSIS
120 net_store_length()
121 packet Store the packed integer here
122 length integers to store
123
124 NOTES
125 This is mostly used to store lengths of strings.
126
127 RETURN
128 Position in 'packet' after the packed length
129*/
130
131uchar *net_store_length(uchar *packet, ulonglong length)
132{
133 if (length < 251)
134 {
135 *packet= (uchar) length;
136 return packet+1;
137 }
138 /* 251 is reserved for NULL */
139 if (length < 65536)
140 {
141 *packet++=252;
142 int2store(packet, (uint) length);
143 return packet+2;
144 }
145 if (length < 16777216)
146 {
147 *packet++=253;
148 int3store(packet, (ulong) length);
149 return packet+3;
150 }
151 *packet++=254;
152 int8store(packet,length);
153 return packet+8;
154}
155
156uchar *safe_net_store_length(uchar *packet, size_t packet_len, ulonglong length)
157{
158 if (length < 251)
159 {
160 if (packet_len < 1)
161 return NULL;
162 *packet= (uchar) length;
163 return packet+1;
164 }
165 /* 251 is reserved for NULL */
166 if (length < 65536)
167 {
168 if (packet_len < 3)
169 return NULL;
170 *packet++=252;
171 int2store(packet, (uint) length);
172 return packet+2;
173 }
174 if (length < 16777216)
175 {
176 if (packet_len < 4)
177 return NULL;
178 *packet++=253;
179 int3store(packet, (ulong) length);
180 return packet+3;
181 }
182 if (packet_len < 9)
183 return NULL;
184 *packet++=254;
185 int8store(packet,length);
186 return packet+8;
187}
188
189
190/**
191 The length of space required to store the resulting length-encoded integer
192 for the given number. This function can be used at places where one needs to
193 dynamically allocate the buffer for a given number to be stored as length-
194 encoded integer.
195
196 @param num [IN] the input number
197
198 @return length of buffer needed to store this number [1, 3, 4, 9].
199*/
200
201uint net_length_size(ulonglong num)
202{
203 if (num < (ulonglong) 251LL)
204 return 1;
205 if (num < (ulonglong) 65536LL)
206 return 3;
207 if (num < (ulonglong) 16777216LL)
208 return 4;
209 return 9;
210}
211