Login
Artifact [0eb8c13ed3]
Login

Artifact 0eb8c13ed3701bfce0df8d0532d965ba8348ab2b:



const Buffer = s2.Buffer.new;

scope {

  var b = Buffer();
  assert b inherits s2.Buffer;
  assert !b.capacity();
  assert !b.length();
  b.length(10);
  assert 10 === b.length();
  assert b.# === b.length();
  assert b.capacity() >= b.length();
}


scope {
    const sz = 20, b = Buffer(sz);
    assert !b.#;
    assert b.isEmpty();
    assert b.capacity() >= sz;
    b.append('a');
    assert !b.isEmpty();
    assert 1 === b.#;
    b.appendf('%1$d', 1);
    assert 2 === b.#;

    b.fill(42);
    assert '**' === b.toString() /* ensure that fill() does not change the length() */;

    b.reset();
    assert 0 === b.#;
    b.fill('!');
    assert undefined === b.byteAt(0) /* ensure that fill() does not change the length() */;

    b.length(sz).fill( '$' );
    assert 36 === b.byteAt( 0 );
    assert 36 === b.byteAt( sz-1 );
    assert undefined === b.byteAt( sz );

    b.fill( '!', 1, 18 );
    assert 36 === b.byteAt( 0 );
    assert 36 === b.byteAt( 19 );
    assert 33 === b.byteAt( 1 );
    assert 33 === b.byteAt( 18 );
    assert '$!' === b.toString( 0, 2 );
}

scope {
    const fmt = proc callee(fmt){
        return callee.buffer.reset( 0 ).appendf.apply( callee.buffer, argv ).toString();
    };
    fmt.buffer = Buffer(100);
    const check = proc(cmp){
        argv.shift();
        const s = fmt.apply(fmt,argv);
        (s===cmp) || throw ("Mismatch: <<<"+cmp+">>> !== <<<" +s+">>>");
        assert 1 /* count the above comparison as an assertion.
                    We use throw only to get more info out of it
                    if it fails*/;
    };
    const av = [ 42, "string formatter", "abcde",
                 19.17, true, false, -13.19];

    assert 'CWAL_RC_RANGE' === catch{fmt("%8$+f", 0)/*not enough args*/}.codeString();

    check( '%', '%%' );
    check( '%x%y', '%%x%%y' );

    check( 'hi, world', "%1$s", 'hi, world' );
    check('hi, world (           hi, world)',
          "%1$s (%1$20s)", 'hi, world');
    check('integer 42 042 02A 002a',
          "%1$y %1$d %1$03d %1$03X %1$04x", av.0);
    check('(        42) (42        )',
          "(%1$10d) (%1$-10d)", av.0);
    check('(       +42) (+42       )',
          "(%1$+10d) (%1$+-10d)", av.0);

    check( '00042', "%1$05d", av.0 );
    check( '42.00000', "%1$0.5f", av.0 );
    check('string formatter', "%2$s", 0, av.1);
    check('string', "%2$.6s", 0, av.1);
    check('string formatter and string formatter',
          "%2$s and %2$s", 0, av.1);
    check( '(abcde     ) (     abcde)',
           "(%3$-10s) (%3$10s)", 0, 0, av.2 );
    check( '(     abcde) (abcde     )',
           "(%3$10s) (%3$-10s)", 0, 0, av.2 );
    check( '(       abc) (abc       )',
           "(%3$10.3s) (%3$-10.3s)", 0, 0, av.2 );
    check( '(abc       ) (       abc)',
           "(%3$-10.3s) (%3$10.3s)", 0, 0, av.2 );
    check( '(abcd) (abcd    )',
           "(%3$.4s) (%3$-8.4s)", 0, 0, av.2 );
    check( '19.17 19.2 19.17 19.170',
           "%4$f %4$.1f %4$.2f %4$.3f", 0, 0, 0, av.3 );
    check( '+19.17 (19.170    ) (    19.170) (+00019.170)',
           "%4$+0f (%4$-10.3f) (%4$10.3f) (%4$+010.3f)", 0, 0, 0, av.3 );
    check( '1 true false null undefined',
           "%5$d %5$b %6$b %5$N %5$U", 0, 0, 0, 0, av.4, av.5 );
    check( '0.0', "%6$+f", 0, 0, 0, 0, 0, av.5 );
    check( '-13.19', "%7$+f", 0, 0, 0, 0, 0, 0, av.6 );

    check( '68692C20776F726C64',
           "%1$B", "hi, world" );
    check( '68692C20',
           "%1$.4B", "hi, world" );
    check( '                     68692C20776F726C64',
           "%1$30B", "hi, world" );

    check( '-1.0', '%1$.1f', -1.02 );
    check( '+1.0', '%1$+.1f', 1.02 );

    check( '-1', '%1$d', (-1) );
    check( '-1', '%1$+d', (-1) );
    check( '+1', '%1$+d', 1 );

    check( 'h', '%1$c', 'hi' );
    check( '     hhhhh', '%1$10.5c', 'hi' );
    check( 'hhhhh     ', '%1$-10.5c', 'hi' );
    check( '  ©', '%1$3c', '©' );
    check( '©©©', '%1$0.3c', '©' );
    check( '©©©', '%1$.3c', '©' );
    check( '©©©  ', '%1$-5.3c', '©' );
    check( '  ©©©', '%1$5.3c', '©' );
    check( 'A', '%1$c', 65 );
    check( 'AAAA', '%1$.4c', 65 );
    check( '10', '%1$o', 8 );
    check( '0010', '%1$04o', 8 );
    check( '  10', '%1$4o', 8 );
    assert '1 2 3' === "%1$d %2$d %3$d".applyFormat( 1,2,3 );
    check( '(NULL)', '%1$q', null );
    check( "h''i", '%1$q', "h'i" );
    check( "'h''i'", '%1$Q', "h'i" );
    check( 'NULL', '%1$Q', null );

    // check 0-precision characters...
    check( '', '%1$.0c', '*' );
    check( '', '%1$0.0c', '*' );
    check( '  ', '%1$2.0c', '*' ) /* arguable, but currently true */;

    // check urlencoding/decoding
    check( 'a%20b%26c', '%1$r', 'a b&c' );
    check( 'a b&c', '%1$R', 'a%20b%26c' );
    check( 'a%2zb', '%1$R', 'a%2zb' );

    assert catch {'%1$.1r'.applyFormat()}.message.indexOf('precision')>0;
    assert catch {'%1$1r'.applyFormat()}.message.indexOf('width')>0;
    assert catch {'%1$.1R'.applyFormat()}.message.indexOf('precision')>0;
    assert catch {'%1$1R'.applyFormat()}.message.indexOf('width')>0;
}

