void qof_instance_foreach_slot (const QofInstance *inst, const char* path, void (*proc)(const char*, const GValue*, void*), void* data) { auto slot = inst->kvp_data->get_slot(path); if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME) return; auto frame = slot->get<KvpFrame*>(); wrap_param new_data {proc, data}; frame->for_each_slot(wrap_gvalue_function, &new_data); }
static void add_kvp_value_node(xmlNodePtr node, const gchar *tag, KvpValue* val) { xmlNodePtr val_node; switch (val->get_type()) { case KvpValue::Type::STRING: { auto newstr = g_strdup(val->get<const char*>()); val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, checked_char_cast (newstr)); g_free (newstr); break; } case KvpValue::Type::TIMESPEC: val_node = NULL; break; case KvpValue::Type::GDATE: { auto d = val->get<GDate>(); val_node = gdate_to_dom_tree(tag, &d); xmlAddChild (node, val_node); break; } default: val_node = xmlNewTextChild(node, NULL, BAD_CAST tag, NULL); break; } switch (val->get_type()) { case KvpValue::Type::INT64: add_text_to_node(val_node, "integer", g_strdup_printf("%" G_GINT64_FORMAT, val->get<int64_t>())); break; case KvpValue::Type::DOUBLE: add_text_to_node(val_node, "double", double_to_string(val->get<double>())); break; case KvpValue::Type::NUMERIC: add_text_to_node(val_node, "numeric", gnc_numeric_to_string(val->get<gnc_numeric>())); break; case KvpValue::Type::STRING: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "string"); break; case KvpValue::Type::GUID: { gchar guidstr[GUID_ENCODING_LENGTH+1]; guid_to_string_buff(val->get<GncGUID*>(), guidstr); add_text_to_node(val_node, "guid", guidstr); break; } case KvpValue::Type::TIMESPEC: { auto ts = val->get<Timespec>(); val_node = timespec_to_dom_tree (tag, &ts); xmlSetProp (val_node, BAD_CAST "type", BAD_CAST "timespec"); xmlAddChild (node, val_node); break; } case KvpValue::Type::GDATE: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "gdate"); break; case KvpValue::Type::GLIST: xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "list"); for (auto cursor = val->get<GList*>(); cursor; cursor = cursor->next) { auto val = static_cast<KvpValue*>(cursor->data); add_kvp_value_node(val_node, "slot:value", val); } break; case KvpValue::Type::FRAME: { xmlSetProp(val_node, BAD_CAST "type", BAD_CAST "frame"); auto frame = val->get<KvpFrame*>(); if (!frame) break; frame->for_each_slot(add_kvp_slot, static_cast<void*>(val_node)); break; } default: break; } }
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 = value->get_type(); switch ( pSlot_info->value_type ) { case KvpValue::Type::FRAME: { auto pKvpFrame = value->get<KvpFrame*>(); auto guid = guid_new(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue{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 ); pKvpFrame->for_each_slot(save_slot, pNewInfo); delete pSlot_info->pKvpValue; pSlot_info->pKvpValue = oldValue; g_string_free( pNewInfo->path, TRUE ); g_slice_free( slot_info_t, pNewInfo ); } break; case KvpValue::Type::GLIST: { GncGUID guid = guid_new_return(); slot_info_t *pNewInfo = slot_info_copy( pSlot_info, &guid ); KvpValue *oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue{&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 (auto cursor = value->get<GList*>(); cursor; cursor = cursor->next) { auto val = static_cast<KvpValue*>(cursor->data); save_slot("", val, pNewInfo); } 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 save_slot (const char* key, KvpValue* value, gpointer data) { slot_info_t* pSlot_info = (slot_info_t*)data; 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; } auto curlen = pSlot_info->path.length(); pSlot_info->pKvpValue = value; if (curlen != 0) pSlot_info->path += "/"; pSlot_info->path += key; pSlot_info->value_type = value->get_type (); switch (pSlot_info->value_type) { case KvpValue::Type::FRAME: { auto pKvpFrame = value->get<KvpFrame*> (); auto guid = guid_new (); slot_info_t* pNewInfo = slot_info_copy (pSlot_info, guid); KvpValue* oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue {guid}; pSlot_info->is_ok = pSlot_info->be->do_db_operation(OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table); g_return_if_fail (pSlot_info->is_ok); pKvpFrame->for_each_slot (save_slot, pNewInfo); delete pSlot_info->pKvpValue; pSlot_info->pKvpValue = oldValue; delete pNewInfo; } break; case KvpValue::Type::GLIST: { GncGUID* guid = guid_new (); slot_info_t* pNewInfo = slot_info_copy (pSlot_info, guid); KvpValue* oldValue = pSlot_info->pKvpValue; pSlot_info->pKvpValue = new KvpValue {guid}; // Transfer ownership! pSlot_info->is_ok = pSlot_info->be->do_db_operation(OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table); g_return_if_fail (pSlot_info->is_ok); for (auto cursor = value->get<GList*> (); cursor; cursor = cursor->next) { auto val = static_cast<KvpValue*> (cursor->data); save_slot ("", val, pNewInfo); } delete pSlot_info->pKvpValue; pSlot_info->pKvpValue = oldValue; delete pNewInfo; } break; default: { pSlot_info->is_ok = pSlot_info->be->do_db_operation (OP_DB_INSERT, TABLE_NAME, TABLE_NAME, pSlot_info, col_table); } break; } pSlot_info->path.erase(curlen); }