Coverage Report

Created: 2026-06-30 08:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  TIGER/Line Translator
4
 * Purpose:  Implements TigerPolygon, providing access to .RTA files.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1999, Frank Warmerdam
9
 * Copyright (c) 2011, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "ogr_tiger.h"
15
#include "cpl_conv.h"
16
17
#include <cinttypes>
18
19
static const TigerFieldInfo rtA_2002_fields[] = {
20
    // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet
21
    {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0},
22
    {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1},
23
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1},
24
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1},
25
    {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1},
26
    {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1},
27
28
    {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1},
29
    {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1},
30
    {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1},
31
32
    {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1},
33
    {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1},
34
    {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1},
35
    {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1},
36
    {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1},
37
    {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1},
38
    {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1},
39
    {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1},
40
    {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1},
41
    {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1},
42
    {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1},
43
    {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1},
44
    {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1},
45
    {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1},
46
    {"MSACMSACU", 'L', 'N', OFTInteger, 101, 104, 4, 1, 1},
47
    {"PMSACU", 'L', 'N', OFTInteger, 105, 108, 4, 1, 1},
48
    {"NECMACU", 'L', 'N', OFTInteger, 109, 112, 4, 1, 1},
49
    {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1},
50
    {"RS_A2", 'L', 'A', OFTString, 115, 119, 5, 1, 1},
51
    {"RS_A3", 'R', 'A', OFTString, 120, 122, 3, 1, 1},
52
    {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1},
53
    {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1},
54
    {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1},
55
    {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1},
56
    {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1},
57
    {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1},
58
    {"RS_A10", 'L', 'A', OFTString, 152, 157, 6, 1, 1},
59
    {"RS_A11", 'L', 'A', OFTString, 158, 163, 6, 1, 1},
60
    {"RS_A12", 'L', 'A', OFTString, 164, 169, 6, 1, 1},
61
    {"RS_A13", 'L', 'A', OFTString, 170, 175, 6, 1, 1},
62
    {"RS_A14", 'L', 'A', OFTString, 176, 181, 6, 1, 1},
63
    {"RS_A15", 'L', 'A', OFTString, 182, 186, 5, 1, 1},
64
    {"RS_A16", 'L', 'A', OFTString, 187, 187, 1, 1, 1},
65
    {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1},
66
    {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1},
67
    {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1},
68
};
69
static const TigerRecordInfo rtA_2002_info = {
70
    rtA_2002_fields, sizeof(rtA_2002_fields) / sizeof(TigerFieldInfo), 210};
71
72
static const TigerFieldInfo rtA_2003_fields[] = {
73
    // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet
74
    {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0},
75
    {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1},
76
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1},
77
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1},
78
    {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1},
79
    {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1},
80
81
    {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1},
82
    {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1},
83
    {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1},
84
85
    {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1},
86
    {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1},
87
    {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1},
88
    {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1},
89
    {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1},
90
    {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1},
91
    {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1},
92
    {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1},
93
    {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1},
94
    {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1},
95
    {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1},
96
    {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1},
97
    {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1},
98
    {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1},
99
    {"RS_A20", 'L', 'A', OFTString, 101, 104, 4, 1, 1},
100
    {"RS_A21", 'L', 'A', OFTString, 105, 108, 4, 1, 1},
101
    {"RS_A22", 'L', 'A', OFTString, 109, 112, 4, 1, 1},
102
    {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1},
103
    {"ZCTA5CU", 'L', 'A', OFTString, 115, 119, 5, 1, 1},
104
    {"ZCTA3CU", 'R', 'A', OFTString, 120, 122, 3, 1, 1},
105
    {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1},
106
    {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1},
107
    {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1},
108
    {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1},
109
    {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1},
110
    {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1},
111
    {"CBSACU", 'L', 'A', OFTInteger, 152, 156, 5, 1, 1},
112
    {"CSACU", 'L', 'A', OFTInteger, 157, 159, 3, 1, 1},
113
    {"NECTACU", 'L', 'A', OFTInteger, 160, 164, 5, 1, 1},
114
    {"CNECTACU", 'L', 'A', OFTInteger, 165, 167, 3, 1, 1},
115
    {"METDIVCU", 'L', 'A', OFTInteger, 168, 172, 5, 1, 1},
