aboutsummaryrefslogblamecommitdiffstats
path: root/libgamma_internal_allocated_any_ramp.c
blob: c9dbe3e4b3a9d1f1df7f113bc8ba9906d390cfc2 (plain) (tree)
1
2
3
4
5
6
7
8
9








                                                         












                                                                             
                                                                                                                            


                                                                             










                                                   







                                               

                                          


                                       
                                    
                                    






                                            



                                                                                           

                             

                                           

                                                                                                                 





                                                           
/* See LICENSE file for copyright and license details. */
#include "common.h"


/**
 * Just an arbitrary version
 */
#define ANY bits64


/**
 * Allocate and initalise a gamma ramp with any depth
 * 
 * @param   ramps_sys  Output gamma ramps
 * @param   ramps      The gamma ramps whose sizes should be duplicated
 * @param   depth      The depth of the gamma ramps to allocate,
 *                     `-1` for `float`, `-2` for `double`
 * @param   elements   Output reference for the grand size of the gamma ramps
 * @return             Zero on success, otherwise (negative) the value of an
 *                     error identifier provided by this library
 */
int
libgamma_internal_allocated_any_ramp(union gamma_ramps_any *restrict ramps_sys, const union gamma_ramps_any *restrict ramps,
                                     signed depth, size_t *restrict elements)
{
	/* Calculate the size of the allocation to do */
	size_t d, n = ramps->ANY.red_size;
	if (n > SIZE_MAX - ramps->ANY.green_size) {
		goto enomem;
	}
	n += ramps->ANY.green_size;
	if (n > SIZE_MAX - ramps->ANY.blue_size) {
	enomem:
		errno = ENOMEM;
		return LIBGAMMA_ERRNO_SET;
	}
	n += ramps->ANY.blue_size;
	switch (depth) {
	case  8:  d = sizeof(uint8_t);   break;
	case 16:  d = sizeof(uint16_t);  break;
	case 32:  d = sizeof(uint32_t);  break;
	case 64:  d = sizeof(uint64_t);  break;
	case -1:  d = sizeof(float);     break;
	case -2:  d = sizeof(double);    break;
	default:
		errno = EINVAL;
		return LIBGAMMA_ERRNO_SET;
	}

	/* Copy the gamma ramp sizes */
	ramps_sys->ANY = ramps->ANY;
	/* Allocate the new ramps */
	if (!n) {
		ramps_sys->ANY.red   = NULL;
		ramps_sys->ANY.green = NULL;
		ramps_sys->ANY.blue  = NULL;
		*elements = n;
		return 0;
	}
#ifdef HAVE_LIBGAMMA_METHOD_LINUX_DRM
	/* Valgrind complains about us reading uninitialize memory if we just use malloc */
	ramps_sys->ANY.red = calloc(n, d);
#else
	if (n > SIZE_MAX / d)
		goto enomem;
	ramps_sys->ANY.red = malloc(n * d);
#endif
	ramps_sys->ANY.green = (void *)&((char *)ramps_sys->ANY.  red)[ramps->ANY.  red_size * d / sizeof(char)];
	ramps_sys->ANY.blue  = (void *)&((char *)ramps_sys->ANY.green)[ramps->ANY.green_size * d / sizeof(char)];

	/* Report the total gamma ramp size */
	*elements = n;
	/* Report successfulness */
	return ramps_sys->ANY.red ? 0 : LIBGAMMA_ERRNO_SET;
}