Subversion Repository Public Repository

litesoft

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
package org.litesoft.codec;

import org.litesoft.charstreams.*;
import org.litesoft.commonfoundation.annotations.*;

public class PrimitiveLongCodec
{
    public static final PrimitiveLongCodec SIGNED = new PrimitiveLongCodec( true );
    public static final PrimitiveLongCodec NON_NEGATIVE = new PrimitiveLongCodec( false );

    private final boolean mSignedValuesOK;

    private PrimitiveLongCodec( boolean pSignedValuesOK )
    {
        mSignedValuesOK = pSignedValuesOK;
    }

    public void encode( @NotNull CharSink pCharSink, long pValue )
    {
        if ( (pValue < 0) && !mSignedValuesOK )
        {
            throw new IllegalArgumentException( "Negative values not supported: " + pValue );
        }
        new Encoder( pCharSink, pValue ).encode();
    }

    public long decode( @NotNull CharSource pCharSource )
    {
        return new Decoder( pCharSource ).decode();
    }

    private static final int NEGATIVE_1ST_CHAR_BIT = 16;
    private static final int NON_NEGATIVE_1ST_CHAR_BIT = 0;

    private static final int SIGNED_1ST_CHAR_MASK = 15;
    private static final int SIGNED_1ST_CHAR_FACTOR = 16;

    private static final int UNSIGNED_1ST_CHAR_MASK = 31;
    private static final int UNSIGNED_1ST_CHAR_FACTOR = 32;

    private static final int MORE_BIT = 32;
    private static final int MORE_MASK = 31;
    private static final int MORE_FACTOR = 32;

    private class Common
    {
        protected final int mFirstCharMask;
        protected final int mFirstCharFactor;

        protected Common()
        {
            if ( mSignedValuesOK )
            {
                mFirstCharMask = SIGNED_1ST_CHAR_MASK;
                mFirstCharFactor = SIGNED_1ST_CHAR_FACTOR;
            }
            else
            {
                mFirstCharMask = UNSIGNED_1ST_CHAR_MASK;
                mFirstCharFactor = UNSIGNED_1ST_CHAR_FACTOR;
            }
        }
    }

    private class Encoder extends Common
    {
        private final CharSink mCharSink;
        private long mValue;

        private Encoder( CharSink pCharSink, long pValue )
        {
            mCharSink = pCharSink;
            mValue = pValue;
        }

        public void encode()
        {
            if ( mSignedValuesOK && (mValue < 0) )
            {
                if ( Long.MIN_VALUE == mValue )
                {
                    mCharSink.add( SixBitCodec.encode( NEGATIVE_1ST_CHAR_BIT ) ); // Record as '-0'
                }
                else
                {
                    mValue = -mValue;
                    encode( NEGATIVE_1ST_CHAR_BIT );
                }
                return;
            }
            if ( mValue < mFirstCharFactor )
            {
                mCharSink.add( SixBitCodec.encode( (int) mValue ) );
            }
            else
            {
                encode( NON_NEGATIVE_1ST_CHAR_BIT );
            }
        }

        private void encode( int pNegativeBit )
        {
            int bits = extractBits( mFirstCharMask, mFirstCharFactor );
            mCharSink.add( SixBitCodec.encode( bits | pNegativeBit ) );
            while ( mValue > 0 )
            {
                bits = extractBits( MORE_MASK, MORE_FACTOR );
                mCharSink.add( SixBitCodec.encode( bits ) );
            }
        }

        private int extractBits( int pBits, int pDivisor )
        {
            int rv = (int) (mValue & pBits);
            if ( (mValue /= pDivisor) > 0 )
            {
                rv |= MORE_BIT;
            }
            return rv;
        }
    }

    private class Decoder extends Common
    {
        private final CharSource mValue;
        private boolean negative;

        private Decoder( CharSource pValue )
        {
            mValue = pValue;
        }

        public long decode()
        {
            int bits = SixBitCodec.decode( mValue.getRequired() );
            negative = mSignedValuesOK & ((bits & NEGATIVE_1ST_CHAR_BIT) != 0);

            long result = (bits & mFirstCharMask);
            for ( long zMultiplier = mFirstCharFactor; (bits & MORE_BIT) != 0; zMultiplier *= MORE_FACTOR )
            {
                bits = SixBitCodec.decode( mValue.getRequired() );
                result += (bits & MORE_MASK) * zMultiplier;
            }
            if ( !negative )
            {
                return result;
            }
            if ( result == 0 ) // '-0'
            {
                return Long.MIN_VALUE;
            }
            return -result;
        }
    }
}

Commits for litesoft/trunk/Java/core/Anywhere/src/org/litesoft/codec/PrimitiveLongCodec.java

Diff revisions: vs.
Revision Author Commited Message
939 Diff Diff GeorgeS picture GeorgeS Mon 02 Jun, 2014 21:30:31 +0000

Extracting commonfoundation

831 GeorgeS picture GeorgeS Fri 31 Aug, 2012 22:39:56 +0000