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 ------------------------- */ |