Fix wrong pointer arithmetic in the PDbox aiff header writing code
[maemo-rb.git] / firmware / general.c
blob8e6d5af9a0c27addf482c89d3d97df5b92f974b7
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Michael Sevakis
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
23 #include <stdio.h>
24 #include "general.h"
25 #include "file.h"
26 #include "dir.h"
27 #include "rbpaths.h"
28 #include "limits.h"
29 #include "stdlib.h"
30 #include "string-extra.h"
31 #include "system.h"
32 #include "time.h"
33 #include "timefuncs.h"
35 #if CONFIG_CODEC == SWCODEC
36 int round_value_to_list32(unsigned long value,
37 const unsigned long list[],
38 int count,
39 bool signd)
41 unsigned long dmin = ULONG_MAX;
42 int idmin = -1, i;
44 for (i = 0; i < count; i++)
46 unsigned long diff;
48 if (list[i] == value)
50 idmin = i;
51 break;
54 if (signd ? ((long)list[i] < (long)value) : (list[i] < value))
55 diff = value - list[i];
56 else
57 diff = list[i] - value;
59 if (diff < dmin)
61 dmin = diff;
62 idmin = i;
66 return idmin;
67 } /* round_value_to_list32 */
69 /* Number of bits set in src_mask should equal src_list length */
70 int make_list_from_caps32(unsigned long src_mask,
71 const unsigned long *src_list,
72 unsigned long caps_mask,
73 unsigned long *caps_list)
75 int i, count;
76 unsigned long mask;
78 for (mask = src_mask, count = 0, i = 0;
79 mask != 0;
80 src_mask = mask, i++)
82 unsigned long test_bit;
83 mask &= mask - 1; /* Zero lowest bit set */
84 test_bit = mask ^ src_mask; /* Isolate the bit */
85 if (test_bit & caps_mask) /* Add item if caps has test bit set */
86 caps_list[count++] = src_list ? src_list[i] : (unsigned long)i;
89 return count;
90 } /* make_list_from_caps32 */
91 #endif /* CONFIG_CODEC == SWCODEC */
93 /* Create a filename with a number part in a way that the number is 1
94 * higher than the highest numbered file matching the same pattern.
95 * It is allowed that buffer and path point to the same memory location,
96 * saving a strcpy(). Path must always be given without trailing slash.
97 * "num" can point to an int specifying the number to use or NULL or a value
98 * less than zero to number automatically. The final number used will also
99 * be returned in *num. If *num is >= 0 then *num will be incremented by
100 * one. */
101 char *create_numbered_filename(char *buffer, const char *path,
102 const char *prefix, const char *suffix,
103 int numberlen IF_CNFN_NUM_(, int *num))
105 DIR *dir;
106 struct dirent *entry;
107 int max_num;
108 int pathlen;
109 int prefixlen = strlen(prefix);
110 int suffixlen = strlen(suffix);
111 char fmtstring[12];
113 if (buffer != path)
114 strlcpy(buffer, path, MAX_PATH);
116 pathlen = strlen(buffer);
118 #ifdef IF_CNFN_NUM
119 if (num && *num >= 0)
121 /* number specified */
122 max_num = *num;
124 else
125 #endif
127 /* automatic numbering */
128 max_num = 0;
130 dir = opendir(pathlen ? buffer : HOME_DIR);
131 if (!dir)
132 return NULL;
134 while ((entry = readdir(dir)))
136 int curr_num, namelen;
138 if (strncasecmp((char *)entry->d_name, prefix, prefixlen))
139 continue;
141 namelen = strlen((char *)entry->d_name);
142 if ((namelen <= prefixlen + suffixlen)
143 || strcasecmp((char *)entry->d_name + namelen - suffixlen, suffix))
144 continue;
146 curr_num = atoi((char *)entry->d_name + prefixlen);
147 if (curr_num > max_num)
148 max_num = curr_num;
151 closedir(dir);
154 max_num++;
156 snprintf(fmtstring, sizeof(fmtstring), "/%%s%%0%dd%%s", numberlen);
157 snprintf(buffer + pathlen, MAX_PATH - pathlen, fmtstring, prefix,
158 max_num, suffix);
160 #ifdef IF_CNFN_NUM
161 if (num)
162 *num = max_num;
163 #endif
165 return buffer;
169 #if CONFIG_RTC
170 /* Create a filename with a date+time part.
171 It is allowed that buffer and path point to the same memory location,
172 saving a strcpy(). Path must always be given without trailing slash.
173 unique_time as true makes the function wait until the current time has
174 changed. */
175 char *create_datetime_filename(char *buffer, const char *path,
176 const char *prefix, const char *suffix,
177 bool unique_time)
179 struct tm *tm = get_time();
180 static struct tm last_tm;
181 int pathlen;
183 while (unique_time && !memcmp(get_time(), &last_tm, sizeof (struct tm)))
184 sleep(HZ/10);
186 last_tm = *tm;
188 if (buffer != path)
189 strlcpy(buffer, path, MAX_PATH);
191 pathlen = strlen(buffer);
192 snprintf(buffer + pathlen, MAX_PATH - pathlen,
193 "/%s%02d%02d%02d-%02d%02d%02d%s", prefix,
194 tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
195 tm->tm_hour, tm->tm_min, tm->tm_sec, suffix);
197 return buffer;
199 #endif /* CONFIG_RTC */
201 /***
202 ** Compacted pointer lists
204 ** N-length list requires N+1 elements to ensure NULL-termination.
207 /* Find a pointer in a pointer array. Returns the addess of the element if
208 * found or the address of the terminating NULL otherwise. This can be used
209 * to bounds check and add items. */
210 void ** find_array_ptr(void **arr, void *ptr)
212 void *curr;
213 for (curr = *arr; curr != NULL && curr != ptr; curr = *(++arr));
214 return arr;
217 /* Remove a pointer from a pointer array if it exists. Compacts it so that
218 * no gaps exist. Returns 0 on success and -1 if the element wasn't found. */
219 int remove_array_ptr(void **arr, void *ptr)
221 void *curr;
222 arr = find_array_ptr(arr, ptr);
224 if (*arr == NULL)
225 return -1;
227 /* Found. Slide up following items. */
230 void **arr1 = arr + 1;
231 *arr++ = curr = *arr1;
233 while (curr != NULL);
235 return 0;