116
    {"NECTADIVCU", 'L', 'A', OFTInteger, 173, 177, 5, 1, 1},
117
    {"RS_A14", 'L', 'A', OFTString, 178, 181, 4, 1, 1},
118
    {"RS_A15", 'L', 'A', OFTString, 182, 186, 5, 1, 1},
119
    {"RS_A16", 'L', 'A', OFTString, 187, 187, 1, 1, 1},
120
    {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1},
121
    {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1},
122
    {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1},
123
};
124
static const TigerRecordInfo rtA_2003_info = {
125
    rtA_2003_fields, sizeof(rtA_2003_fields) / sizeof(TigerFieldInfo), 210};
126
127
static const TigerFieldInfo rtA_2004_fields[] = {
128
    // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet
129
    {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0},
130
    {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 1, 1},
131
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1},
132
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1},
133
    {"STATECU", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1},
134
    {"COUNTYCU", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1},
135
136
    {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 1, 1},
137
    {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 1, 1},
138
    {"BLOCKSUFCU", 'L', 'A', OFTString, 41, 41, 1, 1, 1},
139
140
    {"RS_A1", 'L', 'A', OFTString, 42, 42, 1, 1, 1},
141
    {"AIANHHFPCU", 'L', 'N', OFTInteger, 43, 47, 5, 1, 1},
142
    {"AIANHHCU", 'L', 'N', OFTInteger, 48, 51, 4, 1, 1},
143
    {"AIHHTLICU", 'L', 'A', OFTString, 52, 52, 1, 1, 1},
144
    {"ANRCCU", 'L', 'N', OFTInteger, 53, 57, 5, 1, 1},
145
    {"AITSCECU", 'L', 'N', OFTInteger, 58, 60, 3, 1, 1},
146
    {"AITSCU", 'L', 'N', OFTInteger, 61, 65, 5, 1, 1},
147
    {"CONCITCU", 'L', 'N', OFTInteger, 66, 70, 5, 1, 1},
148
    {"COUSUBCU", 'L', 'N', OFTInteger, 71, 75, 5, 1, 1},
149
    {"SUBMCDCU", 'L', 'N', OFTInteger, 76, 80, 5, 1, 1},
150
    {"PLACECU", 'L', 'N', OFTInteger, 81, 85, 5, 1, 1},
151
    {"SDELMCU", 'L', 'A', OFTString, 86, 90, 5, 1, 1},
152
    {"SDSECCU", 'L', 'A', OFTString, 91, 95, 5, 1, 1},
153
    {"SDUNICU", 'L', 'A', OFTString, 96, 100, 5, 1, 1},
154
    {"RS_A20", 'L', 'A', OFTString, 101, 104, 4, 1, 1},
155
    {"RS_A21", 'L', 'A', OFTString, 105, 108, 4, 1, 1},
156
    {"RS_A22", 'L', 'A', OFTString, 109, 112, 4, 1, 1},
157
    {"CDCU", 'R', 'N', OFTInteger, 113, 114, 2, 1, 1},
158
    {"ZCTA5CU", 'L', 'A', OFTString, 115, 119, 5, 1, 1},
159
    {"ZCTA3CU", 'R', 'A', OFTString, 120, 122, 3, 1, 1},
160
    {"RS_A4", 'R', 'A', OFTString, 123, 128, 6, 1, 1},
161
    {"RS_A5", 'R', 'A', OFTString, 129, 131, 3, 1, 1},
162
    {"RS_A6", 'R', 'A', OFTString, 132, 134, 3, 1, 1},
163
    {"RS_A7", 'R', 'A', OFTString, 135, 139, 5, 1, 1},
164
    {"RS_A8", 'R', 'A', OFTString, 140, 145, 6, 1, 1},
165
    {"RS_A9", 'L', 'A', OFTString, 146, 151, 6, 1, 1},
166
    {"CBSACU", 'L', 'A', OFTInteger, 152, 156, 5, 1, 1},
167
    {"CSACU", 'L', 'A', OFTInteger, 157, 159, 3, 1, 1},
168
    {"NECTACU", 'L', 'A', OFTInteger, 160, 164, 5, 1, 1},
