Login
Check-in [e186ee37ae]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added cssminc_process_cstr() and friends to simplify processing CSS from/to C-style strings, primarily to help support a basic WASM build.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e186ee37ae02f309d514e2f56b2683f5eb64e70803b923b628003e52ec418ab9
User & Date: stephan 2022-06-04 09:12:55
Context
2022-07-10
13:56
Renamed Makefile to GNUmakefile. check-in: f22f86859b user: stephan tags: trunk
2022-06-04
09:12
Added cssminc_process_cstr() and friends to simplify processing CSS from/to C-style strings, primarily to help support a basic WASM build. check-in: e186ee37ae user: stephan tags: trunk
2021-09-15
04:44
download.html wording fixes. check-in: a9bc35b5c2 user: stephan tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to cssminc.c.
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15

16
17
18
19
20
21
22
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
/* vim: set ts=2 et sw=2 tw=80: */
/**
   A mostly-minifier for Cascading Style Sheet (CSS) content.

   This file houses both a library and an app. Compile it with
   CSSMINC_MAIN defined (a value is not required) to build the app,
   otherwise it builds as a library.
*/
#include "cssminc.h"

#include <assert.h>

/*#include <string.h>*/ /* memset() */

const cssminc_state cssminc_state_empty = cssminc_state_empty_m;


#if 1 && !defined(NDEBUG)
#include <stdarg.h>
/* For debugging only */
static void logit(char const * fmt, ...) {
  va_list args;
  fflush(stdout);












>
|


>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
/* vim: set ts=2 et sw=2 tw=80: */
/**
   A mostly-minifier for Cascading Style Sheet (CSS) content.

   This file houses both a library and an app. Compile it with
   CSSMINC_MAIN defined (a value is not required) to build the app,
   otherwise it builds as a library.
*/
#include "cssminc.h"

#include <assert.h>
#include <stdlib.h> /* realloc() */
#include <string.h> /* strlen() */

const cssminc_state cssminc_state_empty = cssminc_state_empty_m;
const cssminc_state_cstr cssminc_state_cstr_empty = {NULL,NULL,NULL,NULL,0U,0U};

#if 1 && !defined(NDEBUG)
#include <stdarg.h>
/* For debugging only */
static void logit(char const * fmt, ...) {
  va_list args;
  fflush(stdout);
400
401
402
403
404
405
406








































































407
408
409
410
411
412
413
  cs.outState = out;
  cs.in = cssminc_input_f_FILE;
  cs.inState = in;
  return cssminc_process(&cs);
}











































































/************************************************************************
The library code ends here. What follows is a quick-and-dirty main()
app for the library..
************************************************************************/
#if defined(CSSMINC_MAIN)
#include "cliapp.h"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  cs.outState = out;
  cs.in = cssminc_input_f_FILE;
  cs.inState = in;
  return cssminc_process(&cs);
}


int cssminc_output_f_cstr(void * state, unsigned char const * bytes,
                          unsigned int n){
  cssminc_state_cstr * const s = (cssminc_state_cstr *)state;
  if(n + s->outLen >= s->outAlloced){
    unsigned int const i = (s->outLen
                            ? ((s->outLen + n) * 3 / 2) + 1
                            : (n < 3 ? 3 : n + 1));
    char * z;
    if(i<=n) return CSSMINC_RC_RANGE/*overflow*/;
    z = realloc(s->zOut, i);
    if(!z) return CSSMINC_RC_OOM;
    s->zOut = z;
    s->outAlloced = i;
  }
  memcpy(s->zOut + s->outLen, bytes, n);
  s->zOut[s->outLen += n] = 0;
  return 0;
}

int cssminc_input_f_cstr(void * state, unsigned char * dest,
                         unsigned int * n) {
  cssminc_state_cstr * const s = (cssminc_state_cstr *)state;
  if(!s->zCursor) s->zCursor = s->zStart;
  if(s->zCursor >= s->zEnd){
    *n = 0;
    return 0;
  }else if(s->zCursor + *n > s->zEnd){
    *n = (unsigned int)(s->zEnd - s->zCursor);
  }
  memcpy(dest, s->zCursor, *n);
  s->zCursor += *n;
  return 0;
}

int cssminc_process_cstr(char const * zIn, int len, char ** zOut, unsigned int * outLen,
                         cssminc_state * const opt){
  cssminc_state cs = cssminc_state_empty;
  cssminc_state_cstr cstr = cssminc_state_cstr_empty;
  int rc;
  if(len<0) len = (int)strlen(zIn);
  if(0==len){
    *zOut = NULL;
    *outLen = 0;
    return 0;
  }
  cs.out = cssminc_output_f_cstr;
  cs.outState = &cstr;
  cs.in = cssminc_input_f_cstr;
  cs.inState = &cstr;
  cstr.zStart = zIn;
  cstr.zEnd = zIn + len;
  if(opt) cs.options = opt->options;
  rc = cssminc_process(&cs);
  if(opt){
    opt->metrics = cs.metrics;
    opt->errInfo = cs.errInfo;
  }
  if(rc){
    free(cstr.zOut);
  }else{
    if(outLen) *outLen = cstr.outLen;
    *zOut = cstr.zOut;
  }
  return rc;    
}

