/* * Finds an entry with a UTF-8 identifier corresponding to a unit. * * Arguments: * map The unit-to-identifier map. * unit The unit to be used as the key in the search. * Returns: * NULL The map doesn't contain an entry corresponding to "unit" whose * identifier is in UTF-8. * else Pointer to the entry corresponding to "unit" whose identifier is * in UTF-8 (and might, actually, be in ASCII). */ static UnitAndId* utimFindUtf8ByUnit( UnitToIdMap* const map, const ut_unit* const unit) { UnitAndId targetEntry; UnitAndId** treeEntry = NULL; /* failure */ targetEntry.unit = (ut_unit*)unit; treeEntry = tfind(&targetEntry, &map->utf8, compareUnits); if (treeEntry == NULL) { treeEntry = tfind(&targetEntry, &map->latin1, compareUnits); if (treeEntry == NULL) { treeEntry = tfind(&targetEntry, &map->ascii, compareUnits); } else { /* * Create the UTF-8 version of the Latin-1 identifier and add it to * the UTF-8 unit-to-id map so that it will be found next time. */ char* const id = latin1ToUtf8((*treeEntry)->id); if (id == NULL) { ut_set_status(UT_OS); ut_handle_error_message(strerror(errno)); ut_handle_error_message( "Couldn't convert identifier from ISO-8859-1 to UTF-8"); treeEntry = NULL; } else { UnitAndId* newEntry = uaiNew(unit, id); if (newEntry != NULL) { treeEntry = tsearch(newEntry, &map->utf8, compareUnits); if (treeEntry == NULL) { uaiFree(newEntry); ut_set_status(UT_OS); ut_handle_error_message(strerror(errno)); ut_handle_error_message( "Couldn't add unit-and-identifier to search-tree"); } } free(id); } /* UTF-8 identifier created */ } /* found Latin-1 identifier */ } /* no UTF-8 identifier */ return treeEntry == NULL ? NULL : *treeEntry; }
/* * Adds an entry to a unit-to-identifier map. * * Arguments: * map Pointer to unit-to-identifier map. * unit The unit. May be freed upon return. * id The identifier. May be freed upon return. * encoding The ostensible encoding of "id". * Returns: * UT_BAD_ARG "id" is inconsistent with "encoding". * UT_OS Operating-system error. See "errno". * UT_EXISTS "unit" already maps to a different identifier. * UT_SUCCESS Success. */ static ut_status utimAdd( UnitToIdMap* const map, const ut_unit* unit, const char* const id, ut_encoding encoding) { ut_status status; assert(map != NULL); assert(unit != NULL); assert(id != NULL); if (adjustEncoding(&encoding, id)) { status = UT_BAD_ARG; ut_set_status(status); ut_handle_error_message("Identifier not in given encoding"); } else { UnitAndId* targetEntry = uaiNew(unit, id); if (targetEntry != NULL) { void** rootp = selectTree(map, encoding); UnitAndId** treeEntry = tsearch(targetEntry, rootp, compareUnits); if (treeEntry == NULL) { status = UT_OS; ut_set_status(status); ut_handle_error_message(strerror(errno)); ut_handle_error_message("Couldn't add search-tree entry"); uaiFree(targetEntry); } else { if (strcmp((*treeEntry)->id, id) != 0) { status = UT_EXISTS; ut_set_status(status); ut_handle_error_message("Unit already maps to \"%s\"", (*treeEntry)->id); } else { status = UT_SUCCESS; } if (targetEntry != *treeEntry) uaiFree(targetEntry); } } /* "targetEntry" allocated */ } /* valid arguments */ return status; }
/* * Adds an entry to an identifier-to-unit map. * * Arguments: * map The database. * id The identifier. May be freed upon return. * unit The unit. May be freed upon return. * Returns: * UT_OS Operating-system error. See "errno". * UT_EXISTS "id" already maps to a different unit. * UT_SUCCESS Success. */ static ut_status itumAdd( IdToUnitMap* map, const char* const id, const ut_unit* const unit) { ut_status status; UnitAndId* targetEntry; assert(map != NULL); assert(id != NULL); assert(unit != NULL); targetEntry = uaiNew(unit, id); if (targetEntry == NULL) { status = ut_get_status(); } else { UnitAndId** treeEntry = tsearch(targetEntry, &map->tree, map->compare); if (treeEntry == NULL) { uaiFree(targetEntry); status = UT_OS; } else { if (ut_compare((*treeEntry)->unit, unit) == 0) { status = UT_SUCCESS; } else { status = UT_EXISTS; ut_set_status(status); ut_handle_error_message( "\"%s\" already maps to existing but different unit", id); } if (targetEntry != *treeEntry) uaiFree(targetEntry); } /* found entry */ } /* "targetEntry" allocated */ return status; }