Made GsweAspectData a refcounted boxed type

This is to satisfy #7, but it also satisfies #8, as gswe_init() is
called where data initialized there is necessary.
This commit is contained in:
Gergely Polonkai 2013-09-30 21:42:19 +02:00
parent 7564183aa2
commit dbee248a6e
5 changed files with 211 additions and 81 deletions

View File

@ -134,7 +134,13 @@ gswe_aspect_info_get_type
<SECTION>
<FILE>gswe-aspect-data</FILE>
GsweAspectData
gswe_aspect_data_new
gswe_aspect_data_new_with_planets
gswe_aspect_data_ref
gswe_aspect_data_unref
gswe_aspect_data_set_planet1
gswe_aspect_data_get_planet1
gswe_aspect_data_set_planet2
gswe_aspect_data_get_planet2
gswe_aspect_data_get_distance
gswe_aspect_data_get_aspect

View File

@ -32,17 +32,17 @@ struct _GsweAspectData {
/* the distance between the two planets, in degrees */
gdouble distance;
/* the aspect between the two planets */
GsweAspect aspect;
/* the #GsweAspectInfo structure associated with the aspect */
GsweAspectInfo *aspect_info;
/* the difference in percent between an exact aspect and this given aspect */
gdouble difference;
/* reference count */
guint refcount;
};
GsweAspectData *gswe_aspect_data_copy(GsweAspectData *aspect_data);
void gswe_aspect_data_calculate(GsweAspectData *aspect_data);
#endif /* __SWE_GLIB_GSWE_ASPECT_DATA_PRIVATE_H__ */
#else /* not defined __SWE_GLIB_BUILDING__ */

View File