169
    {"CNECTACU", 'L', 'A', OFTInteger, 165, 167, 3, 1, 1},
170
    {"METDIVCU", 'L', 'A', OFTInteger, 168, 172, 5, 1, 1},
171
    {"NECTADIVCU", 'L', 'A', OFTInteger, 173, 177, 5, 1, 1},
172
    {"RS_A14", 'L', 'A', OFTString, 178, 181, 4, 1, 1},
173
    {"UACU", 'L', 'N', OFTInteger, 182, 186, 5, 1, 1},
174
    {"URCU", 'L', 'A', OFTString, 187, 187, 1, 1, 1},
175
    {"RS_A17", 'L', 'A', OFTString, 188, 193, 6, 1, 1},
176
    {"RS_A18", 'L', 'A', OFTString, 194, 199, 6, 1, 1},
177
    {"RS_A19", 'L', 'A', OFTString, 200, 210, 11, 1, 1},
178
};
179
static const TigerRecordInfo rtA_2004_info = {
180
    rtA_2004_fields, sizeof(rtA_2004_fields) / sizeof(TigerFieldInfo), 210};
181
182
static const TigerFieldInfo rtA_fields[] = {
183
    // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet
184
    {"MODULE", ' ', ' ', OFTString, 0, 0, 8, 1, 0},
185
    {"FILE", 'L', 'N', OFTString, 6, 10, 5, 1, 1},
186
    {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 1, 1},
187
    {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 1, 1},
188
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 1, 1},
189
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 1, 1},
190
    {"FAIR", 'L', 'N', OFTInteger, 26, 30, 5, 1, 1},
191
    {"FMCD", 'L', 'N', OFTInteger, 31, 35, 5, 1, 1},
192
    {"FPL", 'L', 'N', OFTInteger, 36, 40, 5, 1, 1},
193
    {"CTBNA90", 'L', 'N', OFTInteger, 41, 46, 6, 1, 1},
194
    {"BLK90", 'L', 'A', OFTString, 47, 50, 4, 1, 1},
195
    {"CD106", 'L', 'N', OFTInteger, 51, 52, 2, 1, 1},
196
    {"CD108", 'L', 'N', OFTInteger, 53, 54, 2, 1, 1},
197
    {"SDELM", 'L', 'A', OFTString, 55, 59, 5, 1, 1},
198
    {"SDSEC", 'L', 'N', OFTString, 65, 69, 5, 1, 1},
199
    {"SDUNI", 'L', 'A', OFTString, 70, 74, 5, 1, 1},
200
    {"TAZ", 'R', 'A', OFTString, 75, 80, 6, 1, 1},
201
    {"UA", 'L', 'N', OFTInteger, 81, 84, 4, 1, 1},
202
    {"URBFLAG", 'L', 'A', OFTString, 85, 85, 1, 1, 1},
203
    {"CTPP", 'L', 'A', OFTString, 86, 89, 4, 1, 1},
204
    {"STATE90", 'L', 'N', OFTInteger, 90, 91, 2, 1, 1},
205
    {"COUN90", 'L', 'N', OFTInteger, 92, 94, 3, 1, 1},
206
    {"AIR90", 'L', 'N', OFTInteger, 95, 98, 4, 1, 1}};
207
208
static const TigerRecordInfo rtA_info = {
209
    rtA_fields, sizeof(rtA_fields) / sizeof(TigerFieldInfo), 98};
210
211
static const TigerFieldInfo rtS_2002_fields[] = {
212
    // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet
213
    {"FILE", 'L', 'N', OFTInteger, 6, 10, 5, 0, 0},
214
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0},
215
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0},
216
    {"STATE", 'L', 'N', OFTInteger, 26, 27, 2, 1, 1},
217
    {"COUNTY", 'L', 'N', OFTInteger, 28, 30, 3, 1, 1},
218
    {"TRACT", 'L', 'N', OFTInteger, 31, 36, 6, 0, 0},
219
    {"BLOCK", 'L', 'N', OFTInteger, 37, 40, 4, 0, 0},
220
    {"BLKGRP", 'L', 'N', OFTInteger, 41, 41, 1, 1, 1},
221
    {"AIANHHFP", 'L', 'N', OFTInteger, 42, 46, 5, 1, 1},
