/* ide-triplet.c * * Copyright 2018 Corentin Noël * Copyright 2018 Collabora Ltd. * * 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 3 of the License, or * (at your option) any later version. * * 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 General Public License * along with this program. If not, see . * * SPDX-License-Identifier: GPL-3.0-or-later */ #define G_LOG_DOMAIN "ide-triplet" #include "config.h" #include "ide-triplet.h" G_DEFINE_BOXED_TYPE (IdeTriplet, ide_triplet, ide_triplet_ref, ide_triplet_unref) struct _IdeTriplet { volatile gint ref_count; gchar *full_name; gchar *arch; gchar *vendor; gchar *kernel; gchar *operating_system; }; static IdeTriplet * _ide_triplet_construct (void) { IdeTriplet *self; self = g_slice_new0 (IdeTriplet); self->ref_count = 1; self->full_name = NULL; self->arch = NULL; self->vendor = NULL; self->kernel = NULL; self->operating_system = NULL; return self; } /** * ide_triplet_new: * @full_name: The complete identifier of the machine * * Creates a new #IdeTriplet from a given identifier. This identifier * can be a simple architecture name, a duet of "arch-kernel" (like "m68k-coff"), a triplet * of "arch-kernel-os" (like "x86_64-linux-gnu") or a quadriplet of "arch-vendor-kernel-os" * (like "i686-pc-linux-gnu") * * Returns: (transfer full): An #IdeTriplet. * * Since: 3.32 */ IdeTriplet * ide_triplet_new (const gchar *full_name) { IdeTriplet *self; g_auto (GStrv) parts = NULL; guint parts_length = 0; g_return_val_if_fail (full_name != NULL, NULL); self = _ide_triplet_construct (); self->full_name = g_strdup (full_name); parts = g_strsplit (full_name, "-", 4); parts_length = g_strv_length (parts); /* Currently they can't have more than 4 parts */ if (parts_length >= 4) { self->arch = g_strdup (parts[0]); self->vendor = g_strdup (parts[1]); self->kernel = g_strdup (parts[2]); self->operating_system = g_strdup (parts[3]); } else if (parts_length == 3) { self->arch = g_strdup (parts[0]); self->kernel = g_strdup (parts[1]); self->operating_system = g_strdup (parts[2]); } else if (parts_length == 2) { self->arch = g_strdup (parts[0]); self->kernel = g_strdup (parts[1]); } else if (parts_length == 1) self->arch = g_strdup (parts[0]); return self; } /** * ide_triplet_new_from_system: * * Creates a new #IdeTriplet from a the current system information * * Returns: (transfer full): An #IdeTriplet. * * Since: 3.32 */ IdeTriplet * ide_triplet_new_from_system (void) { static IdeTriplet *system_triplet; if (g_once_init_enter (&system_triplet)) g_once_init_leave (&system_triplet, ide_triplet_new (ide_get_system_type ())); return ide_triplet_ref (system_triplet); } /** * ide_triplet_new_with_triplet: * @arch: The name of the architecture of the machine (like "x86_64") * @kernel: (nullable): The name of the kernel of the machine (like "linux") * @operating_system: (nullable): The name of the os of the machine * (like "gnuabi64") * * Creates a new #IdeTriplet from a given triplet of "arch-kernel-os" * (like "x86_64-linux-gnu") * * Returns: (transfer full): An #IdeTriplet. * * Since: 3.32 */ IdeTriplet * ide_triplet_new_with_triplet (const gchar *arch, const gchar *kernel, const gchar *operating_system) { IdeTriplet *self; g_autofree gchar *full_name = NULL; g_return_val_if_fail (arch != NULL, NULL); self = _ide_triplet_construct (); self->arch = g_strdup (arch); self->kernel = g_strdup (kernel); self->operating_system = g_strdup (operating_system); full_name = g_strdup (arch); if (kernel != NULL) { g_autofree gchar *start_full_name = full_name; full_name = g_strdup_printf ("%s-%s", start_full_name, kernel); } if (operating_system != NULL) { g_autofree gchar *start_full_name = full_name; full_name = g_strdup_printf ("%s-%s", start_full_name, operating_system); } self->full_name = g_steal_pointer (&full_name); return self; } /** * ide_triplet_new_with_quadruplet: * @arch: The name of the architecture of the machine (like "x86_64") * @vendor: (nullable): The name of the vendor of the machine (like "pc") * @kernel: (nullable): The name of the kernel of the machine (like "linux") * @operating_system: (nullable): The name of the os of the machine (like "gnuabi64") * * Creates a new #IdeTriplet from a given quadruplet of * "arch-vendor-kernel-os" (like "i686-pc-linux-gnu") * * Returns: (transfer full): An #IdeTriplet. * * Since: 3.32 */ IdeTriplet * ide_triplet_new_with_quadruplet (const gchar *arch, const gchar *vendor, const gchar *kernel, const gchar *operating_system) { IdeTriplet *self; g_autofree gchar *full_name = NULL; g_return_val_if_fail (arch != NULL, NULL); if (vendor == NULL) return ide_triplet_new_with_triplet (arch, kernel, operating_system); self = _ide_triplet_construct (); self->arch = g_strdup (arch); self->vendor = g_strdup (vendor); self->kernel = g_strdup (kernel); self->operating_system = g_strdup (operating_system); full_name = g_strdup_printf ("%s-%s", arch, vendor); if (kernel != NULL) { g_autofree gchar *start_full_name = full_name; full_name = g_strdup_printf ("%s-%s", start_full_name, kernel); } if (operating_system != NULL) { g_autofree gchar *start_full_name = full_name; full_name = g_strdup_printf ("%s-%s", start_full_name, operating_system); } self->full_name = g_steal_pointer (&full_name); return self; } static void ide_triplet_finalize (IdeTriplet *self) { g_free (self->full_name); g_free (self->arch); g_free (self->vendor); g_free (self->kernel); g_free (self->operating_system); g_slice_free (IdeTriplet, self); } /** * ide_triplet_ref: * @self: An #IdeTriplet * * Increases the reference count of @self * * Returns: (transfer none): An #IdeTriplet. * * Since: 3.32 */ IdeTriplet * ide_triplet_ref (IdeTriplet *self) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (self->ref_count > 0, NULL); g_atomic_int_inc (&self->ref_count); return self; } /** * ide_triplet_unref: * @self: An #IdeTriplet * * Decreases the reference count of @self * Once the reference count reaches 0, the object is freed. * * Since: 3.32 */ void ide_triplet_unref (IdeTriplet *self) { g_return_if_fail (self); g_return_if_fail (self->ref_count > 0); if (g_atomic_int_dec_and_test (&self->ref_count)) ide_triplet_finalize (self); } /** * ide_triplet_get_full_name: * @self: An #IdeTriplet * * Gets the full name of the machine configuration name (can be an architecture name, * a duet, a triplet or a quadruplet). * * Returns: (transfer none): The full name of the machine configuration name * * Since: 3.32 */ const gchar * ide_triplet_get_full_name (IdeTriplet *self) { g_return_val_if_fail (self, NULL); return self->full_name; } /** * ide_triplet_get_arch: * @self: An #IdeTriplet * * Gets the architecture name of the machine * * Returns: (transfer none): The architecture name of the machine * * Since: 3.32 */ const gchar * ide_triplet_get_arch (IdeTriplet *self) { g_return_val_if_fail (self, NULL); return self->arch; } /** * ide_triplet_get_vendor: * @self: An #IdeTriplet * * Gets the vendor name of the machine * * Returns: (transfer none) (nullable): The vendor name of the machine * * Since: 3.32 */ const gchar * ide_triplet_get_vendor (IdeTriplet *self) { g_return_val_if_fail (self, NULL); return self->vendor; } /** * ide_triplet_get_kernel: * @self: An #IdeTriplet * * Gets name of the kernel of the machine * * Returns: (transfer none) (nullable): The name of the kernel of the machine * * Since: 3.32 */ const gchar * ide_triplet_get_kernel (IdeTriplet *self) { g_return_val_if_fail (self, NULL); return self->kernel; } /** * ide_triplet_get_operating_system: * @self: An #IdeTriplet * * Gets name of the operating system of the machine * * Returns: (transfer none) (nullable): The name of the operating system of the machine * * Since: 3.32 */ const gchar * ide_triplet_get_operating_system (IdeTriplet *self) { g_return_val_if_fail (self, NULL); return self->operating_system; } /** * ide_triplet_is_system: * @self: An #IdeTriplet * * Gets whether this is the same architecture as the system * * Returns: %TRUE if this is the same architecture as the system, %FALSE otherwise * * Since: 3.32 */ gboolean ide_triplet_is_system (IdeTriplet *self) { g_autofree gchar *system_arch = ide_get_system_arch (); g_return_val_if_fail (self, FALSE); return g_strcmp0 (self->arch, system_arch) == 0; }