package TestCase::Lib::SPVM::Unicode {
  use SPVM::Unicode;
  
  sub uchar : int () {
    
    {
      my $str = "あaい";
      
      my $pos = 0;
      
      # あ
      {
        my $uchar = SPVM::Unicode->uchar($str, \$pos);

        unless ($uchar == 0x3042) {
          return 0;
        }
        
        unless ($pos == 3) {
          return 0;
        }
      }

      # a
      {
        my $uchar = SPVM::Unicode->uchar($str, \$pos);

        unless ($uchar == 'a') {
          return 0;
        }
        
        unless ($pos == 4) {
          return 0;
        }
      }

      # い
      {
        my $uchar = SPVM::Unicode->uchar($str, \$pos);

        unless ($uchar == 0x3044) {
          return 0;
        }
        
        unless ($pos == 7) {
          return 0;
        }
      }
      
      # End
      {
        my $uchar = SPVM::Unicode->uchar($str, \$pos);
      
        unless ($uchar == -1) {
          return 0;
        }
      }
    }

    {
      my $str = "あaい";
      my $code_points = [0x3042, 'a', 0x3044];
      
      my $pos = 0;
      my $i = 0;
      while ((my $uchar = SPVM::Unicode->uchar($str, \$pos)) >= 0) {
        
        unless ($uchar == $code_points->[$i]) {
          return 0;
        }
        
        $i++;
      }
    }
      
    return 1;
  }

  sub uchar_to_u8 : int () {
    
    {
      my $pos = 0;
      
      # あ
      {
        my $uchar = 0x3042;
        my $u8_bytes = new byte[4];
        my $len = SPVM::Unicode->uchar_to_u8($uchar, $u8_bytes);
        unless ($len == 3) {
          return 0;
        }
        my $u8_str = (string)sliceb($u8_bytes, 0, $len);
        unless ($u8_str eq "あ") {
          return 0;
        }
      }

      # a
      {
        my $uchar = 'a';
        my $u8_bytes = new byte[4];
        my $len = SPVM::Unicode->uchar_to_u8($uchar, $u8_bytes);
        unless ($len == 1) {
          return 0;
        }
        my $u8_str = (string)sliceb($u8_bytes, 0, $len);
        unless ($u8_str eq "a") {
          return 0;
        }
      }

      # い
      {
        my $uchar = 0x3044;
        my $u8_bytes = new byte[4];
        my $len = SPVM::Unicode->uchar_to_u8($uchar, $u8_bytes);
        unless ($len == 3) {
          return 0;
        }
        my $u8_str = (string)sliceb($u8_bytes, 0, $len);
        unless ($u8_str eq "い") {
          return 0;
        }
      }
    }
    return 1;
  }

  sub convert_u32_to_u16 : int () {
    # あaい
    {
      my $u32chars = [0x3042, 'a', 0x3044];
      
      my $u16chars = SPVM::Unicode->convert_u32_to_u16($u32chars);
      
      unless ($u16chars->[0] == $u32chars->[0]) {
        return 0;
      }
      unless ($u16chars->[1] == $u32chars->[1]) {
        return 0;
      }
      
      unless ($u16chars->[2] == $u32chars->[2]) {
        return 0;
      }
    }

    # あ𠮷a(サロゲートペア)
    {
      my $u32chars = [0x3042, 0x20bb7, 'a'];
      
      my $u16chars = SPVM::Unicode->convert_u32_to_u16($u32chars);
      
      unless (@$u16chars == 4) {
        return 0;
      }
      
      unless ($u16chars->[0] == 0x3042) {
        return 0;
      }
      unless ($u16chars->[1] == (short)0xd842) {
        return 0;
      }
      unless ($u16chars->[2] == (short)0xdfb7) {
        return 0;
      }
      
      unless ($u16chars->[3] == 'a') {
        return 0;
      }
    }
    
    return 1;
  }

  sub convert_u16_to_u32 : int () {
    # あaい
    {
      my $u16chars = [(short)0x3042, 'a', 0x3044];
      
      my $u32chars = SPVM::Unicode->convert_u16_to_u32($u16chars);
      
      unless ($u32chars->[0] == $u16chars->[0]) {
        return 0;
      }
      unless ($u32chars->[1] == $u16chars->[1]) {
        return 0;
      }
      
      unless ($u32chars->[2] == $u16chars->[2]) {
        return 0;
      }
    }

    # あ𠮷a(サロゲートペア)
    {
      my $u16chars = [(short)0x3042, (short)0xd842, (short)0xdfb7, 'a'];
      
      my $u32chars = SPVM::Unicode->convert_u16_to_u32($u16chars);
      
      unless ($u32chars->[0] == 0x3042) {
        return 0;
      }
      
      unless ($u32chars->[1] == 0x20bb7) {
        return 0;
      }
      unless ($u32chars->[2] == 'a') {
        return 0;
      }
    }
    
    return 1;
  }

  sub u16 : int () {
    # サロゲートペア含む
    my $str = "あ𠮷a";
    
    my $u16chars = SPVM::Unicode->u16($str);
    
    unless (@$u16chars == 4) {
      return 0;
    }
    unless ($u16chars->[0] == 0x3042) {
      return 0;
    }
    unless ($u16chars->[1] == (short)0xd842) {
      return 0;
    }
    unless ($u16chars->[2] == (short)0xdfb7) {
      return 0;
    }
    
    unless ($u16chars->[3] == 'a') {
      return 0;
    }
    
    return 1;
  }

  sub u8 : int () {
    # サロゲートペア含む
    my $u16chars = [(short)0x3042, (short)0xd842, (short)0xdfb7, 'a'];
    
    my $str = SPVM::Unicode->u8($u16chars);
    
    unless ($str eq "あ𠮷a") {
      return 0;
    }
    
    return 1;
  }
}