222
    {"AIANHH", 'L', 'N', OFTInteger, 47, 50, 4, 1, 1},
223
    {"AIHHTLI", 'L', 'A', OFTString, 51, 51, 1, 1, 1},
224
    {"ANRC", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1},
225
    {"AITSCE", 'L', 'N', OFTInteger, 57, 59, 3, 1, 1},
226
    {"AITS", 'L', 'N', OFTInteger, 60, 64, 5, 1, 1},
227
    {"CONCIT", 'L', 'N', OFTInteger, 65, 69, 5, 1, 1},
228
    {"COUSUB", 'L', 'N', OFTInteger, 70, 74, 5, 1, 1},
229
    {"SUBMCD", 'L', 'N', OFTInteger, 75, 79, 5, 1, 1},
230
    {"PLACE", 'L', 'N', OFTInteger, 80, 84, 5, 1, 1},
231
    {"SDELM", 'L', 'N', OFTInteger, 85, 89, 5, 1, 1},
232
    {"SDSEC", 'L', 'N', OFTInteger, 90, 94, 5, 1, 1},
233
    {"SDUNI", 'L', 'N', OFTInteger, 95, 99, 5, 1, 1},
234
    {"MSACMSA", 'L', 'N', OFTInteger, 100, 103, 4, 1, 1},
235
    {"PMSA", 'L', 'N', OFTInteger, 104, 107, 4, 1, 1},
236
    {"NECMA", 'L', 'N', OFTInteger, 108, 111, 4, 1, 1},
237
    {"CD106", 'L', 'N', OFTInteger, 112, 113, 2, 1, 1},
238
    // Note: spec has CD106 with 'R', but sample data file (08005) seems to
239
    // have been written with 'L', so I'm using 'L' here.  mbp Tue Dec 24
240
    // 19:03:40 2002
241
    {"CD108", 'R', 'N', OFTInteger, 114, 115, 2, 1, 1},
242
    {"PUMA5", 'L', 'N', OFTInteger, 116, 120, 5, 1, 1},
243
    {"PUMA1", 'L', 'N', OFTInteger, 121, 125, 5, 1, 1},
244
    {"ZCTA5", 'L', 'A', OFTString, 126, 130, 5, 1, 1},
245
    {"ZCTA3", 'L', 'A', OFTString, 131, 133, 3, 1, 1},
246
    {"TAZ", 'L', 'A', OFTString, 134, 139, 6, 1, 1},
247
    {"TAZCOMB", 'L', 'A', OFTString, 140, 145, 6, 1, 1},
248
    {"UA", 'L', 'N', OFTInteger, 146, 150, 5, 1, 1},
249
    {"UR", 'L', 'A', OFTString, 151, 151, 1, 1, 1},
250
    {"VTD", 'R', 'A', OFTString, 152, 157, 6, 1, 1},
251
    {"SLDU", 'R', 'A', OFTString, 158, 160, 3, 1, 1},
252
    {"SLDL", 'R', 'A', OFTString, 161, 163, 3, 1, 1},
253
    {"UGA", 'L', 'A', OFTString, 164, 168, 5, 1, 1},
254
};
255
static const TigerRecordInfo rtS_2002_info = {
256
    rtS_2002_fields, sizeof(rtS_2002_fields) / sizeof(TigerFieldInfo), 168};
257
258
static const TigerFieldInfo rtS_2000_Redistricting_fields[] = {
259
    {"FILE", 'L', 'N', OFTString, 6, 10, 5, 0, 0},
260
    {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 0, 0},
261
    {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 0, 0},
262
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0},
263
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0},
264
    {"WATER", 'L', 'N', OFTString, 26, 26, 1, 1, 1},
265
    {"CMSAMSA", 'L', 'N', OFTInteger, 27, 30, 4, 1, 1},
266
    {"PMSA", 'L', 'N', OFTInteger, 31, 34, 4, 1, 1},
267
    {"AIANHH", 'L', 'N', OFTInteger, 35, 39, 5, 1, 1},
268
    {"AIR", 'L', 'N', OFTInteger, 40, 43, 4, 1, 1},
269
    {"TRUST", 'L', 'A', OFTString, 44, 44, 1, 1, 1},
