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)
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
23 #include <fc_config.h>
26 #include "fc_prehdrs.h"
35 #ifdef FREECIV_HAVE_SYS_TYPES_H
36 #include <sys/types.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 #include <sys/socket.h>
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
44 #ifdef HAVE_ARPA_INET_H
45 #include <arpa/inet.h>
49 #include "bitvector.h"
50 #include "capability.h"
58 #include "requirements.h"
64 static bool get_conv(char *dst
, size_t ndst
, const char *src
,
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
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_)); \
85 log_error(_format_, ## __VA_ARGS__); \
87 #else /* FIELD_RANGE_ASSERT */
88 #define FIELD_RANGE_TEST(_test_, _action_, _format_, ...) \
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
,
110 size_t len
= nsrc
; /* length to copy, not including null */
113 if (ndst
> 0 && len
>= ndst
) {
118 memcpy(dst
, src
, len
);
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
;
141 dout
->used
= MAX(dout
->used
, dout
->current
+ size
);
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
157 **************************************************************************/
158 void dio_output_init(struct data_out
*dout
, void *destination
,
161 dout
->dest
= destination
;
162 dout
->dest_size
= dest_size
;
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
)
176 /**************************************************************************
177 Rewinds the stream so that the put-functions start from the
179 **************************************************************************/
180 void dio_output_rewind(struct data_out
*dout
)
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
)
192 din
->src_size
= src_size
;
196 /**************************************************************************
197 Rewinds the stream so that the get-functions start from the
199 **************************************************************************/
200 void dio_input_rewind(struct data_in
*din
)
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
)
232 fc_assert_msg(FALSE
, "data_type %d not handled.", type
);
236 /**************************************************************************
238 **************************************************************************/
239 bool dio_input_skip(struct data_in
*din
, size_t size
)
241 if (enough_data(din
, size
)) {
242 din
->current
+= size
;
249 /**************************************************************************
250 Insert value using 8 bits. May overflow.
251 **************************************************************************/
252 void dio_put_uint8(struct data_out
*dout
, int 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.",
262 if (enough_space(dout
, 1)) {
263 memcpy(ADD_TO_POINTER(dout
->dest
, dout
->current
), &x
, 1);
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);
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);
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
)
313 dio_put_uint8(dout
, value
);
316 dio_put_uint16(dout
, value
);
319 dio_put_uint32(dout
, value
);
322 dio_put_sint8(dout
, value
);
325 dio_put_sint16(dout
, value
);
328 dio_put_sint32(dout
, value
);
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
)
359 dio_put_uint32(dout
, value
);
361 dio_put_uint32(dout
, (0 <= value
? value
: value
+ 0x100000000));
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",
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
)
433 for (count
= 0; values
[count
] != stop_value
; count
++) {
437 if (enough_space(dout
, 1 + count
)) {
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
)
457 for (count
= 0; values
[count
] != stop_value
; count
++) {
461 if (enough_space(dout
, 1 + 2 * count
)) {
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
) {
492 if ((buffer
= (*put_conv_callback
) (value
, &length
))) {
493 dio_put_memory(dout
, buffer
, length
+ 1);
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
)
509 for (i
= 0; i
< MAX_NUM_TECH_LIST
; i
++) {
510 dio_put_uint8(dout
, value
[i
]);
511 if (value
[i
] == A_LAST
) {
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
)
525 for (i
= 0; i
< MAX_NUM_UNIT_LIST
; i
++) {
526 dio_put_uint8(dout
, value
[i
]);
527 if (value
[i
] == U_LAST
) {
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
)
541 for (i
= 0; i
< MAX_NUM_BUILDING_LIST
; i
++) {
542 dio_put_uint8(dout
, value
[i
]);
543 if (value
[i
] == B_LAST
) {
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
)
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");
581 memcpy(&x
, ADD_TO_POINTER(din
->src
, din
->current
), 1);
587 /**************************************************************************
588 Receive uint16 value to dest.
589 **************************************************************************/
590 bool dio_get_uint16(struct data_in
*din
, int *dest
)
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");
602 memcpy(&x
, ADD_TO_POINTER(din
->src
, din
->current
), 2);
608 /**************************************************************************
609 Receive uint32 value to dest.
610 **************************************************************************/
611 bool dio_get_uint32(struct data_in
*din
, int *dest
)
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");
623 memcpy(&x
, ADD_TO_POINTER(din
->src
, din
->current
), 4);
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
)
636 return dio_get_uint8(din
, dest
);
638 return dio_get_uint16(din
, dest
);
640 return dio_get_uint32(din
, dest
);
642 return dio_get_sint8(din
, dest
);
644 return dio_get_sint16(din
, dest
);
646 return dio_get_sint32(din
, dest
);
651 fc_assert_msg(FALSE
, "data_type %d not handled.", type
);
655 /**************************************************************************
656 Take boolean value from 8 bits.
657 **************************************************************************/
658 bool dio_get_bool8(struct data_in
*din
, bool *dest
)
662 if (!dio_get_uint8(din
, &ival
)) {
666 if (ival
!= 0 && ival
!= 1) {
667 log_packet("Got a bad boolean: %d", ival
);
675 /**************************************************************************
676 Take boolean value from 32 bits.
677 **************************************************************************/
678 bool dio_get_bool32(struct data_in
*din
, bool * dest
)
682 if (!dio_get_uint32(din
, &ival
)) {
686 if (ival
!= 0 && ival
!= 1) {
687 log_packet("Got a bad boolean: %d", ival
);
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
)
703 if (!dio_get_uint32(din
, &ival
)) {
707 *dest
= (float) ival
/ float_factor
;
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
)
719 if (!dio_get_sint32(din
, &ival
)) {
723 *dest
= (float) ival
/ float_factor
;
727 /**************************************************************************
728 Take value from 8 bits.
729 **************************************************************************/
730 bool dio_get_sint8(struct data_in
*din
, int *dest
)
734 if (!dio_get_uint8(din
, &tmp
)) {
745 /**************************************************************************
746 Take value from 16 bits.
747 **************************************************************************/
748 bool dio_get_sint16(struct data_in
*din
, int *dest
)
752 if (!dio_get_uint16(din
, &tmp
)) {
763 /**************************************************************************
764 Take value from 32 bits.
765 **************************************************************************/
766 bool dio_get_sint32(struct data_in
*din
, int *dest
)
770 if (!dio_get_uint32(din
, &tmp
)) {
775 if (tmp
> 0x7fffffff) {
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");
794 memcpy(dest
, ADD_TO_POINTER(din
->src
, din
->current
), dest_size
);
795 din
->current
+= dest_size
;
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
)
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");
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
++) {
822 if (offset
>= remaining
) {
823 log_packet("Got a too short string");
827 if (!(*get_conv_callback
) (dest
, max_dest_size
, c
, offset
)) {
828 log_packet("Got a bad encoded string");
832 din
->current
+= offset
+ 1;
836 /**************************************************************************
837 Take tech numbers until A_LAST encountered, or MAX_NUM_TECH_LIST techs
839 **************************************************************************/
840 bool dio_get_tech_list(struct data_in
*din
, int *dest
)
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");
849 if (dest
[i
] == A_LAST
) {
854 for (; i
< MAX_NUM_TECH_LIST
; i
++) {
861 /**************************************************************************
862 Take unit type numbers until U_LAST encountered, or MAX_NUM_UNIT_LIST
864 **************************************************************************/
865 bool dio_get_unit_list(struct data_in
*din
, int *dest
)
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");
874 if (dest
[i
] == U_LAST
) {
879 for (; i
< MAX_NUM_UNIT_LIST
; i
++) {
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
)
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");
899 if (dest
[i
] == B_LAST
) {
904 for (; i
< MAX_NUM_BUILDING_LIST
; i
++) {
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
)
921 if (!dio_get_uint8(din
, &length
)) {
922 log_packet("Got a bad worklist");
926 for (i
= 0; i
< length
; i
++) {
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");
938 * FIXME: the value returned by universal_by_number() should be checked!
940 univ
= universal_by_number(kind
, identifier
);
941 worklist_append(pwl
, &univ
);
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
)
956 if (!dio_get_uint8(din
, &count
)) {
960 vec
= fc_calloc(count
+ 1, sizeof(*vec
));
961 for (inx
= 0; inx
< count
; inx
++) {
962 if (!dio_get_uint8(din
, vec
+ inx
)) {
967 vec
[inx
] = stop_value
;
973 /**************************************************************************
974 Receive vector of uint6 values.
975 **************************************************************************/
976 bool dio_get_uint16_vec8(struct data_in
*din
, int **values
, int stop_value
)
981 if (!dio_get_uint8(din
, &count
)) {
985 vec
= fc_calloc(count
+ 1, sizeof(*vec
));
986 for (inx
= 0; inx
< count
; inx
++) {
987 if (!dio_get_uint16(din
, vec
+ inx
)) {
992 vec
[inx
] = stop_value
;
998 /**************************************************************************
999 De-serialize an action probability.
1000 **************************************************************************/
1001 bool dio_get_action_probability(struct data_in
*din
,
1002 struct act_prob
*aprob
)
1006 if (!dio_get_uint8(din
, &min
)
1007 || !dio_get_uint8(din
, &max
)) {
1008 log_packet("Got a bad action probability");
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");
1047 * FIXME: the value returned by req_from_values() should be checked!
1049 *preq
= req_from_values(type
, range
, survives
, present
, quiet
, value
);
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
);