cr-num.c revision 4ab5a40fd84422a8fe0306b2ccd03d211f4bce81
/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
/*
* This file is part of The Croco Library
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2.1 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* Author: Dodji Seketeli
* See COPYRIGHTS file for copyrights information.
*/
/**
*@file
*The definition
*of the #CRNum class.
*/
#include "cr-num.h"
#include "string.h"
/**
*The default constructor of
*#CRNum.
*@return the newly built instance of
*#CRNum.
*/
CRNum *
cr_num_new (void)
{
CRNum *result = (CRNum *)g_try_malloc (sizeof (CRNum));
if (result == NULL) {
cr_utils_trace_info ("Out of memory");
return NULL;
}
memset (result, 0, sizeof (CRNum));
return result;
}
/**
*A constructor of #CRNum.
*@param a_is_natural indicates whether the intance of #CRNum is
*a natural number or not.
*@param a_integer_part the integer part of the instance
*of #CRNum
*@param a_decimal_part in case the instance of #CRNum
*natural number (but a decimal one) this parameter
*is the decimal part of the instance of #CRNum.
*@return the newly built instance of #CRNum or
*NULL if an error arises.
*/
CRNum *
cr_num_new_with_val (gdouble a_val, enum CRNumType a_type)
{
CRNum *result = NULL;
result = cr_num_new ();
g_return_val_if_fail (result, NULL);
result->val = a_val;
result->type = a_type;
return result;
}
/**
*Returns the string representation of the
*current instance of #CRNum.
*@param a_this the current instance of #CRNum.
*@return the newly built string representation
*of the current instance of #CRNum. The returned
*string is NULL terminated. The caller *must*
*free the returned string.
*/
guchar *
cr_num_to_string (CRNum * a_this)
{
guchar *tmp_char1 = NULL,
*tmp_char2 = NULL,
*result = NULL;
g_return_val_if_fail (a_this, NULL);
gdouble test_val = a_this->val - (glong) a_this->val;
if (!test_val) {
tmp_char1 = (guchar *)g_strdup_printf ("%ld", (glong) a_this->val);
} else {
/* We can't use g_ascii_dtostr, because that sometimes uses
e notation (which wouldn't be a valid number in CSS). */
size_t const buflen = 35; /* fairly arbitrary. */
tmp_char1 = (guchar *)g_malloc (buflen);
g_ascii_formatd ((gchar *)tmp_char1, buflen, "%.17f", a_this->val);
}
g_return_val_if_fail (tmp_char1, NULL);
switch (a_this->type) {
case NUM_LENGTH_EM:
tmp_char2 = (guchar *) "em";
break;
case NUM_LENGTH_EX:
tmp_char2 = (guchar *) "ex";
break;
case NUM_LENGTH_PX:
tmp_char2 = (guchar *) "px";
break;
case NUM_LENGTH_IN:
tmp_char2 = (guchar *) "in";
break;
case NUM_LENGTH_CM:
tmp_char2 = (guchar *) "cm";
break;
case NUM_LENGTH_MM:
tmp_char2 = (guchar *) "mm";
break;
case NUM_LENGTH_PT:
tmp_char2 = (guchar *) "pt";
break;
case NUM_LENGTH_PC:
tmp_char2 = (guchar *) "pc";
break;
case NUM_ANGLE_DEG:
tmp_char2 = (guchar *) "deg";
break;
case NUM_ANGLE_RAD:
tmp_char2 = (guchar *) "rad";
break;
case NUM_ANGLE_GRAD:
tmp_char2 = (guchar *) "grad";
break;
case NUM_TIME_MS:
tmp_char2 = (guchar *) "ms";
break;
case NUM_TIME_S:
tmp_char2 = (guchar *) "s";
break;
case NUM_FREQ_HZ:
tmp_char2 = (guchar *) "Hz";
break;
case NUM_FREQ_KHZ:
tmp_char2 = (guchar *) "KHz";
break;
case NUM_PERCENTAGE:
tmp_char2 = (guchar *) "%";
break;
case NUM_INHERIT:
tmp_char2 = (guchar *) "inherit";
break ;
case NUM_AUTO:
tmp_char2 = (guchar *) "auto";
break ;
case NUM_GENERIC:
tmp_char2 = NULL ;
break ;
default:
tmp_char2 = (guchar *) "unknown";
break;
}
if (tmp_char2) {
result = (guchar *)g_strconcat (
(gchar *)tmp_char1, (gchar *)tmp_char2, NULL);
g_free (tmp_char1);
} else {
result = tmp_char1;
}
return result;
}
/**
*Copies an instance of #CRNum.
*@param a_src the instance of #CRNum to copy.
*Must be non NULL.
*@param a_dst the destination of the copy.
*Must be non NULL
*@return CR_OK upon successful completion, an
*error code otherwise.
*/
enum CRStatus
cr_num_copy (CRNum * a_dest, CRNum * a_src)
{
g_return_val_if_fail (a_dest && a_src, CR_BAD_PARAM_ERROR);
memcpy (a_dest, a_src, sizeof (CRNum));
return CR_OK;
}
/**
*Duplicates an instance of #CRNum
*@param a_this the instance of #CRNum to duplicate.
*@return the newly created (duplicated) instance of #CRNum.
*Must be freed by cr_num_destroy().
*/
CRNum *
cr_num_dup (CRNum * a_this)
{
CRNum *result = NULL;
enum CRStatus status = CR_OK;
g_return_val_if_fail (a_this, NULL);
result = cr_num_new ();
g_return_val_if_fail (result, NULL);
status = cr_num_copy (result, a_this);
g_return_val_if_fail (status == CR_OK, NULL);
return result;
}
/**
*Sets an instance of #CRNum.
*@param a_this the current instance of #CRNum to be set.
*@param a_val the new numerical value to be hold by the current
*instance of #CRNum
*@param a_type the new type of #CRNum.
*/
enum CRStatus
cr_num_set (CRNum * a_this, gdouble a_val, enum CRNumType a_type)
{
g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
a_this->val = a_val;
a_this->type = a_type;
return CR_OK;
}
/**
*Tests if the current instance of #CRNum is a fixed
*length value or not. Typically a fixed length value
*is anything from NUM_LENGTH_EM to NUM_LENGTH_PC.
*See the definition of #CRNumType to see what we mean.
*@return TRUE if the instance of #CRNum is a fixed length number,
*FALSE otherwise.
*/
gboolean
cr_num_is_fixed_length (CRNum * a_this)
{
gboolean result = FALSE;
g_return_val_if_fail (a_this, FALSE);
if (a_this->type >= NUM_LENGTH_EM
&& a_this->type <= NUM_LENGTH_PC) {
result = TRUE ;
}
return result ;
}
/**
*The destructor of #CRNum.
*@param a_this the this pointer of
*the current instance of #CRNum.
*/
void
cr_num_destroy (CRNum * a_this)
{
g_return_if_fail (a_this);
g_free (a_this);
}