~rdoering/ubuntu/karmic/erlang/fix-535090

« back to all changes in this revision

Viewing changes to erts/emulator/beam/erl_bits.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-02-15 16:42:52 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090215164252-q5x4rcf8a5pbesb1
Tags: 1:12.b.5-dfsg-2
Upload to unstable after lenny is released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
736
736
    Uint b;
737
737
    byte *iptr;
738
738
 
 
739
    if (num_bits == 0) {
 
740
        return 1;
 
741
    }
 
742
 
739
743
    bit_offset = BIT_OFFSET(bin_offset);
740
744
    if (is_small(arg)) {
741
745
        Uint rbits = 8 - bit_offset;
820
824
}
821
825
 
822
826
int
 
827
erts_bs_put_utf8(ERL_BITS_PROTO_1(Eterm arg))
 
828
{
 
829
    Uint bin_offset = erts_bin_offset;
 
830
    Uint bit_offset;
 
831
    Uint num_bits;
 
832
    byte tmp_buf[4];
 
833
    byte* dst;
 
834
    Sint val;
 
835
 
 
836
    if (is_not_small(arg)) {
 
837
        return 0;
 
838
    }
 
839
    val = signed_val(arg);
 
840
    if (val < 0) {
 
841
        return 0;
 
842
    }
 
843
 
 
844
    if ((bit_offset = BIT_OFFSET(bin_offset)) == 0) {
 
845
        /* We can write directly into the destination binary. */
 
846
        dst = erts_current_bin+BYTE_OFFSET(bin_offset);
 
847
    } else {
 
848
        /* Unaligned destination binary. Must use a temporary buffer. */
 
849
        dst = tmp_buf;
 
850
    }
 
851
    if (val < 0x80) {
 
852
        dst[0] = val;
 
853
        num_bits = 8;
 
854
    } else if (val < 0x800) {
 
855
        dst[0] = 0xC0 | (val >> 6);
 
856
        dst[1] = 0x80 | (val & 0x3F);
 
857
        num_bits = 16;
 
858
    } else if (val < 0x10000UL) {
 
859
        if ((0xD800 <= val && val <= 0xDFFF) ||
 
860
            val == 0xFFFE || val == 0xFFFF) {
 
861
            return 0;
 
862
        }
 
863
        dst[0] = 0xE0 | (val >> 12);
 
864
        dst[1] = 0x80 | ((val >> 6) & 0x3F);
 
865
        dst[2] = 0x80 | (val & 0x3F);
 
866
        num_bits = 24;
 
867
    } else if (val < 0x110000) {
 
868
        dst[0] = 0xF0 | (val >> 18);
 
869
        dst[1] = 0x80 | ((val >> 12) & 0x3F);
 
870
        dst[2] = 0x80 | ((val >> 6) & 0x3F);
 
871
        dst[3] = 0x80 | (val & 0x3F);
 
872
        num_bits = 32;
 
873
    } else {
 
874
        return 0;
 
875
    }
 
876
 
 
877
    if (bin_offset != 0) {
 
878
        erts_copy_bits(dst, 0, 1, erts_current_bin, bin_offset, 1, num_bits);
 
879
    }
 
880
 
 
881
    erts_bin_offset += num_bits;
 
882
 
 
883
    return 1;
 
884
}
 
885
 
 
886
int
 
887
erts_bs_put_utf16(ERL_BITS_PROTO_2(Eterm arg, Uint flags))
 
888
{
 
889
    Uint bin_offset = erts_bin_offset;
 
890
    Uint bit_offset;
 
891
    Uint num_bits;
 
892
    byte tmp_buf[4];
 
893
    byte* dst;
 
894
    Uint val;
 
895
 
 
896
    if (is_not_small(arg)) {
 
897
        return 0;
 
898
    }
 
899
    val = unsigned_val(arg);
 
900
    if (val > 0x10FFFF || (0xD800 <= val && val <= 0xDFFF) ||
 
901
        val == 0xFFFE || val == 0xFFFF) {
 
902
        return 0;
 
903
    }
 
904
 
 
905
    if ((bit_offset = BIT_OFFSET(bin_offset)) == 0) {
 
906
        /* We can write directly into the destination binary. */
 
907
        dst = erts_current_bin+BYTE_OFFSET(bin_offset);
 
908
    } else {
 
909
        /* Unaligned destination binary. Must use a temporary buffer. */
 
910
        dst = tmp_buf;
 
911
    }
 
912
 
 
913
    if (val < 0x10000UL) {
 
914
        num_bits = 16;
 
915
        if (flags & BSF_LITTLE) {
 
916
            dst[0] = val;
 
917
            dst[1] = val >> 8;
 
918
        } else {
 
919
            dst[0] = val >> 8;
 
920
            dst[1] = val;
 
921
        }
 
922
    } else {
 
923
        Uint16 w1, w2;
 
924
 
 
925
        num_bits = 32;
 
926
        val = val - 0x10000UL;
 
927
        w1 = 0xD800 | (val >> 10);
 
928
        w2 = 0xDC00 | (val & 0x3FF);
 
929
        if (flags & BSF_LITTLE) {
 
930
            dst[0] = w1;
 
931
            dst[1] = w1 >> 8;
 
932
            dst[2] = w2;
 
933
            dst[3] = w2 >> 8;
 
934
        } else {
 
935
            dst[0] = w1 >> 8;
 
936
            dst[1] = w1;
 
937
            dst[2] = w2 >> 8;
 
938
            dst[3] = w2;
 
939
        }
 
940
    }
 
941
 
 
942
    if (bin_offset != 0) {
 
943
        erts_copy_bits(dst, 0, 1, erts_current_bin, bin_offset, 1, num_bits);
 
944
    }
 
945
 
 
946
    erts_bin_offset += num_bits;
 
947
    return 1;
 
948
}
 
