📄 pgpenumeratedset.c
字号:
PGPUInt32 in2;
PGPUInt32 out;
PGPUInt32 outptr;
int comparison;
PGPError err = kPGPError_NoErr;
*newSet = NULL; /* In case there's an error */
err = NewEnumeratedSubsetInternal(set1->keyDB, &set);
if (IsPGPError(err))
return err;
priv = (EnumeratedSubsetPriv *)set->priv;
priv->numKeys = priv1->numKeys + priv2->numKeys;
priv->numObjs = priv1->numObjs + priv2->numObjs;
priv->objArray = (ObjEntry *)pgpContextMemAlloc(context,
priv->numObjs * sizeof(ObjEntry), 0);
if (IsNull(priv->objArray))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
priv->keyPointers = (ObjEntry **)pgpContextMemAlloc(context,
priv->numKeys * sizeof(ObjEntry *), 0);
if (IsNull(priv->keyPointers))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
in1 = in2 = 0;
out = 0; /* Offset in ObjEntry array */
outptr = 0; /* Offset in keyPointer array */
/* Merge the two sorted arrays until we reach the end of one of them */
while (in1 < priv1->numKeys && in2 < priv2->numKeys)
{
/*
* Check for duplicate keys. Note that if keyIDs aren't unique
* then this won't necessarily remove duplicates. This isn't
* a bug, because duplicates needn't be removed for correctness.
* It is merely an optimization.
*/
if (keyPtr1[in1]->obj == keyPtr2[in2]->obj)
{
/* May need to merge child-objects here */
if( keyPtr1[in1]->numChildren == kAllChildren)
{
/* No merge necessary, just copy one entry */
sCopyKeyAndChildren( keyPtr1[in1], priv, &out, &outptr );
} else if( keyPtr2[in2]->numChildren == kAllChildren ) {
/* No merge necessary, just copy one entry */
sCopyKeyAndChildren( keyPtr2[in2], priv, &out, &outptr );
} else {
/* Hard case, must do complicated merge */
sMergeChildren( keyPtr1[in1], keyPtr2[in2], priv,
&out, &outptr );
}
++in1; ++in2;
continue;
}
pgpKeyID8( keyPtr1[in1]->obj, NULL, &keyID1);
pgpKeyID8( keyPtr2[in2]->obj, NULL, &keyID2);
comparison = PGPCompareKeyIDs(&keyID1, &keyID2);
if (comparison <= 0) {
sCopyKeyAndChildren( keyPtr1[in1++], priv, &out, &outptr );
} else if (comparison > 0) {
sCopyKeyAndChildren( keyPtr2[in2++], priv, &out, &outptr );
}
}
/*
* Copy the rest of the remaining array.
* (at most one of these loops will be non-empty)
*/
while (in1 < priv1->numKeys)
sCopyKeyAndChildren( keyPtr1[in1++], priv, &out, &outptr );
while (in2 < priv2->numKeys)
sCopyKeyAndChildren( keyPtr2[in2++], priv, &out, &outptr );
/* Shrink the resulting array, in case there were duplicates */
if (out < priv->numObjs)
priv->numObjs = out;
if( outptr < priv->numKeys )
priv->numKeys = outptr;
*newSet = set;
return kPGPError_NoErr;
}
static void
DestroyEnumeratedSubset(
PGPKeySetRef set)
{
EnumeratedSubsetPriv * priv = (EnumeratedSubsetPriv *)set->priv;
PGPContextRef context = PGPPeekKeySetContext(set);
if( IsntNull( priv ) )
{
if (IsntNull(priv->objArray))
{
pgpContextMemFree(context, priv->objArray);
priv->objArray = NULL;
}
if (IsntNull(priv->keyPointers))
{
pgpContextMemFree(context, priv->keyPointers);
priv->keyPointers = NULL;
}
priv->numObjs = 0;
priv->numKeys = 0;
pgpContextMemFree(context, priv);
}
}
static PGPError
NewEnumeratedSubsetInternal(
PGPKeyDBRef db,
PGPKeySetRef * newSet)
{
PGPContextRef context = PGPPeekKeyDBContext(db);
EnumeratedSubsetPriv * priv;
PGPKeySetRef set;
PGPError err = kPGPError_NoErr;
*newSet = NULL; /* In case there's an error */
priv = (EnumeratedSubsetPriv *)pgpContextMemAlloc(context,
sizeof(*priv), kPGPMemoryMgrFlags_Clear);
if (IsNull(priv))
return kPGPError_OutOfMemory;
priv->keyPointers = NULL;
priv->objArray = NULL;
priv->numKeys = 0;
priv->numObjs = 0;
err = pgpNewKeySetInternal(db, &set);
if (IsPGPError(err))
return err;
pgpAssertAddrValid(set, PGPKeySet);
set->priv = priv;
set->isMember = IsMemberOfEnumeratedSubset;
set->isEmpty = IsEmptyEnumeratedSubset;
set->makeUnion = MakeUnionOfEnumeratedSubsets;
set->destroy = DestroyEnumeratedSubset;
*newSet = set;
return kPGPError_NoErr;
}
/*
* Create an empty enumerated key set
*/
PGPError
PGPNewEmptyKeySet(
PGPKeyDBRef keyDB,
PGPKeySetRef * newSet)
{
PGPKeySetRef set;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( newSet );
*newSet = NULL;
PGPValidateKeyDB( keyDB );
pgpEnterPGPErrorFunction();
err = NewEnumeratedSubsetInternal(keyDB, &set);
if (IsPGPError(err))
return err;
*newSet = set;
pgpAssertErrWithPtr( err, *newSet );
return err;
}
/*
* Create a singleton enumerated key set
* If obj is not a key, singleton does not include its siblings or aunts.
*/
static PGPError
pgpNewOneKeySetInternal(
PGPKeyDBObjRef obj,
PGPKeySetRef * newSet)
{
PGPContextRef context = PGPPeekKeyDBObjContext(obj);
EnumeratedSubsetPriv * priv;
PGPKeySetRef set;
PGPKeyDBObjRef parent;
PGPUInt32 numObjects;
PGPError err = kPGPError_NoErr;
err = NewEnumeratedSubsetInternal(PGPPeekKeyDBObjKeyDB(obj), &set);
if (IsPGPError(err))
return err;
priv = (EnumeratedSubsetPriv *)set->priv;
priv->keyPointers = (ObjEntry **)pgpContextMemAlloc(context,
sizeof(ObjEntry *), 0);
if (IsNull(priv->keyPointers))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
priv->numKeys = 1;
/* Count how many objects we will have */
numObjects = 1;
for( parent = obj; pgpObjectType( parent ) != RINGTYPE_KEY;
parent = parent->up )
{
++numObjects;
}
pgpAssert( numObjects >= 1 && numObjects <= 3 );
priv->objArray = (ObjEntry *)pgpContextMemAlloc(context,
numObjects * sizeof(ObjEntry), 0);
if (IsNull(priv->objArray))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
priv->numObjs = numObjects;
priv->keyPointers[0] = priv->objArray;
priv->objArray[0].obj = parent;
priv->objArray[0].numChildren = (numObjects==1) ? kAllChildren : 1;
if( numObjects > 1 ) {
priv->objArray[1].obj = (numObjects==2) ? obj : obj->up;
priv->objArray[1].numChildren = (numObjects==2) ? kAllChildren : 1;
}
if( numObjects > 2 ) {
priv->objArray[2].obj = obj;
priv->objArray[2].numChildren = 0;
}
*newSet = set;
pgpAssertErrWithPtr( err, *newSet );
return err;
}
PGPError
PGPNewOneKeySet(
PGPKeyDBObjRef obj,
PGPKeySetRef * newSet)
{
PGPKeySetRef uncleSet;
PGPUInt32 addtype;
PGPKeyDBObj * parobj;
PGPKeyDBObj * uncle;
PGPError err;
PGPValidatePtr( newSet );
*newSet = NULL; /* In case there's an error */
PGPValidateKeyDBObj( obj );
pgpEnterPGPErrorFunction();
err = pgpNewOneKeySetInternal( obj, newSet );
if( IsPGPError( err ) )
return err;
/* Must add uncles - all subkeys if userid/sig, all userids if subkey */
parobj = obj;
while( !OBJISUSERID(parobj) && !OBJISKEY(parobj) )
parobj = parobj->up;
if( OBJISTOPKEY(parobj) )
return kPGPError_NoErr;
pgpAssert( OBJISTOPKEY( parobj->up ) );
if( OBJISUSERID(parobj) )
addtype = RINGTYPE_SUBKEY;
else
addtype = RINGTYPE_USERID;
for( uncle = parobj->up->down; IsntNull(uncle); uncle = uncle->next )
{
if( !pgpKeyDBObjIsReal( uncle ) )
continue;
if( pgpObjectType( uncle ) != addtype )
continue;
/* Must add object */
err = pgpNewOneKeySetInternal( uncle, &uncleSet );
if( IsPGPError( err ) )
{
PGPFreeKeySet( *newSet );
*newSet = NULL;
return err;
}
PGPAddKeys( uncleSet, *newSet );
PGPFreeKeySet( uncleSet );
}
return kPGPError_NoErr;
}
/*
* Create an enum set from a list of key addresses. We know these are all
* keys, no sub objects, so we can simplify the code. The key list is
* already sorted by keyid.
*/
PGPError
pgpNewKeyListSet(
PGPKeyDB * db,
PGPKeyDBObjRef * keylist,
PGPUInt32 nkeys,
PGPKeySetRef * newSet)
{
PGPContextRef context;
EnumeratedSubsetPriv * priv;
PGPKeySetRef set;
PGPUInt32 i;
PGPError err = kPGPError_NoErr;
PGPValidatePtr( newSet );
*newSet = NULL; /* In case there's an error */
pgpAssert( nkeys > 0 );
/* Use db from the list; sometimes we don't have a valid one otherwise */
if( nkeys > 0 )
db = PGPPeekKeyDBObjKeyDB( keylist[0] );
context = PGPPeekKeyDBContext(db);
err = NewEnumeratedSubsetInternal(db, &set);
if (IsPGPError(err))
return err;
priv = (EnumeratedSubsetPriv *)set->priv;
priv->keyPointers = (ObjEntry **)pgpContextMemAlloc(context,
nkeys * sizeof(ObjEntry *), 0);
if (IsNull(priv->keyPointers))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
priv->numKeys = nkeys;
priv->objArray = (ObjEntry *)pgpContextMemAlloc(context,
nkeys * sizeof(ObjEntry), 0);
if (IsNull(priv->objArray))
{
PGPFreeKeySet(set);
return kPGPError_OutOfMemory;
}
priv->numObjs = nkeys;
for( i=0; i<nkeys; ++i )
{
pgpAssert( pgpKeyIsValid( keylist[i] ) );
pgpAssert( PGPPeekKeyDBObjKeyDB(keylist[i]) == db );
priv->keyPointers[i] = &priv->objArray[i];
priv->objArray[i].obj = keylist[i];
priv->objArray[i].numChildren = kAllChildren;
}
*newSet = set;
pgpAssertErrWithPtr( err, *newSet );
return err;
}
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -