Prettify long option values in /show output.
[freeciv.git] / common / dataio.c
blob399bb84073aaed2bf26ad40d6f077206f106c933
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 <limits.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38 #ifdef HAVE_NETINET_IN_H
39 #include <netinet/in.h>
40 #endif
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
43 #endif
44 #ifdef HAVE_WINSOCK
45 #include <winsock.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 /**************************************************************************
71 Sets string conversion callback to be used when putting text.
72 **************************************************************************/
73 void dio_set_put_conv_callback(DIO_PUT_CONV_FUN fun)
75 put_conv_callback = fun;
78 /**************************************************************************
79 Returns FALSE if the destination isn't large enough or the source was
80 bad. This is default get_conv_callback.
81 **************************************************************************/
82 static bool get_conv(char *dst, size_t ndst, const char *src,
83 size_t nsrc)
85 size_t len = nsrc; /* length to copy, not including null */
86 bool ret = TRUE;
88 if (ndst > 0 && len >= ndst) {
89 ret = FALSE;
90 len = ndst - 1;
93 memcpy(dst, src, len);
94 dst[len] = '\0';
96 return ret;
99 /**************************************************************************
100 Sets string conversion callback to use when getting text.
101 **************************************************************************/
102 void dio_set_get_conv_callback(DIO_GET_CONV_FUN fun)
104 get_conv_callback = fun;
107 /**************************************************************************
108 Returns TRUE iff the output has size bytes available.
109 **************************************************************************/
110 static bool enough_space(struct data_out *dout, size_t size)
112 if (dout->current + size > dout->dest_size) {
113 dout->too_short = TRUE;
114 return FALSE;
115 } else {
116 dout->used = MAX(dout->used, dout->current + size);
117 return TRUE;
121 /**************************************************************************
122 Returns TRUE iff the input contains size unread bytes.
123 **************************************************************************/
124 static bool enough_data(struct data_in *din, size_t size)
126 return dio_input_remaining(din) >= size;
129 /**************************************************************************
130 Initializes the output to the given output buffer and the given
131 buffer size.
132 **************************************************************************/
133 void dio_output_init(struct data_out *dout, void *destination,
134 size_t dest_size)
136 dout->dest = destination;
137 dout->dest_size = dest_size;
138 dout->current = 0;
139 dout->used = 0;
140 dout->too_short = FALSE;
143 /**************************************************************************
144 Return the maximum number of bytes used.
145 **************************************************************************/
146 size_t dio_output_used(struct data_out *dout)
148 return dout->used;
151 /**************************************************************************
152 Rewinds the stream so that the put-functions start from the
153 beginning.
154 **************************************************************************/
155 void dio_output_rewind(struct data_out *dout)
157 dout->current = 0;
160 /**************************************************************************
161 Initializes the input to the given input buffer and the given
162 number of valid input bytes.
163 **************************************************************************/
164 void dio_input_init(struct data_in *din, const void *src, size_t src_size)
166 din->src = src;
167 din->src_size = src_size;
168 din->current = 0;
171 /**************************************************************************
172 Rewinds the stream so that the get-functions start from the
173 beginning.
174 **************************************************************************/
175 void dio_input_rewind(struct data_in *din)
177 din->current = 0;
180 /**************************************************************************
181 Return the number of unread bytes.
182 **************************************************************************/
183 size_t dio_input_remaining(struct data_in *din)
185 return din->src_size - din->current;
188 /**************************************************************************
189 Return the size of the data_type in bytes.
190 **************************************************************************/
191 size_t data_type_size(enum data_type type)
193 switch (type) {
194 case DIOT_UINT8:
195 case DIOT_SINT8:
196 return 1;
197 case DIOT_UINT16:
198 case DIOT_SINT16:
199 return 2;
200 case DIOT_UINT32:
201 case DIOT_SINT32:
202 return 4;
203 case DIOT_LAST:
204 break;
207 fc_assert_msg(FALSE, "data_type %d not handled.", type);
208 return 0;
211 /**************************************************************************
212 Skips 'n' bytes.
213 **************************************************************************/
214 bool dio_input_skip(struct data_in *din, size_t size)
216 if (enough_data(din, size)) {
217 din->current += size;
218 return TRUE;
219 } else {
220 return FALSE;
224 /**************************************************************************
225 Insert value using 8 bits. May overflow.
226 **************************************************************************/
227 void dio_put_uint8(struct data_out *dout, int value)
229 if (value < 0x00 || 0xff < value) {
230 log_error("Trying to put %d into 8 bits", value);
233 if (enough_space(dout, 1)) {
234 uint8_t x = value;
236 FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_1_byte);
237 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 1);
238 dout->current++;
242 /**************************************************************************
243 Insert value using 16 bits. May overflow.
244 **************************************************************************/
245 void dio_put_uint16(struct data_out *dout, int value)
247 if (value < 0x0000 || 0xffff < value) {
248 log_error("Trying to put %d into 16 bits", value);
251 if (enough_space(dout, 2)) {
252 uint16_t x = htons(value);
254 FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);
255 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 2);
256 dout->current += 2;
260 /**************************************************************************
261 Insert value using 32 bits. May overflow.
262 **************************************************************************/
263 void dio_put_uint32(struct data_out *dout, int value)
265 if (sizeof(value) > 4 && (value < 0x00000000 || 0xffffffff < value)) {
266 log_error("Trying to put %d into 32 bits", value);
269 if (enough_space(dout, 4)) {
270 uint32_t x = htonl(value);
272 FC_STATIC_ASSERT(sizeof(x) == 4, uint32_not_4_bytes);
273 memcpy(ADD_TO_POINTER(dout->dest, dout->current), &x, 4);
274 dout->current += 4;
278 /**************************************************************************
279 Insert value using 'size' bits. May overflow.
280 **************************************************************************/
281 void dio_put_type(struct data_out *dout, enum data_type type, int value)
283 switch (type) {
284 case DIOT_UINT8:
285 dio_put_uint8(dout, value);
286 return;
287 case DIOT_UINT16:
288 dio_put_uint16(dout, value);
289 return;
290 case DIOT_UINT32:
291 dio_put_uint32(dout, value);
292 return;
293 case DIOT_SINT8:
294 dio_put_sint8(dout, value);
295 return;
296 case DIOT_SINT16:
297 dio_put_sint16(dout, value);
298 return;
299 case DIOT_SINT32:
300 dio_put_sint32(dout, value);
301 return;
302 case DIOT_LAST:
303 break;
306 fc_assert_msg(FALSE, "data_type %d not handled.", type);
309 /**************************************************************************
310 Insert value using 8 bits. May overflow.
311 **************************************************************************/
312 void dio_put_sint8(struct data_out *dout, int value)
314 dio_put_uint8(dout, 0 <= value ? value : value + 0x100);
317 /**************************************************************************
318 Insert value using 16 bits. May overflow.
319 **************************************************************************/
320 void dio_put_sint16(struct data_out *dout, int value)
322 dio_put_uint16(dout, 0 <= value ? value : value + 0x10000);
325 /**************************************************************************
326 Insert value using 32 bits. May overflow.
327 **************************************************************************/
328 void dio_put_sint32(struct data_out *dout, int value)
330 #if SIZEOF_INT == 4
331 dio_put_uint32(dout, value);
332 #else
333 dio_put_uint32(dout, (0 <= value ? value : value + 0x100000000));
334 #endif
337 /**************************************************************************
338 Insert value 0 or 1 using 8 bits.
339 **************************************************************************/
340 void dio_put_bool8(struct data_out *dout, bool value)
342 if (value != TRUE && value != FALSE) {
343 log_error("Trying to put a non-boolean: %d", (int) value);
344 value = FALSE;
347 dio_put_uint8(dout, value ? 1 : 0);
350 /**************************************************************************
351 Insert value 0 or 1 using 32 bits.
352 **************************************************************************/
353 void dio_put_bool32(struct data_out *dout, bool value)
355 if (value != TRUE && value != FALSE) {
356 log_error("Trying to put a non-boolean: %d", (int) value);
357 value = FALSE;
360 dio_put_uint32(dout, value ? 1 : 0);
363 /**************************************************************************
364 Insert a float number, which is multiplied by 'float_factor' before
365 being encoded into a uint32.
366 **************************************************************************/
367 void dio_put_float(struct data_out *dout, float value, int float_factor)
369 dio_put_uint32(dout, value * float_factor);
372 /**************************************************************************
373 Insert number of values brefore stop_value using 8 bits. Then
374 insert values using 8 bits for each. stop_value is not required to
375 fit in 8 bits. Actual values may overflow.
376 **************************************************************************/
377 void dio_put_uint8_vec8(struct data_out *dout, int *values, int stop_value)
379 size_t count;
381 for (count = 0; values[count] != stop_value; count++) {
382 /* nothing */
385 if (enough_space(dout, 1 + count)) {
386 size_t i;
388 dio_put_uint8(dout, count);
390 for (i = 0; i < count; i++) {
391 dio_put_uint8(dout, values[i]);
396 /**************************************************************************
397 Insert number of values brefore stop_value using 8 bits. Then
398 insert values using 16 bits for each. stop_value is not required to
399 fit in 16 bits. Actual values may overflow.
400 **************************************************************************/
401 void dio_put_uint16_vec8(struct data_out *dout, int *values, int stop_value)
403 size_t count;
405 for (count = 0; values[count] != stop_value; count++) {
406 /* nothing */
409 if (enough_space(dout, 1 + 2 * count)) {
410 size_t i;
412 dio_put_uint8(dout, count);
414 for (i = 0; i < count; i++) {
415 dio_put_uint16(dout, values[i]);
420 /**************************************************************************
421 Insert block directly from memory.
422 **************************************************************************/
423 void dio_put_memory(struct data_out *dout, const void *value, size_t size)
425 if (enough_space(dout, size)) {
426 memcpy(ADD_TO_POINTER(dout->dest, dout->current), value, size);
427 dout->current += size;
431 /**************************************************************************
432 Insert NULL-terminated string. Conversion callback is used if set.
433 **************************************************************************/
434 void dio_put_string(struct data_out *dout, const char *value)
436 if (put_conv_callback) {
437 size_t length;
438 char *buffer;
440 if ((buffer = (*put_conv_callback) (value, &length))) {
441 dio_put_memory(dout, buffer, length + 1);
442 free(buffer);
444 } else {
445 dio_put_memory(dout, value, strlen(value) + 1);
449 /**************************************************************************
450 Insert tech numbers from value array as 8 bit values until there is value
451 A_LAST or MAX_NUM_TECH_LIST tech numbers have been inserted.
452 **************************************************************************/
453 void dio_put_tech_list(struct data_out *dout, const int *value)
455 int i;
457 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
458 dio_put_uint8(dout, value[i]);
459 if (value[i] == A_LAST) {
460 break;
465 /**************************************************************************
466 Insert unit type numbers from value array as 8 bit values until there is
467 value U_LAST or MAX_NUM_UNIT_LIST numbers have been inserted.
468 **************************************************************************/
469 void dio_put_unit_list(struct data_out *dout, const int *value)
471 int i;
473 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
474 dio_put_uint8(dout, value[i]);
475 if (value[i] == U_LAST) {
476 break;
481 /**************************************************************************
482 Insert building type numbers from value array as 8 bit values until there
483 is value B_LAST or MAX_NUM_BUILDING_LIST numbers have been inserted.
484 **************************************************************************/
485 void dio_put_building_list(struct data_out *dout, const int *value)
487 int i;
489 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
490 dio_put_uint8(dout, value[i]);
491 if (value[i] == B_LAST) {
492 break;
497 /**************************************************************************
498 Insert number of worklist items as 8 bit value and then insert
499 8 bit kind and 8 bit number for each worklist item.
500 **************************************************************************/
501 void dio_put_worklist(struct data_out *dout, const struct worklist *pwl)
503 int i, length = worklist_length(pwl);
505 dio_put_uint8(dout, length);
506 for (i = 0; i < length; i++) {
507 const struct universal *pcp = &(pwl->entries[i]);
509 dio_put_uint8(dout, pcp->kind);
510 dio_put_uint8(dout, universal_number(pcp));
514 /**************************************************************************
515 Receive uint8 value to dest.
516 **************************************************************************/
517 bool dio_get_uint8(struct data_in *din, int *dest)
519 uint8_t x;
521 FC_STATIC_ASSERT(sizeof(x) == 1, uint8_not_byte);
523 if (!enough_data(din, 1)) {
524 log_packet("Packet too short to read 1 byte");
526 return FALSE;
529 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 1);
530 *dest = x;
531 din->current++;
532 return TRUE;
535 /**************************************************************************
536 Receive uint16 value to dest.
537 **************************************************************************/
538 bool dio_get_uint16(struct data_in *din, int *dest)
540 uint16_t x;
542 FC_STATIC_ASSERT(sizeof(x) == 2, uint16_not_2_bytes);
544 if (!enough_data(din, 2)) {
545 log_packet("Packet too short to read 2 bytes");
547 return FALSE;
550 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 2);
551 *dest = ntohs(x);
552 din->current += 2;
553 return TRUE;
556 /**************************************************************************
557 Receive uint32 value to dest.
558 **************************************************************************/
559 bool dio_get_uint32(struct data_in *din, int *dest)
561 uint32_t x;
563 FC_STATIC_ASSERT(sizeof(x) == 4, uint32_not_4_bytes);
565 if (!enough_data(din, 4)) {
566 log_packet("Packet too short to read 4 bytes");
568 return FALSE;
571 memcpy(&x, ADD_TO_POINTER(din->src, din->current), 4);
572 *dest = ntohl(x);
573 din->current += 4;
574 return TRUE;
577 /**************************************************************************
578 Receive value using 'size' bits to dest.
579 **************************************************************************/
580 bool dio_get_type(struct data_in *din, enum data_type type, int *dest)
582 switch (type) {
583 case DIOT_UINT8:
584 return dio_get_uint8(din, dest);
585 case DIOT_UINT16:
586 return dio_get_uint16(din, dest);
587 case DIOT_UINT32:
588 return dio_get_uint32(din, dest);
589 case DIOT_SINT8:
590 return dio_get_sint8(din, dest);
591 case DIOT_SINT16:
592 return dio_get_sint16(din, dest);
593 case DIOT_SINT32:
594 return dio_get_sint32(din, dest);
595 case DIOT_LAST:
596 break;
599 fc_assert_msg(FALSE, "data_type %d not handled.", type);
600 return FALSE;
603 /**************************************************************************
604 Take boolean value from 8 bits.
605 **************************************************************************/
606 bool dio_get_bool8(struct data_in *din, bool *dest)
608 int ival;
610 if (!dio_get_uint8(din, &ival)) {
611 return FALSE;
614 if (ival != 0 && ival != 1) {
615 log_packet("Got a bad boolean: %d", ival);
616 return FALSE;
619 *dest = (ival != 0);
620 return TRUE;
623 /**************************************************************************
624 Take boolean value from 32 bits.
625 **************************************************************************/
626 bool dio_get_bool32(struct data_in *din, bool * dest)
628 int ival;
630 if (!dio_get_uint32(din, &ival)) {
631 return FALSE;
634 if (ival != 0 && ival != 1) {
635 log_packet("Got a bad boolean: %d", ival);
636 return FALSE;
639 *dest = (ival != 0);
640 return TRUE;
643 /**************************************************************************
644 Get a float number, which have been multiplied by 'float_factor' and
645 encoded into a uint32 by dio_put_float().
646 **************************************************************************/
647 bool dio_get_float(struct data_in *din, float *dest, int float_factor)
649 int ival;
651 if (!dio_get_uint32(din, &ival)) {
652 return FALSE;
655 *dest = (float) ival / float_factor;
656 return TRUE;
659 /**************************************************************************
660 Take value from 8 bits.
661 **************************************************************************/
662 bool dio_get_sint8(struct data_in *din, int *dest)
664 int tmp;
666 if (!dio_get_uint8(din, &tmp)) {
667 return FALSE;
670 if (tmp > 0x7f) {
671 tmp -= 0x100;
673 *dest = tmp;
674 return TRUE;
677 /**************************************************************************
678 Take value from 16 bits.
679 **************************************************************************/
680 bool dio_get_sint16(struct data_in *din, int *dest)
682 int tmp;
684 if (!dio_get_uint16(din, &tmp)) {
685 return FALSE;
688 if (tmp > 0x7fff) {
689 tmp -= 0x10000;
691 *dest = tmp;
692 return TRUE;
695 /**************************************************************************
696 Take value from 32 bits.
697 **************************************************************************/
698 bool dio_get_sint32(struct data_in *din, int *dest)
700 int tmp;
702 if (!dio_get_uint32(din, &tmp)) {
703 return FALSE;
706 #if SIZEOF_INT != 4
707 if (tmp > 0x7fffffff) {
708 tmp -= 0x100000000;
710 #endif
712 *dest = tmp;
713 return TRUE;
716 /**************************************************************************
717 Take memory block directly.
718 **************************************************************************/
719 bool dio_get_memory(struct data_in *din, void *dest, size_t dest_size)
721 if (!enough_data(din, dest_size)) {
722 log_packet("Got too short memory");
723 return FALSE;
726 memcpy(dest, ADD_TO_POINTER(din->src, din->current), dest_size);
727 din->current += dest_size;
728 return TRUE;
731 /**************************************************************************
732 Take string. Conversion callback is used.
733 **************************************************************************/
734 bool dio_get_string(struct data_in *din, char *dest, size_t max_dest_size)
736 char *c;
737 size_t offset, remaining;
739 fc_assert(max_dest_size > 0);
741 if (!enough_data(din, 1)) {
742 log_packet("Got a bad string");
743 return FALSE;
746 remaining = dio_input_remaining(din);
747 c = ADD_TO_POINTER(din->src, din->current);
749 /* avoid using strlen (or strcpy) on an (unsigned char*) --dwp */
750 for (offset = 0; offset < remaining && c[offset] != '\0'; offset++) {
751 /* nothing */
754 if (offset >= remaining) {
755 log_packet("Got a too short string");
756 return FALSE;
759 if (!(*get_conv_callback) (dest, max_dest_size, c, offset)) {
760 log_packet("Got a bad encoded string");
761 return FALSE;
764 din->current += offset + 1;
765 return TRUE;
768 /**************************************************************************
769 Take tech numbers until A_LAST encountered, or MAX_NUM_TECH_LIST techs
770 retrieved.
771 **************************************************************************/
772 bool dio_get_tech_list(struct data_in *din, int *dest)
774 int i;
776 for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
777 if (!dio_get_uint8(din, &dest[i])) {
778 log_packet("Got a too short tech list");
779 return FALSE;
781 if (dest[i] == A_LAST) {
782 break;
786 for (; i < MAX_NUM_TECH_LIST; i++) {
787 dest[i] = A_LAST;
790 return TRUE;
793 /**************************************************************************
794 Take unit type numbers until U_LAST encountered, or MAX_NUM_UNIT_LIST
795 types retrieved.
796 **************************************************************************/
797 bool dio_get_unit_list(struct data_in *din, int *dest)
799 int i;
801 for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
802 if (!dio_get_uint8(din, &dest[i])) {
803 log_packet("Got a too short unit list");
804 return FALSE;
806 if (dest[i] == U_LAST) {
807 break;
811 for (; i < MAX_NUM_UNIT_LIST; i++) {
812 dest[i] = U_LAST;
815 return TRUE;
818 /**************************************************************************
819 Take building type numbers until B_LAST encountered, or
820 MAX_NUM_BUILDING_LIST types retrieved.
821 **************************************************************************/
822 bool dio_get_building_list(struct data_in *din, int *dest)
824 int i;
826 for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
827 if (!dio_get_uint8(din, &dest[i])) {
828 log_packet("Got a too short building list");
829 return FALSE;
831 if (dest[i] == B_LAST) {
832 break;
836 for (; i < MAX_NUM_BUILDING_LIST; i++) {
837 dest[i] = B_LAST;
840 return TRUE;
843 /**************************************************************************
844 Take worklist item count and then kind and number for each item, and
845 put them to provided worklist.
846 **************************************************************************/
847 bool dio_get_worklist(struct data_in *din, struct worklist *pwl)
849 int i, length;
851 worklist_init(pwl);
853 if (!dio_get_uint8(din, &length)) {
854 log_packet("Got a bad worklist");
855 return FALSE;
858 for (i = 0; i < length; i++) {
859 int identifier;
860 int kind;
862 if (!dio_get_uint8(din, &kind)
863 || !dio_get_uint8(din, &identifier)) {
864 log_packet("Got a too short worklist");
865 return FALSE;
869 * FIXME: the value returned by universal_by_number() should be checked!
871 worklist_append(pwl, universal_by_number(kind, identifier));
874 return TRUE;
877 /**************************************************************************
878 Take vector of 8 bit values and insert stop_value after them. stop_value
879 does not need to fit in 8 bits.
880 **************************************************************************/
881 bool dio_get_uint8_vec8(struct data_in *din, int **values, int stop_value)
883 int count, inx;
884 int *vec;
886 if (!dio_get_uint8(din, &count)) {
887 return FALSE;
890 vec = fc_calloc(count + 1, sizeof(*vec));
891 for (inx = 0; inx < count; inx++) {
892 if (!dio_get_uint8(din, vec + inx)) {
893 free (vec);
894 return FALSE;
897 vec[inx] = stop_value;
898 *values = vec;
900 return TRUE;
903 /**************************************************************************
904 Receive vector of uint6 values.
905 **************************************************************************/
906 bool dio_get_uint16_vec8(struct data_in *din, int **values, int stop_value)
908 int count, inx;
909 int *vec;
911 if (!dio_get_uint8(din, &count)) {
912 return FALSE;
915 vec = fc_calloc(count + 1, sizeof(*vec));
916 for (inx = 0; inx < count; inx++) {
917 if (!dio_get_uint16(din, vec + inx)) {
918 free (vec);
919 return FALSE;
922 vec[inx] = stop_value;
923 *values = vec;
925 return TRUE;
928 /**************************************************************************
929 De-serialize a requirement.
930 **************************************************************************/
931 bool dio_get_requirement(struct data_in *din, struct requirement *preq)
933 int type, range, value;
934 bool survives, negated;
936 if (!dio_get_uint8(din, &type)
937 || !dio_get_sint32(din, &value)
938 || !dio_get_uint8(din, &range)
939 || !dio_get_bool8(din, &survives)
940 || !dio_get_bool8(din, &negated)) {
941 log_packet("Got a bad requirement");
942 return FALSE;
946 * FIXME: the value returned by req_from_values() should be checked!
948 *preq = req_from_values(type, range, survives, negated, value);
950 return TRUE;
953 /**************************************************************************
954 Serialize a requirement.
955 **************************************************************************/
956 void dio_put_requirement(struct data_out *dout, const struct requirement *preq)
958 int type, range, value;
959 bool survives, negated;
961 req_get_values(preq, &type, &range, &survives, &negated, &value);
963 dio_put_uint8(dout, type);
964 dio_put_sint32(dout, value);
965 dio_put_uint8(dout, range);
966 dio_put_bool8(dout, survives);
967 dio_put_bool8(dout, negated);