rockbox/firmware/general.c

101 lines
3 KiB
C
Raw Normal View History

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <limits.h>
#include "system.h"
#include "config.h"
#include "general.h"
int round_value_to_list32(unsigned long value,
const unsigned long list[],
int count,
bool signd)
{
unsigned long dmin = ULONG_MAX;
int idmin = -1, i;
for (i = 0; i < count; i++)
{
unsigned long diff;
if (list[i] == value)
{
idmin = i;
break;
}
if (signd ? ((long)list[i] < (long)value) : (list[i] < value))
diff = value - list[i];
else
diff = list[i] - value;
if (diff < dmin)
{
dmin = diff;
idmin = i;
}
}
return idmin;
} /* round_value_to_list32 */
/* Number of bits set in src_mask should equal src_list length */
int make_list_from_caps32(unsigned long src_mask,
const unsigned long *src_list,
unsigned long caps_mask,
unsigned long *caps_list)
{
int i, count;
unsigned long mask;
for (mask = src_mask, count = 0, i = 0;
mask != 0;
src_mask = mask, i++)
{
unsigned long test_bit;
mask &= mask - 1; /* Zero lowest bit set */
test_bit = mask ^ src_mask; /* Isolate the bit */
if (test_bit & caps_mask) /* Add item if caps has test bit set */
caps_list[count++] = src_list ? src_list[i] : (unsigned long)i;
}
return count;
} /* make_list_from_caps32 */
/* Align a buffer and size to a size boundary while remaining within
* the original boundaries */
size_t align_buffer(void **start, size_t size, size_t align)
{
void *newstart = *start;
void *newend = newstart + size;
/* Align the end down and the start up */
newend = (void *)ALIGN_DOWN((intptr_t)newend, align);
newstart = (void *)ALIGN_UP((intptr_t)newstart, align);
/* Hmmm - too small for this */
if (newend <= newstart)
return 0;
/* Return adjusted pointer and size */
*start = newstart;
return newend - newstart;
}