📄 pgpgroups.c
字号:
{
PGPUInt32 itemIndex;
if( sIsGroupMember( group, item, &itemIndex ) )
{
err = PGPDeleteIndItemFromGroup( set, id, itemIndex );
}
else
{
err = kPGPError_ItemNotFound;
}
}
return( err );
}
PGPError
PGPGetGroupInfo(
PGPGroupSetRef set,
PGPGroupID id,
PGPGroupInfo * info )
{
PGPError err = kPGPError_NoErr;
PGPGroup const * group = NULL;
PGPValidatePtr( info );
pgpClearMemory( info, sizeof( *info ) );
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, (PGPGroup **)&group );
if ( IsntPGPError( err ) )
{
info->id = id;
strcpy( info->name, group->name );
strcpy( info->description, group->description );
info->userValue = group->userValue;
}
return( err );
}
PGPError
PGPSetGroupName(
PGPGroupSetRef set,
PGPGroupID id,
const char * name )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPValidatePtr( name );
PGPValidateGroupSet( set );
PGPValidateParam( strlen( name ) <= kPGPMaxGroupNameLength );
err = sFindGroupByID( set, id, &group );
if ( IsntPGPError( err ) )
{
strcpy( group->name, name );
set->hasBeenModified = TRUE;
}
return( err );
}
PGPError
PGPSetGroupDescription(
PGPGroupSetRef set,
PGPGroupID id,
const char * description )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPValidatePtr( description );
PGPValidateParam( strlen( description ) <= kPGPMaxGroupDescriptionLength );
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, &group );
if ( IsntPGPError( err ) )
{
strcpy( group->description, description );
set->hasBeenModified = TRUE;
}
return( err );
}
PGPError
PGPSetGroupUserValue(
PGPGroupSetRef set,
PGPGroupID id,
PGPUserValue userValue )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, &group );
if ( IsntPGPError( err ) )
{
group->userValue = userValue;
}
return( err );
}
/*____________________________________________________________________________
Return TRUE if group1 contains group 2, either directly or in a subgroup.
____________________________________________________________________________*/
static PGPBoolean
sGroupContainsGroup(
PGPGroupSetRef set,
PGPGroupID mainGroupID,
PGPGroupID subGroup )
{
PGPError err = kPGPError_NoErr;
PGPGroup * mainGroup = NULL;
PGPBoolean containsGroup = FALSE;
PGPUInt32 itemIndex;
err = sFindGroupByID( set, mainGroupID, &mainGroup );
pgpAssertNoErr( err );
if ( IsPGPError( err ) )
return( FALSE );
if ( mainGroupID == subGroup )
{
/* can't add a group to itself */
return( TRUE );
}
for( itemIndex = 0; itemIndex < mainGroup->numItems; ++itemIndex )
{
PGPGroupItem const * item;
item = &mainGroup->itemsArray[ itemIndex ];
if ( item->type == kPGPGroupItem_Group )
{
if ( item->u.group.id == subGroup )
{
containsGroup = TRUE;
break;
}
else if ( sGroupContainsGroup( set, item->u.group.id, subGroup ) )
{
containsGroup = TRUE;
break;
}
}
}
return( containsGroup );
}
/*____________________________________________________________________________
Add an item to the group. Caller must completely fill in the item
before adding.
____________________________________________________________________________*/
PGPError
PGPAddItemToGroup(
PGPGroupSetRef set,
PGPGroupItem const * item,
PGPGroupID id )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPUInt32 itemIndex;
PGPValidateGroupSet( set );
PGPValidatePtr( item );
PGPValidateParam( item->type == kPGPGroupItem_KeyID ||
item->type == kPGPGroupItem_Group );
/* verify that the group being added to exists */
err = sFindGroupByID( set, id, &group );
if ( IsPGPError( err ) )
return( err );
if ( item->type == kPGPGroupItem_Group )
{
/* verify that if the group being added that exists */
PGPGroup * itemGroup;
err = sFindGroupByID( set, item->u.group.id, &itemGroup );
if ( IsPGPError( err ) )
return( err );
}
/* verify that the group doesn't already contain this item */
if ( sIsGroupMember( group, item, &itemIndex ) )
return( kPGPError_ItemAlreadyExists );
/* verify that a cycle won't be created by adding */
if ( item->type == kPGPGroupItem_Group &&
sGroupContainsGroup( set, item->u.group.id, id ) )
{
return( kPGPError_BadParams );
}
/* OK, all verification is now done */
if ( IsntPGPError( err ) )
{
PGPContextRef context = set->context;
PGPSize newSize;
newSize = ( group->numItems + 1 ) * sizeof( PGPGroupItem );
/* add the new item */
err = pgpContextMemRealloc( context, (void **) &group->itemsArray,
newSize, 0);
if ( IsntPGPError( err ) )
{
(group->itemsArray)[ group->numItems ] = *item;
group->numItems++;
set->hasBeenModified = TRUE;
}
}
return( err );
}
/*____________________________________________________________________________
This can't use an iterator, because it is used to create an iterator.
____________________________________________________________________________*/
PGPError
PGPCountGroupItems(
PGPGroupSetRef set,
PGPGroupID id,
PGPBoolean recursive,
PGPUInt32 * outNumKeys,
PGPUInt32 * outTotal )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPUInt32 numItems = 0;
PGPUInt32 numKeys = 0;
if ( IsntNull( outNumKeys ) )
*outNumKeys = 0;
if ( IsntNull( outTotal ) )
*outTotal = 0;
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, &group);
if ( IsntPGPError( err ) )
{
PGPUInt32 itemIndex;
/* account for all items in this group right here */
numItems += group->numItems;
for (itemIndex = 0; itemIndex < group->numItems; ++itemIndex )
{
PGPGroupItem const *item;
item = &group->itemsArray[ itemIndex ];
if ( item->type == kPGPGroupItem_KeyID )
{
++numKeys;
}
else if ( recursive && item->type == kPGPGroupItem_Group )
{
PGPUInt32 tempTotal;
PGPUInt32 tempKeys;
err = PGPCountGroupItems( set, item->u.group.id, TRUE,
&tempKeys, &tempTotal );
if ( IsPGPError( err ) )
break;
numKeys += tempKeys;
numItems += tempTotal;
}
}
}
if ( IsntPGPError( err ) )
{
if ( IsntNull( outTotal ) )
*outTotal = numItems;
if ( IsntNull( outNumKeys ) )
*outNumKeys = numKeys;
}
return( err );
}
PGPError
PGPGetIndGroupItem(
PGPGroupSetRef set,
PGPGroupID id,
PGPUInt32 itemIndex,
PGPGroupItem * item )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPValidatePtr( item );
pgpClearMemory( item, sizeof( *item ) );
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, &group);
if ( IsntPGPError( err ) )
{
if ( itemIndex < group->numItems )
{
*item = group->itemsArray[ itemIndex ];
}
else
{
err = kPGPError_BadParams;
}
}
return( err );
}
PGPError
PGPSetIndGroupItemUserValue(
PGPGroupSetRef set,
PGPGroupID id,
PGPUInt32 itemIndex,
PGPUserValue userValue )
{
PGPError err = kPGPError_NoErr;
PGPGroup * group = NULL;
PGPValidateGroupSet( set );
err = sFindGroupByID( set, id, &group);
if ( IsntPGPError( err ) )
{
if ( itemIndex < group->numItems )
{
group->itemsArray[ itemIndex ].userValue = userValue;
}
else
{
err = kPGPError_BadParams;
}
}
return( err );
}
/*____________________________________________________________________________
An iterator is implemented by creating an array of pointers to the
elements to be iterated. This uses a modest amount of memory relative
to the overall structure, and results in very fast iteration.
Its drawbacks include the inability to change the overall structure
while iterating (at least in this implementation).
____________________________________________________________________________*/
typedef struct PGPGroupIter PGPGroupIter;
struct PGPGroupIter
{
PGPGroupSetRef set;
const PGPGroupItem ** items;
#define kBeforeFirstItemIndex 0xFFFFFFFF
PGPUInt32 curIndex;
PGPUInt32 numItems;
};
/*____________________________________________________________________________
Fill the iter->items array with pointers to all items in the group.
____________________________________________________________________________*/
static PGPUInt32
sCollectPointersForIter(
PGPGroupIter * iter,
PGPGroupID id,
PGPBoolean recursive,
PGPFlags flags,
PGPUInt32 startSlot )
{
PGPUInt32 nextSlot = startSlot;
PGPUInt32 itemIndex;
PGPGroup const * group = NULL;
PGPError err = kPGPError_NoErr;
pgpAssert( IsntNull( iter ) );
if ( startSlot >= iter->numItems )
{
/* if we've found all the items we could be pointing after
the end of the array, but we shouldn't find any more items
of the desired kind, so no point in continuing */
return( startSlot );
}
err = sFindGroupByID( iter->set, id, (PGPGroup **)&group );
pgpAssertNoErr( err );
for( itemIndex = 0; itemIndex < group->numItems; ++itemIndex )
{
const PGPGroupItem * item;
item = &group->itemsArray[ itemIndex ];
if ( item->type == kPGPGroupItem_KeyID )
{
if ( ( flags & kPGPGroupIterFlags_Keys) != 0 )
{
iter->items[ nextSlot ] = item;
++nextSlot;
}
}
else
{
pgpAssert( item->type == kPGPGroupItem_Group );
if ( ( flags & kPGPGroupIterFlags_Groups) != 0 )
{
iter->items[ nextSlot ] = item;
++nextSlot;
}
if ( recursive )
{
nextSlot = sCollectPointersForIter( iter,
item->u.group.id, TRUE, flags, nextSlot );
}
}
}
return( nextSlot );
}
static PGPError
sInitIter(
PGPGroupSetRef set,
PGPGroupID id,
PGPFlags flags,
PGPGroupIter * iter )
{
PGPError err = kPGPError_NoErr;
PGPUInt32 numKeys;
PGPUInt32 numItems;
Boolean recursive;
PGPGroupID actualID = id;
recursive = (flags & kPGPGroupIterFlags_Recursive) != 0;
pgpClearMemory( iter, sizeof( *iter ) );
if ( IsntPGPError( err ) )
{
iter->set = set;
iter->items = NULL;
iter->curIndex = kBeforeFirstItemIndex;
err = PGPCountGroupItems( set, actualID,
recursive, &numKeys, &numItems );
if ( IsntPGPError( err ) )
{
iter->numItems = 0;
if ( ( flags & kPGPGroupIterFlags_Keys) != 0 )
iter->numItems += numKeys;
if ( ( flags & kPGPGroupIterFlags_Groups) != 0 )
iter->numItems += (numItems - numKeys);
/* create an array of pointers to the items */
iter->items = (const PGPGroupItem **)pgpContextMemAlloc(
set->context,
iter->numItems * sizeof( iter->items[ 0 ] ),
0);
if ( IsNull( iter->items ) )
err = kPGPError_OutOfMemory;
}
if ( IsntPGPError( err ) )
{
PGPUInt32 nextSlot;
/* collect all the pointers we need */
nextSlot = sCollectPointersForIter( iter,
actualID, recursive, flags, 0);
pgpAssert( nextSlot == iter->numItems ||
nextSlot == iter->numItems + 1);
}
}
return( err );
}
PGPError
PGPNewGroupItemIter(
PGPGroupSetRef set,
PGPGroupID id,
PGPFlags flags,
PGPGroupItemIterRef * iterOut )
{
PGPError err = kPGPError_NoErr;
PGPGroupIter * iter = NULL;
PGPValidatePtr( iterOut );
*iterOut = NULL;
PGPValidateGroupSet( set );
PGPValidateParam( (flags & kPGPGroupIterFlags_AllItems) != 0 );
PGPValidateParam( (flags & ~ kPGPGroupIterFlags_AllRecursive) == 0 );
iter = (PGPGroupIter *)pgpContextMemAlloc( set->context,
sizeof( *iter ), kPGPMemoryMgrFlags_Clear );
if ( IsNull( iter ) )
err = kPGPError_OutOfMemory;
if ( IsntPGPError( err ) )
{
err = sInitIter( set, id, flags, iter );
if ( IsPGPError( err ) )
{
pgpContextMemFree( set->context, iter );
iter = NULL;
}
}
*iterOut = iter;
return( err );
}
PGPError
PGPFreeGroupItemIter( PGPGroupItemIterRef iter )
{
PGPError err = kPGPError_NoErr;
PGPValidateParam( IsntNull( iter ) );
if ( IsntNull( iter->items ) )
{
err = pgpContextMemFree( iter->set->context,
(void *) iter->items );
iter->items = NULL;
}
if ( IsntPGPError( err ) )
{
err = pgpContextMemFree( iter->set->context, iter );
}
return( err );
}
/*____________________________________________________________________________
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -