/* ---------------- Test main for the slp_compare.c module ---------------- * * Compile with: * gcc -g -Wall -I .. -o0 -D SLP_COMPARE_TEST -D DEBUG -D HAVE_CONFIG_H \ * -o slp-compare-test slp_compare.c slp_linkedlist.c slp_xmalloc.c */ int main(void) { /* test data */ static char lst1[] = "item_a_1,item_aa_2,item_aaa_3, item_aaaa_4"; static char lst2[] = "item_a_1"; static char lst3[] = "item_aa_2, item_aaaaa_5"; static char lst4[] = "item_aaaaa_5,item_aaaaaa_6"; static char str1[] = "item_x"; static char str2[] = "item_a_1"; static char str3[] = "item_aa_2"; int count; /* *** SLPContainsStringList *** */ count = SLPContainsStringList(sizeof lst1 - 1, lst1, sizeof str1 - 1, str1); if (count != 0) return -1; count = SLPContainsStringList(sizeof lst1 - 1, lst1, sizeof str2 - 1 , str2); if (count != 1) return -1; count = SLPContainsStringList(sizeof lst1 - 1, lst1, sizeof str3 - 1, str3); if (count != 10) return -1; /* *** SLPIntersectStringList *** */ count = SLPIntersectStringList(sizeof lst1 - 1, lst1, sizeof lst2 - 1, lst2); if (count != 1) return -1; count = SLPIntersectStringList(sizeof lst1 - 1, lst1, sizeof lst3 - 1, lst3); if (count != 1) return -1; count = SLPIntersectStringList(sizeof lst1 - 1, lst1, sizeof lst4 - 1, lst4); if (count != 0) return -1; return 0; }
/** Take the union of two string lists. * * Generates a string list that contains all unique strings within * two specified string lists. * * @param[in] list1 - A pointer to the first string-list. * @param[in] list1len - The length in bytes of @p list1. * @param[in] list2 - A pointer to the second string-list. * @param[in] list2len - The length in bytes of @p list2. * @param[out] unionlist - A pointer to a buffer that will receive * the union of @p list1 and @p list2. * @param[in,out] unionlistlen - A pointer to the size in bytes of the * @p unionlist buffer on entry; also receives the number of bytes * written to the @p unionlist buffer on success. * * @return The length of the resulting union list, or a negative value * if @p unionlist is not large enough. If a negative value is returned * @p *unionlist will return the required size of @p unionlist. * * @remarks In order ensure that @p unionlist does not contain duplicates, * @p list1 must not have any duplicates. Also, as a speed optimization, * if neither @p list1 nor @p list2 contain internal duplicates, the * larger list should be passed in as @p list1. * * @remarks To avoid buffer overflow errors pass @p list1len + * @p list2len + 1 as the value for @p unionlistlen. */ int SLPUnionStringList(size_t list1len, const char * list1, size_t list2len, const char * list2, size_t * unionlistlen, char * unionlist) { char * listend = (char *)list2 + list2len; char * itembegin = (char *)list2; char * itemend = itembegin; size_t itemlen; size_t copiedlen; if (unionlist == 0 || *unionlistlen == 0 || *unionlistlen < list1len) { *unionlistlen = list1len + list2len + 1; return -1; } /* Copy list1 into the unionlist since it should not have any duplicates */ memcpy(unionlist, list1, list1len); copiedlen = list1len; while (itemend < listend) { itembegin = itemend; /* seek to the end of the next list item */ while (1) { if (itemend == listend || *itemend == ',') if (*(itemend - 1) != '\\') break; itemend++; } itemlen = itemend - itembegin; if (SLPContainsStringList(list1len, list1, itemlen, itembegin) == 0) { if (copiedlen + itemlen + 1 > *unionlistlen) { *unionlistlen = list1len + list2len + 1; return -1; } /* append a comma if not the first entry*/ if (copiedlen) { unionlist[copiedlen] = ','; copiedlen++; } memcpy(unionlist + copiedlen, itembegin, itemlen); copiedlen += itemlen; } itemend++; } *unionlistlen = copiedlen; return (int)copiedlen; }
/*=========================================================================*/ int SLPIntersectStringList(int list1len, const char* list1, int list2len, const char* list2) /* Calculates the number of common entries between two string-lists */ /* */ /* list1 - pointer to the string-list to be checked */ /* */ /* list1len - length in bytes of the list to be checked */ /* */ /* list2 - pointer to the string-list to be checked */ /* */ /* list2len - length in bytes of the list to be checked */ /* */ /* Returns - The number of common entries. */ /*=========================================================================*/ { int result = 0; char* listend = (char*)list1 + list1len; char* itembegin = (char*)list1; char* itemend = itembegin; while(itemend < listend) { itembegin = itemend; /* seek to the end of the next list item */ while(1) { if(itemend == listend || *itemend == ',') { if(*(itemend - 1) != '\\') { break; } } itemend ++; } if(SLPContainsStringList(list2len, list2, itemend - itembegin, itembegin)) { result ++; } itemend ++; } return result; }
/** Intersects two string lists. * * Calculates the number of common entries between two string-lists. * * @param[in] list1 - A pointer to the string-list to be checked * @param[in] list1len - The length in bytes of the list to be checked * @param[in] list2 - A pointer to the string-list to be checked * @param[in] list2len - The length in bytes of the list to be checked * * @return The number of common entries between @p list1 and @p list2. */ int SLPIntersectStringList(size_t list1len, const char * list1, size_t list2len, const char * list2) { int result = 0; const char * listend = list1 + list1len; const char * itembegin = list1; const char * itemend = itembegin; while (itemend < listend) { itembegin = itemend; /* Seek to the end of the next list item, break on commas. */ while (itemend < listend && itemend[0] != ',') itemend++; if (SLPContainsStringList(list2len, list2, itemend - itembegin, itembegin)) result++; itemend++; } return result; }
/*=========================================================================*/ int SLPUnionStringList(int list1len, const char* list1, int list2len, const char* list2, int* unionlistlen, char * unionlist) /* Generate a string list that is a union of two string lists */ /* */ /* list1len - length in bytes of list1 */ /* */ /* list1 - pointer to a string-list */ /* */ /* list2len - length in bytes of list2 */ /* */ /* list2 - pointer to a string-list */ /* */ /* unionlistlen - pointer to the size in bytes of the unionlist buffer. */ /* also receives the size in bytes of the unionlist buffer */ /* on successful return. */ /* */ /* unionlist - pointer to the buffer that will receive the union list. */ /* */ /* */ /* Returns - Length of the resulting union list or negative if */ /* unionlist is not big enough. If negative is returned */ /* *unionlist will be changed indicate the size of unionlist */ /* buffer needed */ /* */ /* Important: In order ensure that unionlist does not contain any */ /* duplicates, at least list1 must not have any duplicates. */ /* Also, for speed optimization if list1 and list2 are both */ /* with out duplicates, the larger list should be passed in */ /* as list1. */ /* */ /* Note: A good size for unionlist (so that non-zero will never be */ /* returned) is list1len + list2len + 1 */ /*=========================================================================*/ { char* listend = (char*)list2 + list2len; char* itembegin = (char*)list2; char* itemend = itembegin; int itemlen; int copiedlen; if(unionlist == 0 || *unionlistlen == 0 || *unionlistlen < list1len) { *unionlistlen = list1len + list2len + 1; return -1; } /* Copy list1 into the unionlist since it should not have any duplicates */ memcpy(unionlist,list1,list1len); copiedlen = list1len; while(itemend < listend) { itembegin = itemend; /* seek to the end of the next list item */ while(1) { if(itemend == listend || *itemend == ',') { if(*(itemend - 1) != '\\') { break; } } itemend ++; } itemlen = itemend - itembegin; if(SLPContainsStringList(list1len, list1, itemlen, itembegin) == 0) { if(copiedlen + itemlen + 1 > *unionlistlen) { *unionlistlen = list1len + list2len + 1; return -1; } /* append a comma if not the first entry*/ if(copiedlen) { unionlist[copiedlen] = ','; copiedlen++; } memcpy(unionlist + copiedlen, itembegin, itemlen); copiedlen += itemlen; } itemend ++; } *unionlistlen = copiedlen; return copiedlen; }
/** Intersects two string lists, and removes the common entries from * the second list. * * @param[in] list1len - The length in bytes of the list to be checked * @param[in] list1 - A pointer to the string-list to be checked * @param[in] list2len - The length in bytes of the list to be checked * and updated * @param[in] list2 - A pointer to the string-list to be checked and * updated * * @return The number of common entries between @p list1 and @p list2. */ int SLPIntersectRemoveStringList(int list1len, const char* list1, int* list2len, char* list2) { int result = 0; int pos; char* listend = (char*)list1 + list1len; char* itembegin = (char*)list1; char* itemend = itembegin; char* list2end = (char*)list2 + (*list2len); while(itemend < listend) { itembegin = itemend; /* seek to the end of the next list item */ while(1) { if(itemend == listend || *itemend == ',') { if(*(itemend - 1) != '\\') { break; } } itemend++; } if ((pos = SLPContainsStringList(*list2len, list2, itemend - itembegin, itembegin)) != 0) { /* String found in the list at position pos (1-based) */ /* Remove it from list2 */ char* dest = list2+(pos-1); char* src = dest+(itemend-itembegin); result++; if (src < list2end) { if (*src == ',') ++src; } while (src < list2end) { *dest++ = *src++; } list2end = dest; } itemend++; } *list2len = (int)(list2end - (char *)list2); return result; }
/*=========================================================================*/ int SLPDDatabaseSrvTypeRqstStart(SLPMessage msg, SLPDDatabaseSrvTypeRqstResult** result) /* Find service types in the database */ /* */ /* msg (IN) the SrvTypRqst to find. */ /* */ /* result (OUT) pointer result structure */ /* */ /* Returns - Zero on success. Non-zero on failure */ /* */ /* Note: Caller must pass *result to SLPDDatabaseSrvtypeRqstEnd() to */ /* free */ /*=========================================================================*/ { SLPDatabaseHandle dh; SLPDatabaseEntry* entry; SLPSrvReg* entryreg; SLPSrvTypeRqst* srvtyperqst; dh = SLPDatabaseOpen(&G_SlpdDatabase.database); if ( dh ) { /* srvtyperqst is the SrvTypeRqst being made */ srvtyperqst = &(msg->body.srvtyperqst); while ( 1 ) { /*-----------------------------------------------------------------*/ /* Allocate result with generous srvtypelist of url entry pointers */ /*-----------------------------------------------------------------*/ *result = (SLPDDatabaseSrvTypeRqstResult*) xrealloc(*result, sizeof(SLPDDatabaseSrvTypeRqstResult) + G_SlpdDatabase.srvtypelistlen); if ( *result == NULL ) { /* out of memory */ SLPDatabaseClose(dh); return SLP_ERROR_INTERNAL_ERROR; } (*result)->srvtypelist = (char*)((*result) + 1); (*result)->srvtypelistlen = 0; (*result)->reserved = dh; /*-------------------------------------------------*/ /* Rewind enumeration in case we had to reallocate */ /*-------------------------------------------------*/ SLPDatabaseRewind(dh); while ( 1 ) { entry = SLPDatabaseEnum(dh); if ( entry == NULL ) { /* This is the only successful way out */ return 0; } /* entry reg is the SrvReg message from the database */ entryreg = &(entry->msg->body.srvreg); if ( SLPCompareNamingAuth(entryreg->srvtypelen, entryreg->srvtype, srvtyperqst->namingauthlen, srvtyperqst->namingauth) == 0 && SLPIntersectStringList(srvtyperqst->scopelistlen, srvtyperqst->scopelist, entryreg->scopelistlen, entryreg->scopelist) && SLPContainsStringList((*result)->srvtypelistlen, (*result)->srvtypelist, entryreg->srvtypelen, entryreg->srvtype) == 0 ) { /* Check to see if we allocated a big enough srvtypelist */ if ( (*result)->srvtypelistlen + entryreg->srvtypelen > G_SlpdDatabase.srvtypelistlen ) { /* Oops we did not allocate a big enough result */ G_SlpdDatabase.srvtypelistlen *= 2; break; } /* Append a comma if needed */ if ( (*result)->srvtypelistlen ) { (*result)->srvtypelist[(*result)->srvtypelistlen] = ','; (*result)->srvtypelistlen += 1; } /* Append the service type */ memcpy(((*result)->srvtypelist) + (*result)->srvtypelistlen, entryreg->srvtype, entryreg->srvtypelen); (*result)->srvtypelistlen += entryreg->srvtypelen; } } } SLPDatabaseClose(dh); } return 0; }