aboutsummaryrefslogtreecommitdiff
path: root/libplanfahr/providers/hafas-bin6-format.h
blob: e4b38139dc6a2ab20a9b57b18b45849b143674cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/*
 * hafas-bin6-format.h Hafas Binary 6 format
 *
 * Copyright (C) 2014 Guido Günther
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Author: Guido Günther <agx@sigxcpu.org>
 */

#ifndef _HAFAS_BIN6_FORMAT_H
#define _HAFAS_BIN6_FORMAT_H

/**
 * Hafas Binary format version 6
 *
 * The binary format uses several headers that mark contain the start
 * different tables (*_tbl variables). An byte offset into such a table
 * is marked by a variable ending in _off. If the elements in a table
 * are fixed size (array) indexes are used. These end in _idx.
 *
 * Based on AbstractHafasProvider in public-transport-enabler and
 *
 */

#pragma GCC diagnostic ignored "-Wattributes"

/**
 * HafasBin6Header:
 * hafas binary format header version 6
 *
*/
typedef struct _HafasBin6Header {
    guint16 version;                                                 /* 0x00 */
    gchar   start[14];    /* HafasBin6Loc */                         /* 0x02 */
    gchar   end[14];      /* HafasBin6Loc */                         /* 0x10 */
    guint16 num_trips;    /* # of trips in this resp. */             /* 0x1e */
    guint32 service_tbl;  /* Start of service table */               /* 0x20 */
    guint32 strings_tbl;  /* start of strings table */               /* 0x24 */
    gint16  days;         /* date base in days since 1980 */         /* 0x28 */
    gchar   unknown0[12];                                            /* 0x2a */
    guint32 stations_tbl; /* start of stations table */              /* 0x36 */
    guint32 comments_tbl; /* start of comments table */              /* 0x3a */
    gchar   unknown1[8];                                             /* 0x3e */
    guint32 ext;          /* Start of extenson header */             /* 0x46 */
}  __attribute__ ((packed)) HafasBin6Header;


typedef enum _HafasBin6LocTypes {
    HAFAS_BIN6_LOC_TYPE_STATION = 1,
    HAFAS_BIN6_LOC_TYPE_ADDRESS = 2,
    HAFAS_BIN6_LOC_TYPE_POI     = 3,
} HafasBin6LocTypes;

/**
 * HafasBin6Loc:
 *
 * Start and end location from #HafasBin6Header
 */
typedef struct _HafasBin6Loc {
    guint16 name_off;    /* offset into string table */              /* 0x00 */
    guint16 unknown0;                                                /* 0x02 */
    guint16 type;        /* as in HafasBinLocTypes */                /* 0x04 */
    gint32  lon;         /* longitude * 10^6 */                      /* 0x06 */
    gint32  lat;         /* latitude * 10^6 */                       /* 0x0a */
} __attribute__ ((packed)) HafasBin6Loc;

/**
 * HafasBin6Trip:
 *
 * One entry per trip, follows directly after #HafasBin6Header
 */
typedef struct _HafasBin6Trip {
    guint16 service_off; /* offset into service days table */        /* 0x00 */
    guint32 parts_off;   /* offset after header */                   /* 0x02 */
    guint16 part_cnt;    /* number of parts in this trip */          /* 0x06 */
    guint16 changes;     /* number of train changes in this trip */  /* 0x08 */
    guint16 unknown0;                                                /* 0x0a */
} __attribute__ ((packed)) HafasBin6Trip;

/**
 * HafasBin6Station:
 *
 * A station in the stations table as pointed to by the #HafasBin6Header
 */
typedef struct _HafasBin6Station {
    guint16 name_off; /* offset in string table */                   /* 0x00 */
    guint32 id;       /* id of this station */                       /* 0x02 */
    gint32  lon;      /* longitute * 10^6 */                         /* 0x06 */
    gint32  lat;      /* latitude * 10^6 */                          /* 0x0a */
} __attribute__ ((packed)) HafasBin6Station;

/**
 * HafasBin6Errors:
 *
 * Errors in err field of #HafasBin6ExtHeader
 */
typedef enum _HafasBin6Errors {
    HAFAS_BIN6_ERROR_NONE = 0,
    HAFAS_BIN6_ERROR_SESSION_EXPIRED = 1,
    /* TBD */
} HafasBin6Errors;

/**
 * HafasBin6ExtHeader:
 *
 * Hafas Binary format version 6 extension header. If attrs_index0 !=
 * 0 and length >= 0x30 then attribute indexes for all trips follow
 * after this header. Location of this header is determined by ext in
 * the #HafasBin6Header.
 */
typedef struct _HafasBin6ExtHeader {
    guint32 length;                                                  /* 0x00 */
    guint32 unknown0;                                                /* 0x04 */
    guint16 seq;                                                     /* 0x08 */
    guint16 req_id_off;   /* request id offset into string table */  /* 0x0a */
    guint32 details_tbl;  /* offset to trip details header */        /* 0x0c */
    guint16 err;                                                     /* 0x10 */
    gchar   unknown1[14];                                            /* 0x12 */
    guint16 enc_off;      /* encoding offset into string table */    /* 0x20 */
    guint16 ld_off;       /* ld offset into string table */          /* 0x22 */
    guint16 attrs_off;    /* attributes offset */                    /* 0x24 */
    gchar   pad[6];                                                  /* 0x26 */
    guint32 attrs_index0; /* attribute indexes start here  */        /* 0x2c */
} HafasBin6ExtHeader;

/**
 * HafasBin6TripDetailsHeader:
 *
 * Header for all trip details following this header. The details_index_off
 * is relative to this header and stores just another offset to the final
 * location of the #HafasBin6TripDetail.
 */
typedef struct _HafasBin6TripDetailsHeader {
    guint16 version;                                                 /* 0x00 */
    guint16 unknown0;                                                /* 0x02 */
    guint16 details_index_off;                                       /* 0x04 */
    guint16 part_details_off;  /* size of part details struct */     /* 0x06 */
    guint16 part_detail_size;                                        /* 0x08 */
    guint16 stop_size;         /* size of stop struct */             /* 0x0a */
    guint16 stops_off;                                               /* 0x0c */
} HafasBin6TripDetailsHeader;

/**
 * HafasBin6ServiceDay:
 *
 * The service day table is used to calculate day offsets on top of
 * #HafasBin6Header days. See #hafas_binary_parse_service_day for details.
 */
typedef struct _HafasBin6ServiceDay {
    guint16 days_off;  /* offset into string table */                /* 0x00 */
    guint16 byte_base; /* days * 8 */                                /* 0x02 */
    guint16 byte_len;  /* # of bytes to follow */                    /* 0x04 */
    gchar   byte0;     /* first day offset byte */                   /* 0x06 */
} __attribute__ ((packed)) HafasBin6ServiceDay;

typedef enum _HafasBin6TripDetailRTStatus {
    HAFAS_BIN6_RTSTATUS_CANCELLED = 0x0002,
    HAFAS_BIN6_RTSTATUS_NORMAL    = 0xFFFF,
} HafasBin6TripDetailRTStatus;

/**
 * HafasBin6TripDetail:
 *
 * Status of this trip
 */
typedef struct _HafasBin6TripDetail {
    guint16 rt_status; /* real time status */                        /* 0x00 */
    guint16 delay;                                                   /* 0x02 */
}  HafasBin6TripDetail;

typedef enum _HafasBin6TripPartType {
    footway = 1,
    train   = 2,
} HafasBin6TripPartType;

/**
 * HafasBin6TripPartType:
 *
 * A part of the trip using one "vehicle".
 */
typedef struct _HafasBin6TripPart {
    guint16 dep;         /* planned departure time at start */       /* 0x00 */
    guint16 dep_off;     /* start, offset into stations table */     /* 0x02 */
    guint16 arr;         /* planned arrival time at end */           /* 0x04 */
    guint16 arr_off;     /* end, offset into stations table */       /* 0x06 */
    guint16 type;                                                    /* 0x08 */
    guint16 line_off;    /* offset into string table */              /* 0x0a */
    guint16 dep_pos_off; /* offset into string table */              /* 0x0c */
    guint16 arr_pos_off; /* offset into string table */              /* 0x0e */
    guint16 attr_index;                                              /* 0x10 */
    guint16 comments_off; /* offset into comments table */           /* 0x12 */
}  HafasBin6TripPart;

