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 IntegerUtil {
034
035        // ------------------------------------------------------------------------
036
037        public static void encodeInteger(OutputContext ctx, int v) throws IOException {
038                final OutputStream os = ctx.getOutputStream();
039                
040                os.write(v >>> 24);
041                os.write(v >>> 16);
042                os.write(v >>> 8);
043                os.write(v);
044        }
045        
046        public static int decodeInteger(InputContext ctx) throws IOException {
047                return (
048                        ctx.safeRead() << 24 |
049                        ctx.safeRead() << 16 |
050                        ctx.safeRead() << 8  |
051                        ctx.safeRead()
052                );
053        }
054        
055        // ------------------------------------------------------------------------
056        
057        public static int significantIntegerBytesCount0(int v) {
058                if (v < 0)
059                        return 3;
060                if (v <= 0xFFFF)
061                        return (v <= 0xFF ? 0 : 1);
062                return (v <= 0xFFFFFF ? 2 : 3);
063        }
064        
065        public static void encodeInteger(OutputContext ctx, int v, int significantIntegerBytesCount0) throws IOException {
066                final OutputStream os = ctx.getOutputStream();
067                
068                switch (significantIntegerBytesCount0) {
069                case 3:
070                        os.write(v >>> 24);
071                case 2:
072                        os.write(v >>> 16);
073                case 1:
074                        os.write(v >>> 8);
075                case 0:
076                        os.write(v);
077                }
078        }
079        
080        public static int decodeInteger(InputContext ctx, int significantIntegerBytesCount0) throws IOException {
081                int v = 0;
082                
083                switch (significantIntegerBytesCount0) {
084                case 3:
085                        v |= ctx.safeRead() << 24;
086                case 2:
087                        v |= ctx.safeRead() << 16;
088                case 1:
089                        v |= ctx.safeRead() << 8;
090                case 0:
091                        v |= ctx.safeRead();
092                }
093                
094                return v;
095        }
096
097        // ------------------------------------------------------------------------
098        
099        public static void encodeVariableInteger(OutputContext ctx, int v) throws IOException {
100                encodeVariableUnsignedInteger(ctx, (v << 1) ^ (v >> 31));
101        }
102
103        public static int decodeVariableInteger(InputContext ctx) throws IOException {
104                int v = decodeVariableUnsignedInteger(ctx);
105                return ((v & 0x1) == 0 ? (v >>> 1) : (-1 ^ (v >>> 1)));
106        }
107        
108        // ------------------------------------------------------------------------
109        
110        public static void encodeVariableUnsignedInteger(OutputContext ctx, int v) throws IOException {
111                final OutputStream os = ctx.getOutputStream();
112                
113                if (v >= 0 && v < 0x10204080) {
114                        if (v < 0x4080) {
115                                if (v < 0x80)
116                                        os.write(v);
117                                else {
118                                        v -= 0x80;
119                                        os.write(0x80 | v);
120                                        os.write(v >>> 7);
121                                }
122                        }
123                        else if (v < 0x204080) {
124                                v -= 0x4080;
125                                os.write(0x80 | v);
126                                os.write(0x80 | (v >>> 7));
127                                os.write(v >>> 14);
128                        }
129                        else {
130                                v -= 0x204080;
131                                os.write(0x80 | v);
132                                os.write(0x80 | (v >>> 7));
133                                os.write(0x80 | (v >>> 14));
134                                os.write(v >>> 21);
135                        }
136                }
137                else {
138                        os.write(0x80 | v);
139                        os.write(0x80 | (v >>> 7));
140                        os.write(0x80 | (v >>> 14));
141                        os.write(0x80 | (v >>> 21));
142                        os.write(v >>> 28);
143                }
144        }
145        
146        public static int decodeVariableUnsignedInteger(InputContext ctx) throws IOException {
147                int v = ctx.safeRead();
148                
149                if ((v & 0x80) != 0) {
150                        v = (v & 0x7F) | (ctx.safeRead() << 7);
151                        
152                        if ((v & 0x4000) != 0) {
153                                v = (v & 0x3FFF) | (ctx.safeRead() << 14);
154                                
155                                if ((v & 0x200000) != 0) {
156                                        v = (v & 0x1FFFFF) | (ctx.safeRead() << 21);
157                                        
158                                        if ((v & 0x10000000) != 0)
159                                                v = (v & 0x0FFFFFFF) | (ctx.safeRead() << 28);
160                                        else
161                                                v += 0x204080;
162                                }
163                                else
164                                        v += 0x4080;
165                        }
166                        else
167                                v += 0x80;
168                }
169                
170                return v;
171        }
172}