/* ---------- OpenWGroup -----------------------------------------------*/ IFFP OpenWGroup(GroupContext *parent0,GroupContext* new0) { register GroupContext *parent = parent0; register GroupContext *newtmp = new0; register int ckEnd; register IFFP iffp = IFF_OKAY; newtmp->parent = parent; newtmp->clientFrame = parent->clientFrame; newtmp->file = parent->file; newtmp->position = parent->position; newtmp->bound = parent->bound; newtmp->ckHdr.ckID = NULL_CHUNK; newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; if ( Known(parent->ckHdr.ckSize) ) { ckEnd = newtmp->position + ChunkMoreBytes(parent); if ( newtmp->bound == szNotYetKnown || newtmp->bound > ckEnd ) newtmp->bound = ckEnd; }; if ( parent->ckHdr.ckID == NULL_CHUNK || /* not currently writing a chunk*/ IS_ODD(newtmp->position) || (Known(newtmp->bound) && IS_ODD(newtmp->bound)) ) iffp = CLIENT_ERROR; return(iffp); }
/* ---------- PutCkHdr -------------------------------------------------*/ IFFP PutCkHdr(GroupContext *context0, int ckID, int ckSize) { register GroupContext *context = context0; int minPSize = sizeof(ChunkHeader); /* physical chunk >= minPSize bytes*/ /* CLIENT_ERROR if we're already inside a chunk or asked to write * other than one FORM, LIST, or CAT at the top level of a file */ /* Also, non-positive int values are illegal and used for error codes.*/ /* (We could check for other illegal IDs...)*/ if ( context->ckHdr.ckID != NULL_CHUNK || ckID <= 0 ) return(CLIENT_ERROR); else if (context->parent == NULL) { switch (ckID) { case FORM: case LIST: case CAT: break; default: return(CLIENT_ERROR); } if (context->position != 0) return(CLIENT_ERROR); } if ( Known(ckSize) ) { if ( ckSize < 0 ) return(CLIENT_ERROR); minPSize += ckSize; }; if ( Known(context->bound) && context->position + minPSize > context->bound ) return(CLIENT_ERROR); context->ckHdr.ckID = ckID; context->ckHdr.ckSize = ckSize; context->bytesSoFar = 0; { context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize); if (0 > fwrite(&context->ckHdr, 1,sizeof(ChunkHeader),context->file)) return(DOS_ERROR); context->ckHdr.ckSize = endianSwap32(context->ckHdr.ckSize); } context->position += sizeof(ChunkHeader); return(IFF_OKAY); }
/* ---------- IFFWriteBytes ---------------------------------------------*/ IFFP IFFWriteBytes(GroupContext *context0, char *data, int nBytes) { register GroupContext *context = context0; if ( context->ckHdr.ckID == NULL_CHUNK || /* not in a chunk */ nBytes < 0 || /* negative nBytes */ (Known(context->bound) && /* overflow context */ context->position + nBytes > context->bound) || (Known(context->ckHdr.ckSize) && /* overflow chunk */ context->bytesSoFar + nBytes > context->ckHdr.ckSize) ) { return(CLIENT_ERROR); } if (0 > fwrite(data, 1,nBytes,context->file)) return(DOS_ERROR); context->bytesSoFar += nBytes; context->position += nBytes; return(IFF_OKAY); }
IFFP OpenWIFF(BPTR file, GroupContext *new0, int limit) { register GroupContext *newtmp = new0; register IFFP iffp = IFF_OKAY; newtmp->parent = NULL; newtmp->clientFrame = NULL; newtmp->file = file; newtmp->position = 0; newtmp->bound = limit; newtmp->ckHdr.ckID = NULL_CHUNK; /* indicates no current chunk */ newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0; if (0 > Seek(file, 0, OFFSET_BEGINNING)) /* Go to start of the file.*/ iffp = DOS_ERROR; else if ( Known(limit) && IS_ODD(limit) ) iffp = CLIENT_ERROR; return(iffp); }
void FindRoot(const Tree &tree, unsigned *ptruNode1, unsigned *ptruNode2, double *ptrdLength1, double *ptrdLength2, ROOT RootMethod) { #if TRACE tree.LogMe(); #endif if (tree.IsRooted()) Quit("FindRoot: tree already rooted"); const unsigned uNodeCount = tree.GetNodeCount(); const unsigned uLeafCount = tree.GetLeafCount(); if (uNodeCount < 2) Quit("Root: don't support trees with < 2 edges"); EdgeInfo **EIs = new EdgeInfo *[uNodeCount]; for (unsigned uNodeIndex = 0; uNodeIndex < uNodeCount; ++uNodeIndex) EIs[uNodeIndex] = new EdgeInfo[3]; EdgeList Edges; for (unsigned uNodeIndex = 0; uNodeIndex < uNodeCount; ++uNodeIndex) if (tree.IsLeaf(uNodeIndex)) { unsigned uParent = tree.GetNeighbor1(uNodeIndex); Edges.Add(uParent, uNodeIndex); } #if TRACE Log("Edges: "); Edges.LogMe(); #endif // Main loop: iterate until all distances known double dAllMaxDist = -1e20; unsigned uMaxFrom = NULL_NEIGHBOR; unsigned uMaxTo = NULL_NEIGHBOR; for (;;) { EdgeList NextEdges; #if TRACE Log("\nTop of main loop\n"); Log("Edges: "); Edges.LogMe(); Log("MDs:\n"); ListEIs(EIs, uNodeCount); #endif // For all edges const unsigned uEdgeCount = Edges.GetCount(); if (0 == uEdgeCount) break; for (unsigned n = 0; n < uEdgeCount; ++n) { unsigned uNodeFrom; unsigned uNodeTo; Edges.GetEdge(n, &uNodeFrom, &uNodeTo); CalcInfo(tree, uNodeFrom, uNodeTo, EIs); #if TRACE Log("Edge %u -> %u\n", uNodeFrom, uNodeTo); #endif const unsigned uNeighborCount = tree.GetNeighborCount(uNodeFrom); for (unsigned i = 0; i < uNeighborCount; ++i) { const unsigned uNeighborIndex = tree.GetNeighbor(uNodeFrom, i); if (!Known(tree, EIs, uNeighborIndex, uNodeFrom) && AllKnownOut(tree, EIs, uNeighborIndex, uNodeFrom)) NextEdges.Add(uNeighborIndex, uNodeFrom); } } Edges.Copy(NextEdges); } #if TRACE ListEIs(EIs, uNodeCount); #endif switch (RootMethod) { case ROOT_MidLongestSpan: RootByMidLongestSpan(tree, EIs, ptruNode1, ptruNode2, ptrdLength1, ptrdLength2); break; case ROOT_MinAvgLeafDist: RootByMinAvgLeafDist(tree, EIs, ptruNode1, ptruNode2, ptrdLength1, ptrdLength2); break; default: Quit("Invalid RootMethod=%d", RootMethod); } for (unsigned uNodeIndex = 0; uNodeIndex < uNodeCount; ++uNodeIndex) delete[] EIs[uNodeIndex]; delete[] EIs; }