Updated hexemplio road types.
[freeciv.git] / common / dataio.c
blobe13697891381f31715175193f91f99ffabc84083
1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
15 * The DataIO module provides a system independent (endianess and
16 * sizeof(int) independent) way to write and read data. It supports
17 * multiple datas which are collected in a buffer. It provides
18 * recognition of error cases like "not enough space" or "not enough
19 * data".
22 #ifdef HAVE_CONFIG_H
23 #include <fc_config.h>
24 #endif
26 #include "fc_prehdrs.h"
28 #include <limits.h>
29 #include <math.h>
30 #include <stdint.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #ifdef FREECIV_HAVE_SYS_TYPES_H
36 #include <sys/types.h>
37 #endif
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
40 #endif
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
43 #endif
44 #ifdef HAVE_ARPA_INET_H
45 #include <arpa/inet.h>
46 #endif
48 /* utility */
49 #include "bitvector.h"
50 #include "capability.h"
51 #include "log.h"
52 #include "mem.h"
53 #include "support.h"
55 /* common */
56 #include "events.h"
57 #include "player.h"
58 #include "requirements.h"
59 #include "tech.h"
60 #include "worklist.h"
62 #include "dataio.h"
64 static bool get_conv(char *dst, size_t ndst, const char *src,
65 size_t nsrc);
67 static DIO_PUT_CONV_FUN put_conv_callback = NULL;
68 static DIO_GET_CONV_FUN get_conv_callback = get_conv;
70 /* Uncomment to make field range tests to asserts, fatal with -F */
71 /* #define FIELD_RANGE_ASSERT */
73 #if defined(FREECIV_TESTMATIC) && !defined(FIELD_RANGE_ASSERT)
74 #define FIELD_RANGE_ASSERT
75 #endif
77 #ifdef FIELD_RANGE_ASSERT
78 /* This evaluates _test_ twice. If that's a problem,
79 * it should evaluate it just once and store result to variable.
80 * That would lose verbosity of the assert message. */
81 #define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
82 fc_assert(!(_test_)); \
83 if (_test_) { \
84 _action_ \
85 log_error(_format_, ## __VA_ARGS__); \
87 #else /* FIELD_RANGE_ASSERT */
88 #define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
89 if (_test_) { \
90 _action_ \
91 log_error(_format_, ## __VA_ARGS__); \
93 #endif /* FIELD_RANGE_ASSERT */
95 /**************************************************************************
96 Sets string conversion callback to be used when putting text.
97 **************************************************************************/
98 void dio_set_put_conv_callback(DIO_PUT_CONV_FUN fun)
100 put_conv_callback = fun;
103 /**************************************************************************
104 Returns FALSE if the destination isn't large enough or the source was
105 bad. This is default get_conv_callback.
106 **************************************************************************/
107 static bool get_conv(char *dst, size_t ndst, const char *src,
108 size_t nsrc)
110 size_t len = nsrc; /* length to copy, not including null */
111 bool ret = TRUE;
113 if (ndst > 0 && len >= ndst) {
114 ret = FALSE;
115 len = ndst - 1;
118 memcpy(dst, src, len);
119 dst[len] = '\0';
121 return ret;
124 /**************************************************************************
125 Sets string conversion callback to use when getting text.
126 **************************************************************************/
127 void dio_set_get_conv_callback(DIO_GET_CONV_FUN fun)
129 get_conv_callback = fun;
132 /**************************************************************************
133 Returns TRUE iff the output has size bytes available.
134 **************************************************************************/
135 static bool enough_space(struct data_out *dout, size_t size)
137 if (dout->current + size > dout->dest_size) {
138 dout->too_short = TRUE;
139 return FALSE;
140 } else {
141 dout->used = MAX(dout->used, dout->current + size);
142 return TRUE;
146 /**************************************************************************
147 Returns TRUE iff the input contains size unread bytes.
148 **************************************************************************/
149 static bool enough_data(struct data_in *din, size_t size)
151 return dio_input_remaining(din) >= size;
154 /**************************************************************************
155 Initializes the output to the given output buffer and the given
156 buffer size.
157 **************************************************************************/
158 void dio_output_init(struct data_out *dout, void *destination,
159 size_t dest_size)
161 dout->dest = destination;
162 dout->dest_size = dest_size;
163 dout->current = 0;
164 dout->used = 0;
165 dout->too_short = FALSE;
168 /**************************************************************************
169 Return the maximum number of bytes used.
170 **************************************************************************/
171 size_t dio_output_used(struct data_out *dout)
173 return dout->used;
176 /**************************************************************************
177 Rewinds the stream so that the put-functions start from the
178 beginning.
179 **************************************************************************/
180 void dio_output_rewind(struct data_out *dout)
182 dout->current = 0;
185 /**************************************************************************
186 Initializes the input to the given input buffer and the given
187 number of valid input bytes.
188 **************************************************************************/
189 void dio_input_init(struct data_in *din, const void *src, size_t src_size)
191 din->src = src;
192 din->src_size = src_size;
193 din->current = 0;
196 /**************************************************************************
197 Rewinds the stream so that the get-functions start from the
198 beginning.
199 **************************************************************************/
200 void dio_input_rewind(struct data_in *din)
202 din->current = 0;
205 /**************************************************************************
206 Return the number of unread bytes.
207 **************************************************************************/
208 size_t dio_input_remaining(struct data_in *din)
210 return din->src_size - din->current;
213 /**************************************************************************
214 Return the size of the data_type in bytes.
215 **************************************************************************/
216 size_t data_type_size(enum data_type type)
218 switch (type) {
219 case DIOT_UINT8:
220 case DIOT_SINT8:
221 return 1;
222 case DIOT_UINT16:
223 case DIOT_SINT16:
224 return 2;
225 case DIOT_UINT32:
226 case DIOT_SINT32:
227 return 4;
228 case DIOT_LAST:
229 break;
232 fc_assert_msg(FALSE, "data_type %d not handled.", type);
233 return 0;
236 /**************************************************************************
237 Skips 'n' bytes.
238 **************************************************************************/
239 bool dio_input_skip(struct data_in *din, size_t size)
241 if (enough_data(din, size)) {
242 din->current += size;
243 return TRUE;
244 } else {
245 return FALSE;
249 /**************************************************************************
250 Insert value using 8 bits. May overflow.
251 **************************************************************************/
252 void dio_put_uint8(struct data_out *dout, int value)
254 uint8_t x = value;
255 FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_1_byte);
257 FIELD_RANGE_TEST((int) x != value, ,
258 "Trying to put %d into 8 bits; "
259 "it will result %d at receiving side.",
260 value, (int) x);
262 if (enough_space(dout, 1)) {
263 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 1);
264 dout->current++;
268 /**************************************************************************
269 Insert value using 16 bits. May overflow.
270 **************************************************************************/
271 void dio_put_uint16(struct data_out *dout, int value)
273 uint16_t x = htons(value);
274 FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);
276 FIELD_RANGE_TEST((int) ntohs(x) != value, ,
277 "Trying to put %d into 16 bits; "
278 "it will result %d at receiving side.",
279 value, (int) ntohs(x));
281 if (enough_space(dout, 2)) {
282 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 2);
283 dout->current += 2;
287 /**************************************************************************
288 Insert value using 32 bits. May overflow.
289 **************************************************************************/
290 void dio_put_uint32(struct data_out *dout, int value)
292 uint32_t x = htonl(value);
293 FC_STATIC_ASSERT(sizeof(x) == 4, uint32_not_4_bytes);
295 FIELD_RANGE_TEST((int) ntohl(x) != value, ,
296 "Trying to put %d into 32 bits; "
297 "it will result %d at receiving side.",
298 value, (int) ntohl(x));
300 if (enough_space(dout, 4)) {
301 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 4);
302 dout->current += 4;
306 /**************************************************************************
307 Insert value using 'size' bits. May overflow.
308 **************************************************************************/
309 void dio_put_type(struct data_out *dout, enum data_type type, int value)
311 switch (type) {
312 case DIOT_UINT8:
313 dio_put_uint8(dout, value);
314 return;
315 case DIOT_UINT16:
316 dio_put_uint16(dout, value);
317 return;
318 case DIOT_UINT32:
319 dio_put_uint32(dout, value);
320 return;
321 case DIOT_SINT8:
322 dio_put_sint8(dout, value);
323 return;
324 case DIOT_SINT16:
325 dio_put_sint16(dout, value);
326 return;
327 case DIOT_SINT32:
328 dio_put_sint32(dout, value);
329 return;
330 case DIOT_LAST:
331 break;
334 fc_assert_msg(FALSE, "data_type %d not handled.", type);
337 /**************************************************************************
338 Insert value using 8 bits. May overflow.
339 **************************************************************************/
340 void dio_put_sint8(struct data_out *dout, int value)
342 dio_put_uint8(dout, 0 <= value ? value : value + 0x100);
345 /**************************************************************************
346 Insert value using 16 bits. May overflow.
347 **************************************************************************/
348 void dio_put_sint16(struct data_out *dout, int value)
350 dio_put_uint16(dout, 0 <= value ? value : value + 0x10000);
353 /**************************************************************************
354 Insert value using 32 bits. May overflow.
355 **************************************************************************/
356 void dio_put_sint32(struct data_out *dout, int value)
358 #if SIZEOF_INT == 4
359 dio_put_uint32(dout, value);
360 #else
361 dio_put_uint32(dout, (0 <= value ? value : value + 0x100000000));
362 #endif
365 /**************************************************************************
366 Insert value 0 or 1 using 8 bits.
367 **************************************************************************/
368 void dio_put_bool8(struct data_out *dout, bool value)
370 FIELD_RANGE_TEST(value != TRUE && value != FALSE,
371 value = (value != FALSE);,
372 "Trying to put a non-boolean: %d", (int) value);
374 dio_put_uint8(dout, value ? 1 : 0);
377 /**************************************************************************
378 Insert value 0 or 1 using 32 bits.
379 **************************************************************************/
380 void dio_put_bool32(struct data_out *dout, bool value)
382 FIELD_RANGE_TEST(value != TRUE && value != FALSE,
383 value = (value != FALSE);,
384 "Trying to put a non-boolean: %d",
385 (int) value);
387 dio_put_uint32(dout, value ? 1 : 0);
390 /****************************************************************************
391 Insert a float number, which is multiplied by 'float_factor' before
392 being encoded into an uint32.
393 ****************************************************************************/
394 void dio_put_ufloat(struct data_out *dout, float value, int float_factor)
396 uint32_t v = value * float_factor;
398 FIELD_RANGE_TEST(fabsf((float) v / float_factor - value) > 1.1 / float_factor, ,
399 "Trying to put %f with factor %d in 32 bits; "
400 "it will result %f at receiving side, having error of %f units.",
401 value, float_factor, (float) v / float_factor,
402 fabsf((float) v / float_factor - value) * float_factor);
404 dio_put_uint32(dout, v);
407 /****************************************************************************
408 Insert a float number, which is multiplied by 'float_factor' before
409 being encoded into a sint32.
410 ****************************************************************************/
411 void dio_put_sfloat(struct data_out *dout, float value, int float_factor)
413 int32_t v = value * float_factor;
415 FIELD_RANGE_TEST(fabsf((float) v / float_factor - value) > 1.1 / float_factor, ,
416 "Trying to put %f with factor %d in 32 bits; "
417 "it will result %f at receiving side, having error of %f units.",
418 value, float_factor, (float) v / float_factor,
419 fabsf((float) v / float_factor - value) * float_factor);
421 dio_put_sint32(dout, v);
424 /**************************************************************************
425 Insert number of values brefore stop_value using 8 bits. Then
426 insert values using 8 bits for each. stop_value is not required to
427 fit in 8 bits. Actual values may overflow.
428 **************************************************************************/
429 void dio_put_uint8_vec8(struct data_out *dout, int *values, int stop_value)
431 size_t count;
433 for (count = 0; values[count] != stop_value; count++) {
434 /* nothing */
437 if (enough_space(dout, 1 + count)) {
438 size_t i;
440 dio_put_uint8(dout, count);
442 for (i = 0; i < count; i++) {
443 dio_put_uint8(dout, values[i]);
448 /**************************************************************************
449 Insert number of values brefore stop_value using 8 bits. Then
450 insert values using 16 bits for each. stop_value is not required to
451 fit in 16 bits. Actual values may overflow.
452 **************************************************************************/
453 void dio_put_uint16_vec8(struct data_out *dout, int *values, int stop_value)
455 size_t count;
457 for (count = 0; values[count] != stop_value; count++) {
458 /* nothing */
461 if (enough_space(dout, 1 + 2 * count)) {
462 size_t i;
464 dio_put_uint8(dout, count);
466 for (i = 0; i < count; i++) {
467 dio_put_uint16(dout, values[i]);
472 /**************************************************************************
473 Insert block directly from memory.
474 **************************************************************************/
475 void dio_put_memory(struct data_out *dout, const void *value, size_t size)
477 if (enough_space(dout, size)) {
478 memcpy(ADD_TO_POINTER(dout->dest, dout->current), value, size);
479 dout->current += size;
483 /**************************************************************************
484 Insert NULL-terminated string. Conversion callback is used if set.
485 **************************************************************************/
486 void dio_put_string(struct data_out *dout, const char *value)
488 if (put_conv_callback) {
489 size_t length;
490 char *buffer;
492 if ((buffer = (*put_conv_callback) (value, &length))) {
493 dio_put_memory(dout, buffer, length + 1);
494 free(buffer);
496 } else {
497 dio_put_memory(dout, value, strlen(value) + 1);
501 /**************************************************************************
502 Insert tech numbers from value array as 8 bit values until there is value
503 A_LAST or MAX_NUM_TECH_LIST tech numbers have been inserted.
504 **************************************************************************/
505 void dio_put_tech_list(struct data_out *dout, const int *value)
507 int i;
509 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
510 dio_put_uint8(dout, value[i]);
511 if (value[i] == A_LAST) {
512 break;
517 /**************************************************************************
518 Insert unit type numbers from value array as 8 bit values until there is
519 value U_LAST or MAX_NUM_UNIT_LIST numbers have been inserted.
520 **************************************************************************/
521 void dio_put_unit_list(struct data_out *dout, const int *value)
523 int i;
525 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
526 dio_put_uint8(dout, value[i]);
527 if (value[i] == U_LAST) {
528 break;
533 /**************************************************************************
534 Insert building type numbers from value array as 8 bit values until there
535 is value B_LAST or MAX_NUM_BUILDING_LIST numbers have been inserted.
536 **************************************************************************/
537 void dio_put_building_list(struct data_out *dout, const int *value)
539 int i;
541 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
542 dio_put_uint8(dout, value[i]);
543 if (value[i] == B_LAST) {
544 break;
549 /**************************************************************************
550 Insert number of worklist items as 8 bit value and then insert
551 8 bit kind and 8 bit number for each worklist item.
552 **************************************************************************/
553 void dio_put_worklist(struct data_out *dout, const struct worklist *pwl)
555 int i, length = worklist_length(pwl);
557 dio_put_uint8(dout, length);
558 for (i = 0; i < length; i++) {
559 const struct universal *pcp = &(pwl->entries[i]);
561 dio_put_uint8(dout, pcp->kind);
562 dio_put_uint8(dout, universal_number(pcp));
566 /**************************************************************************
567 Receive uint8 value to dest.
568 **************************************************************************/
569 bool dio_get_uint8(struct data_in *din, int *dest)
571 uint8_t x;
573 FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_byte);
575 if (!enough_data(din, 1)) {
576 log_packet("Packet too short to read 1 byte");
578 return FALSE;
581 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 1);
582 *dest = x;
583 din->current++;
584 return TRUE;
587 /**************************************************************************
588 Receive uint16 value to dest.
589 **************************************************************************/
590 bool dio_get_uint16(struct data_in *din, int *dest)
592 uint16_t x;
594 FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);
596 if (!enough_data(din, 2)) {
597 log_packet("Packet too short to read 2 bytes");
599 return FALSE;
602 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 2);
603 *dest = ntohs(x);
604 din->current += 2;
605 return TRUE;
608 /**************************************************************************
609 Receive uint32 value to dest.
610 **************************************************************************/
611 bool dio_get_uint32(struct data_in *din, int *dest)
613 uint32_t x;
615 FC_STATIC_ASSERT(sizeof(x) == 4, uint32_not_4_bytes);
617 if (!enough_data(din, 4)) {
618 log_packet("Packet too short to read 4 bytes");
620 return FALSE;
623 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 4);
624 *dest = ntohl(x);
625 din->current += 4;
626 return TRUE;
629 /**************************************************************************
630 Receive value using 'size' bits to dest.
631 **************************************************************************/
632 bool dio_get_type(struct data_in *din, enum data_type type, int *dest)
634 switch (type) {
635 case DIOT_UINT8:
636 return dio_get_uint8(din, dest);
637 case DIOT_UINT16:
638 return dio_get_uint16(din, dest);
639 case DIOT_UINT32:
640 return dio_get_uint32(din, dest);
641 case DIOT_SINT8:
642 return dio_get_sint8(din, dest);
643 case DIOT_SINT16:
644 return dio_get_sint16(din, dest);
645 case DIOT_SINT32:
646 return dio_get_sint32(din, dest);
647 case DIOT_LAST:
648 break;
651 fc_assert_msg(FALSE, "data_type %d not handled.", type);
652 return FALSE;
655 /**************************************************************************
656 Take boolean value from 8 bits.
657 **************************************************************************/
658 bool dio_get_bool8(struct data_in *din, bool *dest)
660 int ival;
662 if (!dio_get_uint8(din, &ival)) {
663 return FALSE;
666 if (ival != 0 && ival != 1) {
667 log_packet("Got a bad boolean: %d", ival);
668 return FALSE;
671 *dest = (ival != 0);
672 return TRUE;
675 /**************************************************************************
676 Take boolean value from 32 bits.
677 **************************************************************************/
678 bool dio_get_bool32(struct data_in *din, bool * dest)
680 int ival;
682 if (!dio_get_uint32(din, &ival)) {
683 return FALSE;
686 if (ival != 0 && ival != 1) {
687 log_packet("Got a bad boolean: %d", ival);
688 return FALSE;
691 *dest = (ival != 0);
692 return TRUE;
695 /****************************************************************************
696 Get an unsigned float number, which have been multiplied by 'float_factor'
697 and encoded into an uint32 by dio_put_ufloat().
698 ****************************************************************************/
699 bool dio_get_ufloat(struct data_in *din, float *dest, int float_factor)
701 int ival;
703 if (!dio_get_uint32(din, &ival)) {
704 return FALSE;
707 *dest = (float) ival / float_factor;
708 return TRUE;
711 /****************************************************************************
712 Get a signed float number, which have been multiplied by 'float_factor'
713 and encoded into a sint32 by dio_put_sfloat().
714 ****************************************************************************/
715 bool dio_get_sfloat(struct data_in *din, float *dest, int float_factor)
717 int ival;
719 if (!dio_get_sint32(din, &ival)) {
720 return FALSE;
723 *dest = (float) ival / float_factor;
724 return TRUE;
727 /**************************************************************************
728 Take value from 8 bits.
729 **************************************************************************/
730 bool dio_get_sint8(struct data_in *din, int *dest)
732 int tmp;
734 if (!dio_get_uint8(din, &tmp)) {
735 return FALSE;
738 if (tmp > 0x7f) {
739 tmp -= 0x100;
741 *dest = tmp;
742 return TRUE;
745 /**************************************************************************
746 Take value from 16 bits.
747 **************************************************************************/
748 bool dio_get_sint16(struct data_in *din, int *dest)
750 int tmp;
752 if (!dio_get_uint16(din, &tmp)) {
753 return FALSE;
756 if (tmp > 0x7fff) {
757 tmp -= 0x10000;
759 *dest = tmp;
760 return TRUE;
763 /**************************************************************************
764 Take value from 32 bits.
765 **************************************************************************/
766 bool dio_get_sint32(struct data_in *din, int *dest)
768 int tmp;
770 if (!dio_get_uint32(din, &tmp)) {
771 return FALSE;
774 #if SIZEOF_INT != 4
775 if (tmp > 0x7fffffff) {
776 tmp -= 0x100000000;
778 #endif
780 *dest = tmp;
781 return TRUE;
784 /**************************************************************************
785 Take memory block directly.
786 **************************************************************************/
787 bool dio_get_memory(struct data_in *din, void *dest, size_t dest_size)
789 if (!enough_data(din, dest_size)) {
790 log_packet("Got too short memory");
791 return FALSE;
794 memcpy(dest, ADD_TO_POINTER(din->src, din->current), dest_size);
795 din->current += dest_size;
796 return TRUE;
799 /**************************************************************************
800 Take string. Conversion callback is used.
801 **************************************************************************/
802 bool dio_get_string(struct data_in *din, char *dest, size_t max_dest_size)
804 char *c;
805 size_t offset, remaining;
807 fc_assert(max_dest_size > 0);
809 if (!enough_data(din, 1)) {
810 log_packet("Got a bad string");
811 return FALSE;
814 remaining = dio_input_remaining(din);
815 c = ADD_TO_POINTER(din->src, din->current);
817 /* avoid using strlen (or strcpy) on an (unsigned char*) --dwp */
818 for (offset = 0; offset < remaining && c[offset] != '\0'; offset++) {
819 /* nothing */
822 if (offset >= remaining) {
823 log_packet("Got a too short string");
824 return FALSE;
827 if (!(*get_conv_callback) (dest, max_dest_size, c, offset)) {
828 log_packet("Got a bad encoded string");
829 return FALSE;
832 din->current += offset + 1;
833 return TRUE;
836 /**************************************************************************
837 Take tech numbers until A_LAST encountered, or MAX_NUM_TECH_LIST techs
838 retrieved.
839 **************************************************************************/
840 bool dio_get_tech_list(struct data_in *din, int *dest)
842 int i;
844 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
845 if (!dio_get_uint8(din, &dest[i])) {
846 log_packet("Got a too short tech list");
847 return FALSE;
849 if (dest[i] == A_LAST) {
850 break;
854 for (; i < MAX_NUM_TECH_LIST; i++) {
855 dest[i] = A_LAST;
858 return TRUE;
861 /**************************************************************************
862 Take unit type numbers until U_LAST encountered, or MAX_NUM_UNIT_LIST
863 types retrieved.
864 **************************************************************************/
865 bool dio_get_unit_list(struct data_in *din, int *dest)
867 int i;
869 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
870 if (!dio_get_uint8(din, &dest[i])) {
871 log_packet("Got a too short unit list");
872 return FALSE;
874 if (dest[i] == U_LAST) {
875 break;
879 for (; i < MAX_NUM_UNIT_LIST; i++) {
880 dest[i] = U_LAST;
883 return TRUE;
886 /**************************************************************************
887 Take building type numbers until B_LAST encountered, or
888 MAX_NUM_BUILDING_LIST types retrieved.
889 **************************************************************************/
890 bool dio_get_building_list(struct data_in *din, int *dest)
892 int i;
894 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
895 if (!dio_get_uint8(din, &dest[i])) {
896 log_packet("Got a too short building list");
897 return FALSE;
899 if (dest[i] == B_LAST) {
900 break;
904 for (; i < MAX_NUM_BUILDING_LIST; i++) {
905 dest[i] = B_LAST;
908 return TRUE;
911 /**************************************************************************
912 Take worklist item count and then kind and number for each item, and
913 put them to provided worklist.
914 **************************************************************************/
915 bool dio_get_worklist(struct data_in *din, struct worklist *pwl)
917 int i, length;
919 worklist_init(pwl);
921 if (!dio_get_uint8(din, &length)) {
922 log_packet("Got a bad worklist");
923 return FALSE;
926 for (i = 0; i < length; i++) {
927 int identifier;
928 int kind;
929 struct universal univ;
931 if (!dio_get_uint8(din, &kind)
932 || !dio_get_uint8(din, &identifier)) {
933 log_packet("Got a too short worklist");
934 return FALSE;
938 * FIXME: the value returned by universal_by_number() should be checked!
940 univ = universal_by_number(kind, identifier);
941 worklist_append(pwl, &univ);
944 return TRUE;
947 /**************************************************************************
948 Take vector of 8 bit values and insert stop_value after them. stop_value
949 does not need to fit in 8 bits.
950 **************************************************************************/
951 bool dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value)
953 int count, inx;
954 int *vec;
956 if (!dio_get_uint8(din, &count)) {
957 return FALSE;
960 vec = fc_calloc(count + 1, sizeof(*vec));
961 for (inx = 0; inx < count; inx++) {
962 if (!dio_get_uint8(din, vec + inx)) {
963 free (vec);
964 return FALSE;
967 vec[inx] = stop_value;
968 *values = vec;
970 return TRUE;
973 /**************************************************************************
974 Receive vector of uint6 values.
975 **************************************************************************/
976 bool dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value)
978 int count, inx;
979 int *vec;
981 if (!dio_get_uint8(din, &count)) {
982 return FALSE;
985 vec = fc_calloc(count + 1, sizeof(*vec));
986 for (inx = 0; inx < count; inx++) {
987 if (!dio_get_uint16(din, vec + inx)) {
988 free (vec);
989 return FALSE;
992 vec[inx] = stop_value;
993 *values = vec;
995 return TRUE;
998 /**************************************************************************
999 De-serialize an action probability.
1000 **************************************************************************/
1001 bool dio_get_action_probability(struct data_in *din,
1002 struct act_prob *aprob)
1004 int min, max;
1006 if (!dio_get_uint8(din, &min)
1007 || !dio_get_uint8(din, &max)) {
1008 log_packet("Got a bad action probability");
1009 return FALSE;
1012 aprob->min = min;
1013 aprob->max = max;
1015 return TRUE;
1018 /**************************************************************************
1019 Serialize an action probability.
1020 **************************************************************************/
1021 void dio_put_action_probability(struct data_out *dout,
1022 const struct act_prob *aprob)
1024 dio_put_uint8(dout, aprob->min);
1025 dio_put_uint8(dout, aprob->max);
1028 /**************************************************************************
1029 De-serialize a requirement.
1030 **************************************************************************/
1031 bool dio_get_requirement(struct data_in *din, struct requirement *preq)
1033 int type, range, value;
1034 bool survives, present, quiet;
1036 if (!dio_get_uint8(din, &type)
1037 || !dio_get_sint32(din, &value)
1038 || !dio_get_uint8(din, &range)
1039 || !dio_get_bool8(din, &survives)
1040 || !dio_get_bool8(din, &present)
1041 || !dio_get_bool8(din, &quiet)) {
1042 log_packet("Got a bad requirement");
1043 return FALSE;
1047 * FIXME: the value returned by req_from_values() should be checked!
1049 *preq = req_from_values(type, range, survives, present, quiet, value);
1051 return TRUE;
1054 /**************************************************************************
1055 Serialize a requirement.
1056 **************************************************************************/
1057 void dio_put_requirement(struct data_out *dout, const struct requirement *preq)
1059 int type, range, value;
1060 bool survives, present, quiet;
1062 req_get_values(preq, &type, &range, &survives, &present, &quiet, &value);
1064 dio_put_uint8(dout, type);
1065 dio_put_sint32(dout, value);
1066 dio_put_uint8(dout, range);
1067 dio_put_bool8(dout, survives);
1068 dio_put_bool8(dout, present);
1069 dio_put_bool8(dout, quiet);