Changeset aaf962e6 in mainline


Ignore:
Timestamp:
2020-09-21T21:41:53Z (4 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ea459d4
Parents:
d145ecb
Message:

Need to be able to skip unknown chunks easily

This is, afterall the whole point of having a self-describing format:
new (optional) chunks types can be inserted without having to modify the
reader.

Location:
uspace/lib/riff
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/riff/include/riff/chunk.h

    rd145ecb raaf962e6  
    5252extern errno_t riff_read_uint32(riff_rchunk_t *, uint32_t *);
    5353extern errno_t riff_rchunk_start(riff_rchunk_t *, riff_rchunk_t *);
     54extern errno_t riff_rchunk_match(riff_rchunk_t *, riff_ckid_t, riff_rchunk_t *);
     55extern errno_t riff_rchunk_list_match(riff_rchunk_t *, riff_ltype_t,
     56    riff_rchunk_t *);
    5457extern errno_t riff_rchunk_end(riff_rchunk_t *);
    5558extern errno_t riff_read(riff_rchunk_t *, void *, size_t, size_t *);
  • uspace/lib/riff/include/types/riff/chunk.h

    rd145ecb raaf962e6  
    4242typedef uint32_t riff_ckid_t;
    4343typedef uint32_t riff_cksize_t;
     44typedef uint32_t riff_ltype_t;
    4445
    4546/** RIFF writer */
  • uspace/lib/riff/src/chunk.c

    rd145ecb raaf962e6  
    3939#include <macros.h>
    4040#include <riff/chunk.h>
     41#include <stdbool.h>
    4142#include <stdlib.h>
    4243
     
    271272 * @param rchunk RIFF chunk
    272273 * @param v  Place to store value
    273  * @return EOK on success, EIO on error.
     274 * @return EOK on success, ELIMIT if at the end of parent chunk, EIO on error.
    274275 */
    275276errno_t riff_read_uint32(riff_rchunk_t *rchunk, uint32_t *v)
     
    295296 * @param rchunk Pointer to chunk structure to fill in
    296297 *
    297  * @return EOK on success, EIO on error.
     298 * @return EOK on success, ELIMIT if at the end of parent chunk,
     299 *         EIO on error.
    298300 */
    299301errno_t riff_rchunk_start(riff_rchunk_t *parent, riff_rchunk_t *rchunk)
     
    320322error:
    321323        return rc;
     324}
     325
     326/** Find and start reading RIFF chunk of with specific chunk ID.
     327 * Other types of chunks are skipped.
     328 *
     329 * @param parent Parent chunk
     330 * @param rchunk Pointer to chunk structure to fill in
     331 *
     332 * @return EOK on success, ENOENT chunk was not found and end was reached
     333 *         EIO on error.
     334 */
     335errno_t riff_rchunk_match(riff_rchunk_t *parent, riff_ckid_t ckid,
     336    riff_rchunk_t *rchunk)
     337{
     338        errno_t rc;
     339
     340        while (true) {
     341                rc = riff_rchunk_start(parent, rchunk);
     342                if (rc == ELIMIT)
     343                        return ENOENT;
     344                if (rc != EOK)
     345                        return rc;
     346
     347                if (rchunk->ckid == ckid)
     348                        break;
     349
     350                rc = riff_rchunk_end(rchunk);
     351                if (rc != EOK)
     352                        return rc;
     353        }
     354
     355        return EOK;
     356}
     357
     358/** Find and start reading RIFF LIST chunk of specified type.
     359 * Other chunks or LIST chunks of other type are skipped.
     360 *
     361 * @param parent Parent chunk
     362 * @param rchunk Pointer to chunk structure to fill in
     363 *
     364 * @return EOK on success, ENOENT chunk was not found and end was reached
     365 *         EIO on error.
     366 */
     367errno_t riff_rchunk_list_match(riff_rchunk_t *parent, riff_ltype_t ltype,
     368    riff_rchunk_t *rchunk)
     369{
     370        errno_t rc;
     371        riff_ltype_t rltype;
     372
     373        while (true) {
     374                rc = riff_rchunk_match(parent, CKID_LIST, rchunk);
     375                if (rc == ELIMIT)
     376                        return ENOENT;
     377                if (rc != EOK)
     378                        return rc;
     379
     380                rc = riff_read_uint32(parent, &rltype);
     381                if (rc != EOK)
     382                        return rc;
     383
     384                if (rltype == ltype)
     385                        break;
     386
     387                rc = riff_rchunk_end(rchunk);
     388                if (rc != EOK)
     389                        return rc;
     390        }
     391
     392        return EOK;
    322393}
    323394
  • uspace/lib/riff/test/chunk.c

    rd145ecb raaf962e6  
    327327        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
    328328
    329 //      (void) remove(p);
     329        (void) remove(p);
    330330}
    331331
     332/** Match specific chunk type in a RIFF file */
     333PCUT_TEST(match_chunk)
     334{
     335        char fname[L_tmpnam];
     336        char *p;
     337        riffw_t *rw;
     338        riffr_t *rr;
     339        riff_wchunk_t wriffck;
     340        riff_wchunk_t wdatack;
     341        riff_rchunk_t rriffck;
     342        riff_rchunk_t rdatack;
     343        uint32_t rword;
     344        errno_t rc;
     345
     346        p = tmpnam(fname);
     347        PCUT_ASSERT_NOT_NULL(p);
     348
     349        /* Write RIFF file */
     350
     351        rc = riff_wopen(p, &rw);
     352        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     353        PCUT_ASSERT_NOT_NULL(rw);
     354
     355        rc = riff_wchunk_start(rw, CKID_RIFF, &wriffck);
     356        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     357
     358        /* Write first data chunk */
     359
     360        rc = riff_wchunk_start(rw, CKID_dat1, &wdatack);
     361        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     362
     363        rc = riff_write_uint32(rw, 1);
     364        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     365
     366        rc = riff_wchunk_end(rw, &wdatack);
     367        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     368
     369        /* Write second data chunk */
     370
     371        rc = riff_wchunk_start(rw, CKID_dat2, &wdatack);
     372        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     373
     374        rc = riff_write_uint32(rw, 2);
     375        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     376
     377        rc = riff_wchunk_end(rw, &wdatack);
     378        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     379
     380        /* Write third data chunk */
     381
     382        rc = riff_wchunk_start(rw, CKID_dat1, &wdatack);
     383        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     384
     385        rc = riff_write_uint32(rw, 3);
     386        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     387
     388        rc = riff_wchunk_end(rw, &wdatack);
     389        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     390
     391        rc = riff_wchunk_end(rw, &wriffck);
     392        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     393
     394        rc = riff_wclose(rw);
     395        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     396
     397        /* Read back RIFF file */
     398
     399        rc = riff_ropen(p, &rriffck, &rr);
     400        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     401        PCUT_ASSERT_NOT_NULL(rr);
     402
     403        PCUT_ASSERT_INT_EQUALS(CKID_RIFF, rriffck.ckid);
     404
     405        /* Match second data chunk */
     406
     407        rc = riff_rchunk_match(&rriffck, CKID_dat2, &rdatack);
     408        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     409        PCUT_ASSERT_INT_EQUALS(CKID_dat2, rdatack.ckid);
     410
     411        rc = riff_read_uint32(&rdatack, &rword);
     412        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     413
     414        PCUT_ASSERT_INT_EQUALS(2, rword);
     415
     416        rc = riff_rchunk_end(&rdatack);
     417        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     418
     419        /* Try matching dat2 again (should not match) */
     420
     421        rc = riff_rchunk_match(&rriffck, CKID_dat2, &rdatack);
     422        PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
     423
     424        /* Try matching dat1 again (but there's nothing left) */
     425
     426        rc = riff_rchunk_match(&rriffck, CKID_dat1, &rdatack);
     427        PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
     428
     429        rc = riff_rclose(rr);
     430        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     431
     432        (void) remove(p);
     433}
     434
     435/** Match specific LIST chunk type in a RIFF file */
     436PCUT_TEST(list_match)
     437{
     438        char fname[L_tmpnam];
     439        char *p;
     440        riffw_t *rw;
     441        riffr_t *rr;
     442        riff_wchunk_t wriffck;
     443        riff_wchunk_t wdatack;
     444        riff_rchunk_t rriffck;
     445        riff_rchunk_t rdatack;
     446        uint32_t rword;
     447        errno_t rc;
     448
     449        p = tmpnam(fname);
     450        PCUT_ASSERT_NOT_NULL(p);
     451
     452        /* Write RIFF file */
     453
     454        rc = riff_wopen(p, &rw);
     455        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     456        PCUT_ASSERT_NOT_NULL(rw);
     457
     458        rc = riff_wchunk_start(rw, CKID_RIFF, &wriffck);
     459        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     460
     461        /* Write first LIST chunk */
     462
     463        rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
     464        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     465
     466        rc = riff_write_uint32(rw, LTYPE_lst1);
     467        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     468
     469        rc = riff_write_uint32(rw, 1);
     470        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     471
     472        rc = riff_wchunk_end(rw, &wdatack);
     473        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     474
     475        /* Write second data chunk */
     476
     477        rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
     478        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     479
     480        rc = riff_write_uint32(rw, LTYPE_lst2);
     481        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     482
     483        rc = riff_write_uint32(rw, 2);
     484        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     485
     486        rc = riff_wchunk_end(rw, &wdatack);
     487        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     488
     489        /* Write third data chunk */
     490
     491        rc = riff_wchunk_start(rw, CKID_LIST, &wdatack);
     492        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     493
     494        rc = riff_write_uint32(rw, LTYPE_lst1);
     495        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     496
     497        rc = riff_write_uint32(rw, 3);
     498        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     499
     500        rc = riff_wchunk_end(rw, &wdatack);
     501        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     502
     503        rc = riff_wchunk_end(rw, &wriffck);
     504        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     505
     506        rc = riff_wclose(rw);
     507        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     508
     509        /* Read back RIFF file */
     510
     511        rc = riff_ropen(p, &rriffck, &rr);
     512        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     513        PCUT_ASSERT_NOT_NULL(rr);
     514
     515        PCUT_ASSERT_INT_EQUALS(CKID_RIFF, rriffck.ckid);
     516
     517        /* Match second LIST chunk */
     518
     519        rc = riff_rchunk_list_match(&rriffck, LTYPE_lst2, &rdatack);
     520        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     521
     522        rc = riff_read_uint32(&rdatack, &rword);
     523        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     524
     525        PCUT_ASSERT_INT_EQUALS(2, rword);
     526
     527        rc = riff_rchunk_end(&rdatack);
     528        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     529
     530        /* Try matching lst2 again (should not match) */
     531
     532        rc = riff_rchunk_list_match(&rriffck, LTYPE_lst2, &rdatack);
     533        PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
     534
     535        /* Try matching lst1 again (but there's nothing left) */
     536
     537        rc = riff_rchunk_list_match(&rriffck, LTYPE_lst1, &rdatack);
     538        PCUT_ASSERT_ERRNO_VAL(ENOENT, rc);
     539
     540        rc = riff_rclose(rr);
     541        PCUT_ASSERT_ERRNO_VAL(EOK, rc);
     542
     543        (void) remove(p);
     544}
     545
    332546PCUT_EXPORT(chunk);
Note: See TracChangeset for help on using the changeset viewer.