/**
 * HAFAS_BIN6_NO_PLATFORM: no platform for this stop
 */
#define HAFAS_BIN6_NO_PLATFORM "---"
/**
 * HAFAS_BIN6_NO_REALTIME: no realtime information for this stop
 */
#define HAFAS_BIN6_NO_REALTIME 0xFFFF

/**
 * HafasBin6TripPartDetail:
 *
 * More details of one part of the trip. In contrast to
 * #HafasBin6TripPart times and platforms are predicted instead of
 * planned values.
 */
typedef struct _HafasBin6TripPartDetail {
    guint16 dep_pred; /* predicted departure time */                 /* 0x00 */
    guint16 arr_pred; /* predicted arrival time */                   /* 0x02 */
    guint16 dep_pos_pred_off;  /* offset into string table */        /* 0x04 */
    guint16 arr_pos_pred_off;  /* offset into string table */        /* 0x06 */
    guint16 flags;      /* flags */                                  /* 0x08 */
    guint16 unknown0;                                                /* 0x0a */
    guint16 stop_index; /* index of first stop */                    /* 0x0c */
    guint16 stops_cnt;  /* number of stops */                        /* 0x0e */
} HafasBin6TripPartDetail;

#define HAFAS_BIN6_PART_DETAIL_FLAGS_STOP_CANCELED 0x20 /* stop was cancelled */
#define HAFAS_BIN6_PART_DETAIL_FLAGS_TRIP_CANCELED 0x30 /* trip was cancelled */

#define HAFAS_BIN6_PART_DETAIL_FLAGS_CANCELED_MASK 0x30 /* trip was cancelled */

/**
 * HafasBin6Stop:
 *
 * Platforms and times (planned and predicted) for stops on the trip
 */
typedef struct _HafasBin6TripStop {
    guint16 dep; /* planned departure time at this stop */           /* 0x00 */
    guint16 arr; /* planned arrival time at this stop */             /* 0x02 */
    guint16 dep_pos_off; /* platform, offset into string table */    /* 0x04 */
    guint16 arr_pos_off; /* platfrom, offset into string table */    /* 0x06 */
    guint32 unknown0;                                                /* 0x08 */
    guint16 dep_pred; /* predicted departure time at this stop */    /* 0x0c */
    guint16 arr_pred; /* predicted arrival time at this stop */      /* 0x0e */
    guint16 dep_pos_pred_off; /* offset into string table */         /* 0x10 */
    guint16 arr_pos_pred_off; /* offset into string table */         /* 0x12 */
    guint32 unknown1;                                                /* 0x14 */
    guint16 stop_idx; /* index into stations table */                /* 0x18 */

} __attribute__ ((packed)) HafasBin6TripStop;

typedef struct _HafasBin6Attr {
    guint16 key_off; /* offset into string table */                  /* 0x00 */
    guint16 val_off; /* offset into string table */                  /* 0x02 */
} HafasBin6Attr;

#pragma GCC diagnostic pop /* "-Wattributes" */

/*
 * Access to headers and tables
 */
/* the main header */
#define HAFAS_BIN6_HEADER(data) ((HafasBin6Header*)(data))
/* extension header */
#define HAFAS_BIN6_EXT_HEADER(data) ((HafasBin6ExtHeader*)((data) + (((HafasBin6Header*)(data))->ext)))
/* trip details header */
#define HAFAS_BIN6_TRIP_DETAILS_HEADER(data) ((HafasBin6TripDetailsHeader*)((data) + HAFAS_BIN6_EXT_HEADER(data)->details_tbl))
/* trip details index table */
#define _HAFAS_BIN6_TRIP_DETAILS_INDEX(data)      ((gchar*)(((gchar*)HAFAS_BIN6_TRIP_DETAILS_HEADER(data)) + \
                                                            (HAFAS_BIN6_TRIP_DETAILS_HEADER(data)->details_index_off)))
