~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
# -*- cperl -*-
2
3
package My::Config::Option;
4
5
use strict;
6
use warnings;
7
8
9
sub new {
10
  my ($class, $option_name, $option_value)= @_;
11
  my $self= bless { name => $option_name,
12
		    value => $option_value
13
		  }, $class;
14
  return $self;
15
}
16
17
18
sub name {
19
  my ($self)= @_;
20
  return $self->{name};
21
}
22
23
24
sub value {
25
  my ($self)= @_;
26
  return $self->{value};
27
}
28
29
30
package My::Config::Group;
31
32
use strict;
33
use warnings;
34
35
36
sub new {
37
  my ($class, $group_name)= @_;
38
  my $self= bless { name => $group_name,
39
		    options => [],
40
		    options_by_name => {},
41
		  }, $class;
42
  return $self;
43
}
44
45
46
sub insert {
47
  my ($self, $option_name, $value, $if_not_exist)= @_;
48
  my $option= $self->option($option_name);
49
  if (defined($option) and !$if_not_exist) {
50
    $option->{value}= $value;
51
  }
52
  else {
53
    my $option= My::Config::Option->new($option_name, $value);
54
    # Insert option in list
55
    push(@{$self->{options}}, $option);
56
    # Insert option in hash
57
    $self->{options_by_name}->{$option_name}= $option;
58
  }
59
  return $option;
60
}
61
62
sub remove {
63
  my ($self, $option_name)= @_;
64
65
  # Check that option exists
66
  my $option= $self->option($option_name);
67
68
  return undef unless defined $option;
69
70
  # Remove from the hash
71
  delete($self->{options_by_name}->{$option_name}) or die;
72
73
  # Remove from the array
74
  @{$self->{options}}= grep { $_->name ne $option_name } @{$self->{options}};
75
76
  return $option;
77
}
78
79
80
sub options {
81
  my ($self)= @_;
82
  return @{$self->{options}};
83
}
84
85
86
sub name {
87
  my ($self)= @_;
88
  return $self->{name};
89
}
90
91
92
#
93
# Return a specific option in the group
94
#
95
sub option {
96
  my ($self, $option_name)= @_;
97
98
  return $self->{options_by_name}->{$option_name};
99
}
100
101
102
#
103
# Return a specific value for an option in the group
104
#
105
sub value {
106
  my ($self, $option_name)= @_;
107
  my $option= $self->option($option_name);
108
109
  die "No option named '$option_name' in this group"
110
    if ! defined($option);
111
112
  return $option->value();
113
}
114
115
116
package My::Config;
117
118
use strict;
119
use warnings;
120
use IO::File;
121
use File::Basename;
122
123
#
124
# Constructor for My::Config
125
# - represents a my.cnf config file
126
#
127
# Array of arrays
128
#
129
sub new {
130
  my ($class, $path)= @_;
131
  my $group_name= undef;
132
133
  my $self= bless { groups => [] }, $class;
134
  my $F= IO::File->new($path, "<")
135
    or die "Could not open '$path': $!";
136
137
  while (  my $line= <$F> ) {
138
    chomp($line);
139
140
    # [group]
141
    if ( $line =~ /\[(.*)\]/ ) {
142
      # New group found
143
      $group_name= $1;
144
      #print "group: $group_name\n";
145
146
      $self->insert($group_name, undef, undef);
147
    }
148
149
    # Magic #! comments
150
    elsif ( $line =~ /^#\!/) {
151
      my $magic= $line;
152
      die "Found magic comment '$magic' outside of group"
153
	unless $group_name;
154
155
      #print "$magic\n";
156
      $self->insert($group_name, $magic, undef);
157
    }
158
159
    # Comments
160
    elsif ( $line =~ /^#/ || $line =~ /^;/) {
161
      # Skip comment
162
      next;
163
    }
164
165
    # Empty lines
166
    elsif ( $line =~ /^$/ ) {
167
      # Skip empty lines
168
      next;
169
    }
170
171
    # !include <filename>
172
    elsif ( $line =~ /^\!include\s*(.*?)\s*$/ ) {
173
      my $include_file_name= dirname($path)."/".$1;
174
      # Check that the file exists
175
      die "The include file '$include_file_name' does not exist"
176
	unless -f $include_file_name;
177
178
      $self->append(My::Config->new($include_file_name));
179
    }
180
181
    # <option>
182
    elsif ( $line =~ /^([\@\w-]+)\s*$/ ) {
183
      my $option= $1;
184
185
      die "Found option '$option' outside of group"
186
	unless $group_name;
187
188
      #print "$option\n";
189
      $self->insert($group_name, $option, undef);
190
    }
191
192
    # <option>=<value>
193
    elsif ( $line =~ /^([\@\w-]+)\s*=\s*(.*?)\s*$/ ) {
194
      my $option= $1;
195
      my $value= $2;
196
197
      die "Found option '$option=$value' outside of group"
198
	unless $group_name;
199
200
      #print "$option=$value\n";
201
      $self->insert($group_name, $option, $value);
202
    } else {
203
      die "Unexpected line '$line' found in '$path'";
204
    }
205
206
  }
207
  undef $F;			# Close the file
208
209
  return $self;
210
}
211
212
#
213
# Insert a new group if it does not already exist
214
# and add option if defined
215
#
216
sub insert {
217
  my ($self, $group_name, $option, $value, $if_not_exist)= @_;
218
  my $group;
219
220
  # Create empty array for the group if it doesn't exist
221
  if ( !$self->group_exists($group_name) ) {
222
    $group= $self->_group_insert($group_name);
223
  }
224
  else {
225
    $group= $self->group($group_name);
226
  }
227
228
  if ( defined $option ) {
229
    #print "option: $option, value: $value\n";
230
231
    # Add the option to the group
232
    $group->insert($option, $value, $if_not_exist);
233
  }
234
}
235
236
#
237
# Remove a option, given group and option name
238
#
239
sub remove {
240
  my ($self, $group_name, $option_name)= @_;
241
  my $group= $self->group($group_name);
242
243
  die "group '$group_name' does not exist"
244
    unless defined($group);
245
246
  $group->remove($option_name) or
247
    die "option '$option_name' does not exist";
248
}
249
250
251
252
#
253
# Check if group with given name exists in config
254
#
255
sub group_exists {
256
  my ($self, $group_name)= @_;
257
258
  foreach my $group ($self->groups()) {
259
    return 1 if $group->{name} eq $group_name;
260
  }
261
  return 0;
262
}
263
264
265
#
266
# Insert a new group into config
267
#
268
sub _group_insert {
269
  my ($self, $group_name)= @_;
270
  caller eq __PACKAGE__ or die;
271
272
  # Check that group does not already exist
273
  die "Group already exists" if $self->group_exists($group_name);
274
275
  my $group= My::Config::Group->new($group_name);
276
  push(@{$self->{groups}}, $group);
277
  return $group;
278
}
279
280
281
#
282
# Append a configuration to current config
283
#
284
sub append {
285
  my ($self, $from)= @_;
286
287
  foreach my $group ($from->groups()) {
288
    foreach my $option ($group->options()) {
289
      $self->insert($group->name(), $option->name(), $option->value());
290
    }
291
292
  }
293
}
294
295
296
#
297
# Return a list with all the groups in config
298
#
299
sub groups {
300
  my ($self)= @_;
301
  return ( @{$self->{groups}} );
302
}
303
304
305
#
306
# Return a list of all the groups in config
307
# starting with the given string
308
#
309
sub like {
310
  my ($self, $prefix)= @_;
311
  return ( grep ( $_->{name} =~ /^$prefix/, $self->groups()) );
312
}
313
314
315
#
316
# Return the first group in config
317
# starting with the given string
318
#
319
sub first_like {
320
  my ($self, $prefix)= @_;
321
  return ($self->like($prefix))[0];
322
}
323
324
325
#
326
# Return a specific group in the config
327
#
328
sub group {
329
  my ($self, $group_name)= @_;
330
331
  foreach my $group ( $self->groups() ) {
332
    return $group if $group->{name} eq $group_name;
333
  }
334
  return undef;
335
}
336
337
338
#
339
# Return a list of all options in a specific group in the config
340
#
341
sub options_in_group {
342
  my ($self, $group_name)= @_;
343
344
  my $group= $self->group($group_name);
345
  return () unless defined $group;
346
  return $group->options();
347
}
348
349
350
#
351
# Return a value given group and option name
352
#
353
sub value {
354
  my ($self, $group_name, $option_name)= @_;
355
  my $group= $self->group($group_name);
356
357
  die "group '$group_name' does not exist"
358
    unless defined($group);
359
360
  my $option= $group->option($option_name);
361
  die "option '$option_name' does not exist"
362
    unless defined($option);
363
364
  return $option->value();
365
}
366
367
368
#
369
# Check if an option exists
370
#
371
sub exists {
372
  my ($self, $group_name, $option_name)= @_;
373
  my $group= $self->group($group_name);
374
375
  die "group '$group_name' does not exist"
376
    unless defined($group);
377
378
  my $option= $group->option($option_name);
379
  return defined($option);
380
}
381
382
383
# Overload "to string"-operator with 'stringify'
384
use overload
385
    '""' => \&stringify;
386
387
#
388
# Return the config as a string in my.cnf file format
389
#
390
sub stringify {
391
  my ($self)= @_;
392
  my $res;
393
394
  foreach my $group ($self->groups()) {
395
    $res .= "[$group->{name}]\n";
396
397
    foreach my $option ($group->options()) {
398
      $res .= $option->name();
399
      my $value= $option->value();
400
      if (defined $value) {
401
	$res .= "=$value";
402
      }
403
      $res .= "\n";
404
    }
405
    $res .= "\n";
406
  }
407
  return $res;
408
}
409
410
411
#
412
# Save the config to named file
413
#
414
sub save {
415
    my ($self, $path)= @_;
416
    my $F= IO::File->new($path, ">")
417
	or die "Could not open '$path': $!";
418
    print $F $self;
419
    undef $F; # Close the file
420
}
421
422
1;