270
    {"ANRC", 'L', 'A', OFTInteger, 45, 46, 2, 1, 1},
271
    {"STATECU", 'L', 'N', OFTInteger, 47, 48, 2, 1, 1},
272
    {"COUNTYCU", 'L', 'N', OFTInteger, 49, 51, 3, 1, 1},
273
    {"FCCITY", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1},
274
    {"FMCD", 'L', 'N', OFTInteger, 57, 61, 5, 0, 0},
275
    {"FSMCD", 'L', 'N', OFTInteger, 62, 66, 5, 1, 1},
276
    {"PLACE", 'L', 'N', OFTInteger, 67, 71, 5, 1, 1},
277
    {"CTBNA00", 'L', 'N', OFTInteger, 72, 77, 6, 1, 1},
278
    {"BLK00", 'L', 'N', OFTString, 78, 81, 4, 1, 1},
279
    {"RS10", 'R', 'N', OFTInteger, 82, 82, 0, 0, 1},
280
    {"CDCU", 'L', 'N', OFTInteger, 83, 84, 2, 1, 1},
281
282
    {"SLDU", 'R', 'A', OFTString, 85, 87, 3, 1, 1},
283
    {"SLDL", 'R', 'A', OFTString, 88, 90, 3, 1, 1},
284
    {"UGA", 'L', 'A', OFTString, 91, 95, 5, 1, 1},
285
    {"BLKGRP", 'L', 'N', OFTInteger, 96, 96, 1, 1, 1},
286
    {"VTD", 'R', 'A', OFTString, 97, 102, 6, 1, 1},
287
    {"STATECOL", 'L', 'N', OFTInteger, 103, 104, 2, 1, 1},
288
    {"COUNTYCOL", 'L', 'N', OFTInteger, 105, 107, 3, 1, 1},
289
    {"BLOCKCOL", 'R', 'N', OFTInteger, 108, 112, 5, 1, 1},
290
    {"BLKSUFCOL", 'L', 'A', OFTString, 113, 113, 1, 1, 1},
291
    {"ZCTA5", 'L', 'A', OFTString, 114, 118, 5, 1, 1}};
292
293
static const TigerRecordInfo rtS_2000_Redistricting_info = {
294
    rtS_2000_Redistricting_fields,
295
    sizeof(rtS_2000_Redistricting_fields) / sizeof(TigerFieldInfo), 120};
296
297
static const TigerFieldInfo rtS_fields[] = {
298
    {"FILE", 'L', 'N', OFTString, 6, 10, 5, 0, 0},
299
    {"STATE", 'L', 'N', OFTInteger, 6, 7, 2, 0, 0},
300
    {"COUNTY", 'L', 'N', OFTInteger, 8, 10, 3, 0, 0},
301
    {"CENID", 'L', 'A', OFTString, 11, 15, 5, 0, 0},
302
    {"POLYID", 'R', 'N', OFTInteger, 16, 25, 10, 0, 0},
303
304
    {"WATER", 'L', 'N', OFTString, 26, 26, 1, 1, 1},
305
    {"CMSAMSA", 'L', 'N', OFTInteger, 27, 30, 4, 1, 1},
306
    {"PMSA", 'L', 'N', OFTInteger, 31, 34, 4, 1, 1},
307
    {"AIANHH", 'L', 'N', OFTInteger, 35, 39, 5, 1, 1},
308
    {"AIR", 'L', 'N', OFTInteger, 40, 43, 4, 1, 1},
309
    {"TRUST", 'L', 'A', OFTString, 44, 44, 1, 1, 1},
310
    {"ANRC", 'L', 'A', OFTInteger, 45, 46, 2, 1, 1},
311
    {"STATECU", 'L', 'N', OFTInteger, 47, 48, 2, 1, 1},
312
    {"COUNTYCU", 'L', 'N', OFTInteger, 49, 51, 3, 1, 1},
313
    {"FCCITY", 'L', 'N', OFTInteger, 52, 56, 5, 1, 1},
314
    {"FMCD", 'L', 'N', OFTInteger, 57, 61, 5, 0, 0},
315
    {"FSMCD", 'L', 'N', OFTInteger, 62, 66, 5, 1, 1},
316
    {"PLACE", 'L', 'N', OFTInteger, 67, 71, 5, 1, 1},
317
    {"CTBNA00", 'L', 'N', OFTInteger, 72, 77, 6, 1, 1},
318
    {"BLK00", 'L', 'N', OFTString, 78, 81, 4, 1, 1},
319
    {"RS10", 'R', 'N', OFTInteger, 82, 82, 0, 0, 1},
320
    {"CDCU", 'L', 'N', OFTInteger, 83, 84, 2, 1, 1},
321
322
    {"STSENATE", 'L', 'A', OFTString, 85, 90, 6, 1, 1},
323
    {"STHOUSE", 'L', 'A', OFTString, 91, 96, 6, 1, 1},
324
    {"VTD00", 'L', 'A', OFTString, 97, 102, 6, 1, 1}};