/* trip part details index table */
#define _HAFAS_BIN6_TRIP_PART_DETAILS_INDEX(data) ((gchar*)(((gchar*)HAFAS_BIN6_TRIP_DETAILS_HEADER(data)) + \
                                                           (HAFAS_BIN6_TRIP_DETAILS_HEADER(data)->part_details_off)))
/* stops index table */
#define _HAFAS_BIN6_STOPS_INDEX(data)             ((gchar*)(((gchar*)HAFAS_BIN6_TRIP_DETAILS_HEADER(data)) + \
                                                           (HAFAS_BIN6_TRIP_DETAILS_HEADER(data)->stops_off)))
/* trips table */
#define _HAFAS_BIN6_TRIPS_TABLE(data)             ((gchar*)((data) + sizeof(HafasBin6Header)))

/*
 * Access to the data structures making up the trips
 */
/* Start and end of trip */
#define HAFAS_BIN6_START(data) ((HafasBin6Loc*)(((HafasBin6Header*)data)->start))
#define HAFAS_BIN6_END(data) ((HafasBin6Loc*)(((HafasBin6Header*)data)->end))
/* trip details and trip part details use an indirection via a common index table */
#define _HAFAS_BIN6_TRIP_INDEX(data, idx) \
    (*((guint16*)(_HAFAS_BIN6_TRIP_DETAILS_INDEX(data) + 2 * (idx))))
/* Get a string at offset off */
#define HAFAS_BIN6_STR(data, off) \
    ((const gchar*)((gchar*)((data) + (((HafasBin6Header*)(data))->strings_tbl) + (off))))
/* Get the n-th station from the staitons table */
#define HAFAS_BIN6_STATION(data, idx) \
    ((HafasBin6Station*)((data) + (((HafasBin6Header*)(data))->stations_tbl) + ((idx) * sizeof(HafasBin6Station))))
/* Get the idx-th trip */
#define HAFAS_BIN6_TRIP(data, idx) \
    ((HafasBin6Trip*)((data) + sizeof(HafasBin6Header) + ((idx) * sizeof(HafasBin6Trip))))
/* Get the service table entry for the idx-th trip */
#define HAFAS_BIN6_SERVICE_DAY(data, idx) \
    ((HafasBin6ServiceDay*)((data) + (((HafasBin6Header*)(data))->service_tbl) + \
                            (HAFAS_BIN6_TRIP(data, idx)->service_off)))
/* Get the idy-th part of the idx-th trip */
#define HAFAS_BIN6_TRIP_PART(data, idx, idy) \
    ((HafasBin6TripPart*)(_HAFAS_BIN6_TRIPS_TABLE(data) + \
                          (HAFAS_BIN6_TRIP(data, idx)->parts_off) + \
                          idy * sizeof(HafasBin6TripPart)))
/* Get the trip details for the idx-th trip */
#define HAFAS_BIN6_TRIP_DETAIL(data, idx) \
    ((HafasBin6TripDetail*)(_HAFAS_BIN6_TRIP_DETAILS_INDEX(data) + \
                            _HAFAS_BIN6_TRIP_INDEX(data, idx)))
/* Get the trip part details for the idx-th trip and the idy-th part */
#define HAFAS_BIN6_TRIP_PART_DETAIL(data, idx, idy) \
    ((HafasBin6TripPartDetail*)(_HAFAS_BIN6_TRIP_PART_DETAILS_INDEX(data) + \
                                _HAFAS_BIN6_TRIP_INDEX(data, idx) + \
                                ((idy) * sizeof(HafasBin6TripPartDetail))))
/* Get the idz-th stop of the idy-th part in the idx-th trip */
#define HAFAS_BIN6_STOP(data, idx, idy, idz) \
    ((HafasBin6TripStop*)(_HAFAS_BIN6_STOPS_INDEX(data) + \
                          (HAFAS_BIN6_TRIP_PART_DETAIL(data, idx, idy)->stop_index) * sizeof(HafasBin6TripStop) + \
                          idz * sizeof(HafasBin6TripStop)))


/* Convert hafas longitude/latitude information to floating point */
#define HAFAS_BIN6_LL_DOUBlE(l) ((gdouble) (l) / 1000000.0)

#endif /* _HAFAS_BINARY_H */