$format_list->{$format} = $code;
}
+sub get_format {
+ my ($format) = @_;
+ return $format_list->{$format};
+}
+
# register some common type for pve
register_format('string', sub {}); # allow format => 'string-list'
});
sub check_format {
- my ($format, $value) = @_;
+ my ($format, $value, $path) = @_;
+ return parse_property_string($format, $value, $path) if ref($format) eq 'HASH';
return if $format eq 'regex';
if ($format =~ m/^(.*)-a?list$/) {
die "undefined format '$format'\n" if !$code;
+ return parse_property_string($code, $value, $path) if ref($code) eq 'HASH';
&$code($value);
}
}
+sub parse_size {
+ my ($value) = @_;
+
+ return undef if $value !~ m/^(\d+(\.\d+)?)([KMGT])?$/;
+ my ($size, $unit) = ($1, $3);
+ if ($unit) {
+ if ($unit eq 'K') {
+ $size = $size * 1024;
+ } elsif ($unit eq 'M') {
+ $size = $size * 1024 * 1024;
+ } elsif ($unit eq 'G') {
+ $size = $size * 1024 * 1024 * 1024;
+ } elsif ($unit eq 'T') {
+ $size = $size * 1024 * 1024 * 1024 * 1024;
+ }
+ }
+ return int($size);
+};
+
+sub format_size {
+ my ($size) = @_;
+
+ $size = int($size);
+
+ my $kb = int($size/1024);
+ return $size if $kb*1024 != $size;
+
+ my $mb = int($kb/1024);
+ return "${kb}K" if $mb*1024 != $kb;
+
+ my $gb = int($mb/1024);
+ return "${mb}M" if $gb*1024 != $mb;
+
+ my $tb = int($gb/1024);
+ return "${gb}G" if $tb*1024 != $gb;
+
+ return "${tb}T";
+};
+
+sub parse_property_string {
+ my ($format, $data, $path) = @_;
+
+ my $default_key;
+
+ my $res = {};
+ foreach my $part (split(/,/, $data)) {
+ next if $part =~ /^\s*$/;
+
+ if ($part =~ /^([^=]+)=(.+)$/) {
+ my ($k, $v) = ($1, $2);
+ die "duplicate key in comma-separated list property: $k" if defined($res->{$k});
+ my $schema = $format->{$k};
+ die "invalid key in comma-separated list property: $k" if !$schema;
+ if ($schema->{type} && $schema->{type} eq 'boolean') {
+ $v = 1 if $v =~ m/^(1|on|yes|true)$/i;
+ $v = 0 if $v =~ m/^(0|off|no|false)$/i;
+ }
+ $res->{$k} = $v;
+ } elsif ($part !~ /=/) {
+ die "duplicate key in comma-separated list property: $default_key" if $default_key;
+ foreach my $key (keys %$format) {
+ if ($format->{$key}->{default_key}) {
+ $default_key = $key;
+ if (!$res->{$default_key}) {
+ $res->{$default_key} = $part;
+ last;
+ }
+ die "duplicate key in comma-separated list property: $default_key";
+ }
+ }
+ } else {
+ die "missing key in comma-separated list property";
+ }
+ }
+
+ my $errors = {};
+ check_object($path, $format, $res, undef, $errors);
+ if (scalar(%$errors)) {
+ raise "format error", errors => $errors;
+ }
+
+ return $res;
+}
+
sub add_error {
my ($errors, $path, $msg) = @_;
} else {
if (my $format = $schema->{format}) {
- eval { check_format($format, $value); };
+ eval { check_format($format, $value, $path); };
if ($@) {
add_error($errors, $path, "invalid format - $@");
return;
description => "indicates a required property or a schema that must be validated if this property is present",
},
format => {
- type => "string",
+ type => [ "string", "object" ],
optional => 1,
description => "This indicates what format the data is among some predefined formats which may include:\n\ndate - a string following the ISO format \naddress \nschema - a schema definition object \nperson \npage \nhtml - a string representing HTML",
},
+ default_key => {
+ type => "boolean",
+ optional => 1,
+ description => "Whether this is the default key in a comma separated list property string.",
+ },
default => {
type => "any",
optional => 1,
return $data;
}
-sub generate_typetext {
- my ($schema) = @_;
- my $typetext = '';
- my (@optional, @required);
- foreach my $key (sort keys %$schema) {
- next if !$schema->{$key}->{format_description} &&
- !$schema->{$key}->{typetext};
- if ($schema->{$key}->{optional}) {
- push @optional, $key;
- } else {
- push @required, $key;
- }
- }
- my ($pre, $post) = ('', '');
- my $add = sub {
- my ($key) = @_;
- if (my $desc = $schema->{$key}->{format_description}) {
- $typetext .= "$pre$key=<$desc>$post";
- } elsif (my $text = $schema->{$key}->{typetext}) {
- $typetext .= "$pre$text$post";
- } else {
- die "internal error: neither format_description nor typetext found";
- }
- };
- foreach my $key (@required) {
- &$add($key);
- $pre = ', ';
- }
- $pre = ' [,' if $pre;
- foreach my $key (@optional) {
- &$add($key);
- $pre = ' [,';
- $post = ']';
- }
- return $typetext;
-}
-
1;