xref: /openbsd/gnu/usr.bin/perl/os2/OS2/OS2-PrfDB/PrfDB.pm (revision 73471bf0)
1package OS2::PrfDB;
2
3use strict;
4
5require Exporter;
6use XSLoader;
7use Tie::Hash;
8
9our $debug;
10our @ISA = qw(Exporter Tie::Hash);
11# Items to export into callers namespace by default. Note: do not export
12# names by default without a very good reason. Use EXPORT_OK instead.
13# Do not simply export all your public functions/methods/constants.
14our @EXPORT = qw(
15		 AnyIni UserIni SystemIni
16		);
17our $VERSION = '0.04';
18
19XSLoader::load 'OS2::PrfDB', $VERSION;
20
21# Preloaded methods go here.
22
23sub AnyIni {
24  new_from_int OS2::PrfDB::Hini OS2::Prf::System(0),
25  'Anyone of two "systemish" databases', 1;
26}
27
28sub UserIni {
29  new_from_int OS2::PrfDB::Hini OS2::Prf::System(1), 'User settings database', 1;
30}
31
32sub SystemIni {
33  new_from_int OS2::PrfDB::Hini OS2::Prf::System(2),'System settings database',1;
34}
35
36# Internal structure 0 => HINI, 1 => array of entries, 2 => iterator.
37
38sub TIEHASH {
39  die "Usage: tie %arr, OS2::PrfDB, filename\n" unless @_ == 2;
40  my ($obj, $file) = @_;
41  my $hini = ref $file eq 'OS2::PrfDB::Hini' ? $file
42					     : new OS2::PrfDB::Hini $file;
43  die "Error opening profile database `$file': $!" unless $hini;
44  # print "tiehash `@_', hini $hini\n" if $debug;
45  bless [$hini, undef, undef];
46}
47
48sub STORE {
49  my ($self, $key, $val) = @_;
50  die unless @_ == 3;
51  die unless ref $val eq 'HASH';
52  my %sub;
53  tie %sub, 'OS2::PrfDB::Sub', $self->[0], $key;
54  %sub = %$val;
55}
56
57sub FETCH {
58  my ($self, $key) = @_;
59  die unless @_ == 2;
60  my %sub;
61  tie %sub, 'OS2::PrfDB::Sub', $self->[0], $key;
62  \%sub;
63}
64
65sub DELETE {
66  my ($self, $key) = @_;
67  die unless @_ == 2;
68  my %sub;
69  tie %sub, 'OS2::PrfDB::Sub', $self->[0], $key;
70  %sub = ();
71}
72
73# CLEAR ???? - deletion of the whole
74
75sub EXISTS {
76  my ($self, $key) = @_;
77  die unless @_ == 2;
78  return OS2::Prf::GetLength($self->[0]->[0], $key, undef) >= 0;
79}
80
81sub FIRSTKEY {
82  my $self = shift;
83  my $keys = OS2::Prf::Get($self->[0]->[0], undef, undef);
84  return undef unless defined $keys;
85  chop($keys);
86  $self->[1] = [split /\0/, $keys];
87  # print "firstkey1 $self, `$self->[3]->[0], $self->[3]->[1]'\n" if $debug;
88  $self->[2] = 0;
89  return $self->[1]->[0];
90	  # OS2::Prf::Get($self->[0]->[0], $self->[2], $self->[3]->[0]));
91}
92
93sub NEXTKEY {
94  # print "nextkey `@_'\n" if $debug;
95  my $self = shift;
96  return undef unless $self->[2]++ < $#{$self->[1]};
97  my $key = $self->[1]->[$self->[2]];
98  return $key; #, OS2::Prf::Get($self->[0]->[0], $self->[2], $key));
99}
100
101package OS2::PrfDB::Hini;
102
103sub new {
104  die "Usage: new OS2::PrfDB::Hini filename\n" unless @_ == 2;
105  shift;
106  my $file = shift;
107  my $hini = OS2::Prf::Open($file);
108  die "Error opening profile database `$file': $!" unless $hini;
109  bless [$hini, $file];
110}
111
112# Takes HINI and file name:
113
114sub new_from_int { shift; bless [@_] }
115
116# Internal structure 0 => HINI, 1 => filename, 2 => do-not-close.
117
118sub DESTROY {
119  my $self = shift;
120  my $hini = $self->[0];
121  unless ($self->[2]) {
122    OS2::Prf::Close($hini) or die "Error closing profile `$self->[1]': $!";
123  }
124}
125
126package OS2::PrfDB::Sub;
127use Tie::Hash;
128
129our $debug;
130our @ISA = qw{Tie::Hash};
131
132# Internal structure 0 => HINI, 1 => array of entries, 2 => iterator,
133# 3 => appname.
134
135sub TIEHASH {
136  die "Usage: tie %arr, OS2::PrfDB::Sub, filename, appname\n" unless @_ == 3;
137  my ($obj, $file, $app) = @_;
138  my $hini = ref $file eq 'OS2::PrfDB::Hini' ? $file
139					     : new OS2::PrfDB::Hini $file;
140  die "Error opening profile database `$file': $!" unless $hini;
141  # print "tiehash `@_', hini $hini\n" if $debug;
142  bless [$hini, undef, undef, $app];
143}
144
145sub STORE {
146  my ($self, $key, $val) = @_;
147  die unless @_ == 3;
148  OS2::Prf::Set($self->[0]->[0], $self->[3], $key, $val);
149}
150
151sub FETCH {
152  my ($self, $key) = @_;
153  die unless @_ == 2;
154  OS2::Prf::Get($self->[0]->[0], $self->[3], $key);
155}
156
157sub DELETE {
158  my ($self, $key) = @_;
159  die unless @_ == 2;
160  OS2::Prf::Set($self->[0]->[0], $self->[3], $key, undef);
161}
162
163# CLEAR ???? - deletion of the whole
164
165sub EXISTS {
166  my ($self, $key) = @_;
167  die unless @_ == 2;
168  return OS2::Prf::GetLength($self->[0]->[0], $self->[3], $key) >= 0;
169}
170
171sub FIRSTKEY {
172  my $self = shift;
173  my $keys = OS2::Prf::Get($self->[0]->[0], $self->[3], undef);
174  return undef unless defined $keys;
175  chop($keys);
176  $self->[1] = [split /\0/, $keys];
177  # print "firstkey1 $self, `$self->[3]->[0], $self->[3]->[1]'\n" if $debug;
178  $self->[2] = 0;
179  return $self->[1]->[0];
180	  # OS2::Prf::Get($self->[0]->[0], $self->[2], $self->[3]->[0]));
181}
182
183sub NEXTKEY {
184  # print "nextkey `@_'\n" if $debug;
185  my $self = shift;
186  return undef unless $self->[2]++ < $#{$self->[1]};
187  my $key = $self->[1]->[$self->[2]];
188  return $key; #, OS2::Prf::Get($self->[0]->[0], $self->[2], $key));
189}
190
191# Autoload methods go after =cut, and are processed by the autosplit program.
192
1931;
194__END__
195# Below is the stub of documentation for your module. You better edit it!
196
197=head1 NAME
198
199OS2::PrfDB - Perl extension for access to OS/2 setting database.
200
201=head1 SYNOPSIS
202
203  use OS2::PrfDB;
204  tie %settings, OS2::PrfDB, 'my.ini';
205  tie %subsettings, OS2::PrfDB::Sub, 'my.ini', 'mykey';
206
207  print "$settings{firstkey}{subkey}\n";
208  print "$subsettings{subkey}\n";
209
210  tie %system, OS2::PrfDB, SystemIni;
211  $system{myapp}{mykey} = "myvalue";
212
213
214=head1 DESCRIPTION
215
216The extension provides both high-level and low-level access to .ini
217files.
218
219=head2 High level access
220
221High-level access is the tie-hash access via two packages:
222C<OS2::PrfDB> and C<OS2::PrfDB::Sub>. First one supports one argument,
223the name of the file to open, the second one the name of the file to
224open and so called I<Application name>, or the primary key of the
225database.
226
227  tie %settings, OS2::PrfDB, 'my.ini';
228  tie %subsettings, OS2::PrfDB::Sub, 'my.ini', 'mykey';
229
230One may substitute a handle for already opened ini-file instead of the
231file name (obtained via low-level access functions). In particular, 3
232functions SystemIni(), UserIni(), and AnyIni() provide handles to the
233"systemish" databases. AniIni will read from both, and write into User
234database.
235
236=head2 Low-level access
237
238Low-level access functions reside in the package C<OS2::Prf>. They are
239
240=over 14
241
242=item C<Open(file)>
243
244Opens the database, returns an I<integer handle>.
245
246=item C<Close(hndl)>
247
248Closes the database given an I<integer handle>.
249
250=item C<Get(hndl, appname, key)>
251
252Retrieves data from the database given 2-part-key C<appname> C<key>.
253If C<key> is C<undef>, return the "\0" delimited list of C<key>s,
254terminated by \0. If C<appname> is C<undef>, returns the list of
255possible C<appname>s in the same form.
256
257=item C<GetLength(hndl, appname, key)>
258
259Same as above, but returns the length of the value.
260
261=item C<Set(hndl, appname, key, value [ , length ])>
262
263Sets the value. If the C<value> is not defined, removes the C<key>. If
264the C<key> is not defined, removes the C<appname>.
265
266=item C<System(val)>
267
268Return an I<integer handle> associated with the system database. If
269C<val> is 1, it is I<User> database, if 2, I<System> database, if
2700, handle for "both" of them: the handle works for read from any one,
271and for write into I<User> one.
272
273=item C<Profiles()>
274
275returns a reference to a list of two strings, giving names of the
276I<User> and I<System> databases.
277
278=item C<SetUser(file)>
279
280B<(Not tested.)> Sets the profile name of the I<User> database. The
281application should have a message queue to use this function!
282
283=back
284
285=head2 Integer handles
286
287To convert a name or an integer handle into an object acceptable as
288argument to tie() interface, one may use the following functions from
289the package C<OS2::Prf::Hini>:
290
291=over 14
292
293=item C<new(package, file)>
294
295=item C<new_from_int(package, int_hndl [ , filename ])>
296
297=back
298
299=head2 Exports
300
301SystemIni(), UserIni(), and AnyIni().
302
303=head1 AUTHOR
304
305Ilya Zakharevich, ilya@math.ohio-state.edu
306
307=head1 SEE ALSO
308
309perl(1).
310
311=cut
312
313