325
static const TigerRecordInfo rtS_info = {
326
    rtS_fields, sizeof(rtS_fields) / sizeof(TigerFieldInfo), 120};
327
328
/************************************************************************/
329
/*                            TigerPolygon()                            */
330
/************************************************************************/
331
332
TigerPolygon::TigerPolygon(OGRTigerDataSource *poDSIn,
333
                           const char * /* pszPrototypeModule */)
334
150
    : psRTAInfo(nullptr), psRTSInfo(nullptr), fpRTS(nullptr), bUsingRTS(true),
335
150
      nRTSRecLen(0)
336
150
{
337
150
    poDS = poDSIn;
338
150
    poFeatureDefn = new OGRFeatureDefn("Polygon");
339
150
    poFeatureDefn->Reference();
340
150
    poFeatureDefn->SetGeomType(wkbNone);
341
342
150
    if (poDS->GetVersion() >= TIGER_2004)
343
141
    {
344
141
        psRTAInfo = &rtA_2004_info;
345
141
    }
346
9
    else if (poDS->GetVersion() >= TIGER_2003)
347
0
    {
348
0
        psRTAInfo = &rtA_2003_info;
349
0
    }
350
9
    else if (poDS->GetVersion() >= TIGER_2002)
351
0
    {
352
0
        psRTAInfo = &rtA_2002_info;
353
0
    }
354
9
    else
355
9
    {
356
9
        psRTAInfo = &rtA_info;
357
9
    }
358
359
150
    if (poDS->GetVersion() >= TIGER_2002)
360
141
    {
361
141
        psRTSInfo = &rtS_2002_info;
362
141
    }
363
9
    else if (poDS->GetVersion() >= TIGER_2000_Redistricting)
364
6
    {
365
6
        psRTSInfo = &rtS_2000_Redistricting_info;
366
6
    }
367
3
    else
368
3
    {
369
3
        psRTSInfo = &rtS_info;
370
3
    }
371
372
    /* -------------------------------------------------------------------- */
373
    /*      Fields from type A record.                                      */
374
    /* -------------------------------------------------------------------- */
375
150
    AddFieldDefns(psRTAInfo, poFeatureDefn);
376
377
    /* -------------------------------------------------------------------- */
378
    /*      Add the RTS records if it is available.                         */
379
    /* -------------------------------------------------------------------- */
380
150
    if (bUsingRTS)
381
150
    {
382
150
        AddFieldDefns(psRTSInfo, poFeatureDefn);
383
150
    }
384
150
}
385
386
/************************************************************************/
387
/*                           ~TigerPolygon()                            */
388
/************************************************************************/
389
390
TigerPolygon::~TigerPolygon()
391
392
150
{
393
150
    if (fpRTS != nullptr)
394
0
        VSIFCloseL(fpRTS);
395
150
}
396
397
/************************************************************************/
398
/*                             SetModule()                              */
399
/************************************************************************/
400
401
bool TigerPolygon::SetModule(const char *pszModuleIn)
402
403
302
{
404
302
    if (!OpenFile(pszModuleIn, "A"))
405
152
        return false;
406
407
150
    EstablishFeatureCount();
408
409
    /* -------------------------------------------------------------------- */
410
    /*      Open the RTS file                                               */
411
    /* -------------------------------------------------------------------- */
412
150
    if (bUsingRTS)
413
150
    {
414
150
        if (fpRTS != nullptr)
415
0
        {
416
0
            VSIFCloseL(fpRTS);
417
0
            fpRTS = nullptr;
418
0
        }
419
420
150
        if (pszModuleIn)
421
0
        {
422
0
            char *pszFilename = poDS->BuildFilename(pszModuleIn, "S");
423
424
0
            fpRTS = VSIFOpenL(pszFilename, "rb");
425
426
0
            CPLFree(pszFilename);
427
428
0
            nRTSRecLen = EstablishRecordLength(fpRTS);
429
0
        }
430
150
    }
431
432
150
    return true;
433
302
}
434
435
/************************************************************************/
436
/*                             GetFeature()                             */
437
/************************************************************************/
438
439
OGRFeature *TigerPolygon::GetFeature(int nRecordId)
440
441
0
{
442
0
    char achRecord[OGR_TIGER_RECBUF_LEN];
443
444
0
    if (nRecordId < 0 || nRecordId >= nFeatures)
445
0
    {
446
0
        CPLError(CE_Failure, CPLE_FileIO,
447
0
                 "Request for out-of-range feature %d of %sA", nRecordId,
448
0
                 pszModule);
449
0
        return nullptr;
450
0
    }
451
452
    /* -------------------------------------------------------------------- */
453
    /*      Read the raw record data from the file.                         */
454
    /* -------------------------------------------------------------------- */
455
0
    if (fpPrimary == nullptr)
456
0
        return nullptr;
457
458
0
    if (nRecordLength > static_cast<int>(sizeof(achRecord)))
459
0
    {
460
0
        CPLError(CE_Failure, CPLE_AppDefined, "Record length too large");
461
0
        return nullptr;
462
0
    }
463
464
0
    {
465
0
        const auto nOffset = static_cast<uint64_t>(nRecordId) * nRecordLength;
466
0
        if (VSIFSeekL(fpPrimary, nOffset, SEEK_SET) != 0)
467
0
        {
468
0
            CPLError(CE_Failure, CPLE_FileIO,
469
0
                     "Failed to seek to %" PRIu64 " of %sA", nOffset,
470
0
                     pszModule);
471
0
            return nullptr;
472
0
        }
473
0
    }
474
475
0
    if (VSIFReadL(achRecord, nRecordLength, 1, fpPrimary) != 1)
476
0
    {
477
0
        CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %sA",
478
0
                 nRecordId, pszModule);
479
0
        return nullptr;
480
0
    }
