package TestCase::Lib::SPVM::Unicode {
  use SPVM::Unicode;
  
  sub ERROR_INVALID_UTF8 : int () {
    
    unless (SPVM::Unicode->ERROR_INVALID_UTF8 == -2) {
      return 0;
    }
    
    return 1;
  }
  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_utf8 : int () {
    
    {
      my $pos = 0;
      
      # あ
      {
        my $uchar = 0x3042;
        my $utf8_bytes = SPVM::Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 3) {
          return 0;
        }
        unless ($utf8_bytes eq "あ") {
          return 0;
        }
      }

      # a
      {
        my $uchar = 'a';
        my $utf8_bytes = SPVM::Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 1) {
          return 0;
        }
        unless ($utf8_bytes eq "a") {
          return 0;
        }
      }

      # い
      {
        my $uchar = 0x3044;
        my $utf8_bytes = SPVM::Unicode->uchar_to_utf8($uchar);
        my $len = length $utf8_bytes;
        unless ($len == 3) {
          return 0;
        }
        unless ($utf8_bytes eq "い") {
          return 0;
        }
      }
    }
    return 1;
  }

  sub utf32_to_utf16 : int () {
    # あaい
    {
      my $u32chars = [0x3042, 'a', 0x3044];
      
      my $u16chars = SPVM::Unicode->utf32_to_utf16($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->utf32_to_utf16($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 utf16_to_utf32 : int () {
    # あaい
    {
      my $u16chars = [(short)0x3042, 'a', 0x3044];
      
      my $u32chars = SPVM::Unicode->utf16_to_utf32($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->utf16_to_utf32($u16chars);
      
      unless ($u32chars->[0] == 0x3042) {
        return 0;
      }
      
      unless ($u32chars->[1] == 0x20bb7) {
        return 0;
      }
      unless ($u32chars->[2] == 'a') {
        return 0;
      }
    }
    
    return 1;
  }

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