/* AMSTStressBufferedSeg -- Stress test for a buffered seg * * Test splitting or merging a buffered seg. * * .bmerge: A merge is performed when the segment had previously * been split and the segment above meets the constraints (i.e. empty, * not already attached to a buffer and similar colour) * * .bsplit: Whether or not a merge happpened, a split is performed if * the limit of the buffered region is also the limit of an arena * grain, and yet does not correspond to the segment limit, provided * that the part of the segment above the buffer is all free. */ static void AMSTStressBufferedSeg(Seg seg, Buffer buffer) { AMSTSeg amstseg; AMST amst; Arena arena; Addr limit; Buffer segBuf; AVERT(Seg, seg); AVERT(Buffer, buffer); AVER(SegBuffer(&segBuf, seg) && segBuf == buffer); amstseg = Seg2AMSTSeg(seg); AVERT(AMSTSeg, amstseg); limit = BufferLimit(buffer); arena = PoolArena(SegPool(seg)); amst = PoolAMST(SegPool(seg)); AVERT(AMST, amst); if (amstseg->next != NULL) { Seg segHi = AMSTSeg2Seg(amstseg->next); if (AMSSegIsFree(segHi) && SegGrey(segHi) == SegGrey(seg)) { /* .bmerge */ Seg mergedSeg; Res res; res = SegMerge(&mergedSeg, seg, segHi); if (ResOK == res) { amst->bmerges++; printf("J"); } else { /* deliberate fails only */ AVER(amst->failSegs); } } } if (SegLimit(seg) != limit && AddrIsArenaGrain(limit, arena) && AMSSegRegionIsFree(seg, limit, SegLimit(seg))) { /* .bsplit */ Seg segLo, segHi; Res res; res = SegSplit(&segLo, &segHi, seg, limit); if (ResOK == res) { amst->bsplits++; printf("C"); } else { /* deliberate fails only */ AVER(amst->failSegs); } } }
/* AMSTBufferFill -- the pool class buffer fill method * * Calls next method - but possibly splits or merges the chosen * segment. * * .merge: A merge is performed when the next method returns the * entire segment, this segment had previously been split from the * segment below, and the segment below is appropriately similar * (i.e. not already attached to a buffer and similarly coloured) * * .split: If we're not merging, a split is performed if the next method * returns the entire segment, and yet lower half of the segment would * meet the request. */ static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size size) { Addr base, limit; Arena arena; AMS ams; AMST amst; Bool b; Seg seg; AMSTSeg amstseg; Res res; AVERT(Pool, pool); AVER(baseReturn != NULL); AVER(limitReturn != NULL); /* other parameters are checked by next method */ arena = PoolArena(pool); ams = PoolAMS(pool); amst = PoolAMST(pool); /* call next method */ res = NextMethod(Pool, AMSTPool, bufferFill)(&base, &limit, pool, buffer, size); if (res != ResOK) return res; b = SegOfAddr(&seg, arena, base); AVER(b); amstseg = Seg2AMSTSeg(seg); if (SegLimit(seg) == limit && SegBase(seg) == base) { if (amstseg->prev != NULL) { Seg segLo = AMSTSeg2Seg(amstseg->prev); if (!SegHasBuffer(segLo) && SegGrey(segLo) == SegGrey(seg) && SegWhite(segLo) == SegWhite(seg)) { /* .merge */ Seg mergedSeg; Res mres; AMSUnallocateRange(ams, seg, base, limit); mres = SegMerge(&mergedSeg, segLo, seg); if (ResOK == mres) { /* successful merge */ AMSAllocateRange(ams, mergedSeg, base, limit); /* leave range as-is */ } else { /* failed to merge */ AVER(amst->failSegs); /* deliberate fails only */ AMSAllocateRange(ams, seg, base, limit); } } } else { Size half = SegSize(seg) / 2; if (half >= size && SizeIsArenaGrains(half, arena)) { /* .split */ Addr mid = AddrAdd(base, half); Seg segLo, segHi; Res sres; AMSUnallocateRange(ams, seg, mid, limit); sres = SegSplit(&segLo, &segHi, seg, mid); if (ResOK == sres) { /* successful split */ limit = mid; /* range is lower segment */ } else { /* failed to split */ AVER(amst->failSegs); /* deliberate fails only */ AMSAllocateRange(ams, seg, mid, limit); } } } } *baseReturn = base; *limitReturn = limit; return ResOK; }
void HTTPCollapse( PTEXT *ppText ) { PTEXT output; PTEXT input = *ppText; while( input ) { if( GetText( input )[0] == '+' ) { PTEXT subst; // sometimes a + can be attached to a number // so much for the natural language parser dealing with // a machine oriented protocol... if( GetTextSize( input ) > 1 ) { SegSplit( &input, 1 ); } subst = GetSubst( '+' ); SegInsert( subst, input ); LineRelease( SegGrab( input ) ); input = subst; if( !PRIORLINE( input ) ) (*ppText) = input; } else if( TextIs( input, WIDE("%") ) ) { PTEXT next = NEXTLINE( input ); if( next ) { PTEXT subst; SegSplit( &next, 2 ); subst = GetSubst( *(unsigned short*)GetText( next ) ); if( subst ) { PTEXT nextnext = NEXTLINE( next ); PTEXT prior = SegBreak( input ); if( !prior ) { *ppText = SegAppend( subst, nextnext ); } if( nextnext ) { SegBreak( nextnext ); if( !prior ) *ppText = nextnext; else SegAppend( prior, nextnext ); SegInsert( subst, nextnext ); input = nextnext; continue; } else { SegAppend( prior, (PTEXT)&subst ); input = NULL; continue; } } // if not subst... just continue stepping, no replacement nessecary? } } input = NEXTLINE( input ); } output = BuildLine( *ppText ); LineRelease( *ppText ); (*ppText) = output; }