]> git.xonotic.org Git - xonotic/darkplaces.git/blob - com_infostring.c
physics: fix and refactor unsticking
[xonotic/darkplaces.git] / com_infostring.c
1 /*
2 Copyright (C) 2006-2021 DarkPlaces contributors
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "darkplaces.h"
22
23 size_t InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuesize)
24 {
25         unsigned pos = 0, j;
26         size_t keylength;
27
28         if (!key)
29                 key = "";
30         keylength = strlen(key);
31         if (valuesize < 1 || !value)
32         {
33                 Con_Printf("InfoString_GetValue: no room in value\n");
34                 return 0;
35         }
36         value[0] = '\0';
37         if (strchr(key, '\\'))
38         {
39                 Con_Printf("InfoString_GetValue: key name \"%s\" contains \\ which is not possible in an infostring\n", key);
40                 return 0;
41         }
42         if (strchr(key, '\"'))
43         {
44                 Con_Printf("InfoString_SetValue: key name \"%s\" contains \" which is not allowed in an infostring\n", key);
45                 return 0;
46         }
47         if (!key[0])
48         {
49                 Con_Printf("InfoString_GetValue: can not look up a key with no name\n");
50                 return 0;
51         }
52         while (buffer[pos] == '\\')
53         {
54                 if (!memcmp(buffer + pos+1, key, keylength) &&
55                                 (buffer[pos+1 + keylength] == 0 ||
56                                  buffer[pos+1 + keylength] == '\\'))
57                 {
58                         pos += 1 + keylength;           // Skip \key
59                         if (buffer[pos] == '\\') pos++; // Skip \ before value.
60                         for (j = 0;buffer[pos+j] && buffer[pos+j] != '\\' && j < valuesize - 1;j++)
61                                 value[j] = buffer[pos+j];
62                         value[j] = '\0';
63                         return j;
64                 }
65                 if (buffer[pos] == '\\') pos++; // Skip \ before value.
66                 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
67                 if (buffer[pos] == '\\') pos++; // Skip \ before value.
68                 for (pos++;buffer[pos] && buffer[pos] != '\\';pos++);
69         }
70         // if we reach this point the key was not found
71         return 0;
72 }
73
74 void InfoString_SetValue(char *buffer, size_t bufferlength, const char *key, const char *value)
75 {
76         int pos = 0, pos2;
77         size_t keylength;
78         if (!key)
79                 key = "";
80         if (!value)
81                 value = "";
82         keylength = strlen(key);
83         if (strchr(key, '\\') || strchr(value, '\\'))
84         {
85                 Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \\ which is not possible to store in an infostring\n", key, value);
86                 return;
87         }
88         if (strchr(key, '\"') || strchr(value, '\"'))
89         {
90                 Con_Printf("InfoString_SetValue: \"%s\" \"%s\" contains \" which is not allowed in an infostring\n", key, value);
91                 return;
92         }
93         if (!key[0])
94         {
95                 Con_Printf("InfoString_SetValue: can not set a key with no name\n");
96                 return;
97         }
98         while (buffer[pos] == '\\')
99         {
100                 if (!memcmp(buffer + pos+1, key, keylength) &&
101                                 (buffer[pos+1 + keylength] == 0 ||
102                                  buffer[pos+1 + keylength] == '\\'))
103                         break;
104                 if (buffer[pos] == '\\') pos++; // Skip \ before value.
105                 for (;buffer[pos] && buffer[pos] != '\\';pos++);
106                 if (buffer[pos] == '\\') pos++; // Skip \ before value.
107                 for (;buffer[pos] && buffer[pos] != '\\';pos++);
108         }
109         // if we found the key, find the end of it because we will be replacing it
110         pos2 = pos;
111         if (buffer[pos] == '\\')
112         {
113                 pos2 += 1 + (int)keylength;  // Skip \key
114                 if (buffer[pos2] == '\\') pos2++; // Skip \ before value.
115                 for (;buffer[pos2] && buffer[pos2] != '\\';pos2++);
116         }
117         if (bufferlength <= pos + 1 + strlen(key) + 1 + strlen(value) + strlen(buffer + pos2))
118         {
119                 Con_Printf("InfoString_SetValue: no room for \"%s\" \"%s\" in infostring\n", key, value);
120                 return;
121         }
122         if (value[0])
123         {
124                 // set the key/value and append the remaining text
125                 char tempbuffer[MAX_INPUTLINE];
126                 dp_strlcpy(tempbuffer, buffer + pos2, sizeof(tempbuffer));
127                 dpsnprintf(buffer + pos, bufferlength - pos, "\\%s\\%s%s", key, value, tempbuffer);
128         }
129         else
130         {
131                 // just remove the key from the text
132                 dp_strlcpy(buffer + pos, buffer + pos2, bufferlength - pos);
133         }
134 }
135
136 void InfoString_Print(char *buffer)
137 {
138         int i;
139         char key[MAX_INPUTLINE];
140         char value[MAX_INPUTLINE];
141         while (*buffer)
142         {
143                 if (*buffer != '\\')
144                 {
145                         Con_Printf("InfoString_Print: corrupt string\n");
146                         return;
147                 }
148                 for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++)
149                         if (i < (int)sizeof(key)-1)
150                                 key[i++] = *buffer;
151                 key[i] = 0;
152                 if (*buffer != '\\')
153                 {
154                         Con_Printf("InfoString_Print: corrupt string\n");
155                         return;
156                 }
157                 for (buffer++, i = 0;*buffer && *buffer != '\\';buffer++)
158                         if (i < (int)sizeof(value)-1)
159                                 value[i++] = *buffer;
160                 value[i] = 0;
161                 // empty value is an error case
162                 Con_Printf("%20s %s\n", key, value[0] ? value : "NO VALUE");
163         }
164 }