scope{
    var b = Buffer(100);
    var x = 0, y = 0;
    b << <<<EOF
    for(var i = 0; i < 5; ++i) ++x, --y; 
    1
    EOF;
    var rc = b.evalContents("foo");
    assert 1 === rc;
    assert 5 === x;
    assert -x === y;

    b.reset() << <<<EOF
    0;
    1;
    return {a:'a',b:'bbbb'};
    EOF;
  
    var name = 'bar';
    rc = b.evalContents(name);
    assert rc.a === 'a';
    assert rc.b === 'bbbb';

    b.reset() << <<<EOF
    0;
    1;
    throw 3;
    return {a:'a',b:'bbbb'};
    EOF;
  
    var ex = catch{
        rc = 1
        ? b.evalContents(name)
            : eval ->b;
        throw "NOT REACHED";
    };
    assert ex;
    //print(__FLC,'ex =',ex) /* a cycle (the exception obj!) in the stack trace!?!?!? Corruption??? */;
    // something here is triggering an assertion in cleanup!
    // Worked around: comments are in evalContents() impl for further consideration later.
    assert name === ex.script;
    assert 3 === ex.message;
    assert 3 === ex.line;
    assert 4 === ex.column;

    assert 3 === "a+b".evalContents({a:1,b:2});
    assert 'xyz' === "__FILE".evalContents('xyz');
    assert 'xyz9' === "__FILE+a".evalContents({a:9},'xyz');
    assert 'xyz8' === "__FILE+a".evalContents('xyz',{a:8});
    assert 'test.x' === catch {"A_+B_".evalContents('test.x',{a:1,b:2})}.script;
}

scope {
    var b = Buffer() << "h©, ©orld";
    assert '©, ©' === b.substr(1,4);
    assert 'h©, ©orld' === b.substr(0,-1);
    assert '©orld' === b.substr(4);
    assert ', ©o' === b.substr(2,4);

    b.reset();
    assert '' === b.substr(1);
}

