]>
git.proxmox.com Git - grub2.git/blob - gfxmenu/gui_string_util.c
1 /* gui_string_util.c - String utilities used by the GUI system. */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2008,2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/gui_string_util.h>
21 #include <grub/types.h>
22 #include <grub/misc.h>
25 /* Create a new NUL-terminated string on the heap as a substring of BUF.
26 The range of buf included is the half-open interval [START,END).
27 The index START is inclusive, END is exclusive. */
29 grub_new_substring (const char *buf
,
30 grub_size_t start
, grub_size_t end
)
34 grub_size_t len
= end
- start
;
35 char *s
= grub_malloc (len
+ 1);
38 grub_memcpy (s
, buf
+ start
, len
);
43 /* Eliminate "." and ".." path elements from PATH. A new heap-allocated
44 string is returned. */
46 canonicalize_path (const char *path
)
52 /* Count the path components in path. */
54 for (p
= path
; *p
; p
++)
58 char **path_array
= grub_malloc (components
* sizeof (*path_array
));
62 /* Initialize array elements to NULL pointers; in case once of the
63 allocations fails, the cleanup code can just call grub_free() for all
64 pointers in the array. */
65 for (i
= 0; i
< components
; i
++)
68 /* Parse the path into path_array. */
70 for (i
= 0; i
< components
&& p
; i
++)
72 /* Find the end of the path element. */
73 const char *end
= grub_strchr (p
, '/');
75 end
= p
+ grub_strlen (p
);
77 /* Copy the element. */
78 path_array
[i
] = grub_new_substring (p
, 0, end
- p
);
82 /* Advance p to point to the start of the next element, or NULL. */
89 /* Eliminate '.' and '..' elements from the path array. */
90 int newpath_length
= 0;
91 for (i
= components
- 1; i
>= 0; --i
)
93 if (! grub_strcmp (path_array
[i
], "."))
95 grub_free (path_array
[i
]);
98 else if (! grub_strcmp (path_array
[i
], "..")
101 /* Delete the '..' and the prior path element. */
102 grub_free (path_array
[i
]);
105 grub_free (path_array
[i
]);
110 newpath_length
+= grub_strlen (path_array
[i
]) + 1;
114 /* Construct a new path string. */
115 newpath
= grub_malloc (newpath_length
+ 1);
120 char *newpath_end
= newpath
;
122 for (i
= 0; i
< components
; i
++)
124 char *element
= path_array
[i
];
127 /* For all components but the first, prefix with a slash. */
129 newpath_end
= grub_stpcpy (newpath_end
, "/");
130 newpath_end
= grub_stpcpy (newpath_end
, element
);
136 for (i
= 0; i
< components
; i
++)
137 grub_free (path_array
[i
]);
138 grub_free (path_array
);
143 /* Return a new heap-allocated string representing to absolute path
144 to the file referred to by PATH. If PATH is an absolute path, then
145 the returned path is a copy of PATH. If PATH is a relative path, then
146 BASE is with PATH used to construct the absolute path. */
148 grub_resolve_relative_path (const char *base
, const char *path
)
155 /* If PATH is an absolute path, then just use it as is. */
156 if (path
[0] == '/' || path
[0] == '(')
157 return canonicalize_path (path
);
159 abspath
= grub_malloc (grub_strlen (base
) + grub_strlen (path
) + 3);
163 /* Concatenate BASE and PATH. */
164 p
= grub_stpcpy (abspath
, base
);
165 l
= grub_strlen (abspath
);
166 if (l
== 0 || abspath
[l
-1] != '/')
172 grub_stpcpy (p
, path
);
174 canonpath
= canonicalize_path (abspath
);
182 /* Get the path of the directory where the file at FILE_PATH is located.
183 FILE_PATH should refer to a file, not a directory. The returned path
184 includes a trailing slash.
185 This does not handle GRUB "(hd0,0)" paths properly yet since it only
188 grub_get_dirname (const char *file_path
)
194 for (i
= grub_strlen (file_path
) - 1; i
>= 0; --i
)
196 if (file_path
[i
] == '/')
202 if (last_slash
== -1)
203 return grub_strdup ("/");
205 return grub_new_substring (file_path
, 0, last_slash
+ 1);
211 return ((c
>= '0' && c
<= '9')
212 || (c
>= 'a' && c
<= 'f')
213 || (c
>= 'A' && c
<= 'F'));
217 parse_hex_color_component (const char *s
, unsigned start
, unsigned end
)
223 /* Check the limits so we don't overrun the buffer. */
224 if (len
< 1 || len
> 2)
229 buf
[0] = s
[start
]; /* Get the first and only hex digit. */
230 buf
[1] = buf
[0]; /* Duplicate the hex digit. */
235 buf
[1] = s
[start
+ 1];
240 return grub_strtoul (buf
, 0, 16);
243 /* Parse a color string of the form "r, g, b", "#RGB", "#RGBA",
244 "#RRGGBB", or "#RRGGBBAA". */
246 grub_gui_parse_color (const char *s
, grub_gui_color_t
*color
)
250 /* Skip whitespace. */
251 while (*s
&& grub_isspace (*s
))
256 /* HTML-style. Number if hex digits:
258 [8] #RRGGBBAA [4] #RGBA */
260 s
++; /* Skip the '#'. */
261 /* Count the hexits to determine the format. */
264 while (my_isxdigit (*end
))
270 /* Parse the color components based on the format. */
271 if (hexits
== 3 || hexits
== 4)
273 c
.red
= parse_hex_color_component (s
, 0, 1);
274 c
.green
= parse_hex_color_component (s
, 1, 2);
275 c
.blue
= parse_hex_color_component (s
, 2, 3);
277 c
.alpha
= parse_hex_color_component (s
, 3, 4);
281 else if (hexits
== 6 || hexits
== 8)
283 c
.red
= parse_hex_color_component (s
, 0, 2);
284 c
.green
= parse_hex_color_component (s
, 2, 4);
285 c
.blue
= parse_hex_color_component (s
, 4, 6);
287 c
.alpha
= parse_hex_color_component (s
, 6, 8);
292 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
293 "invalid HTML-type color string `%s'", s
);
295 else if (grub_isdigit (*s
))
297 /* Comma separated decimal values. */
298 c
.red
= grub_strtoul (s
, 0, 0);
299 if ((s
= grub_strchr (s
, ',')) == 0)
300 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
301 "missing 1st comma separator in color `%s'", s
);
303 c
.green
= grub_strtoul (s
, 0, 0);
304 if ((s
= grub_strchr (s
, ',')) == 0)
305 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
306 "missing 2nd comma separator in color `%s'", s
);
308 c
.blue
= grub_strtoul (s
, 0, 0);
309 if ((s
= grub_strchr (s
, ',')) == 0)
314 c
.alpha
= grub_strtoul (s
, 0, 0);
319 if (! grub_gui_get_named_color (s
, &c
))
320 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
321 "invalid named color `%s'", s
);
324 if (grub_errno
== GRUB_ERR_NONE
)