class_metadata_bands: class_RVA_bands class_RIA_bands field_metadata_bands: field_RVA_bands field_RIA_bands method_metadata_bands: method_RVA_bands method_RIA_bands method_RVPA_bands method_RIPA_bands method_AD_bands class_RVA_bands: *class_RVA_anno_N :UNSIGNED5 [...] *class_RVA_type_RS :UNSIGNED5 [...] (cp_Signature) *class_RVA_pair_N :UNSIGNED5 [...] *class_RVA_name_RU :UNSIGNED5 [...] (cp_Utf8) *class_RVA_T :BYTE1 [...] *class_RVA_caseI_KI :UNSIGNED5 [...] (cp_Int) *class_RVA_caseD_KD :UNSIGNED5 [...] (cp_Double) *class_RVA_caseF_KF :UNSIGNED5 [...] (cp_Float) *class_RVA_caseJ_KJ :UNSIGNED5 [...] (cp_Long) *class_RVA_casec_RS :UNSIGNED5 [...] (cp_Signature) *class_RVA_caseet_RS :UNSIGNED5 [...] (cp_Signature) *class_RVA_caseec_RU :UNSIGNED5 [...] (cp_Utf8) *class_RVA_cases_RU :UNSIGNED5 [...] (cp_Utf8) *class_RVA_casearray_N :UNSIGNED5 [...] *class_RVA_nesttype_RS :UNSIGNED5 [...] (cp_Signature) *class_RVA_nestpair_N :UNSIGNED5 [...] *class_RVA_nestname_RU :UNSIGNED5 [...] (cp_Utf8) class_RIA_bands: *class_RIA_anno_N :UNSIGNED5 [...] (analogous to class_RVA_bands) field_RVA_bands: *field_RVA_anno_N :UNSIGNED5 [...] (analogous to class_RVA_bands) field_RIA_bands: *field_RIA_anno_N :UNSIGNED5 [...] (analogous to field_RVA_bands) method_RVA_bands: *method_RVA_anno_N :UNSIGNED5 [...] (analogous to class_RVA_bands) method_RIA_bands: *method_RIA_anno_N :UNSIGNED5 [...] (analogous to method_RIA_bands) method_RVPA_bands: *method_RVPA_param_NB :BYTE1 [...] *method_RVPA_anno_N :UNSIGNED5 [...] (analogous to method_RVA_bands) method_RIPA_bands: *method_RIPA_param_NB :BYTE1 [...] *method_RIPA_anno_N :UNSIGNED5 [...] (analogous to method_RVPA_bands) method_AD_bands *method_AD_T :BYTE1 [...] *method_AD_caseI_KI :UNSIGNED5 [...] (cp_Int) *method_AD_caseD_KD :UNSIGNED5 [...] (cp_Double) *method_AD_caseF_KF :UNSIGNED5 [...] (cp_Float) *method_AD_caseJ_KJ :UNSIGNED5 [...] (cp_Long) *method_AD_casec_RS :UNSIGNED5 [...] (cp_Signature) *method_AD_caseet_RS :UNSIGNED5 [...] (cp_Signature) *method_AD_caseec_RU :UNSIGNED5 [...] (cp_Utf8) *method_AD_cases_RU :UNSIGNED5 [...] (cp_Utf8) *method_AD_casearray_N :UNSIGNED5 [...] *method_AD_nesttype_RS :UNSIGNED5 [...] (cp_Signature) *method_AD_nestpair_N :UNSIGNED5 [...] *method_AD_nestname_RU :UNSIGNED5 [...] (cp_Utf8)
As an aid to understanding the metadata layout, here is a brief description of each of the method metadata bands, as used by classfiles which comply with JSR 175. The class and field metadata bands function in a similar way.
Note that JSR 175 does not allow embedded references to CONSTANT_Class entries, even where a reference to a class is required. Instead, JSR 175 requires that references to classes be encoded as field signatures. (Their names are bracketed by 'L' and ';'.) The Pack200 archive transmits all such values as references into cp_Signature, not cp_Class.
For each use of a parameter annotation attribute, the method_RVPA_param_NB band or method_RIPA_param_NB band (for invisible annotations) transmits an unsigned byte indicating the parameter count. For each use of a non-parameter annotation attribute, the method_RVA_anno_N band or method_RIA_anno_N band (for invisible annotations) transmits an annotation count. Likewise, for each annotated parameter, the method_RVPA_anno_N band or method_RIPA_anno_N band (for invisible annotations) transmits an annotation count.
For each visible non-parameter annotation, the method_RVA_type_RS band transmits an annotation's type, and the method_RVA_pair_N band transmits the number of that annotation's member-value pairs. Analogous values for invisible annotations and parameter annotations are transmitted in the bands method_RIA_type_RS, method_RIA_pair_N, method_RVPA_type_RS, method_RVPA_pair_N, method_RIPA_type_RS, and method_RIPA_pair_N. For each member-value pair transmitted as a direct part of a visible non-parameter annotation, the method_RVA_name_RU band transmits the member name. Analogous values for invisible annotations and parameter annotations are transmitted in the bands method_RIA_name_RU, method_RVPA_name_RU, and method_RIPA_name_RU.
For each value transmitted with a visible non-parameter annotation, whether directly, or indirectly via a nested value or annotation, the method_RVA_T band transmits a byte which selects the format of the annotation value, and analogous values are transmitted in the bands method_RIA_T, method_RVPA_T, method_RIPA_T, and (for annotation defaults) method_AD_T, Direct uses of these value tag bands are counted by summing the values of the corresponding preceding pair-count band (method_RVA_pair_N, etc.). This count also includes the sum of the corresponding following nested pair-count band (method_RVA_nestpair_N, etc.) and nested array length bands (method_RVA_casearray_N, etc.).
Since those latter sums come from backward calls in the attribute layout, they cannot be directly computed by the decompressor, but their sum is reported by the compressor as an element of method_attr_calls. (Note that the last callable in each metadata layout is the target of two backward calls from inside itself.) That band contains these backward call counts for method_RVA_T, method_RIA_T method_RVPA_T, method_RIPA_T method_AD_T, in that order. If there are no occurrences of a method metadata attribute, then the corresponding backward call is omitted. (Thus, there are up to five backward call counts transmitted for method metadata.) If there are compressor-defined recursive layouts used in the archive, their backward call counts follow the counts for metadata in method_attr_calls.
For each value tag of 'B', 'C', 'I', 'S', or 'Z', there is a corresponding element transmitted in method_RVA_caseI_KI which supplies the value as a cp_Int reference. Analogous integer references within invisible and parameter annotations and annotation defaults are transmitted in the bands method_RIA_caseI_KI, method_RVPA_caseI_KI, method_RIPA_caseI_KI, and method_AD_caseI_KI. For each value tag of 'e', the bands method_RVA_caseet_RS and method_RVA_caseec_RU transmit the signature of the class and name of the member of an enumeration constant, as references into cp_Signature and cp_Utf8. For each value tag of '[', the band method_RVA_casearray_N transmits the length of a nested value array. For each value tag of '@', the bands method_RVA_nesttype_RS and method_RVA_nestpair_N transmit the class signature of a nested annotation and the number of its pairs. For each pair in such a nested annotation, the band method_RVA_nestname_RU transmits the name of the pair.
The bands in the following table transmit appropriately-typed constant pool references for each occurrence of specific tag characters.
| Tag(s) | Band | Reference |
|---|---|---|
| 'B','C','I','S','Z' | method_RVA_caseI_KI | cp_Int |
| 'D' | method_RVA_caseD_KD | cp_Double |
| 'F' | method_RVA_caseF_KF | cp_Float |
| 'J' | method_RVA_caseJ_KJ | cp_Long |
| 'c' | method_RVA_casec_RS | cp_Signature |
| 'e' |
method_RVA_caseet_RS method_RVA_caseec_RU |
cp_Signature cp_Utf8 |
| 's' | method_RVA_cases_RU | cp_Utf8 |
Analogous groups of bands transmit values within the other four method annotation types, and within the visible and invisible annotations of classes and fields.
Here are the bands which transmit bytecode instructions:
bc_bands: *bc_codes :BYTE1 [...] *bc_case_count :UNSIGNED5 [COUNT(switch,*bc_codes)] *bc_case_value :DELTA5 [...] *bc_byte :BYTE1 [...] *bc_short :DELTA5 [...] *bc_local :UNSIGNED5 [...] *bc_label :BRANCH5 [...] *bc_intref :DELTA5 [...] (cp_Int) *bc_floatref :DELTA5 [...] (cp_Float) *bc_longref :DELTA5 [...] (cp_Long) *bc_doubleref :DELTA5 [...] (cp_Double) *bc_stringref :DELTA5 [...] (cp_String) *bc_loadablevalueref :DELTA5 [...] (cp_LoadableValue) *bc_classref :UNSIGNED5 [...] (current class or cp_Class) *bc_fieldref :DELTA5 [...] (cp_Field) *bc_methodref :UNSIGNED5 [...] (cp_Method) *bc_imethodref :DELTA5 [...] (cp_Imethod) *bc_indyref :DELTA5 [...] (cp_InvokeDynamic) *bc_thisfield :UNSIGNED5 [...] (cp_Field, only for current class) *bc_superfield :UNSIGNED5 [...] (cp_Field, only for current super) *bc_thismethod :UNSIGNED5 [...] (cp_Method, only for current class) *bc_supermethod :UNSIGNED5 [...] (cp_Method, only for current super) *bc_initref :UNSIGNED5 [...] (cp_Field, only for most recent new) *bc_escref :UNSIGNED5 [COUNT(ref_escape,*bc_codes)] (cp_All) *bc_escrefsize :UNSIGNED5 [...] *bc_escsize :UNSIGNED5 [...] *bc_escbyte :BYTE1 [...]
In order to transmit bytecode instructions more efficiently, some instructions may be rewritten into a transmission form. The ldc, ldc_w, and ldc2_w bytecodes must be rewritten by the compressor into strongly-typed operations; see below. Some getstatic, putstatic, getfield, putfield, invokevirtual, invokespecial, and invokestatic bytecodes may (at the compressor's option) be rewritten into more specialized and compact forms which, because they are context sensitive, select their operands from a smaller set of possibilities.
In all cases, the first byte of each instruction (perhaps rewritten) is determined by a byte transmitted in bc_codes. All operand bytes are decoded into operands and transmitted in separate bands according to the type of operand encoded. The padding bytes of switch instructions and the last two bytes of invokeinterface instructions are discarded, because they can be reconstructed by the decompressor.
A "wide" prefix bytecode is transmitted in bc_codes. The instruction following the prefix is decoded in its wide format, but (except in the case of iinc) it is transmitted in the same way, and using the same bands, as the normal (non-wide) format. The wide format of the iinc instruction uses bc_short instead of bc_byte to transmit its second operand.
Every branch instruction transmits its target (or targets, in the case of the switches) in the bc_label band, encoded as the difference between the renumbered BCI of the branch target and the renumbered BCI of the branch itself. (The renumbering, as described in the section Attribute Layout Definition, numbers the first instruction as zero, the second as one, and so forth.) Differences between renumbered BCIs are very compact; the primary encoding of BRANCH5 also takes advantage of the fact that most such differences are positive, because most branches are forward branches.
The bc_classref band carries incremented indexes into the cp_Class constant pool. The incrementing (by unity) reserves the code zero, which always refers to the current class. (This provides a a compact form for the most common class reference, which is a self-reference.)
The bc_byte and bc_short bands carry fixed-sized operands. These operands are not transmitted as general 32-bit integers because their instructions, as originally defined, already serve as specially compressed transmission formats. Integer values of these bands are treated as unsigned, even when they are semantically signed as operands. The bc_byte band is used for the last operands of multianewarray and non-wide iinc instructions, and for the operands of bipush and newarray instructions. The bc_short band is used for the last operands of wide iinc instructions, and for the operands of sipush instructions.
The bands bc_intref, bc_floatref, bc_longref, bc_doubleref, bc_stringref, bc_fieldref, bc_methodref, and bc_imethodref transmit ordinary indexes into the constant pools cp_Int, cp_Float, cp_Long, cp_Double, cp_String, cp_Field, cp_Method, and cp_Imethod, respectively.
The band bc_indyref transmits indexes into cp_InvokeDynamic, for invokedynamic instructions.
The band bc_loadablevalueref transmits indexes into the constant pool group cp_LoadableValue, such that zero refers to the first CONSTANT_Integer constant, and so on. It is transmitted immediately after bc_stringref. (Typically, this band is used for cp_MethodHandle constants.)
(The invokedynamic instructions may only appear when #archive_majver is 170 or higher. They and their related constant pool types were introduced in recent revisions of the classfile format.)
For every lookupswitch or tableswitch instruction, the number of cases is transmitted in bc_case_count, and the default label is transmitted in bc_label. Each case value and case target of a lookupswitch is transmitted in bc_case_value and bc_label, respectively. The initial case value of a tableswitch is transmitted in bc_case_value, and each of its case targets is transmitted in bc_label.
If the first byte of an instruction has a code in the range [202..255], or if an instruction's operands cannot be parsed according to the requirements of this specification, it is a non-standard instruction. Every byte of a non-standard instruction must be transmitted in a special envelope in order to warn the decompressor to accept it literally. The envelope consists of a series of "byte_escape" and "ref_escape" opcodes in the bc_code band, corresponding sizes in bc_escsize and bc_escrefsize, bytes in bc_escbyte, and constant pool references in bc_escref. Every constant pool reference in a non-standard instruction must be escaped and transmitted in the bc_escref band. Each ref_escape wraps one such constant pool reference, of size up to four bytes. The transmitted reference is an index into cp_All, such that zero refers to the first CONSTANT_Utf8 constant, and so on.
| Escape Opcode |
Size Operand |
Operand Size |
Size Band |
Data Band |
Opcode Value |
|---|---|---|---|---|---|
| byte_escape | N<=255 | N bytes | bc_escsize | bc_escbyte | 254 |
| ref_escape | N<=2 | N bytes | bc_escrefsize | bc_escref | 253 |
There is no need for special transmission of any other operand type within non-standard instructions, because the Pack200 format exactly preserves all instruction bytes except for constant pool references. This specification does not address the means by which compressors adapt to the presence and format of non-standard instructions. It simply requires decompressors to decode them correctly.
Here is a table of the specially rewritten transmission forms for instructions:
| Original Instruction |
Operand | Transmission Instruction |
Rewrite Required? |
Opcode |
|---|---|---|---|---|
| ldc | cp_String[i] | sldc | yes | 18 (=ldc) |
| ldc | cp_Class[i] | cldc | yes | 233 |
| ldc | cp_Int[i] | ildc | yes | 234 |
| ldc | cp_Float[i] | fldc | yes | 235 |
| ldc_w | cp_String[i] | sldc_w | yes | 19 (=ldc_w) |
| ldc_w | cp_Class[i] | cldc_w | yes | 236 |
| ldc_w | cp_Int[i] | ildc_w | yes | 237 |
| ldc_w | cp_Float[i] | fldc_w | yes | 238 |
| ldc2_w | cp_Long[i] | lldc2_w | yes | 20 (=ldc2_w) |
| ldc2_w | cp_Double[i] | dldc2_w | yes | 239 |
| ldc | cp_LoadableValue[i] | qldc | yes | 240 |
| ldc_w | cp_LoadableValue[i] | qldc_w | yes | 241 |
| getstatic | (this class member) | getstatic_this | no | 202 |
| putstatic | (this class member) | putstatic_this | no | 203 |
| getfield | (this class member) | getfield_this | no | 204 |
| putfield | (this class member) | putfield_this | no | 205 |
| invokevirtual | (this class member) | invokevirtual_this | no | 206 |
| invokespecial | (this class member) | invokespecial_this | no | 207 |
| invokestatic | (this class member) | invokestatic_this | no | 208 |
| aload_0; getstatic | (this class member) | aload_0_getstatic_this | no | 209 |
| aload_0; putstatic | (this class member) | aload_0_putstatic_this | no | 210 |
| aload_0; getfield | (this class member) | aload_0_getfield_this | no | 211 |
| aload_0; putfield | (this class member) | aload_0_putfield_this | no | 212 |
| aload_0; invokevirtual | (this class member) | aload_0_invokevirtual_this | no | 213 |
| aload_0; invokespecial | (this class member) | aload_0_invokespecial_this | no | 214 |
| aload_0; invokestatic | (this class member) | aload_0_invokestatic_this | no | 215 |
| getstatic | (super class member) | getstatic_super | no | 216 |
| putstatic | (super class member) | putstatic_super | no | 217 |
| getfield | (super class member) | getfield_super | no | 218 |
| putfield | (super class member) | putfield_super | no | 219 |
| invokevirtual | (super class member) | invokevirtual_super | no | 220 |
| invokespecial | (super class member) | invokespecial_super | no | 221 |
| invokestatic | (super class member) | invokestatic_super | no | 222 |
| aload_0; getstatic | (super class member) | aload_0_getstatic_super | no | 223 |
| aload_0; putstatic | (super class member) | aload_0_putstatic_super | no | 224 |
| aload_0; getfield | (super class member) | aload_0_getfield_super | no | 225 |
| aload_0; putfield | (super class member) | aload_0_putfield_super | no | 226 |
| aload_0; invokevirtual | (super class member) | aload_0_invokevirtual_super | no | 227 |
| aload_0; invokespecial | (super class member) | aload_0_invokespecial_super | no | 228 |
| aload_0; invokestatic | (super class member) | aload_0_invokestatic_super | no | 229 |
| invokespecial | (this class <init>) | invokespecial_this_init | no | 230 |
| invokespecial | (super class <init>) | invokespecial_super_init | no | 231 |
| invokespecial | (new class <init>) | invokespecial_new_init | no | 232 |
| invokespecial | cp_Imethod[i] | invokespecial_int | yes | 242 |
| invokestatic | cp_Imethod[i] | invokestatic_int | yes | 243 |
The qldc and qldc_w instructions use indexes into the constant pool group cp_LoadableValue to select arbitrary loadable constants. (These instructions may only appear when #archive_majver is 170 or higher. Early versions of the classfile format do not require them.) Decompressors are required to accept any constant reference as an operand to one of these instructions, but compressors are encouraged to transmit only constants which cannot be encoded by other variants of ldc, specifically elements of cp_MethodHandle and cp_MethodType.
(Note: A previous version of this specification referred to the string-bearing variants of ldc, sldc and sldc_w, as aldc and aldc_w. Despite the new names, the code points and their interpretation have not changed. The old names are deprecated.)
Every bytecode instruction is contained by a class, called the current class. The superclass (if any) of the current class is the current super class. The operand of the textually most recent "new" instruction (in the same method) is called the current new class.
If an instruction refers to a field or method in the current class, it may (at the compressor's option) be rewritten for transmission as a corresponding opcode spelled with "_this". Likewise, an instruction referring to a field or method in the current super class may be rewritten as a corresponding opcode spelled with "_super". In either case, if the immediately preceding instruction is aload_0 (opcode 42), the transmission of that instruction may be suppressed by the compressor, and the corresponding opcode spelled with "aload_0_" selected instead; otherwise the "aload_0_" variant may not be selected.
If an invokespecial instruction refers to a method named <init> in the current class, the current super class, or the current new class, the compressor may choose to rewrite it as an invokespecial_this_init, invokespecial_super_init, or invokespecial_new_init, respectively.
If an invokespecial or an invokestatic instruction has an operand of type CONSTANT_InterfaceMethodref, then the compressor must transmit those methods using the pseudo-instructions invokespecial_int and invokestatic_int respectively. These instructions may only appear when #archive_majver is 171 or higher.
Field (resp. method) operands of rewritten instructions spelled with "_this" (but not "_init") are transmitted in the special band bc_thisfield (resp. bc_thismethod). The numbering of these operands is defined by taking the sequence of symbols in cp_Field (resp. cp_Method) and selecting only members of the current class. The resulting subset, without changing its order, is renumbered starting with zero. This provides a compact mapping of small integers to members of the current class.
Likewise, operands of rewritten instructions spelled with "_super" (but not "_init") are transmitted in the bc_superfield or bc_supermethod band, and renumbered as a subset of cp_Field or cp_Method, selecting only members of the current super class.
Finally, operands of the rewritten instructions spelled with "_init" are transmitted in the band bc_initref, and renumbered as a subset of cp_Method, selected according to the appropriate class (current, current super, or current new), and also selected to have the name <init>. (The index transmitted is usually very small; in effect it selects only the signature of the invoked method, and most classes possess only a few constructors.)
Here is a table summarizing the transmission of instructions of more than one byte.
| Instruction | Operand | Transmitted Value |
Band |
|---|---|---|---|
| bipush | (byte) x | x & 0xFF | bc_byte |
| sipush | (short) x | x & 0xFFFF | bc_short |
| ildc | cp_Int[i] | i | bc_intref |
| fldc | cp_Float[i] | i | bc_floatref |
| sldc | cp_String[i] | i | bc_stringref |
| qldc | cp_LoadableValue[i] | i | bc_loadablevalueref |
| cldc | current class | 0 | bc_classref |
| cldc | cp_Class[i] | i+1 | bc_classref |
| ildc_w | cp_Int[i] | i | bc_intref |
| fldc_w | cp_Float[i] | i | bc_floatref |
| sldc_w | cp_String[i] | i | bc_stringref |
| qldc_w | cp_LoadableValue[i] | i | bc_loadablevalueref |
| cldc_w | current class | 0 | bc_classref |
| cldc_w | cp_Class[i] | i+1 | bc_classref |
| lldc2_w | cp_Long[i] | i | bc_long |
| dldc2_w | cp_Double[i] | i | bc_double |
| *load | locals[i] | i | bc_local |
| *store | locals[i] | i | bc_local |
| ret | locals[i] | i | bc_local |
| iinc | locals[i] | i | bc_local |
| iinc (not wide) | (byte) x | x & 0xFF | bc_byte |
| iinc (wide) | (short) x | x & 0xFFFF | bc_short |
| if** | pc | (delta/renumbered) | bc_label |
| if_** | pc | (delta/renumbered) | bc_label |
| goto | pc | (delta/renumbered) | bc_label |
| jsr | pc | (delta/renumbered) | bc_label |
| goto_w | pc | (delta/renumbered) | bc_label |
| jsr_w | pc | (delta/renumbered) | bc_label |
| tableswitch | case count | count | bc_case_count |
| tableswitch | default pc | (delta/renumbered) | bc_label |
| tableswitch | first case value | value | bc_case_value |
| tableswitch | each case pc | (delta/renumbered) | bc_label |
| lookupswitch | case count | count | bc_case_count |
| lookupswitch | default pc | (delta/renumbered) | bc_label |
| lookupswitch | each case value | value | bc_case_value |
| lookupswitch | each case pc | (delta/renumbered) | bc_label |
| new | current class | 0 | bc_classref |
| new | cp_Class[i] | 1+i | bc_classref |
| newarray | type code | value | bc_byte |
| anewarray | current class | 0 | bc_classref |
| anewarray | cp_Class[i] | 1+i | bc_classref |
| checkcast | current class | 0 | bc_classref |
| checkcast | cp_Class[i] | 1+i | bc_classref |
| instanceof | current class | 0 | bc_classref |
| instanceof | cp_Class[i] | 1+i | bc_classref |
| multianewarray | cp_Class[i] | 1+i | bc_classref |
| multianewarray | rank | rank & 0xFF | bc_byte |
| getstatic | cp_Field[i] | i | bc_fieldref |
| putstatic | cp_Field[i] | i | bc_fieldref |
| getfield | cp_Field[i] | i | bc_fieldref |
| putfield | cp_Field[i] | i | bc_fieldref |
| invokevirtual | cp_Method[i] | i | bc_methodref |
| invokespecial | cp_Method[i] | i | bc_methodref |
| invokestatic | cp_Method[i] | i | bc_methodref |
| invokeinterface | cp_Imethod[i] | i | bc_imethodref |
| invokespecial_int | cp_Imethod[i] | i | bc_imethodref |
| invokestatic_int | cp_Imethod[i] | i | bc_imethodref |
| invokedynamic | cp_InvokeDynamic[i] | i | bc_indyref |
| **_this | this_fields[i] | i | bc_thisfield |
| **_this | this_methods[i] | i | bc_thismethod |
| **_super | super_fields[i] | i | bc_superfield |
| **_super | super_methods[i] | i | bc_supermethod |
| invokespecial_this_init | this_constructors[i] | i | bc_initref |
| invokespecial_super_init | super_constructors[i] | i | bc_initref |
| invokespecial_new_init | new_constructors[i] | i | bc_initref |
Each integer is coded for transmission as a byte sequence, using between one and five bytes, according to a previously determined encoding. The encoding may by a primary encoding for the current band as specified as part of this Pack200 archive format specification, or the encoding may depend on information transmitted before the occurrence of the encoded integer.
(Note: In this account of encodings, bytes are indivisible octets which express unsigned values in [0,255].)
| Name | Range | Meaning |
|---|---|---|
| B | [1..5] | maximum byte length |
| H | [1..256] | number of high byte values |
| L | [0..255] | number of low byte values, defined as (256-H) |
Given any two values B and H, there is a coding (B,H) which establishes a one-to-one correspondence between an initial sequence of non-negative integers, and an "encoding sets" of short sequences of bytes.
Moreover, no byte sequence in the encoding set is a proper prefix of another byte sequence in the same set. prefix. This means, informally, that encodings are self-sizing, or "parseable".
Also, the encoding set is as full as possible, so that every long-enough sequence of bytes begins with a unique prefix of bytes drawn from the encoding set. In particular, every sequence of B bytes has a (unique) prefix in the encoding set for the (B,H) coding.
Given a (B,H) coding, a sequence of bytes is in its encoding set if and only if all of the following are true:
As a consequence of this definition, the encoding set be regarded as satisfying this regular expression, in terms of high and low bytes:
encoding_set = (high* low) | (high)^B
(Note: In this specification the up-caret sign '^' denotes exponentiation, either of regular expressions as above, or of numbers.)
If n is less than B then the number of (B,H) encodings of length exactly n is (H^(n-1) * L). The number of (B,H) encodings of length exactly B is (H^(B-1) * (L+H)). The sum of these values for all n in [1..B] is the total size of the encoding set for a (B,H) coding. It is called Card(B,H) and is therefore defined as:
Card(B,H) = (L * (1-H^B)/(1-H)) + H^B if H>1, or else Card(B,1) = B*255+1
If H is 256, there are no low bytes, and the encoding set consists of all possible sequences of exactly B bytes, and Card(B,H) is 256^B.
Otherwise, the encoding set consists of sequences of various lengths, from 1 to B inclusive. In particular, there are L one-byte sequences. We will use these elsewhere to encode the "favored" integers of the highest frequency. Note that the encoding rules specified elsewhere in this document are designed to produce smaller integers more frequently than larger ones.
Note that L can be viewed as a "sharpness" parameter, expressing the sharpness of the distribution about zero of the expected values to be encoded. The larger L is, the more the encoding favors distributions of values which are close to zero, and rarely far from it. Larger H values favor "flatter" distributions, up to H=256, L=0, which favorably encodes completely random data within the range of the coding.
Given the sequence of N byte values b[0] .. b[N-1], the sorting-based definition given above implies that the decoded integer value of this byte sequence is the little-endian base-H scaled sum of the bytes, and is called Decode(B,H; b):
Decode(B,H; b[*]) = Sum[0<=i<N]( b[i] * H^i )
As a consequence of this definition, each byte sequence in the encoding set corresponds uniquely to an arithmetic integer value in that range. This correspondence may be observed by ordering the byte sequences first by length, and second according to their antilexicographic (little-endian) order. Each element in resulting sequence decodes into its own zero-based index within the sequence.
Note that the number zero is always encoded by a sequence of B zero bytes (if H is 256) or else by single zero byte.
The largest encoded arithmetic value is always encoded by a sequence of B bytes of value 255.
Note that the (B,H) encodings (1,256), (2,256), and (4,256) are identical with the conventional little-endian representations of unsigned bytes, unsigned 16-bit integers, and unsigned 32-bit integers.
Note that some may represent arithmetic values greater than 2^31-1 or even 2^32-1. This is a feature of the (B,H) coding scheme. (But sometimes intermediate 64-bit values are required when multiple sign bits are being used, as described below. The rules given below for signed values require the compressor to emit the simplest encoding that will suffice to transmit the required 32-bit integer, even if more complex sequences would produce the same 32-bit value, after truncation.)
Note that implementations are not always free to truncate intermediate values when computing (B,H) coding values. However, the final decoded values (after restoration of signs) will always fit in 32 bits, as described in the next section.
| Name | Range | Meaning |
|---|---|---|
| B | [1..5] | maximum byte length |
| H | [1..256] | number of high byte values |
| L | [0..255] | number of low byte values, defined as (256-H) |
| S | [0..2] | number of sign bits |
The whole number U obtained from a (B,H) coding is converted to a signed 32-bit value X in a manner which depends on the parameter S. This process is called sign conversion.
Informally, sign conversion is performed by 32-bit truncation if S=0. Otherwise, the low-order bits of U are collectively treated as a sign bit, so that X will be negative only if all sign bits are set. The two conversions from U to positive X and U to negative X are independently dense and monotonic in opposite directions, as defined below.
Unlike the (B,H) coding, a (B,H,S) coding represents only numbers in a specifically defined range, which is never larger than [-2^31..2^31-1].
In what follows, for each (B,H,S) coding, we define Range(B,H,S), and the method used to represent 32-bit signed values with that coding.
A (B,H) encoding byte sequence is not a legal input to a corresponding (B,H,S) coding if it represents a whole number U which does not convert into the range of the (B,H,S) coding. Also, if there are two byte sequences encoding values U1 and U2 which both map into the same point X in the signed range, only the byte sequence for the smaller of U1 and U2 is legal.
Thus, a (B,H,S) coding may have a smaller cardinality than the corresponding (B,H) coding, due to illegal encoding byte sequences.
The range of a (B,H,S) coding contains all 32-bit signed integers [-2^31..2^31-1] if Card(B,H) is 2^32 or more. (Negative values are represented by 31-bit unsigned overflow.) If the coding encodes fewer unsigned values, the top of its range is clipped to 2^31-1, and the bottom of its range is clipped to -2^31.
More precisely, the range of a (B,H,S) coding is called Range(B,H,S) and is defined (partially, for S=0) as:
Range(B,H,S) = [-2^31..2^31-1] if S=0, Card(B,H) >= 2^32, or Range(B,H,S) = [0..2^31-1] if S=0, 2^31 < Card(B,H) < 2^32, or else Range(B,H,S) = [0..Card(B,H)-1] if S=0, Card(B,H) <= 2^31A compressor is not allowed to emit a byte sequence which, when interpreted according to the current coding, decodes to a value outside of that coding's range.
(Note that decompressors can produce arbitrary answers for out-of-range codings, since compressors are not allowed to emit them. This allows decompressors to use 32-bit arithmetic for most calculations, ignoring the possibility of undesired wraparond.)
If S>0, the decoding of a byte sequence is performed first by decoding it as a (B,H) coding, and then by converting the decoded whole number into a signed 32-bit number. This sign conversion depends only on the arithmetic value U obtained from the (B,H) coding, and on the value of S. The arithmetic value must be preserved beyond 32 bits of precision, if the sign conversion will produce a value within the range of the coding. If the cardinality of the (B,H) coding is 2^32 or more, the (B,H,S) coding produces all possible signed 32-bit negative values, by 32-bit truncation of the intermediate unsigned whole number. The intermediate unsigned arithmetic can be carried out (with some care) using 32-bit unsigned numbers, or it can be carried out on 64-bit signed or unsigned numbers.
More precisely, the sign conversion operation SignConvert(S;U) is defined as:
SignConvert(S; U) = Cast32(U) if S==0; or SignConvert(S; U) = U - Floor(U / 2^S) if S>0, (U % 2^S) < 2^S-1, Card(B,H) < 2^32 SignConvert(S; U) = Cast32(U - Floor(U / 2^S)) if S>0, (U % 2^S) < 2^S-1, Card(B,H) >= 2^32 SignConvert(S; U) = -Floor(U / 2^S)-1 if S>0, (U % 2^S) == 2^S-1The conversion from a large unsigned number of a negative 32-bit number via wraparound is simply the familiar down-cast to a signed 32-bit int. It may be defined mathematically as:
Cast32(U) = ((U + 2^31) mod 2^32) - 2^31
As a consequence of the definition of SignConvert(S;U), the S low-order bits of U function as a sign bit. In effect, U is partitioned into a sign field U0 (consisting of the S low-order bits) and a significand U1 (consisting of all other bits of U).
In this alternative view of the definition of SignConvert, if all S bits of U0 are set, then the decoded signed value is the ones complement of U1. (Since this includes the indefinite number of zero high-order bits of U, the resulting value is arithmetically negative.)
Otherwise, if some of the S bits of U0 are clear, then the significand U1 is scaled by the number of possible values of U0 (i.e., (2^2)-1 if S is 2) and U0 is added back in.
This provides a one-to-one correspondence between some portion of the arithmetic interval [0..Card(B,H)-1] and Range(B,H,S).
The integers "favored" by this encoding are those of small magnitude, but they can have either sign. If S is one, the encoding has a balanced number of positive and negative favored values. If S is two (or more), the encoding is skewed toward positive numbers, but also favors a few negative numbers. We use such codings elsewhere to encode values, such as branch displacements or deltas of mostly-sorted data, which are usually positive but sometimes negative.
Note that if S=1, this definition of sign conversion is equivalent to an unsigned right shift followed by an exclusive-or of the sign bit with all remaining bits:
SignConvert(1; U) = (U >>> 1) ^ -(U & 1)
For S>0, Range(B,H,S) is simply defined as the intersection of the 32-bit signed range [-2^31..2^31-1] with the set SignConvert(S; [0..Card(B,H)-1]), obtained by element-wise application of sign conversion to every arithmetically representable value of (B,H). Therefore, we can complete the definition of Range as follows:
Range(B,H,S) = [-2^31..2^31-1] if Card(B,H) >= 2^32, or Range(B,H,S) = [0..2^31-1] if S=0, 2^31 < Card(B,H) < 2^32, or else Range(B,H,S) = [0..Card(B,H)-1] if S=0, Card(B,H) <= 2^31 Range(B,H,S) = [max( -2^31, min SignConvert(S; Range(B,H,0)) ) .. min( 2^31-1, max SignConvert(S; Range(B,H,0)) )]
(Note: When computing the bounds of a signed encoding (B,H,S), it is useful to start with the largest unsigned value M of (B,H,0) and perform sign-conversion on M, M-1, M-2, etc., noting the first positive and the first negative value to be encountered. These will be the inclusive bounds of the signed encoding's range.)
Card(B,H) = (L * (1-H^B)/(1-H)) + H^B
The cardinality of a (B,H,S) coding is determined by that of its range:
Card(B,H,S) = Card Range(B,H,S) <= Card(B,H)
As defined, the range of any coding (B,H,S) is dense about zero and can therefore be expressed as a closed interval:
Range(B,H,S) = [Min(B,H,S)..Max(B,H,S)] -2^31 <= Min(B,H,S) <= 0 0 < Max(B,H,S) <= 2^31-1
Certain additional attributes can be predicated of codings. A coding can either be signed or not, and it can be a full-range coding, or a sub-range coding (or neither).
A (B,H,S) coding is signed if it can encode at least one negative value. This is true if and only if S is non-zero or S is zero and Card(B,H) is 2^32 or more.
A (B,H,S) coding is full-range if Range(B,H,S) is [-2^31..2^31-1].
A sub-range coding delivers less than 2^31 distinct values. More precisely, a coding (B,H,S) is sub-range if Card(B,H,S) <= 2^31-1. (Some codings are neither full-range nor sub-range codings.)
As a consequence of these definitions, any coding for which B<=3 is a sub-range coding. Longer codings can also be sub-ranges if they are "sharp" enough. Some examples are (4,192,0), (5,32,0), and (5,32,1).
Also, the unsigned coding (4,256,0) is full-range, as is the signed version (4,256,1), but not the doubly-signed version (4,256,2).
The coding (4,255,0) is neither a sub-range nor a full-range coding, since its cardinality is 2^31. It represents only non-negative 32-bit integers, but its cardinality cannot be so represented.
| Name | Range | Meaning |
|---|---|---|
| B | [1..5] | maximum byte length |
| H | [1..256] | number of high byte values |
| L | [0..255] | number of low byte values, defined as (256-H) |
| S | [0..2] | number of sign bits |
| D | [0..1] | delta encoding order |
If D is zero, no differencing is performed, and the (B,H,S,0) coding is in all ways identical to the corresponding (B,H,S) coding. If D is one, the values are encoded in terms of their successive differences.
(Note: Sequences which are mostly monotonically ascending will often be favorably encoded using unsigned delta codings of the form (5,H,0,1).)
Suppose a sequence of values X[i] is given, for some range of i in [0..N-1]. This sequence will be representable by a (B,H,S,1) coding only if the (B,H,S) coding is a sub-range or a full-range coding. (If it is neither, there is no legal (B,H,S,1) coding.)
The sequence X[i] will be representable, only if there is a series of "delta values" D[i] whose partial sums Sum[j<=i](D[j]) can represent the values X[i].
Each (B,H,S,1) coding has a range, in which all X[i] values must lie. This range is defined as Range(B,H,S,1) = Range(B,H,0). The range of a delta coding (B,H,S,1) contains negative numbers only if it is based on a full-range coding (B,H,S). Otherwise, the delta coding can only represent non-negative numbers. In practice, this is not a severe restriction, since in practice very few band elements are negative.
The partial sums Sum[j<=i](D[j]) are allowed to leave the range, but the final X[i] values are always brought back into range by adding or subtracting a multiple of Card Range(B,H,0).
More precisely:
X[i] = Sum[j<=i](D[j]) mod Card(B,H,0) if (B,H,S) is sub-range X[i] = (int32) Sum[j<=i](D[j]) if (B,H,S) is full-range(Here, the cast to int32 denotes truncation to 32 bits.)
Note that implementations can simply ignore 32-bit wraparound when computing partial sums, if the coding is full-range. Otherwise, more care must be taken to bring partial sums back into range by subtracting or adding multiples of the range cardinality. Also, 32-bit wraparound may be a hazard for ranges of size 2^30 or more. It is possible to implement this using only 32-bit signed arithmetic.
The compressor may elect to use a population-based coding transformation in such cases. This transformation takes a sequence S of N arithmetic values and converts it into three value sequences:
Each of these sequences (F, T, and U) is in turn treated as a sub-band, and transmitted with an independent encoding. Each non-zero value in T indexes a value from F, while each zero value in T selects (in order) a value from U:
S[i] = F[T[i]-1] if T[i] != 0 U = { S[i] such that T[i] == 0 }
The "central value" X of F is defined as that element of F which is arithmetically closest to zero. If F contains both a positive X and a negative -X of minimal absolute value, then -X is defined as the central value. (I.e., a negative sign is the tie-breaker. The central value is chosen so as to have a favorable encoding.)
(Note that implementations may compare values for centrality by
using the 32-bit signed int expression
(X>>31)^(X<<1)
as an unsigned comparison
key.)
A valid sentinel value is either the central value of F, or the last value of F. Thus, while parsing F, the decompressor must look for a repetition of either the central value (so far) or of the immediately previous value.
Let K be the number of values in F, ignoring the repetition of the sentinel value. In the next band, values in [1..K] will refer (as 1-origin indexes) to corresponding elements of F.
Each element of T is a token for either a favored or an unfavored value, encoded in the arithmetic range [0..K]. Each non-zero value corresponds in order to an element of F, and produces that favored value. Each zero value in T is a placeholder for an "unfavored" value, which is still unknown.
As mentioned above, each element of F must be referred to by at least one element of T. That is, the following two sets must be the same:
{ F[T[i]-1] such that T[i] != 0 } { F[j] }
The statistics of the sequence T are quite favorable for compact encoding in a suitable (B,H) scheme, assuming that the coder made good choices for the contents of F. Generally speaking, the most commonly occurring input values should be given early positions in F.
A greedy algorithm could sort the input values by number of occurrences and place the most common values at the front of F. This would be likely to produce an improved encoding for the input. Such techniques are neither mandated nor discouraged by this specification.
Taken together, the elements of F and U selected by the elements of T must be identical in value and order to the input of the population transformation.
The decompressor can then read F into memory, read T into memory, and then make a second pass over T, translating token values, either referring to F or reading from U as necessary.
An adaptive coding method handles this situation by allowing value sequences to be partitioned (effectively into sub-bands), with an independent coding used locally in each part.
An adaptive coding method is specified by a count K, a coding method A which will be used to encode K values, and another coding method B which will handle the rest of the values.
Since bands are sized by context, when an adaptive coding method is applied to the bytes of an encoded band, the method will be provided in advance with the count N of values to decode. Thus, after the method A has decoded K values, the method B will be used to decode the rest of the (N-K) values in the band.
Any compressor may elect not to provide a band coding specifier, in which case the band's primary encoding governs the transmission of elements. If the encoding of the first band element under the primary encoding accidentally appears to be a band coding specifier, the compressor is obligated to transmit an explicit band coding specifier that reaffirms the band's primary encoding. This is rare, because (as noted below) band coding specifiers present themselves as negative numbers in the primary encoding, and negative numbers are rare in most bands.
BandCodingSpecifier: (Default | BHSDCode | RunCode | PopCode) BHSDCode: CanonicalBHSDCode | ArbitraryBHSDCode CanonicalBHSDCode: ( '(1,256,0)' | '(1,256,1)' | ... ) ArbitraryBHSDCode: 'arb' ( B H S D ) B, H, S, D: Integer RunCode: 'run' K ACode BCode K: Integer ACode: (Default | BHSDCode | PopCode) BCode: (Default | BHSDCode | RunCode | PopCode) PopCode: 'pop' ( FCode TCode UCode ) FCode: (Default | BHSDCode | RunCode) TCode: (Default | BHSDCode | RunCode) UCode: (Default | BHSDCode | RunCode) Integer: ( '0' | '1' | ... ) Default: 'default'Note that adaptive coding methods ("RunCode" nonterminals) can be chained via the "BCode" nonterminal, but cannot be nested directly via the "ACode" nonterminal. (As the grammar shows, they may be nested indirectly via the "PopCode" nonterminal.)
Also, population coding methods can contain adaptive coding methods, and vice versa. However, although the grammar does not show this fact, population coding methods must not be nested, even indirectly.
Not all possible integer values of K and L are equally well expressible. The intended values of K are commensurate with compressor windows, and the intended values of L are sharpness parameters for BHS encodings.
We denote the application of S in the context of N and D as "S(N,D)". This application decodes up to N elements of transmitted band data.
Just before a band is received, the decompressor knows an expected band length N and a default coding method D, specified statically as the band's primary encoding. The decompressor then reads zero or more bytes which constitute a band encoding specifier, and decodes N elements of band data based on the band encoding specifier.
When the coding specifier is 'default', N values are decoded using the default coding D, which is the band's primary encoding. (This rule is necessary if the band's first element appears to introduce a non-empty coding specifier.
When the coding specifier is another BHSDCode, N values are decoded using that coding. The ambient default D is ignored.
When the coding specifier is a 'run' of K, ACode, BCode, two steps are taken. First, the specifier ACode is given control, as ACode(K,D). That is, N is temporarily set to K. Second, the specifier BCode is given control as BCode(N-K,D). (Note: If N is infinity, N-K will also be infinity.) In both steps, D remains unchanged, so that occurrences of 'default' for ACode or BCode cause D to be used.
It is illegal for a 'run' coding specifier to specify a K of zero, or for it to be used to decode a run of K or fewer values.
When the coding specifier is a 'pop' of FCode, TCode, UCode, three steps are taken. First, FCode is applied as FCode(infinity, D). The decoding of the F values stops when the first duplicate value is encountered. (As specified in the section above on population coding, that duplicate value acts as a sentinel, and must be either the most "central" value read, or else the value immediately previous to the sentinel value.) Let K be the number of unique decoded values.
During the decoding of the F values by FCode, every 'run' specifier in FCode must exhaust its count 'K' without decoding the sentinel value. That is, the sentinel must be decoded by the last simple BHSD coding in FCode.
In the second step, a different coding TCode is used, since the T values are expected to be a dense encoding. TCode is applied as TCode(N,D), and the tokens are read which determine the band values to be delivered. (Note that a 'pop' coding method can only be applied if the N value supplied is finite. This will be true, since the only bands which are read with an infinite N are byte bands such as bc_codes.) Let Z be the number of zeroes decoded using TCode.
The third step is to use UCode to decode Z values, using the original default encoding D. UCode is applied as U(Z,D). The resulting band is produced from the T sequence, as documented above, by replacing zeroes in the T sequence by successive U values, and replacing other elements of the T sequence by those indexed in the F sequence.
It is illegal for a 'pop' coding specifier to be used to decode a run of no values, or of an infinite number of values. If Z (the number of unfavored values) is zero, it is illegal for UCode to be anything other than 'default'.
The common band coding specifier of 'default' is encoded in a way that often requires no extra bytes. If the band has no elements, no parsing at all is done. Otherwise, if the band's default encoding is of variable length, the decompressor is obligated to decode one value X from the initial bytes of the band using the band's default coding D. If possible, the value X is converted into an unsigned byte value XB, which is taken to be the first byte of a band coding specifier, and X will be discarded. Otherwise, the band coding specifier is taken to be 'default', and so D is applied to the entire band, including the bytes which produced the initial value X.
D must be of the form (B,H,S) or (B,H,S,D), where B>1 and H<256. The value is D is irrelevant to the decoding of the first value, and the decoding of X is done using (B,H,S,0). If S is not zero, and if the value X is in the range [-256..-1], the coding specifier byte XB is defined as XB = (-1-X), and X is discarded. Otherwise, if S is zero, and if the value of X is in the range [(256-H)..(511-H)], the coding specifier byte XB is defined as XB = (X-(256-H)), and X is discarded. Otherwise, there is not a coding specifier byte XB, and X is the first band value, as described above.
The value XB, if produced, is taken to be the initial byte of a coding specifier preceding the actual band data. This specifier is parsed, starting with XB, and continuing (if necessary) with bytes bytes taken from band_headers. The parsed specifier is then used to control decoding, starting at the next byte, of all band elements.
If the band really does start with an element X1 in a range ([-256..-1] or [L,L+255]) that requires the production of a band specififer byte XB, but the compressor wishes to use the default encoding, the compressor is required to specify a band header, lest X1 mislead the decompressor. If the compressor wishes to keep the default coding, it must in such cases specify an explicit coding specifier of 'default', using an XB value of zero (as specified below). This zero XB is transmitted, depending on the default encoding, as an X value of -1 (usually the byte 1) or of L (usually the bytes 192,0).
(An immediate consequence of this design is that byte bands can never have non-default encodings, but all other bands can, since all the other bands have default encodigns which are variable length and have a large dynamic range. The "escape" values chosen for X are rare in practice, so they are not usually confused with real band data. Adding an extra zero value to reaffirm the default will always cost one extra byte before the actual band data, and no extra bytes in the band_headers band. In general, the encoding of explicit X values will always require two bytes if S is zero, and at most two bytes if S is not zero.)
The band band_headers transmits the non-initial band header bytes (if any) of each band that has a band header. The order of transmission is consistent with the overall order of all bands in the archive, as given in the present specification's band grammar. The length of band_headers is independently specified (as #band_headers_size) in the archive header. (It should be clear that the decompressor needs to find the end of band_headers before it can read any further bands.)
Thus, the encoding of a coding specifier consists of a sequence of bytes: an initial byte XB, and zero or more non-initial bytes taken from band_headers. The encodings of the little language specified in the previous section are as follows. The encoding 'default' is a zero byte. Of all the possible BHSDCode encodings, a sequence of 115 canonical encodings (defined below) is selected to cover the expected range of uses. A BHSDCode is represented as a single byte whose value is the index (1-based) of the selected canonical coding.
Enc{default} = (0) Enc{CanonicalBHSDCode} = value in [1..115]
The special value 116 introduces an arbitrary, possibly non-canonical BHSD code, described in the following byte.
Enc{ arb ( B H S D ) } = 116 & (D:[0..1] + 2*S[0..2] + 8*(B:[1..5]-1)) & (H[1..256]-1):The B value must be in the range [1..5]. The S value must be in the range [0..2]. The H value must be in the range [1..256]. The D value must be in the range [0..1]. (These ranges are inclusive.) In addition, if B is 1, H must be 256, and if H is 256, B must not be 5.
The 'run' construct encodings begin with a byte in [117..140], and may be followed by an optional byte KB and then by one or two encoding specifiers ACode and BCode. The offset from 117 represents bitwise the following data:
Enc{ run ( K ACode BCode ) } = (117 + (KX:[0..3]) + 4*(KBFlag:[0..1]) + 8*(ABDef:[0..2])) & KB: one of [0..255] if KBFlag=1 & Enc{ ACode } if ADef=0 (ABDef != 1) & Enc{ BCode } if BDef=0 (ABDef != 2)
After the leading byte is parsed, a byte KB is expected if the KBFlag is set, otherwise KB is implicitly given the value 3.
The K value for the 'run' construct can take a range of values, and is determined as follows:
K = (KB+1) * 16^KX
The ACode coding is understood to be 'default' if the ADef bit is set. Otherwise, the representation of ACode is parsed next. Finally, the BCode coding is understood to be 'default' if the BDef bit is set. Otherwise, the representation of BCode is parsed last. Both ADef and BDef may be clear, but both may not be set.
The 'pop' construct encodings begin with a byte in [141..188], and may be followed by one, two, or three encoding specifiers, FCode, UCode, and TCode. The offset from 141 bitwise encodes the following data:
Enc{ pop ( FCode TCode UCode ) } = (141 + (FDef:[0..1]) + 2*UDef:[0..1] + 4*(TDefL:[0..11])) & Enc{ FCode } if FDef=0 & Enc{ TCode } if TDef=0 (TDefL==0) & Enc{ UCode } if UDef=0
If TDef is zero, an explicit encoding specifier determines TCode, and the L parameter is not present. If TDef is one, the L parameter is present and is derived from TDefL, according to the following table:
| TDefL | L |
|---|---|
| 1 | 4 |
| 2 | 8 |
| 3 | 16 |
| 4 | 32 |
| 5 | 64 |
| 6 | 128 |
| 7 | 192 |
| 8 | 224 |
| 9 | 240 |
| 10 | 248 |
| 11 | 252 |
If the L parameter is present, the TCode is derived from the K and L values. If K < 256, then TCode is BYTE1 (1,255,0), and L is ignored. Otherwise, TCode is the (B,H,S) coding where S=0, H=(256-L), and B is the smallest value such that [0..K] is contained in Range(B,H,S). (It is illegal to specify an L so large that Range(5,256-L,0) does not contain K.)
The FCode coding is understood to be 'default' if the FDef bit is set. Otherwise, the representation of FCode is parsed immediately after the initial byte. The TCode coding is understood to be derived from K and L if the TDef bit is set. Otherwise, the representation of TCode is parsed next. Finally, the UCode coding is understood to be 'default' if the UDef bit is set. Otherwise, the representation of UCode is parsed last.
| index | BHSD Coding |
|---|---|
| 1 | (1,256,0) |
| 2 | (1,256,1) |
| 3 | (1,256,0,1) |
| 4 | (1,256,1,1) |
| 5 | (2,256,0) |
| 6 | (2,256,1) |
| 7 | (2,256,0,1) |
| 8 | (2,256,1,1) |
| 9 | (3,256,0) |
| 10 | (3,256,1) |
| 11 | (3,256,0,1) |
| 12 | (3,256,1,1) |
| 13 | (4,256,0) |
| 14 | (4,256,1) |
| 15 | (4,256,0,1) |
| 16 | (4,256,1,1) |
| 17 | (5, 4,0) |
| 18 | (5, 4,1) |
| 19 | (5, 4,2) |
| 20 | (5, 16,0) |
| 21 | (5, 16,1) |
| 22 | (5, 16,2) |
| 23 | (5, 32,0) |
| 24 | (5, 32,1) |
| 25 | (5, 32,2) |
| 26 | (5, 64,0) |
| 27 | (5, 64,1) |
| 28 | (5, 64,2) |
| 29 | (5,128,0) |
| 30 | (5,128,1) |
| 31 | (5,128,2) |
| 32 | (5, 4,0,1) |
| 33 | (5, 4,1,1) |
| 34 | (5, 4,2,1) |
| 35 | (5, 16,0,1) |
| 36 | (5, 16,1,1) |
| 37 | (5, 16,2,1) |
| 38 | (5, 32,0,1) |
| 39 | (5, 32,1,1) |
| 40 | (5, 32,2,1) |
| 41 | (5, 64,0,1) |
| 42 | (5, 64,1,1) |
| 43 | (5, 64,2,1) |
| 44 | (5,128,0,1) |
| 45 | (5,128,1,1) |
| 46 | (5,128,2,1) |
| 47 | (2,192,0) |
| 48 | (2,224,0) |
| 49 | (2,240,0) |
| 50 | (2,248,0) |
| 51 | (2,252,0) |
| 52 | (2, 8,0,1) |
| 53 | (2, 8,1,1) |
| 54 | (2, 16,0,1) |
| 55 | (2, 16,1,1) |
| 56 | (2, 32,0,1) |
| 57 | (2, 32,1,1) |
| 58 | (2, 64,0,1) |
| 59 | (2, 64,1,1) |
| 60 | (2,128,0,1) |
| 61 | (2,128,1,1) |
| 62 | (2,192,0,1) |
| 63 | (2,192,1,1) |
| 64 | (2,224,0,1) |
| 65 | (2,224,1,1) |
| 66 | (2,240,0,1) |
| 67 | (2,240,1,1) |
| 68 | (2,248,0,1) |
| 69 | (2,248,1,1) |
| 70 | (3,192,0) |
| 71 | (3,224,0) |
| 72 | (3,240,0) |
| 73 | (3,248,0) |
| 74 | (3,252,0) |
| 75 | (3, 8,0,1) |
| 76 | (3, 8,1,1) |
| 77 | (3, 16,0,1) |
| 78 | (3, 16,1,1) |
| 79 | (3, 32,0,1) |
| 80 | (3, 32,1,1) |
| 81 | (3, 64,0,1) |
| 82 | (3, 64,1,1) |
| 83 | (3,128,0,1) |
| 84 | (3,128,1,1) |
| 85 | (3,192,0,1) |
| 86 | (3,192,1,1) |
| 87 | (3,224,0,1) |
| 88 | (3,224,1,1) |
| 89 | (3,240,0,1) |
| 90 | (3,240,1,1) |
| 91 | (3,248,0,1) |
| 92 | (3,248,1,1) |
| 93 | (4,192,0) |
| 94 | (4,224,0) |
| 95 | (4,240,0) |
| 96 | (4,248,0) |
| 97 | (4,252,0) |
| 98 | (4, 8,0,1) |
| 99 | (4, 8,1,1) |
| 100 | (4, 16,0,1) |
| 101 | (4, 16,1,1) |
| 102 | (4, 32,0,1) |
| 103 | (4, 32,1,1) |
| 104 | (4, 64,0,1) |
| 105 | (4, 64,1,1) |
| 106 | (4,128,0,1) |
| 107 | (4,128,1,1) |
| 108 | (4,192,0,1) |
| 109 | (4,192,1,1) |
| 110 | (4,224,0,1) |
| 111 | (4,224,1,1) |
| 112 | (4,240,0,1) |
| 113 | (4,240,1,1) |
| 114 | (4,248,0,1) |
| 115 | (4,248,1,1) |
However, for any given Pack200 archive, every decompressor is required to produce a particular byte-wise image for each class file transmitted. This requirement is placed on decompressors in order to make it possible for compressors to transmit information, such as message digests, which relates to the eventual byte-wise contents of transmitted class files. This section describes the restrictions placed on every decompressor that makes the byte-wise contents of its output files a well-defined function of its input.
In general, the order of elements in a decompressed class file must be consistent with the transmission order in the Pack200 archive. For example, the order of a class's fields declared in the class file must correspond to the order in which that class's field descriptors were transmitted in the field_descr band. (This also happens to correspond to the order in the field_flags bands.) This table gives all of the required correspondences of class file order with archive transmission order:
| element in class file |
band which determines order |
|---|---|
| implemented interfaces | class_interface |
| declared fields | field_descr |
| declared methods | method_descr |
| code handler list | code_handler_start_P |
| class attribute list | class_flags, class_attr_indexes |
| field attribute list | field_flags, field_attr_indexes |
| method attribute list | method_flags, method_attr_indexes |
| code attribute list | code_attr_indexes |
| constant pool entries | cp_Utf8, etc. (see below) |
Together, these required correspondences of order determine the exact contents of the decompressed class file. The ordering of interfaces, fields, methods, and exception handlers is directly determined by the ordering of the bands that transmit them.
If an InnerClasses or BootstrapMethods attribute must be added to a class, under the rules given in the next section, those attributes must come last in the class's attribute list. If more than one such attribute is added, the relative ordering is BootstrapMethods, then InnerClasses.
Then cp(X) is defined as if by the following steps, which populate it from the global constant pool cp_All, and also potentially produce an InnerClasses attribute for X.
At this point the constant pool cp(X) is well enough defined to allow the decompressor to compute the set of relevant nested classes, called ic_Relevant(X).
With ic_Relevant(X) and an optionally transmitted ic_Local(X) in hand, the decompressor must next decide whether to store an InnerClasses attribute ic_Stored(X) for X, using these steps.
With the last contributions from nested class records, the decompressor finishes the constant pool using these steps:
After this process, the stored constant pool of X has referential integrity, and all constant references can be coded as indexes into cp(X), which has a definite order derived from cp_All. In particular, if a constant in cp(X) needs to refer to another constant, that constant must already have been inserted into cp(X), during the closure steps.
Note that the ordering of cp(X) is consistent with that of cp_All, except that some signature references are redirected to equivalent pre-existing elements of cp_Utf8, and all operands of ldc bytecodes are forced to the front of the constant pool.
When assigning local indexes to elements of cp(X), the decompressor must of course respect the reservation of empty constant pool slots for index zero, and for CONSTANT_Long and CONSTANT_Double constants, as required by the class file format. Together with these rules, the construction and ordering of cp(X) completely determines the assignment of concrete indexes to constant references within X.
| Band | Default coding |
Length | Constant pool referred to |
|
|---|---|---|---|---|
| archive_magic | BYTE1 | [4] | ||
| archive_header | UNSIGNED5 | [26] | ||
| band_headers | BYTE1 | [...] | ||
| cp_Utf8_prefix | DELTA5 | [MAX(0,#cp_Utf8_count-2)] | ||
| cp_Utf8_suffix | UNSIGNED5 | [MAX(0,#cp_Utf8_count-1)] | ||
| cp_Utf8_chars | CHAR3 | [SUM(*cp_Utf8_suffix)] | ||
| cp_Utf8_big_suffix | DELTA5 | [COUNT(0,*cp_Utf8_suffix)] | ||
| {cp_Utf8_big_chars...} | DELTA5 | [*cp_Utf8_big_suffix[i]] | ||
| cp_Int | UDELTA5 | [#cp_Int_count] | ||
| cp_Float | UDELTA5 | [#cp_Float_count] | ||
| cp_Long_hi | UDELTA5 | [#cp_Long_count] | ||
| cp_Long_lo | DELTA5 | [#cp_Long_count] | ||
| cp_Double_hi | UDELTA5 | [#cp_Double_count] | ||
| cp_Double_lo | DELTA5 | [#cp_Double_count] | ||
| cp_String | UDELTA5 | [#cp_String_count] | cp_Utf8 | |
| cp_Class | UDELTA5 | [#cp_Class_count] | cp_Utf8 | |
| cp_Signature_form | DELTA5 | [#cp_Signature_count] | cp_Utf8 | |
| cp_Signature_classes | UDELTA5 | [COUNT('L',...)] | cp_Class | |
| cp_Descr_name | DELTA5 | [#cp_Descr_count] | cp_Utf8 | |
| cp_Descr_type | UDELTA5 | [#cp_Descr_count] | cp_Signature | |
| cp_Field_class | DELTA5 | [#cp_Field_count] | cp_Class | |
| cp_Field_desc | UDELTA5 | [#cp_Field_count] | cp_Descr | |
| cp_Method_class | DELTA5 | [#cp_Method_count] | cp_Class | |
| cp_Method_desc | UDELTA5 | [#cp_Method_count] | cp_Descr | |
| cp_Imethod_class | DELTA5 | [#cp_Imethod_count] | cp_Class | |
| cp_Imethod_desc | UDELTA5 | [#cp_Imethod_count] | cp_Descr | |
| cp_MethodHandle_refkind | DELTA5 | [#cp_MethodHandle_count] | ||
| cp_MethodHandle_member | UDELTA5 | [#cp_MethodHandle_count] | cp_All | |
| cp_MethodType | UDELTA5 | [#cp_MethodType_count] | cp_Signature | |
| cp_BootstrapMethod_ref | DELTA5 | [#cp_BootstrapMethod_count] | cp_MethodHandle | |
| cp_BootstrapMethod_arg_count | UDELTA5 | [#cp_BootstrapMethod_count]arg_tt> | ||
| cp_BootstrapMethod_arg | DELTA5 | [SUM(*class_interface_count)] | cp_All | |
| cp_InvokeDynamic_spec | DELTA5 | [#cp_InvokeDynamic_count] | cp_BootstrapMethod | |
| cp_InvokeDynamic_descr | UDELTA5 | [#cp_InvokeDynamic_count] | cp_Descr | |
| attr_definition_headers | BYTE1 | [#attr_definition_count] | ||
| attr_definition_name | UNSIGNED5 | [#attr_definition_count] | cp_Utf8 | |
| attr_definition_layout | UNSIGNED5 | [#attr_definition_count] | cp_Utf8 | |
| ic_this_class | UDELTA5 | [#ic_count] | cp_Class | |
| ic_flags | UNSIGNED5 | [#ic_count] | ||
| ic_outer_class | DELTA5 | [COUNT(1<<16,...)] | cp_Class | |
| ic_name | DELTA5 | [COUNT(1<<16,...)] | cp_Utf8 | |
| class_this | DELTA5 | [#class_count] | cp_Class | |
| class_super | DELTA5 | [#class_count] | cp_Class | |
| class_interface_count | DELTA5 | [#class_count] | ||
| class_interface | DELTA5 | [SUM(*class_interface_count)] | cp_Class | |
| class_field_count | DELTA5 | [#class_count] | ||
| class_method_count | DELTA5 | [#class_count] | ||
| field_descr | DELTA5 | [SUM(*class_field_count)] | cp_Descr | |
| field_flags_hi | UNSIGNED5 | [SUM(*class_field_count)*#have_field_flags_hi] | ||
| field_flags_lo | UNSIGNED5 | [SUM(*class_field_count)] | ||
| field_attr_count | UNSIGNED5 | [COUNT(1<<16,...)] | ||
| field_attr_indexes | UNSIGNED5 | [SUM(*field_attr_count)] | ||
| field_attr_calls | UNSIGNED5 | [...] | ||
| field_ConstantValue_KQ | UNSIGNED5 | [COUNT(ConstantValue,...)] | cp_Int, cp_Float, etc. | |
| field_Signature_RS | UNSIGNED5 | [COUNT(Signature,...)] | cp_Signature | |
| field_RVA_anno_N | UNSIGNED5 | [...] | ||
| field_RVA_type_RS | UNSIGNED5 | [...] | cp_Signature | |
| field_RVA_pair_N | UNSIGNED5 | [...] | ||
| field_RVA_name_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| field_RVA_T | BYTE1 | [...] | ||
| field_RVA_caseI_KI | UNSIGNED5 | [...] | cp_Int | |
| field_RVA_caseD_KD | UNSIGNED5 | [...] | cp_Double | |
| field_RVA_caseF_KF | UNSIGNED5 | [...] | cp_Float | |
| field_RVA_caseJ_KJ | UNSIGNED5 | [...] | cp_Long | |
| field_RVA_casec_RS | UNSIGNED5 | [...] | cp_Signature | |
| field_RVA_caseet_RS | UNSIGNED5 | [...] | cp_Signature | |
| field_RVA_caseec_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| field_RVA_cases_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| field_RVA_casearray_N | UNSIGNED5 | [...] | ||
| field_RVA_nesttype_RS | UNSIGNED5 | [...] | cp_Signature | |
| field_RVA_nestpair_N | UNSIGNED5 | [...] | ||
| field_RVA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| field_RIA_anno_N | UNSIGNED5 | [...] | ||
| {field_RIA_...} | ||||
| field_RIA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| {field_attr_element_bands...} | (various) | [...] | (various) | |
| method_descr | MDELTA5 | [SUM(*class_method_count)] | cp_Descr | |
| method_flags_hi | UNSIGNED5 | [SUM(*class_method_count)*#have_method_flags_hi] | ||
| method_flags_lo | UNSIGNED5 | [SUM(*class_method_count)] | ||
| method_attr_count | UNSIGNED5 | [COUNT(1<<16,...)] | ||
| method_attr_indexes | UNSIGNED5 | [SUM(*method_attr_count)] | ||
| method_attr_calls | UNSIGNED5 | [...] | ||
| method_Exceptions_N | UNSIGNED5 | [COUNT(Exceptions,...)] | ||
| method_Exceptions_RC | UNSIGNED5 | [SUM(*method_Exceptions_N)] | cp_Class | |
| method_Signature_RS | UNSIGNED5 | [COUNT(Signature,...)] | cp_Signature | |
| method_RVA_anno_N | UNSIGNED5 | [...] | ||
| method_RVA_type_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_RVA_pair_N | UNSIGNED5 | [...] | ||
| method_RVA_name_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RVA_T | BYTE1 | [...] | ||
| method_RVA_caseI_KI | UNSIGNED5 | [...] | cp_Int | |
| method_RVA_caseD_KD | UNSIGNED5 | [...] | cp_Double | |
| method_RVA_caseF_KF | UNSIGNED5 | [...] | cp_Float | |
| method_RVA_caseJ_KJ | UNSIGNED5 | [...] | cp_Long | |
| method_RVA_casec_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_RVA_caseet_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_RVA_caseec_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RVA_cases_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RVA_casearray_N | UNSIGNED5 | [...] | ||
| method_RVA_nesttype_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_RVA_nestpair_N | UNSIGNED5 | [...] | ||
| method_RVA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RIA_anno_N | UNSIGNED5 | [...] | ||
| {method_RIA_...} | ||||
| method_RIA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RVPA_param_NB | BYTE1 | [...] | ||
| method_RVPA_anno_N | UNSIGNED5 | [...] | ||
| {method_RVPA_...} | ||||
| method_RVPA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_RIPA_param_NB | BYTE1 | [...] | ||
| method_RIPA_anno_N | UNSIGNED5 | [...] | ||
| {method_RIPA_...} | ||||
| method_RIPA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_AD_T | BYTE1 | [...] | ||
| method_AD_caseI_KI | UNSIGNED5 | [...] | cp_Int | |
| method_AD_caseD_KD | UNSIGNED5 | [...] | cp_Double | |
| method_AD_caseF_KF | UNSIGNED5 | [...] | cp_Float | |
| method_AD_caseJ_KJ | UNSIGNED5 | [...] | cp_Long | |
| method_AD_casec_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_AD_caseet_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_AD_caseec_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_AD_cases_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_AD_casearray_N | UNSIGNED5 | [...] | ||
| method_AD_nesttype_RS | UNSIGNED5 | [...] | cp_Signature | |
| method_AD_nestpair_N | UNSIGNED5 | [...] | ||
| method_AD_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| method_MethodParameters_NB | BYTE1 | [...] | ||
| method_MethodParameters_name_RUN | UNSIGNED5 | [...] | null|cp_Utf8 | |
| method_MethodParameters_flag_FH | UNSIGNED5 | [...] | ||
| {method_attr_element_bands...} | (various) | [...] | (various) | |
| class_flags_hi | UNSIGNED5 | [#class_count*#have_class_flags_hi] | ||
| class_flags_lo | UNSIGNED5 | [#class_count] | ||
| class_attr_count | UNSIGNED5 | [COUNT(1<<16,...)] | ||
| class_attr_indexes | UNSIGNED5 | [SUM(*class_attr_count)] | ||
| class_attr_calls | UNSIGNED5 | [...] | ||
| class_SourceFile_RUN | UNSIGNED5 | [COUNT(SourceFile,...)] | null|cp_Utf8 | |
| class_EnclosingMethod_RC | UNSIGNED5 | [COUNT(EnclosingMethod,...)] | cp_Class | |
| class_EnclosingMethod_RDN | UNSIGNED5 | [COUNT(EnclosingMethod,...)] | null|cp_Descr | |
| class_Signature_RS | UNSIGNED5 | [COUNT(Signature,...)] | cp_Signature | |
| class_RVA_anno_N | UNSIGNED5 | [...] | ||
| class_RVA_type_RS | UNSIGNED5 | [...] | cp_Signature | |
| class_RVA_pair_N | UNSIGNED5 | [...] | ||
| class_RVA_name_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| class_RVA_T | BYTE1 | [...] | ||
| class_RVA_caseI_KI | UNSIGNED5 | [...] | cp_Int | |
| class_RVA_caseD_KD | UNSIGNED5 | [...] | cp_Double | |
| class_RVA_caseF_KF | UNSIGNED5 | [...] | cp_Float | |
| class_RVA_caseJ_KJ | UNSIGNED5 | [...] | cp_Long | |
| class_RVA_casec_RS | UNSIGNED5 | [...] | cp_Signature | |
| class_RVA_caseet_RS | UNSIGNED5 | [...] | cp_Signature | |
| class_RVA_caseec_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| class_RVA_cases_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| class_RVA_casearray_N | UNSIGNED5 | [...] | ||
| class_RVA_nesttype_RS | UNSIGNED5 | [...] | cp_Signature | |
| class_RVA_nestpair_N | UNSIGNED5 | [...] | ||
| class_RVA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| class_RIA_anno_N | UNSIGNED5 | [...] | ||
| {class_RIA_...} | ||||
| class_RIA_nestname_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| class_InnerClasses_N | UNSIGNED5 | [COUNT(InnerClasses,...)] | ||
| class_InnerClasses_RC | UNSIGNED5 | [SUM(*class_InnerClasses_N)] | cp_Class | |
| class_InnerClasses_F | UNSIGNED5 | [SUM(*class_InnerClasses_N)] | ||
| class_InnerClasses_outer_RCN | UNSIGNED5 | [COUNT(!=0,*class_InnerClasses_F)] | null|cp_Class | |
| class_InnerClasses_name_RUN | UNSIGNED5 | [COUNT(!=0,*class_InnerClasses_F)] | null|cp_Utf8 | |
| class_file_version_minor_H | UNSIGNED5 | [COUNT(version,...)] | ||
| class_file_version_major_H | UNSIGNED5 | [COUNT(version,...)] | ||
| {class_attr_element_bands...} | (various) | [...] | (various) | |
| code_headers | BYTE1 | [COUNT(Code,...)] | ||
| code_max_stack | UNSIGNED5 | [COUNT(0,*code_headers)] | ||
| code_max_na_locals | UNSIGNED5 | [COUNT(0,*code_headers)] | ||
| code_handler_count | UNSIGNED5 | [COUNT(0,*code_headers)] | ||
| code_handler_start_P | BCI5 | [SUM(*code_header_count)] | ||
| code_handler_end_PO | BRANCH5 | [SUM(*code_header_count)] | ||
| code_handler_catch_PO | BRANCH5 | [SUM(*code_header_count)] | ||
| code_handler_class_RCN | UNSIGNED5 | [SUM(*code_header_count)] | null|cp_Class | |
| code_flags_hi | UNSIGNED5 | [...*#have_code_flags_hi] | ||
| code_flags_lo | UNSIGNED5 | [...] | ||
| code_attr_count | UNSIGNED5 | [COUNT(1<<16,...)] | ||
| code_attr_indexes | UNSIGNED5 | [SUM(*code_attr_count)] | ||
| code_attr_calls | UNSIGNED5 | [...] | ||
| code_StackMapTable_N | UNSIGNED5 | [COUNT(StackMapTable,...)] | ||
| code_StackMapTable_frame_T | BYTE1 | [SUM(*code_StackMapTable_N)] | ||
| code_StackMapTable_local_N | UNSIGNED5 | [COUNT(255,*code_StackMapTable_frame_T)] | ||
| code_StackMapTable_stack_N | UNSIGNED5 | [COUNT(255,*code_StackMapTable_frame_T)] | ||
| code_StackMapTable_offset | UNSIGNED5 | [...] | ||
| code_StackMapTable_T | BYTE1 | [...] | ||
| code_StackMapTable_RC | UNSIGNED5 | [COUNT(7,*code_StackMapTable_T)] | ||
| code_StackMapTable_P | BCI5 | [COUNT(8,*code_StackMapTable_T)] | ||
| code_LineNumberTable_N | UNSIGNED5 | [...] | ||
| code_LineNumberTable_bci_P | BCI5 | [...] | ||
| code_LineNumberTable_line | UNSIGNED5 | [...] | ||
| code_LocalVariableTable_N | UNSIGNED5 | [...] | ||
| code_LocalVariableTable_bci_P | BCI5 | [...] | ||
| code_LocalVariableTable_span_O | BRANCH5 | [...] | ||
| code_LocalVariableTable_name_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| code_LocalVariableTable_type_RS | UNSIGNED5 | [...] | cp_Signature | |
| code_LocalVariableTable_slot | UNSIGNED5 | [...] | ||
| code_LocalVariableTypeTable_N | UNSIGNED5 | [...] | ||
| code_LocalVariableTypeTable_bci_P | BCI5 | [...] | ||
| code_LocalVariableTypeTable_span_O | BRANCH5 | [...] | ||
| code_LocalVariableTypeTable_name_RU | UNSIGNED5 | [...] | cp_Utf8 | |
| code_LocalVariableTypeTable_type_RS | UNSIGNED5 | [...] | cp_Signature | |
| code_LocalVariableTypeTable_slot | UNSIGNED5 | [...] | ||
| {code_attr_element_bands...} | (various) | [...] | (various) | |
| bc_codes | BYTE1 | [...] | ||
| bc_case_count | UNSIGNED5 | [COUNT(switch,*bc_codes)] | ||
| bc_case_value | DELTA5 | [...] | ||
| bc_byte | BYTE1 | [...] | ||
| bc_short | DELTA5 | [...] | ||
| bc_local | UNSIGNED5 | [...] | ||
| bc_label | BRANCH5 | [...] | ||
| bc_intref | DELTA5 | [...] | cp_Int | |
| bc_floatref | DELTA5 | [...] | cp_Float | |
| bc_longref | DELTA5 | [...] | cp_Long | |
| bc_doubleref | DELTA5 | [...] | cp_Double | |
| bc_stringref | DELTA5 | [...] | cp_String | |
| bc_loadablevalueref | DELTA5 | [COUNT({qldc,qldc_w},*bc_codes)] | cp_All | |
| bc_classref | UNSIGNED5 | [...] | cp_Class | |
| bc_fieldref | DELTA5 | [...] | cp_Field | |
| bc_methodref | UNSIGNED5 | [...] | cp_Method | |
| bc_imethodref | DELTA5 | [...] | cp_Imethod | |
| bc_thisfield | UNSIGNED5 | [...] | cp_Field subsequence | |
| bc_superfield | UNSIGNED5 | [...] | cp_Field subsequence | |
| bc_thismethod | UNSIGNED5 | [...] | cp_Method subsequence | |
| bc_supermethod | UNSIGNED5 | [...] | cp_Method subsequence | |
| bc_initref | UNSIGNED5 | [...] | cp_Method subsequence | |
| bc_escref | UNSIGNED5 | [COUNT(ref_escape,*bc_codes)] | cp_All | |
| bc_escrefsize | UNSIGNED5 | [...] | ||
| bc_escsize | UNSIGNED5 | [...] | ||
| bc_escbyte | BYTE1 | [...] | ||
| file_name | UNSIGNED5 | [#file_count] | cp_Utf8 | |
| file_size_hi | UNSIGNED5 | [#file_count*(#have_file_size_hi)] | ||
| file_size_lo | UNSIGNED5 | [#file_count] | ||
| file_modtime | DELTA5 | [#file_count*(#have_file_modtime)] | ||
| file_options | UNSIGNED5 | [#file_count*(#have_file_options)] | ||
| file_bits | BYTE1 | [SUM(*file_size)] |
assert(cp_Utf8[0].equals("")); int cursor = 0; int big_cursor = 0; for (int i = 1; i < cp_Utf8_count; i++) { String thisString = cp_Utf8[i]; int prefix = (i == 1)? 0: cp_Utf8_prefix[i-2]; int suffix = thisString.length() - prefix; String prevString = cp_Utf8[i-1]; String prevPrefix = prevString.substring(0, prefix); String thisPrefix = thisString.substring(0, prefix); assert(prevPrefix.equals(thisPrefix)); int small_suffix = cp_Utf8_suffix[i-1]; char[] suffix_chars; int offset; if (small_suffix != 0) { assert(suffix == small_suffix); suffix_chars = cp_Utf8_chars; offset = cursor; cursor += suffix; } else { assert(suffix == cp_Utf8_big_suffix[big_cursor]); suffix_chars = cp_Utf8_big_chars[big_cursor]; offset = 0; assert(suffix == suffix_chars.length); big_cursor += 1; } String thisSuffix = thisString.substring(prefix); String theseChars = new String(suffix_chars, offset, suffix); assert(thisSuffix.equals(theseChars)); } assert(cp_Utf8_prefix.length == Math.max(0, cp_Utf8_count-2)); assert(cp_Utf8_suffix.length == Math.max(0, cp_Utf8_count-1)); assert(cp_Utf8_chars.length == cursor); assert(cp_Utf8_big_suffix.length == big_cursor); assert(cp_Utf8_big_chars.length == big_cursor);
int cursor = 0; for (int i = 0; i < cp_Signature_count; i++) { String sign = cp_Signature[i]; String form = cp_Signature_form[i]; int form_ptr = 0; int sign_ptr = 0; for (; form_ptr < form.length(); form_ptr++) { assert(form.charAt(form_ptr) == sign.charAt(sign_ptr)); sign_ptr += 1; if (form.charAt(form_ptr) == 'L') { String cls = cp_Class[cursor]; assert(sign.startsWith(cls, sign_ptr)); cursor += 1; sign_ptr += cls.length(); } } assert(sign_ptr == sign.length()); } assert(cp_Signature_form.length == cp_Signature_count); assert(cp_Signature_classes.length == cursor);
// ins_pos is a display of all instruction boundaries int[] ins_pos; ... Arrays.sort(ins_pos); assert(ins_pos[0] == 0); assert(ins_pos[ins_pos.length-1] == bytecodes.length); int regulars = ins_pos.length; // # instruction boundaries ... int renumber_bci(int bci) { int i = Arrays.binarySearch(ins_pos, bci); return (i >= 0) ? i : (i == -1) ? bci : ins_pos.length + bci - (-i-1); } ... for (int bci = -100; bci <= bytecodes.length+100; bci++) { int bci_numbering_for_band = renumber_bci(bci); int i = Arrays.binarySearch(ins_pos, bci); if (i >= 0) { assert(ins_pos[i] == bci); assert(bci_numbering_for_band < regulars); assert(bci_numbering_for_band == i); } else if (0 < bci && bci < bytecodes.length) { int nexti = (-i-1); // index of next instruction assert(ins_pos[nexti-1] < bci && bci < ins_pos[nexti]); int prevRegulars = nexti; int prevAll = bci; int prevIrregulars = prevAll - prevRegulars; assert(bci_numbering_for_band >= regulars); assert(bci_numbering_for_band == regulars + prevIrregulars); } else { // other (random) numbers are unchanged by renumbering assert(bci_numbering_for_band >= bytecodes.length || bci_numbering_for_band < 0); assert(bci_numbering_for_band == bci); } }
String bcn, predictableOuter, predictableICName; ... String name = bcn.substring(bcn.lastIndexOf('/')+1); int dollar2 = name.lastIndexOf('$'); assert(predictableICName == null || (predictableICName.charAt(0) > '9' && predictableICName.indexOf('$') < 0)); if (predictableICName == null) { // bcnCase1 or bcnCase4 assert(predictableOuter == null); assert(dollar2 == -1 || dollar2+1 == name.length() || isDigit(name.charAt(dollar2+1))); } else if (predictableOuter == null) { // bcnCase2 assert(name.endsWith("$"+predictableICName)); int dollar1 = name.substring(0, dollar2).lastIndexOf('$'); assert(dollar1 >= 0 && dollar1+1 < dollar2); assert(isDigitString(name.substring(dollar1+1, dollar2))); } else { // bcnCase3 assert(bcn.equals(predictableOuter+"$"+predictableICName)); }
Why not use an existing generic compression mechanism, such as .jar, .zip, or .tar.gz files? First, it is better to know the structure of a thing compressed. Second, a zip or jar archive is compressed element-wise not globally. This means that any symbol shared by several classes must be mentioned independently once in each class file. Third, the structure of an individual class file is really an interleaving of many different kind of data, each with their own statistics, which limits the effectiveness of a single-stream compressor such as gzip. The specific benefit of reordering the data into bands is about a factor of two, independently of the quality of the off-the-shelf compressor used as a post-pass. There are also significant marginal benefits from the various type-specific recoding techniques. The net result is to improve a compression factor from 2-4X to 7-9X.
Why is this specification so complex? The techniques described here are the result of much experimentation over several years. Each feature of this specification is thought to contribute measurably to the overall compression ratio achieved by this technology. The authors would be happy to be shown, by benchmarks, that some given feature can be omitted without significant loss of compression performance.
(A compression performance multiplier of 1.002 or more for some particular technique is significant, because such multipliers accumulate readily into performance that end-users notice. A multiplier of less than 1.0005 is insignificant.)
The Pack200 transmission format is closely tied to the current class file format. Won't it go out of date as soon as the class file format evolves further? Further developments are likely to take the form of new attributes or perhaps new bytecodes. The layout language defined by Pack200 supports a very wide range of attribute formats, including arbitrary mixes of bytes and constant pool references. Likewise, the bytecode representation includes escape operators which can represent arbitrary mixes of data and constant pool references. Although such constructs will not compress as optimally as the features for which this specification is directly designed, it appears that reasonable future extensions will continue to be transmittable, without disturbing the compression of current features, and without requiring decompressors to be updated.
Since Pack200 is a lossy compression algorithm, won't it break signed JAR files? Signed JAR files contain secure hashes over the bytewise contents of individual class files. Any change to the bits of a class file will change its hash code, making the innocuous changes of Pack200 indistinguishable from attacks on the application code.
Pack200, like many other compression algorithms, allows the compressor many degrees of freedom in choosing the contents of the compressed archive, but no degrees of freedom in choosing the contents of the decompressed JAR file. Given a compressed archive, all compliant Pack200 decompressors must produce the same class file bytes, for each transmitted class file. This stability of output persists for class files even if a resource file (such as the manifest) changes its contents. Thus, for any given class file, compression may be lossy, but the decompression of each class file must be exact, in a useful way defined by the Pack200 specification.
This means that a compressor with the right stability properties can be used to produce a signed, packed JAR using these steps:
(Note: If this specification allows two compliant decompressors to produce different JAR archive elements for the same compressed archive input, it is a bug in the specification. The specification is thought to be free of such bugs, but if you find one please report it.)
What is the relationship between file names in Pack200 archives and file names in JAR (or ZIP) archives or disk files? Pack200 specifies that file names are transmitted as Utf8 strings. Since these strings are intended to function as names of JAR elements in functioning Java applications, the strings must also conform to Java usage, which also represents pathnames as Utf8 strings in JAR files and 16-bit Unicode in memory. Also, in JAR files, pathname components are separated by the forward slash character ('/'), and not by any system-specific character. This allows class loaders to easily convert the internal representation of the class names (e.g., "java/lang/Object") to pathnames (e.g., "java/lang/Object.class").
The Pack200 specification does not dictate the interpretation of file name strings with respect to any other tool or operating system. However, the natural mapping would be as coherent as possible with Java's usages.
What is the relationship between file dates in JAR (or ZIP) archives or disk files? Pack200 specifies that file dates are transmitted as 32-bit counts of seconds relative to Java's time base (i.e., System.currentTimeMillis divided by one thousand). This provides absolute times relative to UTC, at a one-second granularity. If an operating system provides more accurate file times, they must be adjusted to a nearby whole second before transmission in a Pack200 archive.
JAR and ZIP store dates in local format (i.e., "YYYY/MM/DD HH:MM:SS") with no timezone specification. This means that conversion to and from Java's UTC-based times requires a guess at the timezone under which the compressor was operating. (This problem is not unique to Pack200. It is a problem with all uses of ZIP and JAR archives.) For many purposes, the standard guess is that the decompressor and compressor were operating in the same timezone and during the same yearly daylight savings time regime. However, in order to provide more stability in the times transmitted in Pack200 archives, it is expected that most compressors and decompressors will agree to use UTC as the timezone when interpreting ZIP-style local times.
Doesn't the JEFF file format also oprovide a class-specific compression algorithm? Yes, the JEFF Working Group has defined a standard file format (ISO/IEC 20970) which allows class files to be compressed about 50% and also loaded directly into memory for interpretive execution. As compression performance, it is comparable with the DEFLATE algorithm used within JAR archives. Pack200 provides much greater compression. However, Pack200 archives are not designed for direct execution by any virtual machine. The greater compression level of Pack200 is won at a cost of complexity in the unpacker, a complexity incompatible with any requirement of direct loading or execution.
Why doesn't Pack200 use Huffman encoding? (Same question for LZW, or BWT, or move-to-front, or any other standard compression technique.) As a matter of simplicity and division of labor, Pack200 intentionally focuses on finding and removing large-scale redundancies specific to class files. Pack200 produces a byte-oriented output, hopefully with clear patterns and a simple alphabet statistics. It relies on a post-pass compressor to encode these bytes in some more efficient string-sharing, bit-sliced representation.
The following considerations support this design:
How does this specification cope with archive format changes? The major and minor version numbers of a Pack200 archive advertise which version of this standard has been generated by a packer. Because of the flexibility of attribute layouts, packers can sometimes represent new classfile formats in old archive formats, but newer archive formats may be required for reasons of functionality or performance.
Unpacker implementations are strongly encouraged to support each standard version of the archive format, since there is not always a strong alignment between packer and unpacker versions at either end of a deployment channel. Packer implementations are encouraged to preserve the ability to emit older archive formats, to maintain maximum compatibility with unpackers.
The reference implementation chooses to maintain backward compatibility by producing a 1.5 pack format if the input JAR archive contains no 1.6 (or newer) classfiles. In general, it will produce the oldest possible archive version compatible with all the input classfiles. An empty archive will default to the oldest archive version, which is 1.5.


My Logo Comes Here
+
ITEM ONE
ITEM TWO
ITEM THREE
Emmentaler or Emmental is a yellow, medium-hard cheese that originated in the area around Emmental, Switzerland. It is one of the cheeses of Switzerland, and is sometimes known as Swiss cheese.
asdasdsdasdsa
dd
asdasdasd


Welcome to the wonderful world of my portfolio. Herein lies an adventure through my mind in the form of code. I hope you enjoy the journey!


About Me
Education
Relevant Courses
Skills
Objective
Go Back
Hello!
My name is Batu Sipka.
I am a senior at
Worcester Polytechnic Institute
graduating in
May 2017
.
I am double majoring in
Robotics Engineering
and
Electrical and Computer Engineering
.
I have taken the following
courses
;
Robotics:
Unified Robotics Series: Actuation / Sensing / Manipulation / Navigation
Electrical and Computer Engineering:
Embedded Systems / Sensors, Circuits and Systems / Real Time Operating Systems / FPGA Design / Continuous and Discrete Time Signal Analysis
Computer Science:
Object Oriented Program Design / Systems Programming / Software Engineering
Miscellaneous:
Controls Engineering
Software:
C++, C, Java, C#, Python, R, JavaScript, HTML, CSS
Languages:
English, Turkish, French, Chinese
Other / Tools:
IoT, Windows, Linux, VMware, Git, Atom, Bash, CAD, Prototyping, MATLAB, Unity
I am interested in obtaining a
full time position
in robotics or electrical industry doing
hardware and software development
.


Subdivision Ordinance
"If the proposed subdivision is located on a lake, pond, river, saltwater body or stream, a portion of the waterfront
area shall be included in reserved land. If the dimension along the waterfront shall be a minimum of 200 feet, ..."
Selectmen's Meeting 01/27/2020
Port Regulations Ordinance Amendment
"The Port Committee will have the power to establish and revise guidelines and rules for the safe use and operation of
floats, including, but not limited to, the use of slides, swings, diving boards, trampolines, and other ..."
Selectmen's Meeting 01/13/2020
Blasting Ordinance Amendment
"No blasting shall be done without first obtaining a permit to blast from the Code Enforcement Officer pursuant to
this section. The application for a permit to blast shall include ..."
Selectmen's Meeting 01/13/2020
Mobile Food Vendors Ordinance
"No retail/wholesale sales or services of food, beverages or other items intended for immediate human consumption
shall be offered or solicited except on privately owned property, in which the retail sales or services are located,
except for restaurants, which ..."
Selectmen's Meeting 12/23/2019
NOTE
The above information comes from text in a transcript that was tagged as relating to an ordinance, bill, proposal,
proclamation, etc. Clicking on a meeting link would take the user to the full text of that discussion.


Copyright © 2007 Matias Capeletto
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Table of Contents
GroupedLinks is a simple javascript API for building links select boxes.
Features
- Released under Boost Software License.
- Cross-browser.
- Items are populated from a simple XML definition file.
- css based look & feel.
- Support for relative URLs.
- Integration with Boostbook.
- Only standard javascript used.
A GroupedLinks select box is populated from a GroupedLinks XML definition file. This is an important feature, because it means that the items are not harcoded in the HTML saving us space using global definitions and allowing us to change the definition with out touching the HTML files.
GroupedLinks XML definition start with a tag named
groupedLinks
. There are only
three elements:
Table 1.1. Elements
|
Name |
Purpose |
|---|---|
|
|
Add a title to the GroupedLinks select box. This is useful when you do not want to select any of the internals items. The select box will show the title instead. |
|
|
Starts a group list. |
|
|
Links items. They must reside inside a group list. |
All the elements have two attributes:
- tag: Name of the element, it will be showed in the HTML.
- url: URL of the link. It can be relative or absolute. (It is optional)
A GroupedLinks XML definition will look like:
<?xml version="1.0" encoding="UTF-8" ?> <groupedLinks version="1.0"> <title tag="Title" url="group_1.html"/> <group tag="Group 1" url="group_1.html"> <item tag="Item A" url="group_1/item_A.html"/> <item tag="Item B" url="group_1/item_A.html"/> <item tag="Item C" url="http://www.item_C.com"/> </group> <group tag="Group 2" url="group_2.html"> <item tag="Item A" url="group_2/item_A.html"/> <item tag="Item B" url="group_2/item_A.html"/> </group> <group tag="Group 3" url="group_3.html"/> </groupedLinks>
To include a GroupedLinks select box in the body of
your HTML you have to create a form with an unique id and call the javascript
function grouped_links_select_box
inside of it.
Table 1.2. grouped_links_select_box function
|
|
Parameter Name |
Purpose |
|---|---|---|
|
1 |
GroupedLinks XML URL |
GroupedLinks XML definition URL. |
|
2 |
Form id |
id of the form where you want to place the GroupedLinks select box. |
|
3 |
Base URL |
A base URL that will be concatenated to all the relatives URLs. |
|
5 |
Selected item |
The item that is selected by default. This parameter is optional, if you call the function with only three parameters the tag of the title element is used if there is one in the GroupedLinks XML definition. |
It is simple enough to be understood from an example:
<head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Boost.GroupedLinks Example</title> <link rel="stylesheet" href="../../css/grouped_links.css" type="text/css"> </head> <body> <!-- /* Include the grouped links java script api */ --> <script type="text/javascript" src="../../js/grouped_links.js"></script> <!-- /* Add a form with an "id" attribute */ --> <form id="boost_libs_list"> <!--/* Call the GroupedLinks "select box" */--> <script type="text/javascript"> grouped_links_select_box('boost_libs.xml', 'boost_libs_list', '../../', 'Boost Libraries'); </script> </form>
Remember to change the src
of the javascript include line to point to the URL of grouped_links.js
in your system. Try to work with relatives paths so the HTML can be easily
moved.
Add the following lines to your jamfile.v2
<xsl:param>grouped.links.chapters.show="'true'" <xsl:param>grouped.links.sections.show="'true'" <xsl:param>grouped.links.sections.xml="'sections.XML'" # your XML sections
GroupedLinks select boxes for boost libraries and internal sections can be requested to boostbook using the following options:
Table 1.3. Boostbook GroupedLinks Parameters
|
Name |
Purpose |
|---|---|
|
|
Include select box |
|
|
Path to the XML definition |
|
|
Base URL to use with relative paths |
You can configure all the parameters used by boostbook:
<xsl:param>grouped.links.js="'grouped_links.js'" <xsl:param>grouped.links.chapters.show="'true'" <xsl:param>grouped.links.chapters.xml="'boost_libs_grouped_links.XML'" <xsl:param>grouped.links.chapters.url="''" <xsl:param>grouped.links.sections.show="'true'" <xsl:param>grouped.links.sections.xml="'sections_grouped_links.XML'" <xsl:param>grouped.links.sections.url="''"
In the folder example
you can
find two examples using GropedLinks API.
- simple
- How to put a GropedLinks select box in your HTML body.
- boostbook
- How to integrate GroupedLinks with boostbook and quickbook docs.
Thanks Martin Capeletto (my brother) for teaching me the basics of javascript.
Thanks to the ones that participates in constructing the new boost docs look & feel. Special thanks to John Maddock for his support during this period.


Home
Profile
Messages
Home
Profile
Messages
Home
Profile
Messages
Home
Profile
Messages
Home
Profile
Messages
first
second
third
fourth


Angular Tabs underline
Home
Profile
Contact
This is some placeholder content the Home tab's associated content. Clicking another tab
will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.
This is some placeholder content the Profile tab's associated content. Clicking another
tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.
0">
This is some placeholder content the Contact tab's associated content. Clicking another
tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.
Angular Tabs tabs
{{nav.name}}
This is some placeholder content the {{pane.name}} tab's associated content. Clicking
another tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to
control the content visibility and styling. You can use it with tabs, pills, and any other .nav-powered
navigation.
Angular Tabs pills
Home
Profile
Contact
This is some placeholder content the Home tab's associated content. Clicking another tab
will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.
This is some placeholder content the Profile tab's associated content. Clicking another
tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.
This is some placeholder content the Contact tab's associated content. Clicking another
tab will toggle the visibility of this one for the next. The tab JavaScript swaps classes to control the
content visibility and styling. You can use it with tabs, pills, and any other .nav-powered navigation.


{{item.AccountNumber}}
The account has party ID {{item.OracleID}} Some more data about this account here. Some more data about this account here. Some more data about this account here. Some more data about this account here. Some more data about this account here. Some more data about this account here. Some more data about this account here. Some more data about this account here.