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 #include "fc_prehdrs.h"
19 
20 #include <string.h>
21 
22 /* utility */
23 #include "shared.h"		/* TRUE, FALSE */
24 #include "support.h"		/* fc_is* */
25 
26 #include "capability.h"
27 
28 #define GET_TOKEN(start, end)                                               \
29   {                                                                         \
30     /* skip leading whitespace */                                           \
31     while (fc_isspace(*start)) {                                            \
32       start++;                                                              \
33     }                                                                       \
34     /* skip to end of token */                                              \
35     for (end = start; *end != '\0' && !fc_isspace(*end) && *end != ',';     \
36          end++) {                                                           \
37       /* nothing */                                                         \
38     }                                                                       \
39   }
40 
41 /***************************************************************************
42   This routine returns true if the capability in cap appears
43   in the capability list in capstr.  The capabilities in capstr
44   are allowed to start with a "+", but the capability in cap must not.
45 ***************************************************************************/
fc_has_capability(const char * cap,const char * capstr,const size_t cap_len)46 static bool fc_has_capability(const char *cap, const char *capstr,
47                               const size_t cap_len)
48 {
49   const char *next;
50 
51   fc_assert_ret_val(capstr != NULL, FALSE);
52 
53   for (;;) {
54     GET_TOKEN(capstr, next);
55 
56     if (*capstr == '+') {
57       capstr++;
58     }
59 
60     fc_assert(next >= capstr);
61 
62     if (((size_t)(next - capstr) == cap_len)
63         && strncmp(cap, capstr, cap_len) == 0) {
64       return TRUE;
65     }
66     if (*next == '\0') {
67       return FALSE;
68     }
69 
70     capstr = next + 1;
71   }
72 }
73 
74 /***************************************************************************
75   Wrapper for fc_has_capability() for NULL terminated strings.
76 ***************************************************************************/
has_capability(const char * cap,const char * capstr)77 bool has_capability(const char *cap, const char *capstr)
78 {
79   return fc_has_capability(cap, capstr, strlen(cap));
80 }
81 
82 /***************************************************************************
83   This routine returns true if all the mandatory capabilities in
84   us appear in them.
85 ***************************************************************************/
has_capabilities(const char * us,const char * them)86 bool has_capabilities(const char *us, const char *them)
87 {
88   const char *next;
89 
90   for (;;) {
91     GET_TOKEN(us, next);
92 
93     if (*us == '+' && !fc_has_capability(us+1, them, next-(us+1))) {
94       return FALSE;
95     }
96     if (*next == '\0') {
97       return TRUE;
98     }
99 
100     us = next+1;
101   }
102 }
103