949
     
 
950
 
 
951
int
823
952
erts_new_bs_put_binary(ERL_BITS_PROTO_2(Eterm arg, Uint num_bits))
824
953
{
825
954
    byte *bptr;
1384
1513
}
1385
1514
 
1386
1515
Uint32
1387
 
erts_bs_get_unaligned_uint32(Process *p, ErlBinMatchBuffer* mb)
 
1516
erts_bs_get_unaligned_uint32(ErlBinMatchBuffer* mb)
1388
1517
{
1389
1518
    Uint bytes;
1390
1519
    Uint bits;
1408
1537
    return LSB[0] | (LSB[1]<<8) | (LSB[2]<<16) | (LSB[3]<<24);
1409
1538
}
1410
1539
 
 
1540
void
 
1541
erts_align_utf8_bytes(ErlBinMatchBuffer* mb, byte* buf)
 
1542
{
 
1543
    Uint bits = mb->size - mb->offset;
 
1544
 
 
1545
    /*
 
1546
     * Copy up to 4 bytes into the supplied buffer.
 
1547
     */
 
1548
 
 
1549
    ASSERT(bits >= 8);
 
1550
    if (bits <= 15) {
 
1551
        bits = 8;
 
1552
    } else if (bits >= 32) {
 
1553
        bits = 32;
 
1554
    } else if (bits >= 24) {
 
1555
        bits = 24;
 
1556
    } else {
 
1557
        bits = 16;
 
1558
    }
 
1559
    erts_copy_bits(mb->base, mb->offset, 1, buf, 0, 1, bits);
 
1560
}
 
1561
 
 
1562
Eterm
 
1563
erts_bs_get_utf16(ErlBinMatchBuffer* mb, Uint flags)
 
1564
{
 
1565
    Uint bit_offset;
 
1566
    Uint num_bits = mb->size - mb->offset;
 
1567
    byte* src;
 
1568
    byte tmp_buf[4];
 
1569
    Uint16 w1;
 
1570
    Uint16 w2;
 
1571
 
 
1572
    if (num_bits < 16) {
 
1573
        return THE_NON_VALUE;
 
1574
    }
 
1575
 
 
1576
    /*
 
1577
     * Set up the pointer to the source bytes.
 
1578
     */
 
1579
    if ((bit_offset = BIT_OFFSET(mb->offset)) == 0) {
 
1580
        /* We can access the binary directly because the bytes are aligned. */
 
1581
        src = mb->base + BYTE_OFFSET(mb->offset);
 
1582
    } else {
 
1583
        /*
 
1584
         * We must copy the data to a temporary buffer. If possible,
 
1585
         * get 4 bytes, otherwise two bytes.
 
1586
         */
 
1587
        Uint n = num_bits < 32 ? 16 : 32;
 
1588
        erts_copy_bits(mb->base, mb->offset, 1, tmp_buf, 0, 1, n);
 
1589
        src = tmp_buf;
 
1590
    }
 
1591
    
 
1592
    /*
 
1593
     * Get the first (and maybe only) 16-bit word. See if we are done.
 
1594
     */
 
1595
    if (flags & BSF_LITTLE) {
 
1596
        w1 = src[0] | (src[1] << 8);
 
1597
    } else {
 
1598
        w1 = (src[0] << 8) | src[1];
 
1599
    }
 
1600
    if (w1 < 0xD800 || w1 > 0xDFFF) {
 
1601
        if (w1 == 0xFFFE || w1 == 0xFFFF) {
 
1602
            return THE_NON_VALUE;
 
1603
        }
 
1604
        mb->offset += 16;
 
1605
        return make_small(w1);
 
1606
    } else if (w1 > 0xDBFF) {
 
1607
        return THE_NON_VALUE;
 
1608
    }
 
1609
 
 
1610
    /*
 
1611
     * Get the second 16-bit word and combine it with the first.
 
1612
     */
 
1613
    if (num_bits < 32) {
 
1614
        return THE_NON_VALUE;
 
1615
    } else if (flags & BSF_LITTLE) {
 
1616
        w2 = src[2] | (src[3] << 8);
 
1617
    } else {
 
1618
        w2 = (src[2] << 8) | src[3];
 
1619
    }
 
1620
    if (!(0xDC00 <= w2 && w2 <= 0xDFFF)) {
 
1621
        return THE_NON_VALUE;
 
1622
    }
 
1623
    mb->offset += 32;
 
1624
    return make_small((((w1 & 0x3FF) << 10) | (w2 & 0x3FF)) + 0x10000UL);
 
1625
}
1411
1626
 
1412
1627
static byte
1413
1628
get_bit(byte b, size_t offs)