@ -15,8 +15,15 @@
* You should have received a copy of the GNU General Public License
* along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <glib-object.h>
#include "swe-glib-private.h"
#include "swe-glib.h"
#include "gswe-planet-data-private.h"
#include "gswe-planet-info-private.h"
#include "gswe-aspect-info.h"
#include "gswe-aspect-info-private.h"
#include "gswe-aspect-data.h"
#include "gswe-aspect-data-private.h"
@ -31,32 +38,164 @@
* #GsweAspectData is a structure that represents two planets relation to each
* other, like their aspect and the aspect's difference from an exact aspect.
*/
G_DEFINE_BOXED_TYPE(GsweAspectData, gswe_aspect_data, (GBoxedCopyFunc)gswe_aspect_data_copy, (GBoxedFreeFunc)g_free);
G_DEFINE_BOXED_TYPE(GsweAspectData, gswe_aspect_data, (GBoxedCopyFunc)gswe_aspect_data_ref, (GBoxedFreeFunc)gswe_aspect_data_unref);
static void
gswe_aspect_data_free(GsweAspectData *aspect_data)
{
if (aspect_data->planet1) {
gswe_planet_data_unref(aspect_data->planet1);
}
if (aspect_data->planet2) {
gswe_planet_data_unref(aspect_data->planet2);
}
if (aspect_data->aspect_info) {
gswe_aspect_info_unref(aspect_data->aspect_info);
}
g_free(aspect_data);
}
static gboolean
find_aspect(gpointer aspect_p, GsweAspectInfo *aspect_info, GsweAspectData *aspect_data)
{
gdouble diff,
planet_orb,
aspect_orb;
diff = fabs(aspect_info->size - aspect_data->distance);
planet_orb = fmin(aspect_data->planet1->planet_info->orb, aspect_data->planet2->planet_info->orb);
aspect_orb = fmax(1.0, planet_orb - aspect_info->orb_modifier);
if (diff < aspect_orb) {
aspect_data->aspect_info = gswe_aspect_info_ref(aspect_info);
if (aspect_info->size == 0) {
aspect_data->difference = (1 - ((360.0 - diff) / 360.0)) * 100.0;
} else {
aspect_data->difference = (1 - ((aspect_info->size - diff) / aspect_info->size)) * 100.0;
}
return TRUE;
}
return FALSE;
}
void
gswe_aspect_data_calculate(GsweAspectData *aspect_data)
{
GsweAspectInfo *aspect_info;
if ((aspect_data->distance = fabs(aspect_data->planet1->position - aspect_data->planet2->position)) > 180.0) {
aspect_data->distance = 360.0 - aspect_data->distance;
}
if ((aspect_info = g_hash_table_find(gswe_aspect_info_table, (GHRFunc)find_aspect, aspect_data)) == NULL) {
aspect_data->aspect_info = gswe_aspect_info_ref(g_hash_table_lookup(gswe_aspect_info_table, GINT_TO_POINTER(GSWE_ASPECT_NONE)));
}
}
/**
* gswe_aspect_data_new:
*
* Creates a new #GsweAspectData with reference count set to 1.
*
* Returns: (transfer full): a new #GsweAspectData
*/
GsweAspectData *
gswe_aspect_data_copy(GsweAspectData *aspect_data)
gswe_aspect_data_new(void)
{
GsweAspectData *ret;
if (aspect_data == NULL) {
return NULL;
}
gswe_init();
ret = g_new0(GsweAspectData, 1);
ret->planet1 = aspect_data->planet1;
ret->planet2 = aspect_data->planet2;
ret->distance = aspect_data->distance;
ret->aspect = aspect_data->aspect;
ret->aspect_info = aspect_data->aspect_info;
ret->difference = aspect_data->difference;
ret->refcount = 1;
return ret;
}
/**
* gswe_aspect_data_new_with_planets:
* @planet1: (in): a #GswePlanetData
* @planet2: (in): a #GswePlanetData
*
* Creates a new #GsweAspectData with a reference count of 1, and both planets
* initially set. Also calculates the aspect between them.
*
* Returns: (transfer full): a new #GsweAspectData with all data set.
*/
GsweAspectData *
gswe_aspect_data_new_with_planets(GswePlanetData *planet1, GswePlanetData *planet2)
{
GsweAspectData *ret;
ret = gswe_aspect_data_new();
ret->planet1 = gswe_planet_data_ref(planet1);
ret->planet2 = gswe_planet_data_ref(planet2);
gswe_aspect_data_calculate(ret);
return ret;
}
/**
* gswe_aspect_data_ref:
* @aspect_data: a #GsweAspectData
*
* Increases reference count of @aspect_data.
*
* Returns: (transfer none): the same #GsweAspectData
*/
GsweAspectData *
gswe_aspect_data_ref(GsweAspectData *aspect_data)
{
aspect_data->refcount++;
return aspect_data;
}
/**
* gswe_aspect_data_unref:
* @aspect_data: (in): a #GsweAspectData
*
* Decreases reference count on @aspect_data. If reference count reaches zero, @aspect_data is freed.
*/
void
gswe_aspect_data_unref(GsweAspectData *aspect_data)
{
if (--aspect_data->refcount == 0) {
gswe_aspect_data_free(aspect_data);
}
}
/**
* gswe_aspect_data_set_planet1:
* @aspect_data: (in): a #GsweAspectData
* @planet1: (in): a #GswePlanetData
*
* Sets @planet1 as the first planet of the aspect.
*/
void
gswe_aspect_data_set_planet1(GsweAspectData *aspect_data, GswePlanetData *planet1)
{
if (aspect_data->planet1) {
gswe_planet_data_unref(aspect_data->planet1);
}
aspect_data->planet1 = gswe_planet_data_ref(planet1);
if (aspect_data->planet2) {
gswe_aspect_data_calculate(aspect_data);
}
}
/**
* gswe_aspect_data_get_planet1:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the first planet in the aspect.
*
@ -65,16 +204,33 @@ gswe_aspect_data_copy(GsweAspectData *aspect_data)
GswePlanetData *
gswe_aspect_data_get_planet1(GsweAspectData *aspect_data)
{
if (aspect_data) {
return aspect_data->planet1;
} else {
return NULL;
return aspect_data->planet1;
}
/**
* gswe_aspect_data_set_planet2:
* @aspect_data: (in): a #GsweAspectData
* @planet2: (in): a #GswePlanetData
*
* Sets @planet2 as the second planet of the aspect.
*/
void
gswe_aspect_data_set_planet2(GsweAspectData *aspect_data, GswePlanetData *planet2)
{
if (aspect_data->planet2) {
gswe_planet_data_unref(aspect_data->planet2);
}
aspect_data->planet2 = gswe_planet_data_ref(planet2);
if (aspect_data->planet1) {
gswe_aspect_data_calculate(aspect_data);
}
}
/**
* gswe_aspect_data_get_planet2:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the second planet in the aspect.
*
@ -92,7 +248,7 @@ gswe_aspect_data_get_planet2(GsweAspectData *aspect_data)
/**
* gswe_aspect_data_get_distance:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the exact distance between the two planets in the aspect.
*
@ -110,7 +266,7 @@ gswe_aspect_data_get_distance(GsweAspectData *aspect_data)
/**
* gswe_aspect_data_get_aspect:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the actual aspect between the two planets.
*
@ -119,8 +275,8 @@ gswe_aspect_data_get_distance(GsweAspectData *aspect_data)
GsweAspect
gswe_aspect_data_get_aspect(GsweAspectData *aspect_data)
{
if (aspect_data) {
return aspect_data->aspect;
if (aspect_data->aspect_info) {
return aspect_data->aspect_info->aspect;
} else {
return GSWE_ASPECT_NONE;
}
@ -128,7 +284,7 @@ gswe_aspect_data_get_aspect(GsweAspectData *aspect_data)
/**
* gswe_aspect_data_get_aspect_info:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the the #GsweAspectInfo object for this aspect.
*
@ -146,7 +302,7 @@ gswe_aspect_data_get_aspect_info(GsweAspectData *aspect_data)
/**
* gswe_aspect_data_get_difference:
* @aspect_data: (in) (allow-none): a #GsweAspectData
* @aspect_data: (in): a #GsweAspectData
*
* Gets the difference between an exact aspect and this one.
*

View File

@ -39,8 +39,18 @@ typedef struct _GsweAspectData GsweAspectData;
GType gswe_aspect_data_get_type(void);
#define GSWE_TYPE_ASPECT_DATA (gswe_aspect_data_get_type())
GsweAspectData *gswe_aspect_data_new(void);
GsweAspectData *gswe_aspect_data_new_with_planets(GswePlanetData *planet1, GswePlanetData *planet2);
GsweAspectData *gswe_aspect_data_ref(GsweAspectData *aspect_data);
void gswe_aspect_data_unref(GsweAspectData *aspect_data);
void gswe_aspect_data_set_planet1(GsweAspectData *aspect_data, GswePlanetData *planet1);
GswePlanetData *gswe_aspect_data_get_planet1(GsweAspectData *aspect_data);
void gswe_aspect_data_set_planet2(GsweAspectData *aspect_data, GswePlanetData *planet2);
GswePlanetData *gswe_aspect_data_get_planet2(GsweAspectData *aspect_data);
gdouble gswe_aspect_data_get_distance(GsweAspectData *aspect_data);
GsweAspect gswe_aspect_data_get_aspect(GsweAspectData *aspect_data);
GsweAspectInfo *gswe_aspect_data_get_aspect_info(GsweAspectData *aspect_data);

View File

@ -202,6 +202,7 @@ gswe_moment_finalize(GObject *gobject)
g_list_free_full(moment->priv->house_list, g_free);
g_list_free_full(moment->priv->planet_list, g_free);
g_list_free_full(moment->priv->aspect_list, (GDestroyNotify)gswe_aspect_data_unref);
G_OBJECT_CLASS(gswe_moment_parent_class)->finalize(gobject);
}
@ -1025,40 +1026,6 @@ find_aspect_by_both_planets(GsweAspectData *aspect, struct GsweAspectFinder *asp
return 1;
}
static gboolean
find_aspect(gpointer aspect_p, GsweAspectInfo *aspect_info, GsweAspectData *aspect_data)
{
GsweAspect aspect = GPOINTER_TO_INT(aspect_p);
gdouble diff,
planet_orb,
aspect_orb;
aspect_data->distance = fabs(aspect_data->planet1->position - aspect_data->planet2->position);
if (aspect_data->distance > 180.0) {
aspect_data->distance = 360.0 - aspect_data->distance;
}
diff = fabs(aspect_info->size - aspect_data->distance);
planet_orb = fmin(aspect_data->planet1->planet_info->orb, aspect_data->planet2->planet_info->orb);
aspect_orb = fmax(1.0, planet_orb - aspect_info->orb_modifier);
if (diff < aspect_orb) {
aspect_data->aspect = aspect;
aspect_data->aspect_info = aspect_info;
if (aspect_info->size == 0) {
aspect_data->difference = (1 - ((360.0 - diff) / 360.0)) * 100.0;
} else {
aspect_data->difference = (1 - ((aspect_info->size - diff) / aspect_info->size)) * 100.0;
}
return TRUE;
}
return FALSE;
}
static void
gswe_moment_calculate_aspects(GsweMoment *moment)
{
@ -1070,7 +1037,7 @@ gswe_moment_calculate_aspects(GsweMoment *moment)
}
gswe_moment_calculate_all_planets(moment);
g_list_free_full(moment->priv->aspect_list, g_free);
g_list_free_full(moment->priv->aspect_list, (GDestroyNotify)gswe_aspect_data_unref);
moment->priv->aspect_list = NULL;
for (oplanet = moment->priv->planet_list; oplanet; oplanet = oplanet->next) {
@ -1079,30 +1046,21 @@ gswe_moment_calculate_aspects(GsweMoment *moment)
*inner_planet = iplanet->data;
struct GsweAspectFinder aspect_finder;
GsweAspectData *aspect_data;
GList *aspect_data_element;
if (outer_planet->planet == inner_planet->planet) {
if (outer_planet->planet_info->planet == inner_planet->planet_info->planet) {
continue;
}
aspect_finder.planet1 = outer_planet->planet;
aspect_finder.planet2 = inner_planet->planet;
aspect_finder.planet1 = outer_planet->planet_info->planet;
aspect_finder.planet2 = inner_planet->planet_info->planet;
if (g_list_find_custom(moment->priv->aspect_list, &aspect_finder, (GCompareFunc)find_aspect_by_both_planets) != NULL) {
continue;
if ((aspect_data_element = g_list_find_custom(moment->priv->aspect_list, &aspect_finder, (GCompareFunc)find_aspect_by_both_planets)) != NULL) {
gswe_aspect_data_calculate(aspect_data_element->data);
} else {
aspect_data = gswe_aspect_data_new_with_planets(inner_planet, outer_planet);
moment->priv->aspect_list = g_list_prepend(moment->priv->aspect_list, aspect_data);
}
aspect_data = g_new0(GsweAspectData, 1);
aspect_data->planet1 = outer_planet;
aspect_data->planet2 = inner_planet;
aspect_data->aspect = GSWE_ASPECT_NONE;
(void)g_hash_table_find(gswe_aspect_info_table, (GHRFunc)find_aspect, aspect_data);
if (aspect_data->aspect == GSWE_ASPECT_NONE) {
aspect_data->aspect_info = g_hash_table_lookup(gswe_aspect_info_table, GINT_TO_POINTER(GSWE_ASPECT_NONE));
}
moment->priv->aspect_list = g_list_prepend(moment->priv->aspect_list, aspect_data);
}
}