| Index: tracing/third_party/tvcm/third_party/rcssmin/rcssmin.c
|
| diff --git a/tracing/third_party/tvcm/third_party/rcssmin/rcssmin.c b/tracing/third_party/tvcm/third_party/rcssmin/rcssmin.c
|
| deleted file mode 100644
|
| index a722fc276a9103960e78f26308dbcd72bf8ff207..0000000000000000000000000000000000000000
|
| --- a/tracing/third_party/tvcm/third_party/rcssmin/rcssmin.c
|
| +++ /dev/null
|
| @@ -1,1163 +0,0 @@
|
| -/*
|
| - * Copyright 2011 - 2014
|
| - * Andr\xe9 Malo or his licensors, as applicable
|
| - *
|
| - * Licensed under the Apache License, Version 2.0 (the "License");
|
| - * you may not use this file except in compliance with the License.
|
| - * You may obtain a copy of the License at
|
| - *
|
| - * http://www.apache.org/licenses/LICENSE-2.0
|
| - *
|
| - * Unless required by applicable law or agreed to in writing, software
|
| - * distributed under the License is distributed on an "AS IS" BASIS,
|
| - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| - * See the License for the specific language governing permissions and
|
| - * limitations under the License.
|
| - */
|
| -
|
| -#include "cext.h"
|
| -EXT_INIT_FUNC;
|
| -
|
| -#ifdef EXT3
|
| -typedef Py_UNICODE rchar;
|
| -#else
|
| -typedef unsigned char rchar;
|
| -#endif
|
| -#define U(c) ((rchar)(c))
|
| -
|
| -typedef struct {
|
| - const rchar *start;
|
| - const rchar *sentinel;
|
| - const rchar *tsentinel;
|
| - Py_ssize_t at_group;
|
| - int in_macie5;
|
| - int in_rule;
|
| - int keep_bang_comments;
|
| -} rcssmin_ctx_t;
|
| -
|
| -typedef enum {
|
| - NEED_SPACE_MAYBE = 0,
|
| - NEED_SPACE_NEVER
|
| -} need_space_flag;
|
| -
|
| -
|
| -#define RCSSMIN_DULL_BIT (1 << 0)
|
| -#define RCSSMIN_HEX_BIT (1 << 1)
|
| -#define RCSSMIN_ESC_BIT (1 << 2)
|
| -#define RCSSMIN_SPACE_BIT (1 << 3)
|
| -#define RCSSMIN_STRING_DULL_BIT (1 << 4)
|
| -#define RCSSMIN_NMCHAR_BIT (1 << 5)
|
| -#define RCSSMIN_URI_DULL_BIT (1 << 6)
|
| -#define RCSSMIN_PRE_CHAR_BIT (1 << 7)
|
| -#define RCSSMIN_POST_CHAR_BIT (1 << 8)
|
| -
|
| -static const unsigned short rcssmin_charmask[128] = {
|
| - 21, 21, 21, 21, 21, 21, 21, 21,
|
| - 21, 28, 8, 21, 8, 8, 21, 21,
|
| - 21, 21, 21, 21, 21, 21, 21, 21,
|
| - 21, 21, 21, 21, 21, 21, 21, 21,
|
| - 28, 469, 4, 85, 85, 85, 85, 4,
|
| - 149, 277, 85, 469, 469, 117, 85, 84,
|
| - 115, 115, 115, 115, 115, 115, 115, 115,
|
| - 115, 115, 468, 340, 85, 469, 468, 85,
|
| - 84, 115, 115, 115, 115, 115, 115, 117,
|
| - 117, 117, 117, 117, 117, 117, 117, 117,
|
| - 117, 117, 117, 117, 117, 117, 117, 117,
|
| - 117, 117, 117, 213, 4, 341, 85, 117,
|
| - 85, 115, 115, 115, 115, 115, 115, 117,
|
| - 117, 117, 117, 117, 117, 117, 117, 117,
|
| - 117, 117, 117, 117, 117, 116, 117, 117,
|
| - 117, 117, 117, 468, 85, 468, 85, 21
|
| -};
|
| -
|
| -#define RCSSMIN_IS_DULL(c) ((U(c) > 127) || \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_DULL_BIT))
|
| -
|
| -#define RCSSMIN_IS_HEX(c) ((U(c) <= 127) && \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_HEX_BIT))
|
| -
|
| -#define RCSSMIN_IS_ESC(c) ((U(c) > 127) || \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_ESC_BIT))
|
| -
|
| -#define RCSSMIN_IS_SPACE(c) ((U(c) <= 127) && \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_SPACE_BIT))
|
| -
|
| -#define RCSSMIN_IS_STRING_DULL(c) ((U(c) > 127) || \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_STRING_DULL_BIT))
|
| -
|
| -#define RCSSMIN_IS_NMCHAR(c) ((U(c) > 127) || \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_NMCHAR_BIT))
|
| -
|
| -#define RCSSMIN_IS_URI_DULL(c) ((U(c) > 127) || \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_URI_DULL_BIT))
|
| -
|
| -#define RCSSMIN_IS_PRE_CHAR(c) ((U(c) <= 127) && \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_PRE_CHAR_BIT))
|
| -
|
| -#define RCSSMIN_IS_POST_CHAR(c) ((U(c) <= 127) && \
|
| - (rcssmin_charmask[U(c) & 0x7F] & RCSSMIN_POST_CHAR_BIT))
|
| -
|
| -
|
| -static const rchar pattern_url[] = {
|
| - /*U('u'),*/ U('r'), U('l'), U('(')
|
| -};
|
| -
|
| -static const rchar pattern_ie7[] = {
|
| - /*U('>'),*/ U('/'), U('*'), U('*'), U('/')
|
| -};
|
| -
|
| -static const rchar pattern_media[] = {
|
| - U('m'), U('e'), U('d'), U('i'), U('a'),
|
| - U('M'), U('E'), U('D'), U('I'), U('A')
|
| -};
|
| -
|
| -static const rchar pattern_document[] = {
|
| - U('d'), U('o'), U('c'), U('u'), U('m'), U('e'), U('n'), U('t'),
|
| - U('D'), U('O'), U('C'), U('U'), U('M'), U('E'), U('N'), U('T')
|
| -};
|
| -
|
| -static const rchar pattern_supports[] = {
|
| - U('s'), U('u'), U('p'), U('p'), U('o'), U('r'), U('t'), U('s'),
|
| - U('S'), U('U'), U('P'), U('P'), U('O'), U('R'), U('T'), U('S')
|
| -};
|
| -
|
| -static const rchar pattern_keyframes[] = {
|
| - U('k'), U('e'), U('y'), U('f'), U('r'), U('a'), U('m'), U('e'), U('s'),
|
| - U('K'), U('E'), U('Y'), U('F'), U('R'), U('A'), U('M'), U('E'), U('S')
|
| -};
|
| -
|
| -static const rchar pattern_vendor_o[] = {
|
| - U('-'), U('o'), U('-'),
|
| - U('-'), U('O'), U('-')
|
| -};
|
| -
|
| -static const rchar pattern_vendor_moz[] = {
|
| - U('-'), U('m'), U('o'), U('z'), U('-'),
|
| - U('-'), U('M'), U('O'), U('Z'), U('-')
|
| -};
|
| -
|
| -static const rchar pattern_vendor_webkit[] = {
|
| - U('-'), U('w'), U('e'), U('b'), U('k'), U('i'), U('t'), U('-'),
|
| - U('-'), U('W'), U('E'), U('B'), U('K'), U('I'), U('T'), U('-')
|
| -};
|
| -
|
| -static const rchar pattern_vendor_ms[] = {
|
| - U('-'), U('m'), U('s'), U('-'),
|
| - U('-'), U('M'), U('S'), U('-')
|
| -};
|
| -
|
| -static const rchar pattern_first[] = {
|
| - U('f'), U('i'), U('r'), U('s'), U('t'), U('-'), U('l'),
|
| - U('F'), U('I'), U('R'), U('S'), U('T'), U('-'), U('L')
|
| -};
|
| -
|
| -static const rchar pattern_line[] = {
|
| - U('i'), U('n'), U('e'),
|
| - U('I'), U('N'), U('E'),
|
| -};
|
| -
|
| -static const rchar pattern_letter[] = {
|
| - U('e'), U('t'), U('t'), U('e'), U('r'),
|
| - U('E'), U('T'), U('T'), U('E'), U('R')
|
| -};
|
| -
|
| -static const rchar pattern_macie5_init[] = {
|
| - U('/'), U('*'), U('\\'), U('*'), U('/')
|
| -};
|
| -
|
| -static const rchar pattern_macie5_exit[] = {
|
| - U('/'), U('*'), U('*'), U('/')
|
| -};
|
| -
|
| -/*
|
| - * Match a pattern (and copy immediately to target)
|
| - */
|
| -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
| -#pragma GCC diagnostic push
|
| -#pragma GCC diagnostic ignored "-Wstrict-overflow"
|
| -#endif
|
| -static int
|
| -copy_match(const rchar *pattern, const rchar *psentinel,
|
| - const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| - rchar c;
|
| -
|
| - while (pattern < psentinel
|
| - && source < ctx->sentinel && target < ctx->tsentinel
|
| - && ((c = *source++) == *pattern++))
|
| - *target++ = c;
|
| -
|
| - *source_ = source;
|
| - *target_ = target;
|
| -
|
| - return (pattern == psentinel);
|
| -}
|
| -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
| -#pragma GCC diagnostic pop
|
| -#endif
|
| -
|
| -#define MATCH(PAT, source, target, ctx) ( \
|
| - copy_match(pattern_##PAT, \
|
| - pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar), \
|
| - source, target, ctx) \
|
| -)
|
| -
|
| -
|
| -/*
|
| - * Match a pattern (and copy immediately to target) - CI version
|
| - */
|
| -static int
|
| -copy_imatch(const rchar *pattern, const rchar *psentinel,
|
| - const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_, *pstart = pattern;
|
| - rchar *target = *target_;
|
| - rchar c;
|
| -
|
| - while (pattern < psentinel
|
| - && source < ctx->sentinel && target < ctx->tsentinel
|
| - && ((c = *source++) == *pattern
|
| - || c == pstart[(pattern - pstart) + (psentinel - pstart)])) {
|
| - ++pattern;
|
| - *target++ = c;
|
| - }
|
| -
|
| - *source_ = source;
|
| - *target_ = target;
|
| -
|
| - return (pattern == psentinel);
|
| -}
|
| -
|
| -#define IMATCH(PAT, source, target, ctx) ( \
|
| - copy_imatch(pattern_##PAT, \
|
| - pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar) / 2, \
|
| - source, target, ctx) \
|
| -)
|
| -
|
| -
|
| -/*
|
| - * Copy characters
|
| - */
|
| -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
| -#pragma GCC diagnostic push
|
| -#pragma GCC diagnostic ignored "-Wstrict-overflow"
|
| -#endif
|
| -static int
|
| -copy(const rchar *source, const rchar *sentinel, rchar **target_,
|
| - rcssmin_ctx_t *ctx)
|
| -{
|
| - rchar *target = *target_;
|
| -
|
| - while (source < sentinel && target < ctx->tsentinel)
|
| - *target++ = *source++;
|
| -
|
| - *target_ = target;
|
| -
|
| - return (source == sentinel);
|
| -}
|
| -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
|
| -#pragma GCC diagnostic pop
|
| -#endif
|
| -
|
| -#define COPY_PAT(PAT, target, ctx) ( \
|
| - copy(pattern_##PAT, \
|
| - pattern_##PAT + sizeof(pattern_##PAT) / sizeof(rchar), \
|
| - target, ctx) \
|
| -)
|
| -
|
| -
|
| -/*
|
| - * The ABORT macros work with known local variables!
|
| - */
|
| -#define ABORT_(RET) do { \
|
| - if (source < ctx->sentinel && !(target < ctx->tsentinel)) { \
|
| - *source_ = source; \
|
| - *target_ = target; \
|
| - } \
|
| - return RET; \
|
| -} while(0)
|
| -
|
| -
|
| -#define CRAPPY_C90_COMPATIBLE_EMPTY
|
| -#define ABORT ABORT_(CRAPPY_C90_COMPATIBLE_EMPTY)
|
| -#define RABORT(RET) ABORT_((RET))
|
| -
|
| -
|
| -/*
|
| - * Copy escape
|
| - */
|
| -static void
|
| -copy_escape(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_, *hsentinel;
|
| - rchar *target = *target_;
|
| - rchar c;
|
| -
|
| - *target++ = U('\\');
|
| - *target_ = target;
|
| -
|
| - if (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source++;
|
| - if (RCSSMIN_IS_ESC(c)) {
|
| - *target++ = c;
|
| - }
|
| - else if (RCSSMIN_IS_HEX(c)) {
|
| - *target++ = c;
|
| -
|
| - /* 6 hex chars max, one we got already */
|
| - if (ctx->sentinel - source > 5)
|
| - hsentinel = source + 5;
|
| - else
|
| - hsentinel = ctx->sentinel;
|
| -
|
| - while (source < hsentinel && target < ctx->tsentinel
|
| - && (c = *source, RCSSMIN_IS_HEX(c))) {
|
| - ++source;
|
| - *target++ = c;
|
| - }
|
| -
|
| - /* One optional space after */
|
| - if (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - if (source == hsentinel)
|
| - c = *source;
|
| - if (RCSSMIN_IS_SPACE(c)) {
|
| - ++source;
|
| - *target++ = U(' ');
|
| - if (c == U('\r') && source < ctx->sentinel
|
| - && *source == U('\n'))
|
| - ++source;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - *target_ = target;
|
| - *source_ = source;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy string
|
| - */
|
| -static void
|
| -copy_string(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| - rchar c, quote = source[-1];
|
| -
|
| - *target++ = quote;
|
| - *target_ = target;
|
| -
|
| - while (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *target++ = *source++;
|
| - if (RCSSMIN_IS_STRING_DULL(c))
|
| - continue;
|
| -
|
| - switch (c) {
|
| - case U('\''): case U('"'):
|
| - if (c == quote) {
|
| - *target_ = target;
|
| - *source_ = source;
|
| - return;
|
| - }
|
| - continue;
|
| -
|
| - case U('\\'):
|
| - if (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source++;
|
| - switch (c) {
|
| - case U('\r'):
|
| - if (source < ctx->sentinel && *source == U('\n'))
|
| - ++source;
|
| - /* fall through */
|
| -
|
| - case U('\n'): case U('\f'):
|
| - --target;
|
| - break;
|
| -
|
| - default:
|
| - *target++ = c;
|
| - }
|
| - }
|
| - continue;
|
| - }
|
| - break; /* forbidden characters */
|
| - }
|
| -
|
| - ABORT;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy URI string
|
| - */
|
| -static int
|
| -copy_uri_string(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| - rchar c, quote = source[-1];
|
| -
|
| - *target++ = quote;
|
| - *target_ = target;
|
| -
|
| - while (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source++;
|
| - if (RCSSMIN_IS_SPACE(c))
|
| - continue;
|
| - *target++ = c;
|
| - if (RCSSMIN_IS_STRING_DULL(c))
|
| - continue;
|
| -
|
| - switch (c) {
|
| - case U('\''): case U('"'):
|
| - if (c == quote) {
|
| - *target_ = target;
|
| - *source_ = source;
|
| - return 0;
|
| - }
|
| - continue;
|
| -
|
| - case U('\\'):
|
| - if (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source;
|
| - switch (c) {
|
| - case U('\r'):
|
| - if ((source + 1) < ctx->sentinel && source[1] == U('\n'))
|
| - ++source;
|
| - /* fall through */
|
| -
|
| - case U('\n'): case U('\f'):
|
| - --target;
|
| - ++source;
|
| - break;
|
| -
|
| - default:
|
| - --target;
|
| - copy_escape(&source, &target, ctx);
|
| - }
|
| - }
|
| - continue;
|
| - }
|
| -
|
| - break; /* forbidden characters */
|
| - }
|
| -
|
| - RABORT(-1);
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy URI (unquoted)
|
| - */
|
| -static int
|
| -copy_uri_unquoted(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| - rchar c;
|
| -
|
| - *target++ = source[-1];
|
| - *target_ = target;
|
| -
|
| - while (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source++;
|
| - if (RCSSMIN_IS_SPACE(c))
|
| - continue;
|
| - *target++ = c;
|
| - if (RCSSMIN_IS_URI_DULL(c))
|
| - continue;
|
| -
|
| - switch (c) {
|
| -
|
| - case U(')'):
|
| - *target_ = target - 1;
|
| - *source_ = source - 1;
|
| - return 0;
|
| -
|
| - case U('\\'):
|
| - if (source < ctx->sentinel && target < ctx->tsentinel) {
|
| - c = *source;
|
| - switch (c) {
|
| - case U('\r'):
|
| - if ((source + 1) < ctx->sentinel && source[1] == U('\n'))
|
| - ++source;
|
| - /* fall through */
|
| -
|
| - case U('\n'): case U('\f'):
|
| - --target;
|
| - ++source;
|
| - break;
|
| -
|
| - default:
|
| - --target;
|
| - copy_escape(&source, &target, ctx);
|
| - }
|
| - }
|
| - continue;
|
| - }
|
| -
|
| - break; /* forbidden characters */
|
| - }
|
| -
|
| - RABORT(-1);
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy url
|
| - */
|
| -static void
|
| -copy_url(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| - rchar c;
|
| -
|
| - *target++ = U('u');
|
| - *target_ = target;
|
| -
|
| - /* Must not be inside an identifier */
|
| - if ((source != ctx->start + 1) && RCSSMIN_IS_NMCHAR(source[-2]))
|
| - return;
|
| -
|
| - if (!MATCH(url, &source, &target, ctx)
|
| - || !(source < ctx->sentinel && target < ctx->tsentinel))
|
| - ABORT;
|
| -
|
| - while (source < ctx->sentinel && RCSSMIN_IS_SPACE(*source))
|
| - ++source;
|
| -
|
| - if (!(source < ctx->sentinel))
|
| - ABORT;
|
| -
|
| - c = *source++;
|
| - switch (c) {
|
| - case U('"'): case U('\''):
|
| - if (copy_uri_string(&source, &target, ctx) == -1)
|
| - ABORT;
|
| -
|
| - while (source < ctx->sentinel && RCSSMIN_IS_SPACE(*source))
|
| - ++source;
|
| - break;
|
| -
|
| - default:
|
| - if (copy_uri_unquoted(&source, &target, ctx) == -1)
|
| - ABORT;
|
| - }
|
| -
|
| - if (!(source < ctx->sentinel && target < ctx->tsentinel))
|
| - ABORT;
|
| -
|
| - if ((*target++ = *source++) != U(')'))
|
| - ABORT;
|
| -
|
| - *target_ = target;
|
| - *source_ = source;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy @-group
|
| - */
|
| -static void
|
| -copy_at_group(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| -
|
| - *target++ = U('@');
|
| - *target_ = target;
|
| -
|
| -#define REMATCH(what) ( \
|
| - source = *source_, \
|
| - target = *target_, \
|
| - IMATCH(what, &source, &target, ctx) \
|
| -)
|
| -#define CMATCH(what) IMATCH(what, &source, &target, ctx)
|
| -
|
| - if (( !CMATCH(media)
|
| - && !REMATCH(supports)
|
| - && !REMATCH(document)
|
| - && !REMATCH(keyframes)
|
| - && !(REMATCH(vendor_webkit) && CMATCH(keyframes))
|
| - && !(REMATCH(vendor_moz) && CMATCH(keyframes))
|
| - && !(REMATCH(vendor_o) && CMATCH(keyframes))
|
| - && !(REMATCH(vendor_ms) && CMATCH(keyframes)))
|
| - || !(source < ctx->sentinel && target < ctx->tsentinel)
|
| - || RCSSMIN_IS_NMCHAR(*source))
|
| - ABORT;
|
| -
|
| -#undef CMATCH
|
| -#undef REMATCH
|
| -
|
| - ++ctx->at_group;
|
| -
|
| - *target_ = target;
|
| - *source_ = source;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Skip space
|
| - */
|
| -static const rchar *
|
| -skip_space(const rchar *source, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *begin = source;
|
| - int res;
|
| - rchar c;
|
| -
|
| - while (source < ctx->sentinel) {
|
| - c = *source;
|
| - if (RCSSMIN_IS_SPACE(c)) {
|
| - ++source;
|
| - continue;
|
| - }
|
| - else if (c == U('/')) {
|
| - ++source;
|
| - if (!(source < ctx->sentinel && *source == U('*'))) {
|
| - --source;
|
| - break;
|
| - }
|
| - ++source;
|
| - res = 0;
|
| - while (source < ctx->sentinel) {
|
| - c = *source++;
|
| - if (c != U('*'))
|
| - continue;
|
| - if (!(source < ctx->sentinel))
|
| - return begin;
|
| - if (*source != U('/'))
|
| - continue;
|
| -
|
| - /* Comment complete */
|
| - ++source;
|
| - res = 1;
|
| - break;
|
| - }
|
| - if (!res)
|
| - return begin;
|
| -
|
| - continue;
|
| - }
|
| -
|
| - break;
|
| - }
|
| -
|
| - return source;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy space
|
| - */
|
| -static void
|
| -copy_space(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx,
|
| - need_space_flag need_space)
|
| -{
|
| - const rchar *source = *source_, *end, *comment;
|
| - rchar *target = *target_;
|
| - int res;
|
| - rchar c;
|
| -
|
| - --source;
|
| - if (need_space == NEED_SPACE_MAYBE
|
| - && source > ctx->start
|
| - && !RCSSMIN_IS_PRE_CHAR(source[-1])
|
| - && (end = skip_space(source, ctx)) < ctx->sentinel
|
| - && (!RCSSMIN_IS_POST_CHAR(*end)
|
| - || (*end == U(':') && !ctx->in_rule && !ctx->at_group))) {
|
| -
|
| - if (!(target < ctx->tsentinel))
|
| - ABORT;
|
| - *target++ = U(' ');
|
| - }
|
| -
|
| - while (source < ctx->sentinel) {
|
| - switch (c = *source) {
|
| -
|
| - /* comment */
|
| - case U('/'):
|
| - comment = source++;
|
| - if (!((source < ctx->sentinel && *source == U('*')))) {
|
| - --source;
|
| - break;
|
| - }
|
| - ++source;
|
| - res = 0;
|
| - while (source < ctx->sentinel) {
|
| - c = *source++;
|
| - if (c != U('*'))
|
| - continue;
|
| - if (!(source < ctx->sentinel))
|
| - ABORT;
|
| - if (*source != U('/'))
|
| - continue;
|
| -
|
| - /* Comment complete */
|
| - ++source;
|
| - res = 1;
|
| -
|
| - if (ctx->keep_bang_comments && comment[2] == U('!')) {
|
| - ctx->in_macie5 = (source[-3] == U('\\'));
|
| - if (!copy(comment, source, &target, ctx))
|
| - ABORT;
|
| - }
|
| - else if (source[-3] == U('\\')) {
|
| - if (!ctx->in_macie5) {
|
| - if (!COPY_PAT(macie5_init, &target, ctx))
|
| - ABORT;
|
| - }
|
| - ctx->in_macie5 = 1;
|
| - }
|
| - else if (ctx->in_macie5) {
|
| - if (!COPY_PAT(macie5_exit, &target, ctx))
|
| - ABORT;
|
| - ctx->in_macie5 = 0;
|
| - }
|
| - /* else don't copy anything */
|
| - break;
|
| - }
|
| - if (!res)
|
| - ABORT;
|
| - continue;
|
| -
|
| - /* space */
|
| - case U(' '): case U('\t'): case U('\r'): case U('\n'): case U('\f'):
|
| - ++source;
|
| - continue;
|
| - }
|
| -
|
| - break;
|
| - }
|
| -
|
| - *source_ = source;
|
| - *target_ = target;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * 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;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * 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 :first-line|letter
|
| - */
|
| -static void
|
| -copy_first(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_, *next, *source_fork;
|
| - rchar *target = *target_, *target_fork;
|
| -
|
| - *target++ = U(':');
|
| - *target_ = target;
|
| -
|
| - if (!IMATCH(first, &source, &target, ctx)
|
| - || !(source < ctx->sentinel && target < ctx->tsentinel))
|
| - ABORT;
|
| -
|
| - source_fork = source;
|
| - target_fork = target;
|
| -
|
| - if (!IMATCH(line, &source, &target, ctx)) {
|
| - source = source_fork;
|
| - target = target_fork;
|
| -
|
| - if (!IMATCH(letter, &source, &target, ctx)
|
| - || !(source < ctx->sentinel && target < ctx->tsentinel))
|
| - ABORT;
|
| - }
|
| -
|
| - next = skip_space(source, ctx);
|
| - if (!(next < ctx->sentinel && target < ctx->tsentinel
|
| - && (*next == U('{') || *next == U(','))))
|
| - ABORT;
|
| -
|
| - *target++ = U(' ');
|
| - *target_ = target;
|
| - *source_ = source;
|
| - (void)copy_space_optional(source_, target_, ctx);
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy IE7 hack
|
| - */
|
| -static void
|
| -copy_ie7hack(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_;
|
| - rchar *target = *target_;
|
| -
|
| - *target++ = U('>');
|
| - *target_ = target;
|
| -
|
| - if (ctx->in_rule || ctx->at_group)
|
| - return; /* abort */
|
| -
|
| - if (!MATCH(ie7, &source, &target, ctx))
|
| - ABORT;
|
| -
|
| - ctx->in_macie5 = 0;
|
| -
|
| - *target_ = target;
|
| - *source_ = source;
|
| -
|
| - (void)copy_space_optional(source_, target_, ctx);
|
| -}
|
| -
|
| -
|
| -/*
|
| - * Copy semicolon; miss out duplicates or even this one (before '}')
|
| - */
|
| -static void
|
| -copy_semicolon(const rchar **source_, rchar **target_, rcssmin_ctx_t *ctx)
|
| -{
|
| - const rchar *source = *source_, *begin, *end;
|
| - rchar *target = *target_;
|
| -
|
| - begin = source;
|
| - while (source < ctx->sentinel) {
|
| - end = skip_space(source, ctx);
|
| - if (!(end < ctx->sentinel)) {
|
| - if (!(target < ctx->tsentinel))
|
| - ABORT;
|
| - *target++ = U(';');
|
| - break;
|
| - }
|
| - switch (*end) {
|
| - case U(';'):
|
| - source = end + 1;
|
| - continue;
|
| -
|
| - case U('}'):
|
| - if (ctx->in_rule)
|
| - break;
|
| -
|
| - /* fall through */
|
| - default:
|
| - if (!(target < ctx->tsentinel))
|
| - ABORT;
|
| - *target++ = U(';');
|
| - break;
|
| - }
|
| -
|
| - break;
|
| - }
|
| -
|
| - source = begin;
|
| - *target_ = target;
|
| - while (source < ctx->sentinel) {
|
| - if (*source == U(';')) {
|
| - ++source;
|
| - continue;
|
| - }
|
| -
|
| - if (copy_space_optional(&source, target_, ctx) == 0)
|
| - continue;
|
| -
|
| - break;
|
| - }
|
| -
|
| - *source_ = source;
|
| -}
|
| -
|
| -
|
| -/*
|
| - * 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);
|
| -}
|
| -
|
| -
|
| -PyDoc_STRVAR(rcssmin_cssmin__doc__,
|
| -"cssmin(style, keep_bang_comments=False)\n\
|
| -\n\
|
| -Minify CSS.\n\
|
| -\n\
|
| -:Note: This is a hand crafted C implementation built on the regex\n\
|
| - semantics.\n\
|
| -\n\
|
| -:Parameters:\n\
|
| - `style` : ``str``\n\
|
| - CSS to minify\n\
|
| -\n\
|
| -:Return: Minified style\n\
|
| -:Rtype: ``str``");
|
| -
|
| -static PyObject *
|
| -rcssmin_cssmin(PyObject *self, PyObject *args, PyObject *kwds)
|
| -{
|
| - PyObject *style, *keep_bang_comments_ = NULL, *result;
|
| - static char *kwlist[] = {"style", "keep_bang_comments", NULL};
|
| - Py_ssize_t rlength, slength, length;
|
| - int keep_bang_comments;
|
| -#ifdef EXT2
|
| - int uni;
|
| -#define UOBJ "O"
|
| -#endif
|
| -#ifdef EXT3
|
| -#define UOBJ "U"
|
| -#endif
|
| -
|
| - if (!PyArg_ParseTupleAndKeywords(args, kwds, UOBJ "|O", kwlist,
|
| - &style, &keep_bang_comments_))
|
| - return NULL;
|
| -
|
| - if (!keep_bang_comments_)
|
| - keep_bang_comments = 0;
|
| - else {
|
| - keep_bang_comments = PyObject_IsTrue(keep_bang_comments_);
|
| - if (keep_bang_comments == -1)
|
| - return NULL;
|
| - }
|
| -
|
| -#ifdef EXT2
|
| - if (PyUnicode_Check(style)) {
|
| - if (!(style = PyUnicode_AsUTF8String(style)))
|
| - return NULL;
|
| - uni = 1;
|
| - }
|
| - else {
|
| - if (!(style = PyObject_Str(style)))
|
| - return NULL;
|
| - uni = 0;
|
| - }
|
| -#endif
|
| -
|
| -#ifdef EXT3
|
| - Py_INCREF(style);
|
| -#define PyString_GET_SIZE PyUnicode_GET_SIZE
|
| -#define PyString_AS_STRING PyUnicode_AS_UNICODE
|
| -#define _PyString_Resize PyUnicode_Resize
|
| -#define PyString_FromStringAndSize PyUnicode_FromUnicode
|
| -#endif
|
| -
|
| - rlength = slength = PyString_GET_SIZE(style);
|
| -
|
| -again:
|
| - if (!(result = PyString_FromStringAndSize(NULL, rlength))) {
|
| - Py_DECREF(style);
|
| - return NULL;
|
| - }
|
| - Py_BEGIN_ALLOW_THREADS
|
| - length = rcssmin((rchar *)PyString_AS_STRING(style),
|
| - (rchar *)PyString_AS_STRING(result),
|
| - slength, rlength, keep_bang_comments);
|
| - Py_END_ALLOW_THREADS
|
| -
|
| - if (length > rlength) {
|
| - Py_DECREF(result);
|
| - rlength = length;
|
| - goto again;
|
| - }
|
| -
|
| - Py_DECREF(style);
|
| - if (length < 0) {
|
| - Py_DECREF(result);
|
| - return NULL;
|
| - }
|
| - if (length != rlength && _PyString_Resize(&result, length) == -1)
|
| - return NULL;
|
| -
|
| -#ifdef EXT2
|
| - if (uni) {
|
| - style = PyUnicode_DecodeUTF8(PyString_AS_STRING(result),
|
| - PyString_GET_SIZE(result), "strict");
|
| - Py_DECREF(result);
|
| - if (!style)
|
| - return NULL;
|
| - result = style;
|
| - }
|
| -#endif
|
| - return result;
|
| -}
|
| -
|
| -/* ------------------------ BEGIN MODULE DEFINITION ------------------------ */
|
| -
|
| -EXT_METHODS = {
|
| - {"cssmin",
|
| - (PyCFunction)rcssmin_cssmin, METH_VARARGS | METH_KEYWORDS,
|
| - rcssmin_cssmin__doc__},
|
| -
|
| - {NULL} /* Sentinel */
|
| -};
|
| -
|
| -PyDoc_STRVAR(EXT_DOCS_VAR,
|
| -"C implementation of rcssmin\n\
|
| -===========================\n\
|
| -\n\
|
| -C implementation of rcssmin.");
|
| -
|
| -
|
| -EXT_DEFINE(EXT_MODULE_NAME, EXT_METHODS_VAR, EXT_DOCS_VAR);
|
| -
|
| -EXT_INIT_FUNC {
|
| - PyObject *m;
|
| -
|
| - /* Create the module and populate stuff */
|
| - if (!(m = EXT_CREATE(&EXT_DEFINE_VAR)))
|
| - EXT_INIT_ERROR(NULL);
|
| -
|
| - EXT_ADD_UNICODE(m, "__author__", "Andr\xe9 Malo", "latin-1");
|
| - EXT_ADD_STRING(m, "__docformat__", "restructuredtext en");
|
| -
|
| - EXT_INIT_RETURN(m);
|
| -}
|
| -
|
| -/* ------------------------- END MODULE DEFINITION ------------------------- */
|
|
|