guint asCFlag(USER_OBJECT_ s_flag, GType ftype) { GFlagsClass* fclass = g_type_class_ref(ftype); guint flags = 0; if (IS_INTEGER(s_flag) || IS_NUMERIC(s_flag)) { if (asCNumeric(s_flag) > fclass->mask) { PROBLEM "The flags value %f is too high", asCNumeric(s_flag) ERROR; } flags = asCNumeric(s_flag); } else { int i; for (i = 0; i < GET_LENGTH(s_flag); i++) { const gchar *fname = CHAR_DEREF(STRING_ELT(s_flag, i)); /*Rprintf("Searching for flag value %s\n", fname);*/ GFlagsValue *fvalue = g_flags_get_value_by_name(fclass, fname); if (!fvalue) fvalue = g_flags_get_value_by_nick(fclass, fname); if (!fvalue && atoi(fname) <= fclass->mask) { flags |= atoi(fname); continue; } if (!fvalue) { PROBLEM "Could not find flag by name %s", fname ERROR; } /*Rprintf("Found: %d\n", fvalue->value);*/ flags |= fvalue->value; } } return(flags); }
/* Flags can contain multiple values. We assume here that values are like * C identifiers (that is, they match /[A-Za-z_][A-Za-z0-9_]+/), although * that doesn't seem to be a requirement of GLib. With that assumption in * mind, we look for the format "FLAG_1 | FLAG_2 | ... | FLAG_N". */ static gboolean g_value_set_flags_from_string(GValue * val, char * string) { guint value = 0; char * strtok_saveptr; char * string_copy; char * strtok_first_arg; const char delim[] = " \t,|"; GFlagsClass * flags_class; flags_class = (GFlagsClass*) g_type_class_ref(G_VALUE_TYPE(val)); g_return_val_if_fail(flags_class != NULL, FALSE); g_return_val_if_fail(G_IS_FLAGS_CLASS(flags_class), FALSE); /* Don't let strtok stop on original. */ strtok_first_arg = string_copy = strdup(string); for (;;) { GFlagsValue * flag_value; char * token = strtok_r(strtok_first_arg, delim, &strtok_saveptr); strtok_first_arg = NULL; if (token == NULL) { break; } flag_value = g_flags_get_value_by_name(flags_class, token); if (flag_value == NULL) { flag_value = g_flags_get_value_by_nick(flags_class, token); } if (flag_value == NULL) { g_fprintf(stderr, _("Invalid flag %s for type %s\n"), token, g_type_name(G_VALUE_TYPE(val))); continue; } value |= flag_value->value; } amfree(string_copy); if (value == 0) { g_fprintf(stderr, _("No valid flags for type %s in string %s\n"), g_type_name(G_VALUE_TYPE(val)), string); return FALSE; } g_value_set_flags(val, value); return TRUE; }
static void _xfdashboard_gvalue_transform_string_flags(const GValue *inSourceValue, GValue *ioDestValue) { GFlagsClass *flagsClass; GFlagsValue *flagsValue; guint finalValue; gchar **values, **entry; /* Reference flags class to keep it alive for transformation */ flagsClass=g_type_class_ref(G_VALUE_TYPE(ioDestValue)); /* Split string into space-separated needles and lookup each needle * for a match and add found values OR'ed to final value */ finalValue=0; entry=values=g_strsplit(inSourceValue->data[0].v_pointer, " ", 0); while(*entry) { /* Do not look-up empty values */ if(!entry[0]) continue; /* Get flags value either by name or by nickname (whatever matches first) */ flagsValue=g_flags_get_value_by_name(flagsClass, *entry); if(!flagsValue) flagsValue=g_flags_get_value_by_nick(flagsClass, *entry); /* Add value OR'ed if flags could be found */ if(flagsValue) finalValue|=flagsValue->value; else { XFDASHBOARD_DEBUG(NULL, MISC, "Cannot get value for unknown flag '%s' for type %s", *entry, g_type_name(G_VALUE_TYPE(ioDestValue))); } /* Continue with next entry */ entry++; } g_strfreev(values); /* Set value */ ioDestValue->data[0].v_uint=finalValue; /* Release allocated resources */ g_type_class_unref(flagsClass); }
int main(int argc, char **argv) { GEnumClass *xenum = g_type_class_ref(MESON_TYPE_THE_XENUM); GFlagsClass *flags_enum = g_type_class_ref(MESON_TYPE_THE_FLAGS_ENUM); if (g_enum_get_value_by_name(xenum, "MESON_THE_XVALUE")->value != MESON_THE_XVALUE) { fprintf(stderr, "Get MESON_THE_XVALUE by name failed.\n"); return 1; } if (g_enum_get_value_by_nick(xenum, "the-xvalue")->value != MESON_THE_XVALUE) { fprintf(stderr, "Get MESON_THE_XVALUE by nick failed.\n"); return 2; } if (g_flags_get_value_by_name(flags_enum, "MESON_THE_FIRST_VALUE")->value != MESON_THE_FIRST_VALUE) { fprintf(stderr, "Get MESON_THE_FIRST_VALUE by name failed.\n"); return 3; } if (g_flags_get_value_by_nick(flags_enum, "the-first-value")->value != MESON_THE_FIRST_VALUE) { fprintf(stderr, "Get MESON_THE_FIRST_VALUE by nick failed.\n"); return 4; } g_type_class_unref(xenum); g_type_class_unref(flags_enum); fprintf(stderr, "All ok.\n"); return 0; }
static gboolean flags_from_string (GType type, const gchar *string, gint *flags_value) { GFlagsClass *fclass; gchar *endptr, *prevptr; guint i, j, ret, value; gchar *flagstr; GFlagsValue *fv; const gchar *flag; gunichar ch; gboolean eos; g_return_val_if_fail (G_TYPE_IS_FLAGS (type), 0); g_return_val_if_fail (string != 0, 0); ret = TRUE; value = strtoul (string, &endptr, 0); if (endptr != string) /* parsed a number */ *flags_value = value; else { fclass = g_type_class_ref (type); flagstr = g_strdup (string); for (value = i = j = 0; ; i++) { eos = flagstr[i] == '\0'; if (!eos && flagstr[i] != '|') continue; flag = &flagstr[j]; endptr = &flagstr[i]; if (!eos) { flagstr[i++] = '\0'; j = i; } /* trim spaces */ for (;;) { ch = g_utf8_get_char (flag); if (!g_unichar_isspace (ch)) break; flag = g_utf8_next_char (flag); } while (endptr > flag) { prevptr = g_utf8_prev_char (endptr); ch = g_utf8_get_char (prevptr); if (!g_unichar_isspace (ch)) break; endptr = prevptr; } if (endptr > flag) { *endptr = '\0'; fv = g_flags_get_value_by_name (fclass, flag); if (!fv) fv = g_flags_get_value_by_nick (fclass, flag); if (fv) value |= fv->value; else { ret = FALSE; break; } } if (eos) { *flags_value = value; break; } } g_free (flagstr); g_type_class_unref (fclass); } return ret; }
/** * pyg_flags_get_value: * @flag_type: the GType of the flag. * @obj: a Python object representing the flag value * @val: a pointer to the location to store the integer representation of the flag. * * Converts a Python object to the integer equivalent. The conversion * will depend on the type of the Python object. If the object is an * integer, it is passed through directly. If it is a string, it will * be treated as a full or short flag name as defined in the GType. * If it is a tuple, then the items are treated as strings and ORed * together. * * Returns: 0 on success or -1 on failure */ gint pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val) { GFlagsClass *fclass = NULL; gint res = -1; g_return_val_if_fail(val != NULL, -1); if (!obj) { *val = 0; res = 0; } else if (PYGLIB_PyLong_Check(obj)) { *val = PYGLIB_PyLong_AsUnsignedLong(obj); res = 0; } else if (PyLong_Check(obj)) { *val = PyLong_AsLongLong(obj); res = 0; } else if (PYGLIB_PyUnicode_Check(obj)) { GFlagsValue *info; char *str = PYGLIB_PyUnicode_AsString(obj); if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type)); else { PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value"); res = -1; } info = g_flags_get_value_by_name(fclass, str); g_type_class_unref(fclass); if (!info) info = g_flags_get_value_by_nick(fclass, str); if (info) { *val = info->value; res = 0; } else { PyErr_SetString(PyExc_TypeError, "could not convert string"); res = -1; } } else if (PyTuple_Check(obj)) { int i, len; len = PyTuple_Size(obj); *val = 0; res = 0; if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type)); else { PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value"); res = -1; } for (i = 0; i < len; i++) { PyObject *item = PyTuple_GetItem(obj, i); char *str = PYGLIB_PyUnicode_AsString(item); GFlagsValue *info = g_flags_get_value_by_name(fclass, str); if (!info) info = g_flags_get_value_by_nick(fclass, str); if (info) { *val |= info->value; } else { PyErr_SetString(PyExc_TypeError, "could not convert string"); res = -1; break; } } g_type_class_unref(fclass); } else { PyErr_SetString(PyExc_TypeError, "flag values must be strings, ints, longs, or tuples"); res = -1; } return res; }
static guint resolve_flags_value(VALUE klass, GFlagsClass *gclass, VALUE flag_or_flags) { guint value = 0; switch (TYPE(flag_or_flags)) { case RUBY_T_NIL: value = 0; break; case RUBY_T_FIXNUM: case RUBY_T_BIGNUM: value = NUM2UINT(flag_or_flags); break; case RUBY_T_STRING: case RUBY_T_SYMBOL: { const gchar *name; GFlagsValue *info; name = RVAL2CSTR_ACCEPT_SYMBOL(flag_or_flags); info = g_flags_get_value_by_name(gclass, name); if (!info) { gchar *nick; nick = rbg_name_to_nick(name); info = g_flags_get_value_by_nick(gclass, nick); g_free(nick); } if (!info) { rb_raise(rb_eArgError, "unknown flag name: <%s>(%s)", name, g_type_name(G_TYPE_FROM_CLASS(gclass))); } value = info->value; break; } case RUBY_T_ARRAY: { int i, n; n = RARRAY_LEN(flag_or_flags); for (i = 0; i < n; i++) { value |= resolve_flags_value(klass, gclass, RARRAY_PTR(flag_or_flags)[i]); } break; } default: if (RVAL2CBOOL(rb_obj_is_kind_of(flag_or_flags, klass))) { value = NUM2UINT(rb_funcall(flag_or_flags, id_to_i, 0)); } else { rb_raise(rb_eArgError, "flag value must be one of " "nil, Fixnum, String, Symbol, %s or Array of them: " "<%s>(%s)", RBG_INSPECT(klass), RBG_INSPECT(flag_or_flags), g_type_name(G_TYPE_FROM_CLASS(gclass))); } break; } return value; }