+ goto error;
+ }
+
+ goto end;
+
+error:
+ BT_PUT(class);
+ ret = -1;
+
+end:
+ return ret;
+}
+
+struct bt_component_class *bt_component_class_source_create(const char *name,
+ bt_component_class_source_init_iterator_method init_iterator_method)
+{
+ struct bt_component_class_source *source_class = NULL;
+ int ret;
+
+ if (!name || !init_iterator_method) {
+ goto end;
+ }
+
+ source_class = g_new0(struct bt_component_class_source, 1);
+ if (!source_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&source_class->parent,
+ BT_COMPONENT_CLASS_TYPE_SOURCE, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ source_class = NULL;
+ goto end;
+ }
+
+ source_class->methods.init_iterator = init_iterator_method;
+
+end:
+ return &source_class->parent;
+}
+
+struct bt_component_class *bt_component_class_filter_create(const char *name,
+ bt_component_class_filter_init_iterator_method init_iterator_method)
+{
+ struct bt_component_class_filter *filter_class = NULL;
+ int ret;
+
+ if (!name || !init_iterator_method) {
+ goto end;
+ }
+
+ filter_class = g_new0(struct bt_component_class_filter, 1);
+ if (!filter_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&filter_class->parent,
+ BT_COMPONENT_CLASS_TYPE_FILTER, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ filter_class = NULL;
+ goto end;
+ }
+
+ filter_class->methods.init_iterator = init_iterator_method;
+
+end:
+ return &filter_class->parent;
+}
+
+struct bt_component_class *bt_component_class_sink_create(const char *name,
+ bt_component_class_sink_consume_method consume_method)
+{
+ struct bt_component_class_sink *sink_class = NULL;
+ int ret;
+
+ if (!name || !consume_method) {
+ goto end;
+ }
+
+ sink_class = g_new0(struct bt_component_class_sink, 1);
+ if (!sink_class) {
+ goto end;
+ }
+
+ ret = bt_component_class_init(&sink_class->parent,
+ BT_COMPONENT_CLASS_TYPE_SINK, name);
+ if (ret) {
+ /*
+ * If bt_component_class_init() fails, the component
+ * class is put, therefore its memory is already
+ * freed.
+ */
+ sink_class = NULL;
+ goto end;
+ }
+
+ sink_class->methods.consume = consume_method;
+
+end:
+ return &sink_class->parent;
+}
+
+int bt_component_class_set_init_method(
+ struct bt_component_class *component_class,
+ bt_component_class_init_method init_method)
+{
+ int ret = 0;
+
+ if (!component_class || !init_method) {
+ ret = -1;
+ goto end;
+ }
+
+ component_class->methods.init = init_method;
+
+end:
+ return ret;
+}
+
+int bt_component_class_set_destroy_method(
+ struct bt_component_class *component_class,
+ bt_component_class_destroy_method destroy_method)
+{
+ int ret = 0;
+
+ if (!component_class || !destroy_method) {
+ ret = -1;