1magic = (
2    b"\x00\x00\x00\x00\x00\x00\x00\x00"
3    + b"\x00\x00\x00\x00\xc2\xea\x81\x60"
4    + b"\xb3\x14\x11\xcf\xbd\x92\x08\x00"
5    + b"\x09\xc7\x31\x8c\x18\x1f\x10\x11"
6)
7
8align_1_checker_value = b"3"
9align_1_offset = 32
10align_1_length = 1
11align_1_value = 4
12u64_byte_checker_value = b"3"
13align_2_offset = 35
14align_2_length = 1
15align_2_value = 4
16endianness_offset = 37
17endianness_length = 1
18platform_offset = 39
19platform_length = 1
20encoding_offset = 70
21encoding_length = 1
22dataset_offset = 92
23dataset_length = 64
24file_type_offset = 156
25file_type_length = 8
26date_created_offset = 164
27date_created_length = 8
28date_modified_offset = 172
29date_modified_length = 8
30header_size_offset = 196
31header_size_length = 4
32page_size_offset = 200
33page_size_length = 4
34page_count_offset = 204
35page_count_length = 4
36sas_release_offset = 216
37sas_release_length = 8
38sas_server_type_offset = 224
39sas_server_type_length = 16
40os_version_number_offset = 240
41os_version_number_length = 16
42os_maker_offset = 256
43os_maker_length = 16
44os_name_offset = 272
45os_name_length = 16
46page_bit_offset_x86 = 16
47page_bit_offset_x64 = 32
48subheader_pointer_length_x86 = 12
49subheader_pointer_length_x64 = 24
50page_type_offset = 0
51page_type_length = 2
52block_count_offset = 2
53block_count_length = 2
54subheader_count_offset = 4
55subheader_count_length = 2
56page_meta_type = 0
57page_data_type = 256
58page_amd_type = 1024
59page_metc_type = 16384
60page_comp_type = -28672
61page_mix_types = [512, 640]
62subheader_pointers_offset = 8
63truncated_subheader_id = 1
64compressed_subheader_id = 4
65compressed_subheader_type = 1
66text_block_size_length = 2
67row_length_offset_multiplier = 5
68row_count_offset_multiplier = 6
69col_count_p1_multiplier = 9
70col_count_p2_multiplier = 10
71row_count_on_mix_page_offset_multiplier = 15
72column_name_pointer_length = 8
73column_name_text_subheader_offset = 0
74column_name_text_subheader_length = 2
75column_name_offset_offset = 2
76column_name_offset_length = 2
77column_name_length_offset = 4
78column_name_length_length = 2
79column_data_offset_offset = 8
80column_data_length_offset = 8
81column_data_length_length = 4
82column_type_offset = 14
83column_type_length = 1
84column_format_text_subheader_index_offset = 22
85column_format_text_subheader_index_length = 2
86column_format_offset_offset = 24
87column_format_offset_length = 2
88column_format_length_offset = 26
89column_format_length_length = 2
90column_label_text_subheader_index_offset = 28
91column_label_text_subheader_index_length = 2
92column_label_offset_offset = 30
93column_label_offset_length = 2
94column_label_length_offset = 32
95column_label_length_length = 2
96rle_compression = b"SASYZCRL"
97rdc_compression = b"SASYZCR2"
98
99compression_literals = [rle_compression, rdc_compression]
100
101# Incomplete list of encodings, using SAS nomenclature:
102# http://support.sas.com/documentation/cdl/en/nlsref/61893/HTML/default/viewer.htm#a002607278.htm
103encoding_names = {
104    29: "latin1",
105    20: "utf-8",
106    33: "cyrillic",
107    60: "wlatin2",
108    61: "wcyrillic",
109    62: "wlatin1",
110    90: "ebcdic870",
111}
112
113
114class SASIndex:
115    row_size_index = 0
116    column_size_index = 1
117    subheader_counts_index = 2
118    column_text_index = 3
119    column_name_index = 4
120    column_attributes_index = 5
121    format_and_label_index = 6
122    column_list_index = 7
123    data_subheader_index = 8
124
125
126subheader_signature_to_index = {
127    b"\xF7\xF7\xF7\xF7": SASIndex.row_size_index,
128    b"\x00\x00\x00\x00\xF7\xF7\xF7\xF7": SASIndex.row_size_index,
129    b"\xF7\xF7\xF7\xF7\x00\x00\x00\x00": SASIndex.row_size_index,
130    b"\xF7\xF7\xF7\xF7\xFF\xFF\xFB\xFE": SASIndex.row_size_index,
131    b"\xF6\xF6\xF6\xF6": SASIndex.column_size_index,
132    b"\x00\x00\x00\x00\xF6\xF6\xF6\xF6": SASIndex.column_size_index,
133    b"\xF6\xF6\xF6\xF6\x00\x00\x00\x00": SASIndex.column_size_index,
134    b"\xF6\xF6\xF6\xF6\xFF\xFF\xFB\xFE": SASIndex.column_size_index,
135    b"\x00\xFC\xFF\xFF": SASIndex.subheader_counts_index,
136    b"\xFF\xFF\xFC\x00": SASIndex.subheader_counts_index,
137    b"\x00\xFC\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.subheader_counts_index,
138    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFC\x00": SASIndex.subheader_counts_index,
139    b"\xFD\xFF\xFF\xFF": SASIndex.column_text_index,
140    b"\xFF\xFF\xFF\xFD": SASIndex.column_text_index,
141    b"\xFD\xFF\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.column_text_index,
142    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFD": SASIndex.column_text_index,
143    b"\xFF\xFF\xFF\xFF": SASIndex.column_name_index,
144    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.column_name_index,
145    b"\xFC\xFF\xFF\xFF": SASIndex.column_attributes_index,
146    b"\xFF\xFF\xFF\xFC": SASIndex.column_attributes_index,
147    b"\xFC\xFF\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.column_attributes_index,
148    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC": SASIndex.column_attributes_index,
149    b"\xFE\xFB\xFF\xFF": SASIndex.format_and_label_index,
150    b"\xFF\xFF\xFB\xFE": SASIndex.format_and_label_index,
151    b"\xFE\xFB\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.format_and_label_index,
152    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFB\xFE": SASIndex.format_and_label_index,
153    b"\xFE\xFF\xFF\xFF": SASIndex.column_list_index,
154    b"\xFF\xFF\xFF\xFE": SASIndex.column_list_index,
155    b"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF": SASIndex.column_list_index,
156    b"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE": SASIndex.column_list_index,
157}
158
159
160# List of frequently used SAS date and datetime formats
161# http://support.sas.com/documentation/cdl/en/etsug/60372/HTML/default/viewer.htm#etsug_intervals_sect009.htm
162# https://github.com/epam/parso/blob/master/src/main/java/com/epam/parso/impl/SasFileConstants.java
163sas_date_formats = (
164    "DATE",
165    "DAY",
166    "DDMMYY",
167    "DOWNAME",
168    "JULDAY",
169    "JULIAN",
170    "MMDDYY",
171    "MMYY",
172    "MMYYC",
173    "MMYYD",
174    "MMYYP",
175    "MMYYS",
176    "MMYYN",
177    "MONNAME",
178    "MONTH",
179    "MONYY",
180    "QTR",
181    "QTRR",
182    "NENGO",
183    "WEEKDATE",
184    "WEEKDATX",
185    "WEEKDAY",
186    "WEEKV",
187    "WORDDATE",
188    "WORDDATX",
189    "YEAR",
190    "YYMM",
191    "YYMMC",
192    "YYMMD",
193    "YYMMP",
194    "YYMMS",
195    "YYMMN",
196    "YYMON",
197    "YYMMDD",
198    "YYQ",
199    "YYQC",
200    "YYQD",
201    "YYQP",
202    "YYQS",
203    "YYQN",
204    "YYQR",
205    "YYQRC",
206    "YYQRD",
207    "YYQRP",
208    "YYQRS",
209    "YYQRN",
210    "YYMMDDP",
211    "YYMMDDC",
212    "E8601DA",
213    "YYMMDDN",
214    "MMDDYYC",
215    "MMDDYYS",
216    "MMDDYYD",
217    "YYMMDDS",
218    "B8601DA",
219    "DDMMYYN",
220    "YYMMDDD",
221    "DDMMYYB",
222    "DDMMYYP",
223    "MMDDYYP",
224    "YYMMDDB",
225    "MMDDYYN",
226    "DDMMYYC",
227    "DDMMYYD",
228    "DDMMYYS",
229    "MINGUO",
230)
231
232sas_datetime_formats = (
233    "DATETIME",
234    "DTWKDATX",
235    "B8601DN",
236    "B8601DT",
237    "B8601DX",
238    "B8601DZ",
239    "B8601LX",
240    "E8601DN",
241    "E8601DT",
242    "E8601DX",
243    "E8601DZ",
244    "E8601LX",
245    "DATEAMPM",
246    "DTDATE",
247    "DTMONYY",
248    "DTMONYY",
249    "DTWKDATX",
250    "DTYEAR",
251    "TOD",
252    "MDYAMPM",
253)
254