scope {
    var b = Buffer() << 1.00;
    assert "1.0" === b.toString() /* bugfix check: leave final trailing 0 after the dot. */;


    /* Testing Buffer.slice()... */
    b.reset() << "012345";
    proc x(expect,offset=0,count=-1){
        const v = b.slice(offset, count).toString();
        (expect === v) && (assert "slice() check passed") && return x;
        throw "Mismatch: expecting ["+expect+"] but got: ["+v.toString()+"]";
    }
    ("012345")
    ("012345",0)
    ("012345",0,-1)
    ("12345",1,-1)
    ("12345",1,50)
    ("5", 5, 1)
    ("5", 5, 10)
    ("", 5, 0)
    ("1234", 1, 4)
    ;

    /* Buffer.replace() tests... */
    b.reset() << "012345";
    const check = proc callee(needle,replace/*,limitAndOrExpect*/){
        const expect = argv.3 ||| argv.2,
           limit = argv.3 ? argv.2 : 0;
        const v = b.replace(needle, replace, limit).toString();
        (expect === v) && (assert 1 /*Buffer.replace() check passed*/) && return callee;
        throw "Mismatch: expecting ["+expect+"] but got: ["+v+"]";
    }
    ('1', '9', '092345')
    (57, 42, '0*2345')
    ('345', '**', 42, '0*2**')
    ('*', 'x', 1, '0x2**')
    ('0x2', '', '**')
    (42, 0, '\0\0')
    ;
    assert !b.isEmpty() /* technically speaking */;
    assert 2 === b.#;
    assert 0 === b.byteAt(1);
    var v = b.toString();
    assert 2 === v.#;
    assert '\0\0' === v;

    b.reset() << "012345";
    check('1', '©', '0©2345')
         ('345', '©©', '0©2©©')
    ;

    b.reset() << "a*b*c";
    assert b.replace(42,33).toString() === "a!b!c";
    b.reset() << "a*b*c";
    assert b.replace(42,33,1).toString() === "a!b*c";

    assert catch {b.replace("","x")}.codeString() === 'CWAL_RC_RANGE' /* needle must be >0 bytes */;
}

scope {
    /*
      Ensure that evalContents() behaves safely when the being-eval'd
      buffer's contents are modified during evaluation. i.e. the
      modifications are only temporary and get discarded when
      evalContents() is done.
    */
    const contents = "x = 2; b<<'abc'; assert 'abc'===b.takeString()";
    var x, b = Buffer() << contents;
    b.evalContents(__FLC);
    assert 2 === x;
    assert contents === b.takeString();
}


if(const BB = s2.Buffer.compression ? s2.Buffer : 0){
    assert 0 === catch {BB.isCompressed()}.message.indexOf("'this'");
    assert 0 === catch {BB.isCompressed(1)}.message.indexOf("Argument");
    assert 0 === catch {BB.uncompressedSize()}.message.indexOf("'this'");
    assert 0 === catch {BB.uncompressedSize(1)}.message.indexOf("Argument");
    const b = BB.readFile(__FILE);
    const len = b.#;
    assert len > 5000;
    assert !b.isCompressed();
    assert !b.isCompressed(b);
    assert 0 === catch {b.isCompressed(1)}.message.indexOf("Argument");
    assert !BB.isCompressed(b);
    assert undefined === b.uncompressedSize();
    assert undefined === BB.uncompressedSize(b);
    assert b === b.uncompress() /* must be a no-op */;
    assert b.# === len;

    assert b === b.compress();
    assert b.isCompressed();
    assert b.isCompressed(b);
    assert BB.isCompressed(b);
    const zlen = b.#;
    assert zlen < len;
    assert zlen > len/10;
    assert b === BB.compress(b) /* must be a no-op */;
    assert b.# === zlen;
    assert len === b.uncompressedSize();
    assert len === BB.uncompressedSize(b);

    assert b === BB.uncompress(b);
    assert !b.isCompressed();
    assert !b.isCompressed(b);
    assert b.# === len;
    assert undefined === b.uncompressedSize();
    assert undefined === BB.uncompressedSize(b);

}else{
    /* For the benefit of the -A flag (assert tracing). */
    var b = Buffer();
    assert !b.isCompressed();
    assert 'CWAL_RC_UNSUPPORTED' === catch {b.compress()}.codeString();
    assert 'CWAL_RC_UNSUPPORTED' === catch {b.uncompress()}.codeString();
    assert undefined === b.uncompressedSize();
    /* note that b.uncompressedSize() _would_ work if it was compressed,
       but that's hard to demonstrate here w/o compression support. */
}