size_t fixed_memory_sweep(Memory *mem) { Array *stack = mem->stack; Array *from = mem->heap; Array *to = from==&mem->h1 ? &mem->h2 : &mem->h1; Object scanned; size_t from_size, to_size; from_size = from->current - from->head; to->current = to->head; /* copy objects referenced by root set(stack-space). */ copy_space(stack, to); /* to-space has gray color objects. * copy objects referenced by gray color objects. */ copy_space(to, to); to_size = to->current - to->head; scanned = from->head; while(scanned!=from->current) { /* obj is garbage if TYPE(obj)!=T_FORWARD */ if(TYPE(scanned)==T_STR) { free(STR_BUF(scanned)); } ++scanned; } mem->heap = to; return from_size - to_size; }
/* * Copy space if exists */ static int copy_space_optional(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx) { const rchar *source = *source_; if (!(source < ctx->sentinel)) return -1; if (*source == U('/')) { *source_ = source + 1; return copy_space_comment(source_, target_, ctx, NEED_SPACE_NEVER); } else if (RCSSMIN_IS_SPACE(*source)) { *source_ = source + 1; copy_space(source_, target_, ctx, NEED_SPACE_NEVER); return 0; } return -1; }
/* * Copy space if comment */ static int copy_space_comment(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx, need_space_flag need_space) { const rchar *source = *source_; rchar *target = *target_; if (source < ctx->sentinel && *source == U('*')) { copy_space(source_, target_, ctx, need_space); if (*source_ > source) return 0; } if (!(target < ctx->tsentinel)) RABORT(-1); *target++ = source[-1]; /* *source_ = source; <-- unchanged */ *target_ = target; return -1; }
/* * Main function * * The return value determines the result length (kept in the target buffer). * However, if the target buffer is too small, the return value is greater * than tlength. The difference to tlength is the number of unconsumed source * characters at the time the buffer was full. In this case you should resize * the target buffer to the return value and call rcssmin again. Repeat as * often as needed. */ static Py_ssize_t rcssmin(const rchar *source, rchar *target, Py_ssize_t slength, Py_ssize_t tlength, int keep_bang_comments) { rcssmin_ctx_t ctx_, *ctx = &ctx_; const rchar *tstart = target; rchar c; ctx->start = source; ctx->sentinel = source + slength; ctx->tsentinel = target + tlength; ctx->at_group = 0; ctx->in_macie5 = 0; ctx->in_rule = 0; ctx->keep_bang_comments = keep_bang_comments; while (source < ctx->sentinel && target < ctx->tsentinel) { c = *source++; if (RCSSMIN_IS_DULL(c)) { *target++ = c; continue; } else if (RCSSMIN_IS_SPACE(c)) { copy_space(&source, &target, ctx, NEED_SPACE_MAYBE); continue; } switch (c) { /* Escape */ case U('\\'): copy_escape(&source, &target, ctx); continue; /* String */ case U('"'): case U('\''): copy_string(&source, &target, ctx); continue; /* URL */ case U('u'): copy_url(&source, &target, ctx); continue; /* IE7hack */ case U('>'): copy_ie7hack(&source, &target, ctx); continue; /* @-group */ case U('@'): copy_at_group(&source, &target, ctx); continue; /* ; */ case U(';'): copy_semicolon(&source, &target, ctx); continue; /* :first-line|letter followed by [{,] */ /* (apparently needed for IE6) */ case U(':'): copy_first(&source, &target, ctx); continue; /* { */ case U('{'): if (ctx->at_group) --ctx->at_group; else ++ctx->in_rule; *target++ = c; continue; /* } */ case U('}'): if (ctx->in_rule) --ctx->in_rule; *target++ = c; continue; /* space starting with comment */ case U('/'): (void)copy_space_comment(&source, &target, ctx, NEED_SPACE_MAYBE); continue; /* Fallback: copy character. Better safe than sorry. Should not be * reached, though */ default: *target++ = c; continue; } } return (Py_ssize_t)(target - tstart) + (Py_ssize_t)(ctx->sentinel - source); }