00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "opensync.h"
00022 #include "opensync_internals.h"
00023
00028
00029 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00030 typedef struct conv_tree {
00031 OSyncFormatEnv *env;
00032 OSyncObjType *type;
00033
00034
00035 GList *unused;
00036
00037 GList *search;
00038 } conv_tree;
00039
00040 typedef struct vertice {
00041 OSyncObjFormat *format;
00042
00043
00044
00045
00046
00047
00048 OSyncChange *change;
00049 osync_bool free_change_data;
00050 osync_bool free_change;
00051
00057 size_t references;
00058
00060 GList *path;
00061
00062 unsigned losses;
00063 unsigned objtype_changes;
00064 unsigned conversions;
00065
00066 } vertice;
00067 #endif
00068
00069 static OSyncFormatConverter *osync_conv_find_converter_objformat(OSyncFormatEnv *env, OSyncObjFormat *fmt_src, OSyncObjFormat *fmt_trg)
00070 {
00071 GList *element = NULL;
00072 for (element = env->converters; element; element = element->next) {
00073 OSyncFormatConverter *converter = element->data;
00074 if (fmt_src == converter->source_format && fmt_trg == converter->target_format)
00075 return converter;
00076 }
00077 return NULL;
00078 }
00079
00080 osync_bool osync_converter_invoke(OSyncFormatConverter *converter, OSyncChange *change, void *converter_data, OSyncError **error)
00081 {
00082 osync_trace(TRACE_ENTRY, "osync_converter_invoke(%p, %p, %p)", converter, change, error);
00083 osync_trace(TRACE_INTERNAL, "converter: Type: %i, source: %s, target %s", converter->type, converter->source_format->name, converter->target_format->name);
00084 char *data = NULL;
00085 int datasize = 0;
00086 osync_bool ret = TRUE;
00087 if (converter->type == CONVERTER_DETECTOR && !converter->convert_func) {
00088 change->format = converter->target_format;
00089 change->objtype = osync_change_get_objformat(change)->objtype;
00090 osync_trace(TRACE_EXIT, "osync_converter_invoke: TRUE: Detector path");
00091 return TRUE;
00092 }
00093
00094 if (!converter->convert_func) {
00095 osync_error_set(error, OSYNC_ERROR_GENERIC, "Invalid converter");
00096 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00097 return FALSE;
00098 }
00099
00100 if (change->data) {
00101
00102
00103 osync_bool free_input = FALSE;
00104 if ((ret = converter->convert_func(converter_data, change->data, change->size, &data, &datasize, &free_input, error))) {
00105
00106 if (converter->type == CONVERTER_DECAP) {
00107 if (!free_input) {
00108
00109 if (!converter->target_format->copy_func) {
00110
00111
00112
00113 osync_debug("OSYNC", 0, "Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
00114 osync_error_set(error, OSYNC_ERROR_GENERIC, "Format %s don't have a copy function, but a no-copy converter was registered", converter->target_format->name);
00115 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00116 return FALSE;
00117 }
00118 converter->target_format->copy_func(data, datasize, &data, &datasize);
00119 }
00120 }
00121
00122 if (free_input) {
00123 if (converter->source_format->destroy_func) {
00124 converter->source_format->destroy_func(change->data, change->size);
00125 } else
00126 osync_debug("OSYNC", 1, "Format %s don't have a destroy function. Possible memory leak", converter->source_format->name);
00127 }
00128 change->data = data;
00129 change->size = datasize;
00130
00131
00132 }
00133 }
00134
00135 if (ret) {
00136 osync_debug("OSYNC", 3, "Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
00137 change->format = converter->target_format;
00138 change->objtype = osync_change_get_objformat(change)->objtype;
00139 osync_trace(TRACE_EXIT, "osync_converter_invoke: TRUE");
00140 } else
00141 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke: %s", osync_error_print(error));
00142 return ret;
00143 }
00144
00145 OSyncChange *osync_converter_invoke_decap(OSyncFormatConverter *converter, OSyncChange *change, osync_bool *free_output)
00146 {
00147 osync_trace(TRACE_ENTRY, "osync_converter_invoke_decap(%p, %p, %p)", converter, change, free_output);
00148
00149 *free_output = FALSE;
00150
00151 if (!converter->convert_func) {
00152 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: No convert function");
00153 return NULL;
00154 }
00155
00156 if (converter->type != CONVERTER_DECAP) {
00157 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: Not a decap");
00158 return NULL;
00159 }
00160
00161 OSyncChange *new_change = osync_change_new();
00162
00163
00164 if (change->changetype != CHANGE_DELETED && change->data) {
00165
00166 OSyncError *error = NULL;
00167 if (!converter->convert_func(NULL, change->data, change->size, &(new_change->data), &(new_change->size), free_output, &error)) {
00168 osync_trace(TRACE_EXIT_ERROR, "osync_converter_invoke_decap: %s", osync_error_print(&error));
00169 osync_error_free(&error);
00170 return NULL;
00171 }
00172 new_change->has_data = change->has_data;
00173 }
00174 osync_debug("OSYNC", 3, "Converting! replacing format %s with %s", converter->source_format->name, converter->target_format->name);
00175 new_change->format = converter->target_format;
00176 new_change->objtype = osync_change_get_objformat(new_change)->objtype;
00177 new_change->changetype = change->changetype;
00178 osync_trace(TRACE_EXIT, "osync_converter_invoke_decap: %p", new_change);
00179 return new_change;
00180 }
00181
00189 int compare_vertice_distance(const void *a, const void *b)
00190 {
00191 const vertice *va = a;
00192 const vertice *vb = b;
00193 if (va->losses < vb->losses)
00194 return -1;
00195 else if (va->losses > vb->losses)
00196 return 1;
00197 else if (va->objtype_changes < vb->objtype_changes)
00198 return -1;
00199 else if (va->objtype_changes > vb->objtype_changes)
00200 return 1;
00201 else if (va->conversions < vb->conversions)
00202 return -1;
00203 else if (va->conversions > vb->conversions)
00204 return 1;
00205 else
00206 return 0;
00207 }
00208
00210
00211
00212
00213
00214
00217 static void deref_vertice(vertice *vertice)
00218 {
00219
00220
00221
00222
00223 if (--vertice->references > 0)
00224 return;
00225
00226 g_list_free(vertice->path);
00227 if (vertice->change && vertice->free_change) {
00228 if (vertice->free_change_data)
00229 osync_change_free_data(vertice->change);
00230 osync_change_free(vertice->change);
00231 }
00232
00233 g_free(vertice);
00234 }
00235
00241 vertice *get_next_vertice_neighbour(OSyncFormatEnv *env, conv_tree *tree, vertice *ve)
00242 {
00243 GList *c = NULL;
00244 osync_trace(TRACE_ENTRY, "get_next_vertice_neighbour(%p, %p, %p:%s)", env, tree, ve, ve->format ? ve->format->name : "None");
00245
00246 for (c = tree->unused; c; c = c->next) {
00247 OSyncFormatConverter *converter = c->data;
00248 OSyncObjFormat *fmt_target = converter->target_format;
00249
00250
00251 if (strcmp(converter->source_format->name, ve->format->name))
00252 continue;
00253
00254
00255 if (converter->detect_func) {
00256 if (!ve->change) {
00257 osync_trace(TRACE_INTERNAL,
00258 "We would call a converter to %s, but there is no change data on vertice", fmt_target->name);
00259 continue;
00260 }
00261
00262 if (ve->change->changetype != CHANGE_DELETED) {
00263 if (!converter->detect_func(env, ve->change->data, ve->change->size)) {
00264 osync_trace(TRACE_INTERNAL, "Invoked detector for converter from %s to %s: FALSE", converter->source_format->name, converter->target_format->name);
00265 continue;
00266 }
00267 }
00268
00269 osync_trace(TRACE_INTERNAL, "Invoked detector for converter from %s to %s: TRUE", converter->source_format->name, converter->target_format->name);
00270 }
00271
00272 OSyncChange *new_change = NULL;
00273 osync_bool free_output = TRUE;
00274 if (converter->type == CONVERTER_DECAP) {
00275 if (!ve->change) {
00276 osync_trace(TRACE_INTERNAL, "A desencapsulator to %s would be called, but we can't because the data on this vertice wasn't converted", fmt_target->name);
00277 continue;
00278 }
00279
00280 if (!(new_change = osync_converter_invoke_decap(converter, ve->change, &free_output)))
00281 continue;
00282 }
00283
00284
00285
00286
00287
00288
00289 tree->unused = g_list_remove(tree->unused, converter);
00290
00291
00292 vertice *neigh = g_malloc0(sizeof(vertice));
00293
00294 neigh->references = 1;
00295 neigh->format = fmt_target;
00296 neigh->path = g_list_copy(ve->path);
00297 neigh->path = g_list_append(neigh->path, converter);
00298
00299 if (new_change) {
00300 neigh->change = new_change;
00301 neigh->free_change = TRUE;
00302 neigh->free_change_data = free_output;
00303 } else {
00304 neigh->change = NULL;
00305 neigh->free_change = FALSE;
00306 neigh->free_change_data = FALSE;
00307 }
00308
00309
00310 neigh->conversions = ve->conversions + 1;
00311 neigh->losses = ve->losses;
00312 if (converter->type == CONVERTER_DECAP)
00313 neigh->losses++;
00314 neigh->objtype_changes = ve->objtype_changes;
00315 if (converter->source_format->objtype != converter->target_format->objtype)
00316 neigh->objtype_changes++;
00317
00318 osync_trace(TRACE_EXIT, "get_next_vertice_neighbour: %p:%s", neigh, neigh->format ? neigh->format->name : "None");
00319 return neigh;
00320 }
00321 osync_trace(TRACE_EXIT, "get_next_vertice_neighbour: None found");
00322 return NULL;
00323 }
00324
00348 static osync_bool osync_conv_find_path_fn(OSyncFormatEnv *env, OSyncChange *start, OSyncPathTargetFn target_fn, const void *fndata, GList **path_edges)
00349 {
00350 osync_trace(TRACE_ENTRY, "osync_conv_find_path_fn(%p, %p(%s, %s), %p, %p, %p)", env, start, start ? start->uid : "None", start ? start->format->name : "None", target_fn, fndata, path_edges);
00351
00352 g_assert(start->format);
00353
00354 *path_edges = NULL;
00355 osync_bool ret = FALSE;
00356 vertice *result = NULL;
00357
00358
00359
00360
00361
00362 conv_tree *tree = g_malloc0(sizeof(conv_tree));
00363 tree->unused = g_list_copy(env->converters);
00364
00365
00366
00367 vertice *begin = g_malloc0(sizeof(vertice));
00368 begin->format = start->format;
00369 begin->path = NULL;
00370 begin->references = 1;
00371 begin->change = start;
00372 begin->free_change_data = FALSE;
00373 begin->free_change = FALSE;
00374
00375 tree->search = g_list_append(NULL, begin);
00376
00377 while (g_list_length(tree->search)) {
00378 vertice *neighbour = NULL;
00379
00380
00381 vertice *current = tree->search->data;
00382 tree->search = g_list_remove(tree->search, current);
00383
00384 osync_debug("OSCONV", 4, "Next vertice: %s.", current->format->name);
00385
00386 if (target_fn(fndata, current->format)) {
00387
00388 result = current;
00389 break;
00390 }
00391 osync_debug("OSCONV", 4, "Looking at %s's neighbours.", current->format->name);
00392 while ((neighbour = get_next_vertice_neighbour(env, tree, current))) {
00393 osync_debug("OSCONV", 4, "%s's neighbour: %s", current->format->name, neighbour->format->name);
00394 tree->search = g_list_insert_sorted(tree->search, neighbour, compare_vertice_distance);
00395 }
00396
00397 deref_vertice(current);
00398 }
00399
00400 g_list_foreach(tree->search, (GFunc)deref_vertice, NULL);
00401
00402 if (result) {
00403
00404 *path_edges = g_list_copy(result->path);
00405
00406 deref_vertice(result);
00407 ret = TRUE;
00408 goto free_tree;
00409 }
00410
00411 free_tree:
00412 g_list_free(tree->unused);
00413 g_list_free(tree->search);
00414 g_free(tree);
00415 if (ret)
00416 osync_trace(TRACE_EXIT, "osync_conv_find_path_fn: TRUE");
00417 else
00418 osync_trace(TRACE_EXIT_ERROR, "osync_conv_find_path_fn: FALSE");
00419 return ret;
00420 }
00421
00422 osync_bool osync_conv_convert_fn(OSyncFormatEnv *env, OSyncChange *change, OSyncPathTargetFn target_fn, const void *fndata, const char *extension_name, OSyncError **error)
00423 {
00424 osync_trace(TRACE_ENTRY, "osync_conv_convert_fn(%p, %p, %p, %p, %p)", env, change, target_fn, fndata, error);
00425 g_assert(change);
00426 g_assert(target_fn);
00427 OSyncObjFormat *source = osync_change_get_objformat(change);
00428 osync_assert_msg(source, "Cannot convert! change has no objformat!");
00429 GList *path = NULL;
00430 osync_bool ret = TRUE;
00431
00432
00433 if (target_fn(fndata, source)) {
00434 osync_trace(TRACE_EXIT, "osync_conv_convert_fn: Target already valid");
00435 return TRUE;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 ret = FALSE;
00452 if (!osync_conv_find_path_fn(env, change, target_fn, fndata, &path)) {
00453 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to find a conversion path to the format requested");
00454 osync_trace(TRACE_EXIT_ERROR, "osync_conv_convert_fn: %s", osync_error_print(error));
00455 goto out;
00456 }
00457
00458 if (change->changetype == CHANGE_DELETED) {
00459 OSyncFormatConverter *converter = g_list_last(path)->data;
00460 change->format = converter->target_format;
00461 change->objtype = osync_change_get_objformat(change)->objtype;
00462 } else {
00463 for (; path; path = path->next) {
00464 OSyncFormatConverter *converter = path->data;
00465
00466 osync_trace(TRACE_INTERNAL, "initialize converter: %p", converter->init_func);
00467
00468
00469 void *converter_data = NULL;
00470 if (converter->init_func)
00471 converter_data = converter->init_func();
00472
00473 if (extension_name) {
00474 osync_trace(TRACE_INTERNAL, "initialize extension: %s", extension_name);
00475
00476
00477 OSyncFormatExtension *extension = osync_conv_find_extension(env, converter->source_format, converter->target_format, extension_name);
00478 osync_trace(TRACE_INTERNAL, "extension: %p", extension);
00479 if (extension)
00480 extension->init_func(converter_data);
00481 } else {
00482
00483 osync_trace(TRACE_INTERNAL, "initialize all extensions");
00484
00485 GList *e;
00486 for (e = env->extensions; e; e = e->next) {
00487 OSyncFormatExtension *extension = e->data;
00488 osync_trace(TRACE_INTERNAL, "extension: %s", extension->name);
00489 osync_trace(TRACE_INTERNAL, "%p:%p %p:%p", extension->from_format, converter->source_format, extension->to_format, converter->target_format);
00490 if (extension->from_format == converter->source_format && extension->to_format == converter->target_format)
00491 extension->init_func(converter_data);
00492 }
00493 }
00494
00495 if (!osync_converter_invoke(converter, change, converter_data, error)) {
00496 osync_trace(TRACE_EXIT_ERROR, "osync_conv_convert_fn: %s", osync_error_print(error));
00497 goto out_free_path;
00498 }
00499
00500
00501 if (converter->fin_func)
00502 converter->fin_func(converter_data);
00503
00504 }
00505 }
00506 ret = TRUE;
00507
00508 osync_trace(TRACE_EXIT, "osync_conv_convert_fn: TRUE");
00509 out_free_path:
00510 g_list_free(path);
00511 out:
00512 return ret;
00513 }
00514
00519 static osync_bool target_fn_fmtlist(const void *data, OSyncObjFormat *fmt)
00520 {
00521 const GList *l = data;
00522 const GList *i;
00523 for (i = l; i; i = i->next) {
00524 OSyncObjFormat *f = i->data;
00525 if (!strcmp(fmt->name, f->name))
00526 return TRUE;
00527 }
00528
00529 return FALSE;
00530 }
00531
00534 osync_bool osync_conv_convert_fmtlist(OSyncFormatEnv *env, OSyncChange *change, GList *targets)
00535 {
00536 return osync_conv_convert_fn(env, change, target_fn_fmtlist, targets, NULL, NULL);
00537 }
00538
00539 osync_bool osync_conv_find_path_fmtlist(OSyncFormatEnv *env, OSyncChange *start, GList *targets, GList **retlist)
00540 {
00541 return osync_conv_find_path_fn(env, start, target_fn_fmtlist, targets, retlist);
00542 }
00543
00544 osync_bool osync_conv_objtype_is_any(const char *objstr)
00545 {
00546 if (!strcmp(objstr, "data"))
00547 return TRUE;
00548 return FALSE;
00549 }
00550
00560
00568 OSyncFormatEnv *osync_conv_env_new(OSyncEnv *env)
00569 {
00570 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, env);
00571 OSyncFormatEnv *conv_env = g_malloc0(sizeof(OSyncFormatEnv));
00572 GList *o;
00573
00574
00575
00576 OSyncObjType *type = NULL;
00577 for (o = env->objtype_templates; o; o = o->next) {
00578 OSyncObjTypeTemplate *otempl = o->data;
00579 type = g_malloc0(sizeof(OSyncObjType));
00580 type->name = g_strdup(otempl->name);
00581 type->env = conv_env;
00582 conv_env->objtypes = g_list_append(conv_env->objtypes, type);
00583 }
00584
00585
00586 GList *f = NULL;
00587 for (f = env->format_templates; f; f = f->next) {
00588 OSyncObjFormatTemplate *ftempl = f->data;
00589 OSyncObjType *type = osync_conv_find_objtype(conv_env, ftempl->objtype);
00590 g_assert(type);
00591 OSyncObjFormat *format = g_malloc0(sizeof(OSyncObjFormat));
00592 format->env = conv_env;
00593 format->name = g_strdup(ftempl->name);
00594 format->objtype = type;
00595
00596 format->cmp_func = ftempl->cmp_func;
00597 format->merge_func = ftempl->merge_func;
00598 format->duplicate_func = ftempl->duplicate_func;
00599 format->copy_func = ftempl->copy_func;
00600 format->create_func = ftempl->create_func;
00601 format->destroy_func = ftempl->destroy_func;
00602 format->print_func = ftempl->print_func;
00603 format->revision_func = ftempl->revision_func;
00604 format->marshall_func = ftempl->marshall_func;
00605 format->demarshall_func = ftempl->demarshall_func;
00606 type->formats = g_list_append(type->formats, format);
00607 conv_env->objformats = g_list_append(conv_env->objformats, format);
00608 }
00609
00610
00611 GList *i;
00612 for (i = env->extension_templates; i; i = i->next) {
00613 OSyncFormatExtensionTemplate *extension_template = i->data;
00614 OSyncObjFormat *from_format = osync_conv_find_objformat(conv_env, extension_template->from_formatname);
00615 OSyncObjFormat *to_format = osync_conv_find_objformat(conv_env, extension_template->to_formatname);
00616 if (!from_format || !to_format)
00617 continue;
00618
00619 OSyncFormatExtension *extension = g_malloc0(sizeof(OSyncFormatExtension));
00620 extension->name = g_strdup(extension_template->name);
00621 extension->init_func = extension_template->init_func;
00622 extension->from_format = from_format;
00623 extension->to_format = to_format;
00624
00625 conv_env->extensions = g_list_append(conv_env->extensions, extension);
00626 }
00627
00628
00629 for (i = env->converter_templates; i; i = i->next) {
00630 OSyncConverterTemplate *convtmpl = i->data;
00631
00632 osync_trace(TRACE_INTERNAL, "New converter from %s to %s", convtmpl->source_format, convtmpl->target_format);
00633
00634 OSyncObjFormat *fmt_src = osync_conv_find_objformat(conv_env, convtmpl->source_format);
00635 OSyncObjFormat *fmt_trg = osync_conv_find_objformat(conv_env, convtmpl->target_format);
00636 if (!fmt_src || !fmt_trg)
00637 continue;
00638 OSyncFormatConverter *converter = g_malloc0(sizeof(OSyncFormatConverter));
00639 converter->source_format = fmt_src;
00640 converter->target_format = fmt_trg;
00641 converter->convert_func = convtmpl->convert_func;
00642 converter->type = convtmpl->type;
00643 converter->init_func = convtmpl->init_func;
00644
00645 conv_env->converters = g_list_append(conv_env->converters, converter);
00646 }
00647
00648
00649 for (i = env->data_detectors; i; i = i->next) {
00650 OSyncDataDetector *detector = i->data;
00651 OSyncFormatConverter *converter = osync_conv_find_converter(conv_env, detector->sourceformat, detector->targetformat);
00652 if (!converter) {
00653 OSyncObjFormat *fmt_src = osync_conv_find_objformat(conv_env, detector->sourceformat);
00654 OSyncObjFormat *fmt_trg = osync_conv_find_objformat(conv_env, detector->targetformat);
00655 if (!fmt_src || !fmt_trg)
00656 continue;
00657 converter = g_malloc0(sizeof(OSyncFormatConverter));
00658 converter->source_format = fmt_src;
00659 converter->target_format = fmt_trg;
00660 converter->type = CONVERTER_DETECTOR;
00661 }
00662 converter->detect_func = detector->detect_func;
00663 conv_env->converters = g_list_append(conv_env->converters, converter);
00664 }
00665
00666
00667 conv_env->filter_functions = g_list_copy(env->filter_functions);
00668
00669 osync_conv_set_common_format(conv_env, "contact", "xml-contact", NULL);
00670 osync_conv_set_common_format(conv_env, "event", "xml-event", NULL);
00671 osync_conv_set_common_format(conv_env, "todo", "xml-todo", NULL);
00672 osync_conv_set_common_format(conv_env, "note", "xml-note", NULL);
00673
00674 osync_trace(TRACE_EXIT, "%s: %p", __func__, conv_env);
00675 return conv_env;
00676 }
00677
00685 void osync_conv_env_free(OSyncFormatEnv *env)
00686 {
00687 g_assert(env);
00688
00689
00690
00691 g_free(env);
00692 }
00693
00703 osync_bool osync_conv_set_common_format(OSyncFormatEnv *env, const char *objtypestr, const char *formatname, OSyncError **error)
00704 {
00705 OSyncObjType *type = osync_conv_find_objtype(env, objtypestr);
00706 if (!type) {
00707 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to set a common format: Unable to find the object-type \"%s\"", objtypestr);
00708 return FALSE;
00709 }
00710 OSyncObjFormat *format = osync_conv_find_objformat(env, formatname);
00711 if (!format) {
00712 osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to set a common format: Unable to find the format \"%s\"", formatname);
00713 return FALSE;
00714 }
00715 type->common_format = format;
00716 return TRUE;
00717 }
00718
00726 OSyncObjType *osync_conv_find_objtype(OSyncFormatEnv *env, const char *name)
00727 {
00728 g_assert(env);
00729 g_assert(name);
00730
00731 GList *element = NULL;
00732 for (element = env->objtypes; element; element = element->next) {
00733 OSyncObjType *type = element->data;
00734 if (!strcmp(type->name, name))
00735 return type;
00736 }
00737 osync_debug("CONV", 1, "Unable to find the requested objtype \"%s\"", name);
00738 return NULL;
00739 }
00740
00747 int osync_conv_num_objtypes(OSyncFormatEnv *env)
00748 {
00749 g_assert(env);
00750 return g_list_length(env->objtypes);
00751 }
00752
00760 OSyncObjType *osync_conv_nth_objtype(OSyncFormatEnv *env, int nth)
00761 {
00762 g_assert(env);
00763 return g_list_nth_data(env->objtypes, nth);
00764 }
00765
00773 OSyncObjFormat *osync_conv_find_objformat(OSyncFormatEnv *env, const char *name)
00774 {
00775 g_assert(env);
00776 g_assert(name);
00777
00778 GList *element = NULL;
00779 for (element = env->objformats; element; element = element->next) {
00780 OSyncObjFormat *format = element->data;
00781 if (!strcmp(format->name, name))
00782 return format;
00783 }
00784 return NULL;
00785 }
00786
00793 int osync_conv_num_objformats(OSyncObjType *type)
00794 {
00795 g_assert(type);
00796 return g_list_length(type->formats);
00797 }
00798
00806 OSyncObjFormat *osync_conv_nth_objformat(OSyncObjType *type, int nth)
00807 {
00808 g_assert(type);
00809 return g_list_nth_data(type->formats, nth);
00810 }
00811
00820 OSyncFormatConverter *osync_conv_find_converter(OSyncFormatEnv *env, const char *sourcename, const char *targetname)
00821 {
00822 g_assert(env);
00823 g_assert(sourcename);
00824 g_assert(targetname);
00825
00826 OSyncObjFormat *fmt_src = osync_conv_find_objformat(env, sourcename);
00827 if (!fmt_src)
00828 return NULL;
00829 OSyncObjFormat *fmt_trg = osync_conv_find_objformat(env, targetname);
00830 if (!fmt_trg)
00831 return NULL;
00832
00833 return osync_conv_find_converter_objformat(env, fmt_src, fmt_trg);
00834 }
00835
00845 OSyncFormatExtension *osync_conv_find_extension(OSyncFormatEnv *env, OSyncObjFormat *from_format, OSyncObjFormat *to_format, const char *extension_name)
00846 {
00847 g_assert(env);
00848 g_assert(extension_name);
00849
00850 GList *i = NULL;
00851 for (i = env->extensions; i; i = i->next) {
00852 OSyncFormatExtension *extension = i->data;
00853 osync_trace(TRACE_INTERNAL, "comparing format %p:%p %p:%p name %s:%s", extension->from_format, from_format, extension->to_format, to_format, extension->name, extension_name);
00854 if ((extension->from_format == from_format || !from_format) && (extension->to_format == to_format || !to_format) && !strcmp(extension->name, extension_name))
00855 return extension;
00856 }
00857 return NULL;
00858 }
00859
00866 const char *osync_objtype_get_name(OSyncObjType *type)
00867 {
00868 g_assert(type);
00869 return type->name;
00870 }
00871
00878 const char *osync_objformat_get_name(OSyncObjFormat *format)
00879 {
00880 g_assert(format);
00881 return format->name;
00882 }
00883
00890 OSyncObjType *osync_objformat_get_objtype(OSyncObjFormat *format)
00891 {
00892 g_assert(format);
00893 return format->objtype;
00894 }
00895