| 1 | /* |
| 2 | * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. Oracle designates this |
| 8 | * particular file as subject to the "Classpath" exception as provided |
| 9 | * by Oracle in the LICENSE file that accompanied this code. |
| 10 | * |
| 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 14 | * version 2 for more details (a copy is included in the LICENSE file that |
| 15 | * accompanied this code). |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License version |
| 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | * |
| 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 22 | * or visit www.oracle.com if you need additional information or have any |
| 23 | * questions. |
| 24 | */ |
| 25 | |
| 26 | struct unpacker; |
| 27 | |
| 28 | #define INT_MAX_VALUE ((int)0x7FFFFFFF) |
| 29 | #define INT_MIN_VALUE ((int)0x80000000) |
| 30 | |
| 31 | #define CODING_SPEC(B, H, S, D) ((B)<<20|(H)<<8|(S)<<4|(D)<<0) |
| 32 | #define CODING_B(x) ((x)>>20 & 0xF) |
| 33 | #define CODING_H(x) ((x)>>8 & 0xFFF) |
| 34 | #define CODING_S(x) ((x)>>4 & 0xF) |
| 35 | #define CODING_D(x) ((x)>>0 & 0xF) |
| 36 | |
| 37 | #define CODING_INIT(B, H, S, D) \ |
| 38 | { CODING_SPEC(B, H, S, D) , 0, 0, 0, 0, 0, 0, 0, 0} |
| 39 | |
| 40 | // For debugging purposes, some compilers do not like this and will complain. |
| 41 | // #define long do_not_use_C_long_types_use_jlong_or_int |
| 42 | // Use of the type "long" is problematic, do not use it. |
| 43 | |
| 44 | struct coding { |
| 45 | int spec; // B,H,S,D |
| 46 | |
| 47 | // Handy values derived from the spec: |
| 48 | int B() { return CODING_B(spec); } |
| 49 | int H() { return CODING_H(spec); } |
| 50 | int S() { return CODING_S(spec); } |
| 51 | int D() { return CODING_D(spec); } |
| 52 | int L() { return 256-CODING_H(spec); } |
| 53 | int min, max; |
| 54 | int umin, umax; |
| 55 | char isSigned, isSubrange, isFullRange, isMalloc; |
| 56 | |
| 57 | coding* init(); // returns self or null if error |
| 58 | coding* initFrom(int spec_) { |
| 59 | assert(this->spec == 0); |
| 60 | this->spec = spec_; |
| 61 | return init(); |
| 62 | } |
| 63 | |
| 64 | static coding* findBySpec(int spec); |
| 65 | static coding* findBySpec(int B, int H, int S=0, int D=0); |
| 66 | static coding* findByIndex(int irregularCodingIndex); |
| 67 | |
| 68 | static uint parse(byte* &rp, int B, int H); |
| 69 | static uint parse_lgH(byte* &rp, int B, int H, int lgH); |
| 70 | static void parseMultiple(byte* &rp, int N, byte* limit, int B, int H); |
| 71 | |
| 72 | uint parse(byte* &rp) { |
| 73 | return parse(rp, CODING_B(spec), CODING_H(spec)); |
| 74 | } |
| 75 | void parseMultiple(byte* &rp, int N, byte* limit) { |
| 76 | parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec)); |
| 77 | } |
| 78 | |
| 79 | bool canRepresent(int x) { return (x >= min && x <= max); } |
| 80 | bool canRepresentUnsigned(int x) { return (x >= umin && x <= umax); } |
| 81 | |
| 82 | int sumInUnsignedRange(int x, int y); |
| 83 | |
| 84 | int readFrom(byte* &rpVar, int* dbase); |
| 85 | void readArrayFrom(byte* &rpVar, int* dbase, int length, int* values); |
| 86 | void skipArrayFrom(byte* &rpVar, int length) { |
| 87 | readArrayFrom(rpVar, (int*)NULL, length, (int*)NULL); |
| 88 | } |
| 89 | |
| 90 | #ifndef PRODUCT |
| 91 | const char* string(); |
| 92 | #endif |
| 93 | |
| 94 | void free(); // free self if isMalloc |
| 95 | |
| 96 | // error handling |
| 97 | static void abort(const char* msg = null) { unpack_abort(msg); } |
| 98 | }; |
| 99 | |
| 100 | enum coding_method_kind { |
| 101 | cmk_ERROR, |
| 102 | cmk_BHS, |
| 103 | cmk_BHS0, |
| 104 | cmk_BHS1, |
| 105 | cmk_BHSD1, |
| 106 | cmk_BHS1D1full, // isFullRange |
| 107 | cmk_BHS1D1sub, // isSubRange |
| 108 | |
| 109 | // special cases hand-optimized (~50% of all decoded values) |
| 110 | cmk_BYTE1, //(1,256) 6% |
| 111 | cmk_CHAR3, //(3,128) 7% |
| 112 | cmk_UNSIGNED5, //(5,64) 13% |
| 113 | cmk_DELTA5, //(5,64,1,1) 5% |
| 114 | cmk_BCI5, //(5,4) 18% |
| 115 | cmk_BRANCH5, //(5,4,2) 4% |
| 116 | //cmk_UNSIGNED5H16, //(5,16) 5% |
| 117 | //cmk_UNSIGNED2H4, //(2,4) 6% |
| 118 | //cmk_DELTA4H8, //(4,8,1,1) 10% |
| 119 | //cmk_DELTA3H16, //(3,16,1,1) 9% |
| 120 | cmk_BHS_LIMIT, |
| 121 | |
| 122 | cmk_pop, |
| 123 | cmk_pop_BHS0, |
| 124 | cmk_pop_BYTE1, |
| 125 | cmk_pop_LIMIT, |
| 126 | |
| 127 | cmk_LIMIT |
| 128 | }; |
| 129 | |
| 130 | enum { |
| 131 | BYTE1_spec = CODING_SPEC(1, 256, 0, 0), |
| 132 | CHAR3_spec = CODING_SPEC(3, 128, 0, 0), |
| 133 | UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0), |
| 134 | UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0), |
| 135 | SIGNED5_spec = CODING_SPEC(5, 64, 1, 0), |
| 136 | DELTA5_spec = CODING_SPEC(5, 64, 1, 1), |
| 137 | UDELTA5_spec = CODING_SPEC(5, 64, 0, 1), |
| 138 | MDELTA5_spec = CODING_SPEC(5, 64, 2, 1), |
| 139 | BCI5_spec = CODING_SPEC(5, 4, 0, 0), |
| 140 | BRANCH5_spec = CODING_SPEC(5, 4, 2, 0) |
| 141 | }; |
| 142 | |
| 143 | enum { |
| 144 | B_MAX = 5, |
| 145 | C_SLOP = B_MAX*10 |
| 146 | }; |
| 147 | |
| 148 | struct coding_method; |
| 149 | |
| 150 | // iterator under the control of a meta-coding |
| 151 | struct value_stream { |
| 152 | // current coding of values or values |
| 153 | coding c; // B,H,S,D,etc. |
| 154 | coding_method_kind cmk; // type of decoding needed |
| 155 | byte* rp; // read pointer |
| 156 | byte* rplimit; // final value of read pointer |
| 157 | int sum; // partial sum of all values so far (D=1 only) |
| 158 | coding_method* cm; // coding method that defines this stream |
| 159 | |
| 160 | void init(byte* band_rp, byte* band_limit, coding* defc); |
| 161 | void init(byte* band_rp, byte* band_limit, int spec) |
| 162 | { init(band_rp, band_limit, coding::findBySpec(spec)); } |
| 163 | |
| 164 | void setCoding(coding* c); |
| 165 | void setCoding(int spec) { setCoding(coding::findBySpec(spec)); } |
| 166 | |
| 167 | // Parse and decode a single value. |
| 168 | int getInt(); |
| 169 | |
| 170 | // Parse and decode a single byte, with no error checks. |
| 171 | int getByte() { |
| 172 | assert(cmk == cmk_BYTE1); |
| 173 | assert(rp < rplimit); |
| 174 | return *rp++ & 0xFF; |
| 175 | } |
| 176 | |
| 177 | // Used only for asserts. |
| 178 | bool hasValue(); |
| 179 | |
| 180 | void done() { assert(!hasValue()); } |
| 181 | |
| 182 | // Sometimes a value stream has an auxiliary (but there are never two). |
| 183 | value_stream* helper() { |
| 184 | assert(hasHelper()); |
| 185 | return this+1; |
| 186 | } |
| 187 | bool hasHelper(); |
| 188 | |
| 189 | // error handling |
| 190 | // inline void abort(const char* msg); |
| 191 | // inline void aborting(); |
| 192 | }; |
| 193 | |
| 194 | struct coding_method { |
| 195 | value_stream vs0; // initial state snapshot (vs.meta==this) |
| 196 | |
| 197 | coding_method* next; // what to do when we run out of bytes |
| 198 | |
| 199 | // these fields are used for pop codes only: |
| 200 | int* fValues; // favored value array |
| 201 | int fVlength; // maximum favored value token |
| 202 | coding_method* uValues; // unfavored value stream |
| 203 | |
| 204 | // pointer to outer unpacker, for error checks etc. |
| 205 | unpacker* u; |
| 206 | |
| 207 | // Initialize a value stream. |
| 208 | void reset(value_stream* state); |
| 209 | |
| 210 | // Parse a band header, size a band, and initialize for further action. |
| 211 | // band_rp advances (but not past band_limit), and meta_rp advances. |
| 212 | // The mode gives context, such as "inside a pop". |
| 213 | // The defc and N are the incoming parameters to a meta-coding. |
| 214 | // The value sink is used to collect output values, when desired. |
| 215 | void init(byte* &band_rp, byte* band_limit, |
| 216 | byte* &meta_rp, int mode, |
| 217 | coding* defc, int N, |
| 218 | intlist* valueSink); |
| 219 | |
| 220 | // error handling |
| 221 | void abort(const char* msg) { unpack_abort(msg, u); } |
| 222 | bool aborting() { return unpack_aborting(u); } |
| 223 | }; |
| 224 | |
| 225 | //inline void value_stream::abort(const char* msg) { cm->abort(msg); } |
| 226 | //inline void value_stream::aborting() { cm->aborting(); } |
| 227 | |