KvpFrame * kvp_frame_get_frame(const KvpFrame *frame, const char *path) { char *key = NULL; frame = get_trailer_or_null (frame, path, &key); return kvp_value_get_frame(kvp_frame_get_slot (frame, key)); }
KvpValue * kvp_frame_get_slot_path (KvpFrame *frame, const char *first_key, ...) { va_list ap; KvpValue *value; const char *key; if (!frame || !first_key) return NULL; va_start (ap, first_key); key = first_key; value = NULL; while (TRUE) { value = kvp_frame_get_slot (frame, key); if (!value) break; key = va_arg (ap, const char *); if (!key) break; frame = kvp_value_get_frame (value); if (!frame) { value = NULL; break; } } va_end (ap); return value; }
/* Get pointer to last frame in path, or NULL if the path doesn't * exist. The string stored in keypath will be hopelessly mangled . */ static inline const KvpFrame * kvp_frame_get_frame_or_null_slash_trash (const KvpFrame *frame, char *key_path) { KvpValue *value; char *key, *next; if (!frame || !key_path) return NULL; key = key_path; key --; while (key) { key ++; while ('/' == *key) { key++; } if (0x0 == *key) break; /* trailing slash */ next = strchr (key, '/'); if (next) *next = 0x0; value = kvp_frame_get_slot (frame, key); if (!value) return NULL; frame = kvp_value_get_frame (value); if (!frame) return NULL; key = next; } return frame; }
void kvp_frame_set_slot_path (KvpFrame *frame, const KvpValue *new_value, const char *first_key, ...) { va_list ap; const char *key; if (!frame) return; g_return_if_fail (first_key && *first_key != '\0'); va_start (ap, first_key); key = first_key; while (TRUE) { KvpValue *value; const char *next_key; next_key = va_arg (ap, const char *); if (!next_key) { kvp_frame_set_slot (frame, key, new_value); break; } g_return_if_fail (*next_key != '\0'); value = kvp_frame_get_slot (frame, key); if (!value) { KvpFrame *new_frame = kvp_frame_new (); KvpValue *frame_value = kvp_value_new_frame (new_frame); kvp_frame_set_slot_nc (frame, key, frame_value); value = kvp_frame_get_slot (frame, key); if (!value) break; } frame = kvp_value_get_frame (value); if (!frame) break; key = next_key; } va_end (ap); }
/* Get the named frame, or create it if it doesn't exist. * gcc -O3 should inline it. It performs no error checks, * the caller is responsible of passing good keys and frames. */ static inline KvpFrame * get_or_make (KvpFrame *fr, const char * key) { KvpFrame *next_frame; KvpValue *value; value = kvp_frame_get_slot (fr, key); if (value) { next_frame = kvp_value_get_frame (value); } else { next_frame = kvp_frame_new (); kvp_frame_set_slot_nc (fr, key, kvp_value_new_frame_nc (next_frame)); } return next_frame; }
void kvp_frame_set_slot_path_gslist (KvpFrame *frame, const KvpValue *new_value, GSList *key_path) { if (!frame || !key_path) return; while (TRUE) { const char *key = static_cast<char*>(key_path->data); KvpValue *value; if (!key) return; g_return_if_fail (*key != '\0'); key_path = key_path->next; if (!key_path) { kvp_frame_set_slot (frame, key, new_value); return; } value = kvp_frame_get_slot (frame, key); if (!value) { KvpFrame *new_frame = kvp_frame_new (); KvpValue *frame_value = kvp_value_new_frame (new_frame); kvp_frame_set_slot_nc (frame, key, frame_value); value = kvp_frame_get_slot (frame, key); if (!value) return; } frame = kvp_value_get_frame (value); if (!frame) return; } }
/* Check if the session requires features unknown to this version of GnuCash. * * Returns a message to display if we found unknown features, NULL if we're okay. */ gchar *gnc_features_test_unknown (QofBook *book) { KvpFrame *frame = qof_book_get_slots (book); KvpValue *value; /* Setup the known_features hash table */ gnc_features_init(); g_assert(frame); value = kvp_frame_get_value(frame, "features"); if (value) { GList* features_list = NULL; frame = kvp_value_get_frame(value); g_assert(frame); /* Iterate over the members of this frame for unknown features */ kvp_frame_for_each_slot(frame, &gnc_features_test_one, &features_list); if (features_list) { GList *i; char* msg = g_strdup( _("This Dataset contains features not supported by this " "version of GnuCash. You must use a newer version of " "GnuCash in order to support the following features:" )); for (i = features_list; i; i = i->next) { char *tmp = g_strconcat(msg, "\n* ", i->data, NULL); g_free (msg); msg = tmp; } g_list_free(features_list); return msg; } } return NULL; }
KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame, const GSList *key_path) { if (!frame || !key_path) return NULL; while (TRUE) { const char *key = static_cast<const char*>(key_path->data); KvpValue *value; if (!key) break; value = kvp_frame_get_slot (frame, key); if (!value) break; key_path = key_path->next; if (!key_path) return value; frame = kvp_value_get_frame (value); if (!frame) break; } return NULL; }
gchar* kvp_value_to_string(const KvpValue *val) { gchar *tmp1; gchar *tmp2; const gchar *ctmp; g_return_val_if_fail(val, NULL); switch (kvp_value_get_type(val)) { case KVP_TYPE_GINT64: return g_strdup_printf("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")", kvp_value_get_gint64(val)); break; case KVP_TYPE_DOUBLE: return g_strdup_printf("KVP_VALUE_DOUBLE(%g)", kvp_value_get_double(val)); break; case KVP_TYPE_NUMERIC: tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val)); tmp2 = g_strdup_printf("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : ""); g_free(tmp1); return tmp2; break; case KVP_TYPE_STRING: tmp1 = kvp_value_get_string (val); return g_strdup_printf("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : ""); break; case KVP_TYPE_GUID: gchar guidstr[GUID_ENCODING_LENGTH+1]; guid_to_string_buff(kvp_value_get_guid(val),guidstr); tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", guidstr); return tmp2; break; case KVP_TYPE_TIMESPEC: tmp1 = g_new0 (char, 40); gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1); tmp2 = g_strdup_printf("KVP_VALUE_TIMESPEC(%s)", tmp1); g_free(tmp1); return tmp2; break; case KVP_TYPE_BINARY: { guint64 len; void *data; data = kvp_value_get_binary(val, &len); tmp1 = binary_to_string(data, len); return g_strdup_printf("KVP_VALUE_BINARY(%s)", tmp1 ? tmp1 : ""); } break; case KVP_TYPE_GLIST: tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val)); tmp2 = g_strdup_printf("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : ""); g_free(tmp1); return tmp2; break; case KVP_TYPE_FRAME: tmp1 = kvp_frame_to_string(kvp_value_get_frame(val)); tmp2 = g_strdup_printf("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : ""); g_free(tmp1); return tmp2; break; case KVP_TYPE_GDATE: return g_strdup_printf("KVP_VALUE_GDATE(%04d-%02d-%02d)", g_date_get_year(&val->value.gdate), g_date_get_month(&val->value.gdate), g_date_get_day(&val->value.gdate)); default: break; } g_assert(FALSE); /* must not be reached */ return g_strdup(""); }
static void save_slot( const gchar* key, KvpValue* value, gpointer data ) { slot_info_t* pSlot_info = (slot_info_t*)data; gsize curlen; g_return_if_fail( key != NULL ); g_return_if_fail( value != NULL ); g_return_if_fail( data != NULL ); // Ignore if we've already run into a failure if ( !pSlot_info->is_ok ) { return; } curlen = pSlot_info->path->len; pSlot_info->pKvpValue = value; if ( curlen != 0 ) { (void)g_string_append( pSlot_info->path, "/" ); } (void)g_string_append( pSlot_info->path, key ); pSlot_info->value_type = kvp_value_get_type( value ); switch ( pSlot_info->value_type ) { case KVP_TYPE_FRAME: { KvpFrame* pKvpFrame = kvp_value_get_frame( value ); GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = kvp_value_new_guid( &guid ); pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); kvp_frame_for_each_slot( pKvpFrame, save_slot, pNewInfo ); kvp_value_delete( pSlot_info->pKvpValue ); pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; case KVP_TYPE_GLIST: { GList *cursor; GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = kvp_value_new_guid( &guid ); pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); g_return_if_fail( pSlot_info->is_ok ); for (cursor = kvp_value_get_glist(value); cursor; cursor = cursor->next) { kvp_value *val = (kvp_value*)cursor->data; save_slot("", val, pNewInfo); } kvp_value_delete( pSlot_info->pKvpValue ); pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; default: { pSlot_info->is_ok = gnc_sql_do_db_operation( pSlot_info->be, OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table ); } break; } (void)g_string_truncate( pSlot_info->path, curlen ); }
static void add_kvp_value_node(xmlNodePtr node, gchar *tag, kvp_value* val) { xmlNodePtr val_node; gchar *tmp_str1; kvp_value_t kvp_type; kvp_type = kvp_value_get_type(val); if (kvp_type == KVP_TYPE_STRING) val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, BAD_CAST kvp_value_get_string(val)); else if (kvp_type == KVP_TYPE_TIMESPEC) val_node = NULL; else if (kvp_type == KVP_TYPE_GDATE) { GDate d = kvp_value_get_gdate(val); val_node = gdate_to_dom_tree(tag, &d); xmlAddChild (node, val_node); } else val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, NULL); switch (kvp_value_get_type(val)) { case KVP_TYPE_GINT64: add_text_to_node(val_node, "integer", g_strdup_printf("%" G_GINT64_FORMAT, kvp_value_get_gint64(val))); break; case KVP_TYPE_DOUBLE: add_text_to_node(val_node, "double", double_to_string(kvp_value_get_double(val))); break; case KVP_TYPE_NUMERIC: add_text_to_node(val_node, "numeric", gnc_numeric_to_string(kvp_value_get_numeric(val))); break; case KVP_TYPE_STRING: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string"); break; case KVP_TYPE_GUID: /* THREAD-UNSAFE */ add_text_to_node(val_node, "guid", g_strdup(guid_to_string(kvp_value_get_guid(val)))); break; case KVP_TYPE_TIMESPEC: { Timespec ts = kvp_value_get_timespec (val); val_node = timespec_to_dom_tree (tag, &ts); xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec"); xmlAddChild (node, val_node); } break; case KVP_TYPE_GDATE: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "gdate"); break; case KVP_TYPE_BINARY: { guint64 size; void *binary_data = kvp_value_get_binary(val, &size); xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "binary"); g_return_if_fail(binary_data); tmp_str1 = binary_to_string(binary_data, size); xmlNodeSetContent(val_node, BAD_CAST tmp_str1); g_free(tmp_str1); } break; case KVP_TYPE_GLIST: { GList *cursor; xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list"); for (cursor = kvp_value_get_glist(val); cursor; cursor = cursor->next) { kvp_value *val = (kvp_value*)cursor->data; add_kvp_value_node(val_node, "slot:value", val); } } break; case KVP_TYPE_FRAME: { kvp_frame *frame; xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "frame"); frame = kvp_value_get_frame (val); if (!frame || !kvp_frame_get_hash (frame)) break; g_hash_table_foreach_sorted(kvp_frame_get_hash(frame), add_kvp_slot, val_node, (GCompareFunc)strcmp); } break; } }
static void add_kvp_value_node(xmlNodePtr node, gchar *tag, KvpValue* val) { xmlNodePtr val_node; kvp_value_t kvp_type; kvp_type = kvp_value_get_type(val); if (kvp_type == KVP_TYPE_STRING) { gchar *newstr = g_strdup (kvp_value_get_string(val)); val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, checked_char_cast (newstr)); g_free (newstr); } else if (kvp_type == KVP_TYPE_TIMESPEC) val_node = NULL; else if (kvp_type == KVP_TYPE_GDATE) { GDate d = kvp_value_get_gdate(val); val_node = gdate_to_dom_tree(tag, &d); xmlAddChild (node, val_node); } else val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, NULL); switch (kvp_value_get_type(val)) { case KVP_TYPE_GINT64: add_text_to_node(val_node, "integer", g_strdup_printf("%" G_GINT64_FORMAT, kvp_value_get_gint64(val))); break; case KVP_TYPE_DOUBLE: add_text_to_node(val_node, "double", double_to_string(kvp_value_get_double(val))); break; case KVP_TYPE_NUMERIC: add_text_to_node(val_node, "numeric", gnc_numeric_to_string(kvp_value_get_numeric(val))); break; case KVP_TYPE_STRING: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string"); break; case KVP_TYPE_GUID: { gchar guidstr[GUID_ENCODING_LENGTH+1]; guid_to_string_buff(kvp_value_get_guid(val), guidstr); add_text_to_node(val_node, "guid", guidstr); break; } case KVP_TYPE_TIMESPEC: { Timespec ts = kvp_value_get_timespec (val); val_node = timespec_to_dom_tree (tag, &ts); xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec"); xmlAddChild (node, val_node); } break; case KVP_TYPE_GDATE: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "gdate"); break; case KVP_TYPE_GLIST: { GList *cursor; xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list"); for (cursor = kvp_value_get_glist(val); cursor; cursor = cursor->next) { KvpValue *val = (KvpValue*)cursor->data; add_kvp_value_node(val_node, "slot:value", val); } } break; case KVP_TYPE_FRAME: { KvpFrame *frame; const char ** keys; unsigned int i; xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "frame"); frame = kvp_value_get_frame (val); if (!frame) break; keys = kvp_frame_get_keys(frame); for (i = 0; keys[i]; ++i) add_kvp_slot(keys[i], kvp_frame_get_value(frame, keys[i]), val_node); g_free(keys); } break; default: break; } }