char * cssminc_process_cstr2(char const * zIn, int inLen, cssminc_state * const opt){
  char * zOut = 0;
  cssminc_process_cstr(zIn, inLen, &zOut, NULL, opt);
  return zOut;
}


/************************************************************************
The library code ends here. What follows is a quick-and-dirty main()
app for the library..
************************************************************************/
#if defined(CSSMINC_MAIN)
#include "cliapp.h"
672
673
674
675
676
677
678















679
680
681
682
683
684
685
    goto end;
  }

  if(cssmincGotHelpFlag){
    cssminc_show_help();
    goto end;
  }
















  {
    FILE * in = 0, * out = 0;
    if(!App.inFile || ('-'==App.inFile[0] && !App.inFile[1])){
      in = stdin;
    }else if(App.inFile){
      in = fopen(App.inFile, "rb");







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
    goto end;
  }

  if(cssmincGotHelpFlag){
    cssminc_show_help();
    goto end;
  }

  if(0){
    /* Just testing cssminc_process_cstr() and friends. */
    char const * zCss = "/* foo */\nx {y : z}\n"
      "/* comment */ xyz,  zyx {one: \"two\"}";
    char * zOut = NULL;
    didSomething = 1;
    rc = cssminc_process_cstr(zCss, -1, &zOut, NULL, cs);
    cliapp_warn("rc=%d zOut=%s\n", rc, zOut);
    free(zOut);
    zOut = cssminc_process_cstr2(zCss, -1, cs);
    cliapp_warn("zOut=%s\n", zOut);
    free(zOut);
    goto end;
  }

  {
    FILE * in = 0, * out = 0;
    if(!App.inFile || ('-'==App.inFile[0] && !App.inFile[1])){
      in = stdin;
    }else if(App.inFile){
      in = fopen(App.inFile, "rb");
Changes to cssminc.h.
76
77
78
79
80
81
82
83





84
85
86
87
88
89
90
/** The obligatory "not-an-error" code. */
CSSMINC_RC_OK = 0,
/** Indicates that cssminc_process() encountered something it couldn't
    parse. */
CSSMINC_RC_PARSE = 1,
/** Used by cssminc_output_f_FILE() and cssminc_input_f_FILE() to
    indicate I/O errors. */
CSSMINC_RC_IO = 2





};

/**
   Abstract streaming output interface used by the cssminc
   library. The first argument is an implementation-specific state
   type (may be NULL if the implementation allows it).








|
>
>
>
>
>







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/** The obligatory "not-an-error" code. */
CSSMINC_RC_OK = 0,
/** Indicates that cssminc_process() encountered something it couldn't
    parse. */
CSSMINC_RC_PARSE = 1,
/** Used by cssminc_output_f_FILE() and cssminc_input_f_FILE() to
    indicate I/O errors. */
CSSMINC_RC_IO = 2,
/** Indicates some form of range error, e.g. overflow. */
CSSMINC_RC_RANGE = 3,
/** Used by cssminc_process_cstr() to indicate a memory allocation
    failure. */
CSSMINC_RC_OOM = 4
};

/**
   Abstract streaming output interface used by the cssminc
   library. The first argument is an implementation-specific state
   type (may be NULL if the implementation allows it).

290
291
292
293
294
295
296
297

298
299
300
301
302
303
304





























































































































305
306
307
308
309
310
311

   If passed a NULL state pointer, it uses stdin.

   Returns 0 on success, CSSMINC_RC_IO on error.
*/
int cssminc_input_f_FILE(void * state, unsigned char * dest,
                        unsigned int * n);


/**
   A convenience wrapper which is equivalent to initializing a
   cssminc_state instance using cssminc_input_f_FILE() matched with the
   given input source, cssminc_output_f_FILE() matched with the given
   destination file, and passing it to cssminc_process().
*/
int cssminc_process_FILE(FILE * src, FILE * dest);






























































































































/* LICENSE

   This software's source code, including accompanying documentation and
   demonstration applications, are licensed under the following
   conditions...









>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

   If passed a NULL state pointer, it uses stdin.

   Returns 0 on success, CSSMINC_RC_IO on error.
*/
int cssminc_input_f_FILE(void * state, unsigned char * dest,
                        unsigned int * n);


/**
   A convenience wrapper which is equivalent to initializing a
   cssminc_state instance using cssminc_input_f_FILE() matched with the
   given input source, cssminc_output_f_FILE() matched with the given
   destination file, and passing it to cssminc_process().
*/
int cssminc_process_FILE(FILE * src, FILE * dest);

/**
   State for managing C-string input and/or output for
   cssminc_process(). It can be used as state for both
   cssminc_input_f_cstr() and cssminc_output_f_cstr() to fetch input
   from a string and/or send output to a dynamically-allocated string.
   For input processing, it requires that all input be available in
   memory for the duration of processing. For output processing it
   must (re)allocate dynamic memory an arbitrary number of times.
*/
struct cssminc_state_cstr {
  /** Input: pointer to the start of the input string. Client must set
      this before processing starts and it must not change during
      processing. */
  char const * zStart;
  /** Input: pointer to the one-past-the-end of the input
      string. Client must set this before processing starts and it
      must not change during processing. */
  char const * zEnd;
  /** Input: must initially be set to zStart or NULL (same effect
      either way). Client must set this before processing starts,
      after which it's managed by cssminc_input_f_cstr(). */
  char const * zCursor;
  /**
     Output: pointer to the dynamically-allocated output. Must
     normally be set to NULL before processing, after which it is
     managed by cssminc_output_f_cstr(), which always NUL-terminates
     it.

     It is legal for clients to set this to non-NULL before starting
     if (and only if):

     1) The memory is allocated by malloc() or realloc().

     2) The outAlloced member is set to the number of bytes allocated
     in that block. If output grows beyond that point, this member
     gets reallocated and that member gets updated with the new
     allocation size.
  */
  char * zOut;
  /** Output: the current string length, in bytes, of zOut (as opposed
      to its reserved-for-use length). Must be set to 0 before
      processing, after which it is managed by
      cssminc_output_f_cstr(). */
  unsigned int outLen;
  /** Output: current amount of memory allocated for use by zOut. Must
      be set to 0 before processing, after which it is managed by
      cssminc_output_f_cstr(). */
  unsigned int outAlloced;
};
typedef struct cssminc_state_cstr cssminc_state_cstr;
/**
   An empty-initialized cssminc_state_cstr instance intended for copy
   initialization.
*/
extern const cssminc_state_cstr cssminc_state_cstr_empty;

/**
   A cssminc_output_f() impl which requires that its state pointer be
   a (cssminc_state_cstr*). This function manages the zOut, outLen,
   and outAlloced members of that object and requires that all have
   initial values of 0.

   All memory allocation for the zOut member is performed using
   realloc() and must eventually be released by passing it to free().

   Returns 0 on success, CSSMINC_RC_OOM on allocation error, or
   CSSMINC_RC_RANGE if calculating the allocation size would overflow.
*/
int cssminc_output_f_cstr(void * state, unsigned char const * bytes,
                          unsigned int n);

/**
   A cssminc_input_f() impl which requires that its state pointer be a
   (cssminc_state_cstr*) with its zStart, zEnd, and zCursor pointers
   set up properly. This function manages the zCursor pointer.

   Returns 0 on success and has no error conditions which it can
   detect.
*/
int cssminc_input_f_cstr(void * state, unsigned char * dest,
                         unsigned int * n);

/**
   A convenience wrapper which uses cssminc_state_cstr and friends to
   process input from a C-string and output it to a C-string.

   The final argument may be NULL, in which case default processing
   options are used. If it is not NULL, its in/out members are ignored
   but its `options` member is honored and its `metrics` and `errInfo`
   members will be populated by this function.

   If inLen is negative then strlen() is used to calculate zIn's length.
   On success:

   - 0 is returned.

   - `*zOut` will be set to the start of the output string.

   - `*outLen` (if `outLen` is not NULL) will be set to the length of
     `*zOut`, in bytes.

   - Ownership of `*zOut` is transfered to the caller, who must
     eventually pass it to free().

   On error non-0 is returned and neither `zOut` nor `outLen` are
   modified.
*/
int cssminc_process_cstr(char const * zIn, int inLen, char ** zOut,
                         unsigned int * outLen,
                         cssminc_state * const opt);

/**
   A convenience form of cssminc_process_cstr() intended primarily for
   use in WASM bindings. zIn is the input CSS, inLen is its length.
   If inLen is negative, strlen() is used to calculate it. On success
   it returns the minified output CSS, else returns NULL on error. If
   it returns non-NULL then ownership of the memory is transfered to
   the caller, who must eventually relinquish it using free().

   The final argument may be NULL and is treated as documented for
   cssminc_process_cstr().
*/
char * cssminc_process_cstr2(char const * zIn, int inLen, cssminc_state * const opt);


/* LICENSE

   This software's source code, including accompanying documentation and
   demonstration applications, are licensed under the following
   conditions...