package PO4Moz::Util;

use strict;

sub unescape_string {
  my $string = shift;
  
  $string =~ s/\\\n//g;
  $string =~ s/\\n/\n/g;
  $string =~ s/\\r/\r/g;
  $string =~ s/\\t/\t/g;
  $string =~ s/\\f/\f/g;
  $string =~ s/\\e/\e/g;
  $string =~ s/\\0/\0/g;
  $string =~ s/\\([0-7]{3})/chr(oct($1))/eg;
  $string =~ s/\\x([0-9a-fA-F]{2})/chr(hex($1))/eg;
  $string =~ s/\\u([0-9a-fA-F]{4})/chr(hex($1))/eg;
  $string =~ s/\\(.)/$1/g;
  
  return $string;
}

sub escape_string {
  my $string = shift;
  
  $string =~ s/\\/\\\\/g;
  $string =~ s/\n/\\n/g;
  $string =~ s/\r/\\r/g;
  $string =~ s/\t/\\t/g;
  $string =~ s/\f/\\f/g;
  $string =~ s/\e/\\e/g;
  $string =~ s/\0/\\0/g;
  $string =~ s/"/\\"/g;
  $string =~ s/([[:^print:]])/ord($1)<256?$1:sprintf("\\u%04x", ord($1))/eg;
  
  return $string;
}

sub parse_quoted_string {
  my $string = shift;
  my $out = "";
  
  $string =~ s/^(\s|\n)*//;
  while ($string =~ s/^(["'])((?:\\\1|.)*?)\1(?:\s|\n)*//s) {
    # undo quote b0rkage in editors: "
    $out .= unescape_string($2);
  }
  
  return $out;
}

sub po_quote_string {
  my $string = shift;
  my $length = 67;
  my $out = "";
  my $line = "";

  $string = escape_string($string);
  #'
  
  while ($string ne "") {
    $string =~ s/^(.*?(?:\s+|\\n|$))//;
    $line .= $1;
    if (length($line) > $length || $line =~ /\\n$/ || $string eq "") {
      $out .= "\"$line\"\n";
      $line = "";
    }
  }
  $out =~ s/\n$//;
  $out = "\"\"\n$out" if ($out =~ /"\n"/);
  $out = "\"\"" if ($out eq "");
  
  return $out;
}

sub dtd_quote_string {
  my $string = shift;

  if ($string =~ /"/s && $string !~ /'/s) {
    #"
    return "\'$string\'";
  }
  else {
    $string =~ s/"/&quot;/sg;
    #"
    return "\"$string\"";
  }
}

sub dtd_unquote_string {
  my $string = shift;
  
  $string =~ s/^\s*(["'])(.*?)\1(\s|\n)*$/$2/s;
  #"
  return $string;
}

sub prop_quote_string {
  my $string = escape_string(shift);
  
  $string =~ s/\\"/"/g;
  # double quote b0rkage, again: "
  $string =~ s/([[:^ascii:]])/ord($1)<256?$1:sprintf("\\u%04x", ord($1))/eg;
  return $string;
}

1;