001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *   Granite Data Services is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *
012 *   Granite Data Services is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 *   General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public
018 *   License along with this library; if not, write to the Free Software
019 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 *   USA, or see <http://www.gnu.org/licenses/>.
021 */
022package org.granite.messaging.jmf.codec.std.impl.util;
023
024import java.io.IOException;
025import java.io.OutputStream;
026
027import org.granite.messaging.jmf.InputContext;
028import org.granite.messaging.jmf.OutputContext;
029
030/**
031 * @author Franck WOLFF
032 */
033public class LongUtil {
034
035        // ------------------------------------------------------------------------
036
037        public static void encodeLong(OutputContext ctx, long v) throws IOException {
038                final OutputStream os = ctx.getOutputStream();
039                
040                os.write((int)(v >>> 56));
041                os.write((int)(v >>> 48));
042                os.write((int)(v >>> 40));
043                os.write((int)(v >>> 32));
044                os.write((int)(v >>> 24));
045                os.write((int)(v >>> 16));
046                os.write((int)(v >>> 8));
047                os.write((int)v);
048        }
049        
050        public static long decodeLong(InputContext ctx) throws IOException {
051                return (
052                        ctx.safeReadLong() << 56 |
053                        ctx.safeReadLong() << 48 |
054                        ctx.safeReadLong() << 40 |
055                        ctx.safeReadLong() << 32 |
056                        ctx.safeReadLong() << 24 |
057                        ctx.safeReadLong() << 16 |
058                        ctx.safeReadLong() << 8  |
059                        ctx.safeReadLong()
060                );
061        }
062
063        // ------------------------------------------------------------------------
064        
065        public static int significantLongBytesCount0(long v) {
066                if (v < 0L)
067                        return 7;
068                if (v <= 0xFFFFFFFFL) {
069                        if (v <= 0xFFFFL)
070                                return (v <= 0xFFL ? 0 : 1);
071                        return (v <= 0xFFFFFFL ? 2 : 3);
072                }
073                if (v <= 0xFFFFFFFFFFFFL)
074                        return (v <= 0xFFFFFFFFFFL ? 4 : 5);
075                return (v <= 0xFFFFFFFFFFFFFFL ? 6 : 7);
076        }
077
078        public static void encodeLong(OutputContext ctx, long v, int significantLongBytesCount0) throws IOException {
079                final OutputStream os = ctx.getOutputStream();
080                
081                switch (significantLongBytesCount0) {
082                case 7:
083                        os.write((int)(v >>> 56));
084                case 6:
085                        os.write((int)(v >>> 48));
086                case 5:
087                        os.write((int)(v >>> 40));
088                case 4:
089                        os.write((int)(v >>> 32));
090                case 3:
091                        os.write((int)(v >>> 24));
092                case 2:
093                        os.write((int)(v >>> 16));
094                case 1:
095                        os.write((int)(v >>> 8));
096                case 0:
097                        os.write((int)v);
098                }
099        }
100        
101        public static long decodeLong(InputContext ctx, int significantLongBytesCount0) throws IOException {
102                long v = 0L;
103                
104                switch (significantLongBytesCount0) {
105                case 7:
106                        v |= ctx.safeReadLong() << 56;
107                case 6:
108                        v |= ctx.safeReadLong() << 48;
109                case 5:
110                        v |= ctx.safeReadLong() << 40;
111                case 4:
112                        v |= ctx.safeReadLong() << 32;
113                case 3:
114                        v |= ctx.safeReadLong() << 24;
115                case 2:
116                        v |= ctx.safeReadLong() << 16;
117                case 1:
118                        v |= ctx.safeReadLong() << 8;
119                case 0:
120                        v |= ctx.safeReadLong();
121                }
122                
123                return v;
124        }
125        
126        // ------------------------------------------------------------------------
127        
128        public static final long MIN_1_BYTES_VARIABLE_LONG = -0x40L;
129        public static final long MAX_1_BYTES_VARIABLE_LONG =  0x3FL;
130        
131        public static final long MIN_2_BYTES_VARIABLE_LONG = -0x2040L;
132        public static final long MAX_2_BYTES_VARIABLE_LONG =  0x203FL;
133        
134        public static final long MIN_3_BYTES_VARIABLE_LONG = -0x102040L;
135        public static final long MAX_3_BYTES_VARIABLE_LONG =  0x10203FL;
136        
137        public static final long MIN_4_BYTES_VARIABLE_LONG = -0x8102040L;
138        public static final long MAX_4_BYTES_VARIABLE_LONG =  0x810203FL;
139        
140        public static final long MIN_5_BYTES_VARIABLE_LONG = -0x408102040L;
141        public static final long MAX_5_BYTES_VARIABLE_LONG =  0x40810203FL;
142        
143        public static final long MIN_6_BYTES_VARIABLE_LONG = -0x20408102040L;
144        public static final long MAX_6_BYTES_VARIABLE_LONG =  0x2040810203FL;
145        
146        public static final long MIN_7_BYTES_VARIABLE_LONG = -0x1020408102040L;
147        public static final long MAX_7_BYTES_VARIABLE_LONG =  0x102040810203FL;
148        
149        public static final long MIN_8_BYTES_VARIABLE_LONG = -0x81020408102040L;
150        public static final long MAX_8_BYTES_VARIABLE_LONG =  0x8102040810203FL;
151        
152        // ------------------------------------------------------------------------
153
154        public static void encodeVariableLong(OutputContext ctx, long v) throws IOException {
155                encodeVariableUnsignedLong(ctx, (v << 1) ^ (v >> 63));
156        }
157        
158        public static long decodeVariableLong(InputContext ctx) throws IOException {
159                long v = decodeVariableUnsignedLong(ctx);
160                return ((v & 0x1L) == 0 ? (v >>> 1) : (-1L ^ (v >>> 1)));
161        }
162        
163        // ------------------------------------------------------------------------
164
165        public static void encodeVariableUnsignedLong(OutputContext ctx, long v) throws IOException {
166                final OutputStream os = ctx.getOutputStream();
167                
168                if (v >= 0 && v < 0x102040810204080L) {
169                        
170                        if (v < 0x10204080L) {
171                                if (v < 0x4080L) {
172                                        if (v < 0x80L)
173                                                os.write((int)v);
174                                        else {
175                                                v -= 0x80L;
176                                                os.write(0x80 | (int)v);
177                                                os.write((int)(v >>> 7));
178                                        }
179                                }
180                                else if (v < 0x204080L) {
181                                        v -= 0x4080L;
182                                        os.write(0x80 | (int)v);
183                                        os.write(0x80 | (int)(v >>> 7));
184                                        os.write((int)(v >>> 14));
185                                }
186                                else {
187                                        v -= 0x204080L;
188                                        os.write(0x80 | (int)v);
189                                        os.write(0x80 | (int)(v >>> 7));
190                                        os.write(0x80 | (int)(v >>> 14));
191                                        os.write((int)(v >>> 21));
192                                }
193                        }
194                        else if (v < 0x40810204080L){
195                                if (v < 0x810204080L) {
196                                        v -= 0x10204080L;
197                                        os.write(0x80 | (int)v);
198                                        os.write(0x80 | (int)(v >>> 7));
199                                        os.write(0x80 | (int)(v >>> 14));
200                                        os.write(0x80 | (int)(v >>> 21));
201                                        os.write((int)(v >>> 28));
202                                }
203                                else {
204                                        v -= 0x810204080L;
205                                        os.write(0x80 | (int)v);
206                                        os.write(0x80 | (int)(v >>> 7));
207                                        os.write(0x80 | (int)(v >>> 14));
208                                        os.write(0x80 | (int)(v >>> 21));
209                                        os.write(0x80 | (int)(v >>> 28));
210                                        os.write((int)(v >>> 35));
211                                }
212                        }
213                        else if (v < 0x2040810204080L) {
214                                v -= 0x40810204080L;
215                                os.write(0x80 | (int)v);
216                                os.write(0x80 | (int)(v >>> 7));
217                                os.write(0x80 | (int)(v >>> 14));
218                                os.write(0x80 | (int)(v >>> 21));
219                                os.write(0x80 | (int)(v >>> 28));
220                                os.write(0x80 | (int)(v >>> 35));
221                                os.write((int)(v >>> 42));
222                        }
223                        else {
224                                v -= 0x2040810204080L;
225                                os.write(0x80 | (int)v);
226                                os.write(0x80 | (int)(v >>> 7));
227                                os.write(0x80 | (int)(v >>> 14));
228                                os.write(0x80 | (int)(v >>> 21));
229                                os.write(0x80 | (int)(v >>> 28));
230                                os.write(0x80 | (int)(v >>> 35));
231                                os.write(0x80 | (int)(v >>> 42));
232                                os.write((int)(v >>> 49));
233                        }
234                }
235                else {
236                        os.write(0x80 | (int)v);
237                        os.write(0x80 | (int)(v >>> 7));
238                        os.write(0x80 | (int)(v >>> 14));
239                        os.write(0x80 | (int)(v >>> 21));
240                        os.write(0x80 | (int)(v >>> 28));
241                        os.write(0x80 | (int)(v >>> 35));
242                        os.write(0x80 | (int)(v >>> 42));
243                        os.write(0x80 | (int)(v >>> 49));
244                        os.write((int)(v >>> 56));
245                }
246        }
247
248        public static long decodeVariableUnsignedLong(InputContext ctx) throws IOException {
249                long v = ctx.safeReadLong();
250                
251                if ((v & 0x80L) != 0) {
252                        v = (v & 0x7FL) | (ctx.safeReadLong() << 7);
253                        
254                        if ((v & 0x4000L) != 0) {
255                                v = (v & 0x3FFFL) | (ctx.safeReadLong() << 14);
256                                
257                                if ((v & 0x200000L) != 0) {
258                                        v = (v & 0x1FFFFFL) | (ctx.safeReadLong() << 21);
259                                        
260                                        if ((v & 0x10000000L) != 0) {
261                                                v = (v & 0xFFFFFFFL) | (ctx.safeReadLong() << 28);
262                                                
263                                                if ((v & 0x800000000L) != 0) {
264                                                        v = (v & 0x7FFFFFFFFL) | (ctx.safeReadLong() << 35);
265                                                        
266                                                        if ((v & 0x40000000000L) != 0) {
267                                                                v = (v & 0x3FFFFFFFFFFL) | (ctx.safeReadLong() << 42);
268
269                                                                if ((v & 0x2000000000000L) != 0) {
270                                                                        v = (v & 0x1FFFFFFFFFFFFL) | (ctx.safeReadLong() << 49);
271
272                                                                        if ((v & 0x100000000000000L) != 0)
273                                                                                v = (v & 0xFFFFFFFFFFFFFFL) | (ctx.safeReadLong() << 56);
274                                                                        else
275                                                                                v += 0x2040810204080L;
276                                                                }
277                                                                else
278                                                                        v += 0x40810204080L;
279                                                        }
280                                                        else
281                                                                v += 0x810204080L;
282                                                }
283                                                else
284                                                        v += 0x10204080L;
285                                        }
286                                        else
287                                                v += 0x204080L;
288                                }
289                                else
290                                        v += 0x4080L;
291                        }
292                        else
293                                v += 0x80L;
294                }
295                
296                return v;
297        }
298}