Freeciv-3.1
Loading...
Searching...
No Matches
dataio_json.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#ifdef FREECIV_JSON_CONNECTION
19
20#include "fc_prehdrs.h"
21
22#include <curl/curl.h>
23
24#include <limits.h>
25#include <math.h>
26#include <stdint.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#ifdef FREECIV_HAVE_SYS_TYPES_H
32#include <sys/types.h>
33#endif
34#ifdef HAVE_SYS_SOCKET_H
35#include <sys/socket.h>
36#endif
37#ifdef HAVE_NETINET_IN_H
38#include <netinet/in.h>
39#endif
40#ifdef HAVE_ARPA_INET_H
41#include <arpa/inet.h>
42#endif
43
44/* utility */
45#include "bitvector.h"
46#include "capability.h"
47#include "log.h"
48#include "mem.h"
49#include "support.h"
50
51/* common */
52#include "events.h"
53#include "player.h"
54#include "requirements.h"
55#include "tech.h"
56#include "worklist.h"
57
58/* common/aicore */
59#include "cm.h"
60
61#include "dataio.h"
62
63static bool dio_get_bool8_json_internal(json_t *json_packet,
64 const struct plocation *location,
65 bool *dest);
66
67/**********************************************************************/
70static CURL *get_curl(void)
71{
72 static CURL *curl_easy_handle = NULL;
73
74 if (curl_easy_handle == NULL) {
75 curl_easy_handle = curl_easy_init();
76 } else {
77 /* Reuse the existing CURL easy handle */
78 curl_easy_reset(curl_easy_handle);
79 }
80
81 return curl_easy_handle;
82}
83
84static void plocation_write_data(json_t *item,
85 const struct plocation *location,
86 json_t *data);
87
88/**********************************************************************/
91static void plocation_write_field(json_t *item,
92 const struct plocation *location,
93 json_t *data)
94{
95 if (location->sub_location == NULL) {
96 json_object_set_new(item, location->name, data);
97 } else {
98 plocation_write_data(json_object_get(item, location->name),
99 location->sub_location, data);
100 }
101}
102
103/**********************************************************************/
106static void plocation_write_elem(json_t *item,
107 const struct plocation *location,
108 json_t *data)
109{
110 if (location->sub_location == NULL) {
111 json_array_set_new(item, location->number, data);
112 } else {
113 plocation_write_data(json_array_get(item, location->number),
114 location->sub_location, data);
115 }
116}
117
118/**********************************************************************/
122static void plocation_write_data(json_t *item,
123 const struct plocation *location,
124 json_t *data)
125{
126 switch (location->kind) {
127 case PADR_FIELD:
128 plocation_write_field(item, location, data);
129 return;
130 case PADR_ELEMENT:
131 plocation_write_elem(item, location, data);
132 return;
133 default:
134 log_error("Unknown packet part location kind.");
135 return;
136 }
137}
138
139static json_t *plocation_read_data(json_t *item,
140 const struct plocation *location);
141
142/**********************************************************************/
145static json_t *plocation_read_field(json_t *item,
146 const struct plocation *location)
147{
148 if (location->sub_location == NULL) {
149 return json_object_get(item, location->name);
150 } else {
151 return plocation_read_data(json_object_get(item, location->name),
152 location->sub_location);
153 }
154}
155
156/**********************************************************************/
159static json_t *plocation_read_elem(json_t *item,
160 const struct plocation *location)
161{
162 if (location->sub_location == NULL) {
163 return json_array_get(item, location->number);
164 } else {
165 return plocation_read_data(json_array_get(item, location->number),
166 location->sub_location);
167 }
168}
169
170/**********************************************************************/
173static json_t *plocation_read_data(json_t *item,
174 const struct plocation *location)
175{
176 switch (location->kind) {
177 case PADR_FIELD:
178 return plocation_read_field(item, location);
179 case PADR_ELEMENT:
180 return plocation_read_elem(item, location);
181 default:
182 log_error("Unknown packet part location kind.");
183 return NULL;
184 }
185}
186
187/**********************************************************************/
190void dio_put_uint8_json(struct json_data_out *dout,
191 const struct plocation *location,
192 int value)
193{
194 if (dout->json) {
195 plocation_write_data(dout->json, location, json_integer(value));
196 } else {
197 dio_put_uint8_raw(&dout->raw, value);
198 }
199}
200
201/**********************************************************************/
204void dio_put_sint8_json(struct json_data_out *dout,
205 const struct plocation *location,
206 int value)
207{
208 if (dout->json) {
209 plocation_write_data(dout->json, location, json_integer(value));
210 } else {
211 dio_put_sint8_raw(&dout->raw, value);
212 }
213}
214
215/**********************************************************************/
218void dio_put_uint16_json(struct json_data_out *dout,
219 const struct plocation *location, int value)
220{
221 if (dout->json) {
222 plocation_write_data(dout->json, location, json_integer(value));
223 } else {
224 dio_put_uint16_raw(&dout->raw, value);
225 }
226}
227
228/**********************************************************************/
231void dio_put_sint16_json(struct json_data_out *dout,
232 const struct plocation *location, int value)
233{
234 if (dout->json) {
235 plocation_write_data(dout->json, location, json_integer(value));
236 } else {
237 dio_put_sint16_raw(&dout->raw, value);
238 }
239}
240
241/**********************************************************************/
245 struct plocation *location,
246 const struct cm_parameter *param)
247{
248 if (dout->json) {
249 json_t *obj = json_object();
250 json_t *min_surplus = json_array();
251 json_t *factor = json_array();
252 int i;
253
254 for (i = 0; i < O_LAST; i++) {
255 json_array_append_new(min_surplus,
256 json_integer(param->minimal_surplus[i]));
257 json_array_append_new(factor,
258 json_integer(param->factor[i]));
259 }
260
261 json_object_set_new(obj, "minimal_surplus", min_surplus);
262 json_object_set_new(obj, "factor", factor);
263 json_object_set_new(obj, "max_growth", json_boolean(param->max_growth));
264 json_object_set_new(obj, "require_happy",
265 json_boolean(param->require_happy));
266 json_object_set_new(obj, "allow_disorder",
267 json_boolean(param->allow_disorder));
268 json_object_set_new(obj, "allow_specialists",
269 json_boolean(param->allow_specialists));
270 json_object_set_new(obj, "happy_factor",
271 json_integer(param->happy_factor));
272 plocation_write_data(dout->json, location, obj);
273 } else {
274 dio_put_cm_parameter_raw(&dout->raw, param);
275 }
276}
277
278/**********************************************************************/
281void dio_put_unit_order_json(struct json_data_out *dout,
282 struct plocation *location,
283 const struct unit_order *order)
284{
285 if (dout->json) {
286 json_t *obj = json_object();
287 json_object_set_new(obj, "order", json_integer(order->order));
288 json_object_set_new(obj, "activity", json_integer(order->activity));
289 json_object_set_new(obj, "target", json_integer(order->target));
290 json_object_set_new(obj, "sub_target", json_integer(order->sub_target));
291 json_object_set_new(obj, "action", json_integer(order->action));
292 if (order->dir == -1) {
293 /* Avoid integer underflow */
294 json_object_set_new(obj, "dir", json_integer(-1));
295 } else {
296 json_object_set_new(obj, "dir", json_integer(order->dir));
297 }
298 plocation_write_data(dout->json, location, obj);
299 } else {
300 dio_put_unit_order_raw(&dout->raw, order);
301 }
302}
303
304/**********************************************************************/
307void dio_put_worklist_json(struct json_data_out *dout,
308 struct plocation *location,
309 const struct worklist *pwl)
310{
311 if (dout->json) {
312 int i;
313 const int size = worklist_length(pwl);
314
315 /* Must create the array before insertion. */
316 dio_put_farray_json(dout, location, size);
317
318 location->sub_location = plocation_elem_new(0);
319
320 for (i = 0; i < size; i++) {
321 const struct universal *pcp = &(pwl->entries[i]);
322 json_t *universal = json_object();
323
324 location->sub_location->number = i;
325
326 json_object_set_new(universal, "kind", json_integer(pcp->kind));
327 json_object_set_new(universal, "value",
328 json_integer(universal_number(pcp)));
329
330 plocation_write_data(dout->json, location, universal);
331 }
332
333 FC_FREE(location->sub_location);
334 } else {
335 dio_put_worklist_raw(&dout->raw, pwl);
336 }
337}
338
339/**********************************************************************/
342static bool dio_get_uint8_json_internal(json_t *json_packet,
343 const struct plocation *location,
344 int *dest)
345{
346 json_t *pint = plocation_read_data(json_packet, location);
347
348 if (!pint) {
349 log_error("ERROR: Unable to get uint8 from location: %s", plocation_name(location));
350 return FALSE;
351 }
352 *dest = json_integer_value(pint);
353
354 if (!dest) {
355 log_error("ERROR: Unable to get unit8 from location: %s", plocation_name(location));
356 return FALSE;
357 }
358
359 return TRUE;
360}
361
362/**********************************************************************/
365bool dio_get_uint8_json(struct connection *pc, struct data_in *din,
366 const struct plocation *location, int *dest)
367{
368 if (pc->json_mode) {
369 return dio_get_uint8_json_internal(pc->json_packet, location, dest);
370 } else {
371 return dio_get_uint8_raw(din, dest);
372 }
373}
374
375/**********************************************************************/
378bool dio_get_uint16_json(struct connection *pc, struct data_in *din,
379 const struct plocation *location, int *dest)
380{
381 if (pc->json_mode) {
382 json_t *pint = plocation_read_data(pc->json_packet, location);
383
384 if (!pint) {
385 log_error("ERROR: Unable to get uint16 from location: %s", plocation_name(location));
386 return FALSE;
387 }
388 *dest = json_integer_value(pint);
389
390 if (!dest) {
391 log_error("ERROR: Unable to get unit16 from location: %s", plocation_name(location));
392 return FALSE;
393 }
394 } else {
395 return dio_get_uint16_raw(din, dest);
396 }
397
398 return TRUE;
399}
400
401/**********************************************************************/
404static bool dio_get_uint32_json_internal(json_t *json_packet,
405 const struct plocation *location,
406 int *dest)
407{
408 json_t *pint = plocation_read_data(json_packet, location);
409
410 if (!pint) {
411 log_error("ERROR: Unable to get uint32 from location: %s", plocation_name(location));
412 return FALSE;
413 }
414 *dest = json_integer_value(pint);
415
416 if (!dest) {
417 log_error("ERROR: Unable to get unit32 from location: %s", plocation_name(location));
418 return FALSE;
419 }
420
421 return TRUE;
422}
423
424/**********************************************************************/
427bool dio_get_uint32_json(struct connection *pc, struct data_in *din,
428 const struct plocation *location, int *dest)
429{
430 if (pc->json_mode) {
431 return dio_get_uint32_json_internal(pc->json_packet, location, dest);
432 } else {
433 return dio_get_uint32_raw(din, dest);
434 }
435}
436
437/**********************************************************************/
440bool dio_get_sint32_json(struct connection *pc, struct data_in *din,
441 const struct plocation *location, int *dest)
442{
443 if (pc->json_mode) {
444 return dio_get_uint32_json_internal(pc->json_packet, location, dest);
445 } else {
446 return dio_get_sint32_raw(din, dest);
447 }
448}
449
450/**********************************************************************/
453bool dio_get_cm_parameter_json(struct connection *pc, struct data_in *din,
454 struct plocation *location,
455 struct cm_parameter *param)
456{
457 if (pc->json_mode) {
458 int i;
459
460 cm_init_parameter(param);
461
462 location->sub_location = plocation_field_new("max_growth");
463 if (!dio_get_bool8_json(pc, din, location, &param->max_growth)) {
464 log_packet("Corrupt cm_parameter.max_growth");
465 FC_FREE(location->sub_location);
466 return FALSE;
467 }
468
469 location->sub_location->name = "require_happy";
470 if (!dio_get_bool8_json(pc, din, location, &param->require_happy)) {
471 log_packet("Corrupt cm_parameter.require_happy");
472 FC_FREE(location->sub_location);
473 return FALSE;
474 }
475
476 location->sub_location->name = "allow_disorder";
477 if (!dio_get_bool8_json(pc, din, location, &param->allow_disorder)) {
478 log_packet("Corrupt cm_parameter.allow_disorder");
479 FC_FREE(location->sub_location);
480 return FALSE;
481 }
482
483 location->sub_location->name = "allow_specialists";
484 if (!dio_get_bool8_json(pc, din, location, &param->allow_specialists)) {
485 log_packet("Corrupt cm_parameter.allow_specialists");
486 FC_FREE(location->sub_location);
487 FC_FREE(location->sub_location);
488 return FALSE;
489 }
490
491 location->sub_location->name = "happy_factor";
492 if (!dio_get_uint16_json(pc, din, location, &param->happy_factor)) {
493 log_packet("Corrupt cm_parameter.happy_factor");
494 FC_FREE(location->sub_location);
495 return FALSE;
496 }
497
498 location->sub_location->name = "factor";
500 for (i = 0; i < O_LAST; i++) {
501 location->sub_location->sub_location->number = i;
502 if (!dio_get_uint16_json(pc, din, location, &param->factor[i])) {
503 log_packet("Corrupt cm_parameter.factor");
505 FC_FREE(location->sub_location);
506 return FALSE;
507 }
508 }
509
510 location->sub_location->name = "minimal_surplus";
511 for (i = 0; i < O_LAST; i++) {
512 location->sub_location->sub_location->number = i;
513 if (!dio_get_sint16_json(pc, din, location,
514 &param->minimal_surplus[i])) {
515 log_packet("Corrupt cm_parameter.minimal_surplus");
517 FC_FREE(location->sub_location);
518 return FALSE;
519 }
520 }
521
523 FC_FREE(location->sub_location);
524 } else {
525 return dio_get_cm_parameter_raw(din, param);
526 }
527
528 return TRUE;
529}
530
531/**********************************************************************/
534bool dio_get_unit_order_json(struct connection *pc, struct data_in *din,
535 struct plocation *location,
536 struct unit_order *order)
537{
538 if (pc->json_mode) {
539 struct plocation *loc;
540 int iorder, iactivity, idir; /* These fields are enums */
541
542 /* Orders may be located in a nested field (as items in an array) */
543 loc = location;
544 while (loc->sub_location) {
545 loc = loc->sub_location;
546 }
547
548 loc->sub_location = plocation_field_new("order");
549 if (!dio_get_uint8_json(pc, din, location, &iorder)) {
550 log_packet("Corrupt order.order");
551 FC_FREE(loc->sub_location);
552 return FALSE;
553 }
554
555 loc->sub_location->name = "activity";
556 if (!dio_get_uint8_json(pc, din, location, &iactivity)) {
557 log_packet("Corrupt order.activity");
558 FC_FREE(loc->sub_location);
559 return FALSE;
560 }
561
562 loc->sub_location->name = "target";
563 if (!dio_get_sint32_json(pc, din, location, &order->target)) {
564 log_packet("Corrupt order.target");
565 FC_FREE(loc->sub_location);
566 return FALSE;
567 }
568
569 loc->sub_location->name = "sub_target";
570 if (!dio_get_sint16_json(pc, din, location, &order->sub_target)) {
571 log_packet("Corrupt order.sub_target");
572 FC_FREE(loc->sub_location);
573 return FALSE;
574 }
575
576 loc->sub_location->name = "action";
577 if (!dio_get_uint8_json(pc, din, location, &order->action)) {
578 log_packet("Corrupt order.action");
579 FC_FREE(loc->sub_location);
580 return FALSE;
581 }
582
583 loc->sub_location->name = "dir";
584 if (!dio_get_uint8_json(pc, din, location, &idir)) {
585 log_packet("Corrupt order.dir");
586 FC_FREE(loc->sub_location);
587 return FALSE;
588 }
589
590 /*
591 * FIXME: The values should be checked!
592 */
593 order->order = iorder;
594 order->activity = iactivity;
595 order->dir = idir;
596
597 FC_FREE(loc->sub_location);
598 } else {
599 return dio_get_unit_order_raw(din, order);
600 }
601
602 return TRUE;
603}
604
605/**********************************************************************/
608bool dio_get_worklist_json(struct connection *pc, struct data_in *din,
609 struct plocation *location,
610 struct worklist *pwl)
611{
612 if (pc->json_mode) {
613 int i, length;
614
615 const json_t *wlist = plocation_read_data(pc->json_packet, location);
616
617 worklist_init(pwl);
618
619 if (!json_is_array(wlist)) {
620 log_packet("Not a worklist");
621 return FALSE;
622 }
623
624 /* Safe. Checked that it was an array above. */
625 length = json_array_size(wlist);
626
627 /* A worklist is an array... */
628 location->sub_location = plocation_elem_new(0);
629
630 /* ... of universal objects. */
631 location->sub_location->sub_location = plocation_field_new("kind");
632
633 for (i = 0; i < length; i++) {
634 int value;
635 int kind;
636 struct universal univ;
637
638 location->sub_location->number = i;
639
640 location->sub_location->sub_location->name = "kind";
641 if (!dio_get_uint8_json_internal(pc->json_packet, location, &kind)) {
642 log_packet("Corrupt worklist element kind");
644 FC_FREE(location->sub_location);
645 return FALSE;
646 }
647
648 location->sub_location->sub_location->name = "value";
649 if (!dio_get_uint8_json_internal(pc->json_packet, location, &value)) {
650 log_packet("Corrupt worklist element value");
652 FC_FREE(location->sub_location);
653 return FALSE;
654 }
655
656 /*
657 * FIXME: the value returned by universal_by_number() should be checked!
658 */
660 worklist_append(pwl, &univ);
661 }
662
664 FC_FREE(location->sub_location);
665 } else {
666 return dio_get_worklist_raw(din, pwl);
667 }
668
669 return TRUE;
670}
671
672/**********************************************************************/
675bool dio_get_uint8_vec8_json(struct connection *pc, struct data_in *din,
676 const struct plocation *location,
677 int **values, int stop_value)
678{
679 if (pc->json_mode) {
680 /* TODO: implement */
681 log_warn("Received unimplemeted data type uint8_vec8.");
682 } else {
683 return dio_get_uint8_vec8_raw(din, values, stop_value);
684 }
685
686 return TRUE;
687}
688
689/**********************************************************************/
692bool dio_get_uint16_vec8_json(struct connection *pc, struct data_in *din,
693 const struct plocation *location,
694 int **values,
695 int stop_value)
696{
697 if (pc->json_mode) {
698 /* TODO: implement */
699 log_warn("Received unimplemeted data type uint16_vec8.");
700 } else {
701 return dio_get_uint16_vec8_raw(din, values, stop_value);
702 }
703
704 return TRUE;
705}
706
707/**********************************************************************/
710bool dio_get_requirement_json(struct connection *pc, struct data_in *din,
711 const struct plocation *location,
712 struct requirement *preq)
713{
714 if (pc->json_mode) {
715 int kind, range, value;
716 bool survives, present, quiet;
717
718 struct plocation *req_field;
719
720 /* Find the requirement object. */
721 json_t *requirement = plocation_read_data(pc->json_packet, location);
722
723 if (!requirement) {
724 log_error("ERROR: Unable to get requirement from location: %s", plocation_name(location));
725 return FALSE;
726 }
727
728 /* Find the requirement object fields and translate their values. */
729 req_field = plocation_field_new("kind");
730 if (!dio_get_uint8_json_internal(requirement, req_field, &kind)) {
731 log_error("ERROR: Unable to get part of requirement from location: %s",
732 plocation_name(location));
733 return FALSE;
734 }
735
736 req_field->name = "value";
737 if (!dio_get_uint32_json_internal(requirement, req_field, &value)) {
738 log_error("ERROR: Unable to get part of requirement from location: %s",
739 plocation_name(location));
740 return FALSE;
741 }
742
743 req_field->name = "range";
744 if (!dio_get_uint8_json_internal(requirement, req_field, &range)) {
745 log_error("ERROR: Unable to get part of requirement from location: %s",
746 plocation_name(location));
747 return FALSE;
748 }
749
750 req_field->name = "survives";
751 if (!dio_get_bool8_json_internal(requirement, req_field, &survives)) {
752 log_error("ERROR: Unable to get part of requirement from location: %s",
753 plocation_name(location));
754 return FALSE;
755 }
756
757 req_field->name = "present";
758 if (!dio_get_bool8_json_internal(requirement, req_field, &present)) {
759 log_error("ERROR: Unable to get part of requirement from location: %s",
760 plocation_name(location));
761 return FALSE;
762 }
763
764 req_field->name = "quiet";
765 if (!dio_get_bool8_json_internal(requirement, req_field, &quiet)) {
766 log_error("ERROR: Unable to get part of requirement from location: %s",
767 plocation_name(location));
768 return FALSE;
769 }
770
771 FC_FREE(req_field);
772
773 /* Create a requirement with the values sent over the network. */
774 *preq = req_from_values(kind, range, survives, present, quiet, value);
775 } else {
776 return dio_get_requirement_raw(din, preq);
777 }
778
779 return TRUE;
780}
781
782/**********************************************************************/
785bool dio_get_action_probability_json(struct connection *pc, struct data_in *din,
786 const struct plocation *location,
787 struct act_prob *prob)
788{
789 if (pc->json_mode) {
790 struct plocation *ap_field;
791
792 /* Find the action probability object. */
793 json_t *action_probability = plocation_read_data(pc->json_packet, location);
794
795 if (!action_probability) {
796 log_error("ERROR: Unable to get action probability from location: %s",
797 plocation_name(location));
798 return FALSE;
799 }
800
801 /* Find the action probability object fields and translate their
802 * values. */
803 ap_field = plocation_field_new("min");
804 if (!dio_get_uint8_json_internal(action_probability, ap_field, &prob->min)) {
805 log_error("ERROR: Unable to get part of action probability "
806 "from location: %s",
807 plocation_name(location));
808 return FALSE;
809 }
810
811 ap_field->name = "max";
812 if (!dio_get_uint8_json_internal(action_probability, ap_field, &prob->max)) {
813 log_error("ERROR: Unable to get part of action probability "
814 "from location: %s",
815 plocation_name(location));
816 return FALSE;
817 }
818
819 FC_FREE(ap_field);
820 } else {
821 return dio_get_action_probability_raw(din, prob);
822 }
823
824 return TRUE;
825}
826
827/**********************************************************************/
830void dio_put_farray_json(struct json_data_out *dout,
831 const struct plocation *location, int size)
832{
833 if (dout->json) {
834 int i;
835 json_t *farray = json_array();
836
837 /* Jansson's json_array_set_new() refuses to create array elements so
838 * they must be created with the array. */
839 for (i = 0; i < size; i++) {
840 json_array_append_new(farray, json_null());
841 }
842
843 plocation_write_data(dout->json, location, farray);
844 } else {
845 /* No caller needs this */
846 }
847}
848
849/**********************************************************************/
852void dio_put_uint32_json(struct json_data_out *dout,
853 const struct plocation *location, int value)
854{
855 if (dout->json) {
856 plocation_write_data(dout->json, location, json_integer(value));
857 } else {
858 dio_put_uint32_raw(&dout->raw, value);
859 }
860}
861
862/**********************************************************************/
865void dio_put_sint32_json(struct json_data_out *dout,
866 const struct plocation *location, int value)
867{
868 if (dout->json) {
869 plocation_write_data(dout->json, location, json_integer(value));
870 } else {
871 dio_put_sint32_raw(&dout->raw, value);
872 }
873}
874
875/**********************************************************************/
878void dio_put_bool8_json(struct json_data_out *dout,
879 const struct plocation *location, bool value)
880{
881 if (dout->json) {
882 plocation_write_data(dout->json, location, value ? json_true() : json_false());
883 } else {
884 dio_put_bool8_raw(&dout->raw, value);
885 }
886}
887
888/**********************************************************************/
891void dio_put_bool32_json(struct json_data_out *dout,
892 const struct plocation *location, bool value)
893{
894 if (dout->json) {
895 plocation_write_data(dout->json, location, value ? json_true() : json_false());
896 } else {
897 dio_put_bool32_raw(&dout->raw, value);
898 }
899}
900
901/**********************************************************************/
904void dio_put_ufloat_json(struct json_data_out *dout,
905 const struct plocation *location,
906 float value, int float_factor)
907{
908 if (dout->json) {
909 plocation_write_data(dout->json, location, json_real(value));
910 } else {
911 dio_put_ufloat_raw(&dout->raw, value, float_factor);
912 }
913}
914
915/**********************************************************************/
918void dio_put_sfloat_json(struct json_data_out *dout,
919 const struct plocation *location,
920 float value, int float_factor)
921{
922 if (dout->json) {
923 plocation_write_data(dout->json, location, json_real(value));
924 } else {
925 dio_put_sfloat_raw(&dout->raw, value, float_factor);
926 }
927}
928
929/**********************************************************************/
932void dio_put_uint8_vec8_json(struct json_data_out *dout,
933 const struct plocation *location,
934 int *values, int stop_value)
935{
936 if (dout->json) {
937 /* TODO: implement. */
938 log_error("Tried to send unimplemeted data type uint8_vec8.");
939 } else {
940 dio_put_uint8_vec8_raw(&dout->raw, values, stop_value);
941 }
942}
943
944/**********************************************************************/
948 const struct plocation *location, int *values,
949 int stop_value)
950{
951 if (dout->json) {
952 /* TODO: implement. */
953 log_error("Tried to send unimplemeted data type uint16_vec8.");
954 } else {
955 dio_put_uint16_vec8_raw(&dout->raw, values, stop_value);
956 }
957}
958
959/**********************************************************************/
962void dio_put_memory_json(struct json_data_out *dout,
963 struct plocation *location,
964 const void *value,
965 size_t size)
966{
967 if (dout->json) {
968 int i;
969
970 dio_put_farray_json(dout, location, size);
971
972 location->sub_location = plocation_elem_new(0);
973
974 for (i = 0; i < size; i++) {
975 location->sub_location->number = i;
976
977 dio_put_uint8_json(dout, location,
978 ((unsigned char *)value)[i]);
979 }
980
981 FC_FREE(location->sub_location);
982 } else {
983 dio_put_memory_raw(&dout->raw, value, size);
984 }
985}
986
987/**********************************************************************/
990void dio_put_string_json(struct json_data_out *dout,
991 const struct plocation *location,
992 const char *value)
993{
994 if (dout->json) {
995 plocation_write_data(dout->json, location, json_string(value));
996 } else {
997 dio_put_string_raw(&dout->raw, value);
998 }
999}
1000
1001/**********************************************************************/
1004void dio_put_estring_json(struct json_data_out *dout,
1005 const struct plocation *location,
1006 const char *value)
1007{
1008 if (dout->json) {
1009 char *escaped_value;
1010
1011 /* Let CURL find the length it self by passing 0 */
1012 escaped_value = curl_easy_escape(get_curl(), value, 0);
1013
1014 /* Handle as a regular string from now on. */
1015 dio_put_string_json(dout, location, escaped_value);
1016
1017 /* CURL's memory management wants to free this it self. */
1018 curl_free(escaped_value);
1019 } else {
1020 dio_put_estring_raw(&dout->raw, value);
1021 }
1022}
1023
1024/**********************************************************************/
1027void dio_put_requirement_json(struct json_data_out *dout,
1028 const struct plocation *location,
1029 const struct requirement *preq)
1030{
1031 if (dout->json) {
1032 int kind, range, value;
1033 bool survives, present, quiet;
1034
1035 /* Create the requirement object. */
1036 json_t *requirement = json_object();
1037
1038 /* Read the requirement values. */
1039 req_get_values(preq, &kind, &range, &survives, &present, &quiet, &value);
1040
1041 /* Write the requirement values to the fields of the requirement
1042 * object. */
1043 json_object_set_new(requirement, "kind", json_integer(kind));
1044 json_object_set_new(requirement, "value", json_integer(value));
1045
1046 json_object_set_new(requirement, "range", json_integer(range));
1047
1048 json_object_set_new(requirement, "survives", json_boolean(survives));
1049 json_object_set_new(requirement, "present", json_boolean(present));
1050 json_object_set_new(requirement, "quiet", json_boolean(quiet));
1051
1052 /* Put the requirement object in the packet. */
1053 plocation_write_data(dout->json, location, requirement);
1054 } else {
1055 dio_put_requirement_raw(&dout->raw, preq);
1056 }
1057}
1058
1059/**********************************************************************/
1063 const struct plocation *location,
1064 const struct act_prob *prob)
1065{
1066 if (dout->json) {
1067 /* Create the action probability object. */
1068 json_t *action_probability = json_object();
1069
1070 /* Write the action probability values to the fields of the action
1071 * probability object. */
1072 json_object_set_new(action_probability, "min", json_integer(prob->min));
1073 json_object_set_new(action_probability, "max", json_integer(prob->max));
1074
1075 /* Put the action probability object in the packet. */
1076 plocation_write_data(dout->json, location, action_probability);
1077 } else {
1078 dio_put_action_probability_raw(&dout->raw, prob);
1079 }
1080}
1081
1082/**********************************************************************/
1085static bool dio_get_bool8_json_internal(json_t *json_packet,
1086 const struct plocation *location,
1087 bool *dest)
1088{
1089 json_t *pbool = plocation_read_data(json_packet, location);
1090
1091 if (!pbool) {
1092 log_error("ERROR: Unable to get bool8 from location: %s", plocation_name(location));
1093 return FALSE;
1094 }
1095 *dest = json_is_true(pbool);
1096
1097 if (!dest) {
1098 log_error("ERROR: Unable to get bool from location: %s", plocation_name(location));
1099 return FALSE;
1100 }
1101
1102 return TRUE;
1103}
1104
1105/**********************************************************************/
1108bool dio_get_bool8_json(struct connection *pc, struct data_in *din,
1109 const struct plocation *location, bool *dest)
1110{
1111 if (pc->json_mode) {
1112 return dio_get_bool8_json_internal(pc->json_packet, location, dest);
1113 } else {
1114 return dio_get_bool8_raw(din, dest);
1115 }
1116}
1117
1118/**********************************************************************/
1121bool dio_get_bool32_json(struct connection *pc, struct data_in *din,
1122 const struct plocation *location, bool *dest)
1123{
1124 if (pc->json_mode) {
1125 json_t *pbool = plocation_read_data(pc->json_packet, location);
1126
1127 if (!pbool) {
1128 log_error("ERROR: Unable to get bool32 from location: %s", plocation_name(location));
1129 return FALSE;
1130 }
1131 *dest = json_is_true(pbool);
1132
1133 if (!dest) {
1134 log_error("ERROR: Unable to get bool32 from location: %s", plocation_name(location));
1135 return FALSE;
1136 }
1137 } else {
1138 return dio_get_bool32_raw(din, dest);
1139 }
1140
1141 return TRUE;
1142}
1143
1144/**********************************************************************/
1147bool dio_get_ufloat_json(struct connection *pc, struct data_in *din,
1148 const struct plocation *location,
1149 float *dest, int float_factor)
1150{
1151 if (pc->json_mode) {
1152 json_t *preal = plocation_read_data(pc->json_packet, location);
1153
1154 if (!preal) {
1155 log_error("ERROR: Unable to get real from location: %s", plocation_name(location));
1156 return FALSE;
1157 }
1158 *dest = json_real_value(preal);
1159 } else {
1160 return dio_get_ufloat_raw(din, dest, float_factor);
1161 }
1162
1163 return TRUE;
1164}
1165
1166/**********************************************************************/
1169bool dio_get_sfloat_json(struct connection *pc, struct data_in *din,
1170 const struct plocation *location,
1171 float *dest, int float_factor)
1172{
1173 if (pc->json_mode) {
1174 json_t *preal = plocation_read_data(pc->json_packet, location);
1175
1176 if (!preal) {
1177 log_error("ERROR: Unable to get real from location: %s", plocation_name(location));
1178 return FALSE;
1179 }
1180 *dest = json_real_value(preal);
1181 } else {
1182 return dio_get_sfloat_raw(din, dest, float_factor);
1183 }
1184
1185 return TRUE;
1186}
1187
1188/**********************************************************************/
1191bool dio_get_sint8_json(struct connection *pc, struct data_in *din,
1192 const struct plocation *location, int *dest)
1193{
1194 if (pc->json_mode) {
1195 json_t *pint = plocation_read_data(pc->json_packet, location);
1196
1197 if (!pint) {
1198 log_error("ERROR: Unable to get sint8 from location: %s", plocation_name(location));
1199 return FALSE;
1200 }
1201 *dest = json_integer_value(pint);
1202
1203 if (!dest) {
1204 log_error("ERROR: Unable to get sint8 from location: %s", plocation_name(location));
1205 return FALSE;
1206 }
1207 } else {
1208 return dio_get_sint8_raw(din, dest);
1209 }
1210
1211 return TRUE;
1212}
1213
1214/**********************************************************************/
1217bool dio_get_sint16_json(struct connection *pc, struct data_in *din,
1218 const struct plocation *location, int *dest)
1219{
1220 if (pc->json_mode) {
1221 json_t *pint = plocation_read_data(pc->json_packet, location);
1222
1223 if (!pint) {
1224 log_error("ERROR: Unable to get sint16 from location: %s", plocation_name(location));
1225 return FALSE;
1226 }
1227 *dest = json_integer_value(pint);
1228
1229 if (!dest) {
1230 log_error("ERROR: Unable to get sint16 from location: %s", plocation_name(location));
1231 return FALSE;
1232 }
1233 } else {
1234 return dio_get_sint16_raw(din, dest);
1235 }
1236
1237 return TRUE;
1238}
1239
1240/**********************************************************************/
1243bool dio_get_memory_json(struct connection *pc, struct data_in *din,
1244 struct plocation *location,
1245 void *dest, size_t dest_size)
1246{
1247 if (pc->json_mode) {
1248 int i;
1249
1250 location->sub_location = plocation_elem_new(0);
1251
1252 for (i = 0; i < dest_size; i++) {
1253 int val;
1254
1255 location->sub_location->number = i;
1256
1257 if (!dio_get_uint8_json_internal(pc->json_packet, location, &val)) {
1258 free(location->sub_location);
1259 return FALSE;
1260 }
1261 ((unsigned char *)dest)[i] = val;
1262 }
1263
1264 FC_FREE(location->sub_location);
1265 } else {
1266 return dio_get_memory_raw(din, dest, dest_size);
1267 }
1268
1269 return TRUE;
1270}
1271
1272/**********************************************************************/
1275static bool dio_get_string_json_internal(json_t *json_packet,
1276 const struct plocation *location,
1277 char *dest, size_t max_dest_size)
1278{
1279 json_t *pstring = plocation_read_data(json_packet, location);
1280 const char *result_str;
1281
1282 if (!pstring) {
1283 log_error("ERROR: Unable to get string from location: %s", plocation_name(location));
1284 return FALSE;
1285 }
1286
1287 result_str = json_string_value(pstring);
1288
1289 if (dest
1290 && !dataio_get_conv_callback(dest, max_dest_size, result_str, strlen(result_str))) {
1291 log_error("ERROR: Unable to get string from location: %s", plocation_name(location));
1292 return FALSE;
1293 }
1294
1295 return TRUE;
1296}
1297
1298/**********************************************************************/
1301bool dio_get_string_json(struct connection *pc, struct data_in *din,
1302 const struct plocation *location,
1303 char *dest, size_t max_dest_size)
1304{
1305 if (pc->json_mode) {
1306 return dio_get_string_json_internal(pc->json_packet, location,
1307 dest, max_dest_size);
1308 } else {
1309 return dio_get_string_raw(din, dest, max_dest_size);
1310 }
1311}
1312
1313/**********************************************************************/
1318bool dio_get_estring_json(struct connection *pc, struct data_in *din,
1319 const struct plocation *location,
1320 char *dest, size_t max_dest_size)
1321{
1322 if (pc->json_mode) {
1323 char *escaped_value;
1324 char *unescaped_value;
1325
1326 /* The encoded string has the same size limit as the decoded string. */
1327 escaped_value = fc_malloc(max_dest_size);
1328
1329 if (!dio_get_string_json_internal(pc->json_packet, location,
1330 escaped_value, max_dest_size)) {
1331 /* dio_get_string_json() has logged this already. */
1332 return FALSE;
1333 }
1334
1335 /* Let CURL find the length it self by passing 0 */
1336 unescaped_value = curl_easy_unescape(get_curl(), escaped_value, 0, NULL);
1337
1338 /* Done with the escaped value. */
1339 FC_FREE(escaped_value);
1340
1341 /* Copy the unescaped value so CURL can free its own copy. */
1342 memcpy(dest, unescaped_value,
1343 /* Don't copy the memory following unescaped_value. */
1344 MIN(max_dest_size, strlen(unescaped_value) + 1));
1345
1346 /* CURL's memory management wants to free this it self. */
1347 curl_free(unescaped_value);
1348
1349 /* Make sure that the string is terminated. */
1350 dest[max_dest_size - 1] = '\0';
1351 } else {
1352 return dio_get_estring_raw(din, dest, max_dest_size);
1353 }
1354
1355 return TRUE;
1356}
1357
1358#endif /* FREECIV_JSON_CONNECTION */
void cm_init_parameter(struct cm_parameter *dest)
Definition cm.c:2181
void dio_put_sint8_json(struct json_data_out *dout, const struct plocation *location, int value)
void dio_put_uint32_json(struct json_data_out *dout, const struct plocation *location, int value)
bool dio_get_uint16_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
bool dio_get_estring_json(struct connection *pc, struct data_in *din, const struct plocation *location, char *dest, size_t max_dest_size)
void dio_put_sfloat_json(struct json_data_out *dout, const struct plocation *location, float value, int float_factor)
bool dio_get_worklist_json(struct connection *pc, struct data_in *din, struct plocation *location, struct worklist *pwl)
void dio_put_sint16_json(struct json_data_out *dout, const struct plocation *location, int value)
bool dio_get_sint16_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
bool dio_get_sint32_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
void dio_put_uint8_vec8_json(struct json_data_out *dout, const struct plocation *location, int *values, int stop_value)
bool dio_get_sint8_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
void dio_put_string_json(struct json_data_out *dout, const struct plocation *location, const char *value)
bool dio_get_bool32_json(struct connection *pc, struct data_in *din, const struct plocation *location, bool *dest)
bool dio_get_uint32_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
bool dio_get_string_json(struct connection *pc, struct data_in *din, const struct plocation *location, char *dest, size_t max_dest_size)
void dio_put_bool8_json(struct json_data_out *dout, const struct plocation *location, bool value)
bool dio_get_requirement_json(struct connection *pc, struct data_in *din, const struct plocation *location, struct requirement *preq)
void dio_put_uint16_json(struct json_data_out *dout, const struct plocation *location, int value)
bool dio_get_uint8_vec8_json(struct connection *pc, struct data_in *din, const struct plocation *location, int **values, int stop_value)
void dio_put_uint16_vec8_json(struct json_data_out *dout, const struct plocation *location, int *values, int stop_value)
bool dio_get_cm_parameter_json(struct connection *pc, struct data_in *din, struct plocation *location, struct cm_parameter *param)
bool dio_get_sfloat_json(struct connection *pc, struct data_in *din, const struct plocation *location, float *dest, int float_factor)
bool dio_get_uint8_json(struct connection *pc, struct data_in *din, const struct plocation *location, int *dest)
void dio_put_worklist_json(struct json_data_out *dout, struct plocation *location, const struct worklist *pwl)
bool dio_get_memory_json(struct connection *pc, struct data_in *din, struct plocation *location, void *dest, size_t dest_size)
bool dio_get_unit_order_json(struct connection *pc, struct data_in *din, struct plocation *location, struct unit_order *order)
void dio_put_cm_parameter_json(struct json_data_out *dout, struct plocation *location, const struct cm_parameter *order)
bool dio_get_ufloat_json(struct connection *pc, struct data_in *din, const struct plocation *location, float *dest, int float_factor)
void dio_put_bool32_json(struct json_data_out *dout, const struct plocation *location, bool value)
void dio_put_requirement_json(struct json_data_out *dout, const struct plocation *location, const struct requirement *preq)
void dio_put_unit_order_json(struct json_data_out *dout, struct plocation *location, const struct unit_order *order)
void dio_put_memory_json(struct json_data_out *dout, struct plocation *location, const void *value, size_t size)
bool dio_get_action_probability_json(struct connection *pc, struct data_in *din, const struct plocation *location, struct act_prob *prob)
void dio_put_sint32_json(struct json_data_out *dout, const struct plocation *location, int value)
void dio_put_action_probability_json(struct json_data_out *dout, const struct plocation *location, const struct act_prob *prob)
bool dio_get_bool8_json(struct connection *pc, struct data_in *din, const struct plocation *location, bool *dest)
void dio_put_estring_json(struct json_data_out *dout, const struct plocation *location, const char *value)
void dio_put_ufloat_json(struct json_data_out *dout, const struct plocation *location, float value, int float_factor)
bool dio_get_uint16_vec8_json(struct connection *pc, struct data_in *din, const struct plocation *location, int **values, int stop_value)
void dio_put_uint8_json(struct json_data_out *dout, const struct plocation *location, int value)
void dio_put_farray_json(struct json_data_out *dout, const struct plocation *location, int size)
void dio_put_cm_parameter_raw(struct raw_data_out *dout, const struct cm_parameter *param)
Definition dataio_raw.c:517
void dio_put_action_probability_raw(struct raw_data_out *dout, const struct act_prob *aprob)
void dio_put_unit_order_raw(struct raw_data_out *dout, const struct unit_order *order)
Definition dataio_raw.c:541
bool dio_get_requirement_raw(struct data_in *din, struct requirement *preq)
bool dio_get_sint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:733
void dio_put_ufloat_raw(struct raw_data_out *dout, float value, int float_factor)
Definition dataio_raw.c:407
struct plocation * plocation_field_new(char *name)
bool dio_get_worklist_raw(struct data_in *din, struct worklist *pwl)
Definition dataio_raw.c:906
bool dio_get_action_probability_raw(struct data_in *din, struct act_prob *aprob)
Definition dataio_raw.c:992
void dio_put_bool8_raw(struct raw_data_out *dout, bool value)
Definition dataio_raw.c:381
void dio_put_uint16_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:284
void dio_put_sfloat_raw(struct raw_data_out *dout, float value, int float_factor)
Definition dataio_raw.c:424
bool dataio_get_conv_callback(char *dst, size_t ndst, const char *src, size_t nsrc)
Definition dataio_raw.c:139
bool dio_get_sfloat_raw(struct data_in *din, float *dest, int float_factor)
Definition dataio_raw.c:718
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
void dio_put_sint16_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:361
bool dio_get_uint32_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:614
bool dio_get_sint16_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:751
bool dio_get_unit_order_raw(struct data_in *din, struct unit_order *order)
Definition dataio_raw.c:880
bool dio_get_sint32_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:769
void dio_put_sint32_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:369
bool dio_get_cm_parameter_raw(struct data_in *din, struct cm_parameter *param)
Definition dataio_raw.c:842
bool dio_get_uint8_vec8_raw(struct data_in *din, int **values, int stop_value)
Definition dataio_raw.c:942
void dio_put_uint32_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:303
bool dio_get_uint16_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:593
bool dio_get_memory_raw(struct data_in *din, void *dest, size_t dest_size)
Definition dataio_raw.c:790
void dio_put_memory_raw(struct raw_data_out *dout, const void *value, size_t size)
Definition dataio_raw.c:488
void dio_put_uint16_vec8_raw(struct raw_data_out *dout, int *values, int stop_value)
Definition dataio_raw.c:466
bool dio_get_bool32_raw(struct data_in *din, bool *dest)
Definition dataio_raw.c:681
bool dio_get_ufloat_raw(struct data_in *din, float *dest, int float_factor)
Definition dataio_raw.c:702
void dio_put_worklist_raw(struct raw_data_out *dout, const struct worklist *pwl)
Definition dataio_raw.c:556
void dio_put_requirement_raw(struct raw_data_out *dout, const struct requirement *preq)
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:572
bool dio_get_uint16_vec8_raw(struct data_in *din, int **values, int stop_value)
Definition dataio_raw.c:967
void dio_put_uint8_vec8_raw(struct raw_data_out *dout, int *values, int stop_value)
Definition dataio_raw.c:442
struct plocation * plocation_elem_new(int number)
bool dio_get_bool8_raw(struct data_in *din, bool *dest)
Definition dataio_raw.c:661
void dio_put_string_raw(struct raw_data_out *dout, const char *value)
Definition dataio_raw.c:499
bool dio_get_string_raw(struct data_in *din, char *dest, size_t max_dest_size)
Definition dataio_raw.c:805
const char * plocation_name(const struct plocation *loc)
void dio_put_bool32_raw(struct raw_data_out *dout, bool value)
Definition dataio_raw.c:393
void dio_put_sint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:353
@ PADR_FIELD
Definition dataio_raw.h:57
@ PADR_ELEMENT
Definition dataio_raw.h:59
#define dio_get_estring_raw
Definition dataio_raw.h:161
#define dio_put_estring_raw
Definition dataio_raw.h:162
@ O_LAST
Definition fc_types.h:91
struct tile * loc
Definition citydlg.c:220
#define log_packet
Definition log.h:137
#define log_warn(message,...)
Definition log.h:105
#define log_error(message,...)
Definition log.h:103
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
void req_get_values(const struct requirement *req, int *type, int *range, bool *survives, bool *present, bool *quiet, int *value)
struct requirement req_from_values(int type, int range, bool survives, bool present, bool quiet, int value)
struct universal universal_by_number(const enum universals_n kind, const int value)
int universal_number(const struct universal *source)
#define MIN(x, y)
Definition shared.h:55
size_t size
Definition specvec.h:72
bool allow_disorder
Definition cm.h:44
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool allow_specialists
Definition cm.h:45
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
Definition climisc.h:82
json_t * json
Definition dataio_json.h:36
struct raw_data_out raw
Definition dataio_json.h:35
enum plocation_kind kind
Definition dataio_raw.h:65
struct plocation * sub_location
Definition dataio_raw.h:78
char * name
Definition dataio_raw.h:72
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
struct universal entries[MAX_LEN_WORKLIST]
Definition worklist.h:30
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Definition worklist.c:147
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57