481
482
    /* -------------------------------------------------------------------- */
483
    /*      Set fields.                                                     */
484
    /* -------------------------------------------------------------------- */
485
486
0
    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
487
488
0
    SetFields(psRTAInfo, poFeature, achRecord);
489
490
    /* -------------------------------------------------------------------- */
491
    /*      Read RTS record, and apply fields.                              */
492
    /* -------------------------------------------------------------------- */
493
494
0
    if (fpRTS != nullptr)
495
0
    {
496
0
        char achRTSRec[OGR_TIGER_RECBUF_LEN];
497
498
0
        {
499
0
            const auto nOffset = static_cast<uint64_t>(nRecordId) * nRTSRecLen;
500
0
            if (VSIFSeekL(fpRTS, nOffset, SEEK_SET) != 0)
501
0
            {
502
0
                CPLError(CE_Failure, CPLE_FileIO,
503
0
                         "Failed to seek to %" PRIu64 " of %sS", nOffset,
504
0
                         pszModule);
505
0
                delete poFeature;
506
0
                return nullptr;
507
0
            }
508
0
        }
509
510
        // Overflow cannot happen since psRTInfo->nRecordLength is unsigned
511
        // char and sizeof(achRecord) == OGR_TIGER_RECBUF_LEN > 255
512
0
        if (VSIFReadL(achRTSRec, psRTSInfo->nRecordLength, 1, fpRTS) != 1)
513
0
        {
514
0
            CPLError(CE_Failure, CPLE_FileIO, "Failed to read record %d of %sS",
515
0
                     nRecordId, pszModule);
516
0
            delete poFeature;
517
0
            return nullptr;
518
0
        }
519
520
0
        SetFields(psRTSInfo, poFeature, achRTSRec);
521
0
    }
522
523
0
    return poFeature;
524
0
}