File Coverage

blib/lib/Convert/ASCIInames.pm
Criterion Covered Total %
statement 74 75 98.6
branch 13 16 81.2
condition 22 27 81.4
subroutine 14 14 100.0
pod 6 8 75.0
total 129 140 92.1


line stmt bran cond sub pod time code
1             package Convert::ASCIInames;
2             #
3             # $Id: ASCIInames.pm,v 1.2 2004/02/18 13:58:58 coar Exp $
4             #
5             # CPAN module Convert::ASCIInames
6             #
7             # Copyright 2004 Ken A L Coar
8             #
9             # Licensed under the Apache License, Version 2.0 (the "License");
10             # you may not use this package or any files in it except in
11             # compliance with the License. A copy of the License should be
12             # included as part of the package; the normative version may be
13             # obtained a copy of the License at
14             #
15             # http://www.apache.org/licenses/LICENSE-2.0
16             #
17             # Unless required by applicable law or agreed to in writing, software
18             # distributed under the License is distributed on an "AS IS" BASIS,
19             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20             # See the License for the specific language governing permissions and
21             # limitations under the License.
22             #
23              
24 7     7   157253 use strict;
  7         16  
  7         268  
25 7     7   39 use Carp;
  7         15  
  7         674  
26              
27             #
28             BEGIN {
29 7     7   37 use Exporter ();
  7         16  
  7         4748  
30 7     7   240 use vars qw ($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  7         12  
  7         1892  
31 7     7   36 use vars qw (%ord2name %ord2alt %name2ord %alt2ord $config);
  7         13  
  7         4245  
32 7     7   81 $VERSION = sprintf('%d.%03d', q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
33 7         170 @ISA = qw (Exporter);
34             #
35             # Give a hoot and don't pollute, do not export more than needed by default
36             #
37 7         23 @EXPORT = qw (ASCIIname
38             ASCIIaltname
39             ASCIIordinal
40             ASCIIdescription
41             ASCIIaltdescription
42             );
43 7         14 @EXPORT_OK = qw ();
44 7         16 %EXPORT_TAGS = ();
45              
46             #
47             # Set up our constants and configuration; since this isn't an
48             # object-oriented module, these values apply throughout.
49             #
50 7         26 $config->{fallthrough} = 1;
51 7         16 $config->{strict_ordinals} = 0;
52 7         52 %ord2alt = (
53             0x09 => [ 'TAB', 'Horizontal tab' ],
54             0x11 => [ 'XON', 'Flow control on' ],
55             0x13 => [ 'XOFF', 'Flow control off' ],
56             0x20 => [ 'SP', 'Space' ],
57             );
58 7         666 %ord2name = (
59             0x00 => [ 'NUL', 'Null character' ],
60             0x01 => [ 'SOH', 'Start of Header' ],
61             0x02 => [ 'STX', 'Start of Text' ],
62             0x03 => [ 'ETX', 'End Of Text' ],
63             0x04 => [ 'EOT', 'End Of Transmission' ],
64             0x05 => [ 'ENQ', 'Enquiry' ],
65             0x06 => [ 'ACK', 'Acknowledge' ],
66             0x07 => [ 'BEL', 'Bell' ],
67             0x08 => [ 'BS', 'Backspace' ],
68             0x09 => [ 'HT', 'Horizontal Tab' ],
69             0x0a => [ 'LF', 'Linefeed' ],
70             0x0b => [ 'VT', 'Vertical Tab' ],
71             0x0c => [ 'FF', 'Formfeed' ],
72             0x0d => [ 'CR', 'Carriage Return' ],
73             0x0e => [ 'SO', 'Shift Out' ],
74             0x0f => [ 'SI', 'Shift In' ],
75             0x10 => [ 'DLE', 'Data Link Escape' ],
76             0x11 => [ 'DC1', 'Device Control 1' ],
77             0x12 => [ 'DC2', 'Device Control 2' ],
78             0x13 => [ 'DC3', 'Device Control 3' ],
79             0x14 => [ 'DC4', 'Device Control 4' ],
80             0x15 => [ 'NAK', 'Negative Acknowledge' ],
81             0x16 => [ 'SYN', 'Synchronous Idle' ],
82             0x17 => [ 'ETB', 'End of Transmission Block' ],
83             0x18 => [ 'CAN', 'Cancel' ],
84             0x19 => [ 'EM', 'End of Medium' ],
85             0x1a => [ 'SUB', 'Substitute' ],
86             0x1b => [ 'ESC', 'Escape' ],
87             0x1c => [ 'FS', 'File Separator' ],
88             0x1d => [ 'GS', 'Group Separator' ],
89             0x1e => [ 'RS', 'Record Separator' ],
90             0x1f => [ 'US', 'Unit Separator' ],
91             0x7f => [ 'DEL', 'Delete' ],
92             0x80 => [ 'RES1', 'Reserved for future standardizaton' ],
93             0x81 => [ 'RES2', 'Reserved for future standardizaton' ],
94             0x82 => [ 'RES3', 'Reserved for future standardizaton' ],
95             0x83 => [ 'RES4', 'Reserved for future standardizaton' ],
96             0x84 => [ 'IND', 'Index' ],
97             0x85 => [ 'NEL', 'Next Line' ],
98             0x86 => [ 'SSA', 'Start of Selected Area' ],
99             0x87 => [ 'ESA', 'End of Selected Area' ],
100             0x88 => [ 'HTS', 'Horizontal Tabulation Set' ],
101             0x89 => [ 'HTJ', 'Horizontal Tab with Justify' ],
102             0x8a => [ 'VTS', 'Vertical Tabulation Set' ],
103             0x8b => [ 'PLD', 'Partial Line Down' ],
104             0x8c => [ 'PLU', 'Partial Line Up' ],
105             0x8d => [ 'RI', 'Reverse Index' ],
106             0x8e => [ 'SS2', 'Single Shift 2' ],
107             0x8f => [ 'SS3', 'Single Shift 3' ],
108             0x90 => [ 'DCS', 'Device control string' ],
109             0x91 => [ 'PU1', 'Private Use 1' ],
110             0x92 => [ 'PU2', 'Private Use 2' ],
111             0x93 => [ 'STS', 'Set Transmission State' ],
112             0x94 => [ 'CCH', 'Cancel Character' ],
113             0x95 => [ 'MW', 'Message Waiting' ],
114             0x96 => [ 'SPA', 'Start of Protected Area' ],
115             0x97 => [ 'EPA', 'End of Protected Area' ],
116             0x98 => [ 'RES5', 'Reserved for future standardization' ],
117             0x99 => [ 'RES6', 'Reserved for future standardization' ],
118             0x9a => [ 'RES7', 'Reserved for future standardization' ],
119             0x9b => [ 'CSI', 'Control Sequence Introducer' ],
120             0x9c => [ 'ST', 'String Terminator' ],
121             0x9d => [ 'OSC', 'Operating System Command' ],
122             0x9e => [ 'PM', 'Privacy Message' ],
123             0x9f => [ 'APC', 'Application Program Command' ],
124             );
125 7         29 %alt2ord = ();
126 7         10 %name2ord = ();
127              
128             #
129             # Now for the backward conversions
130             #
131 7         48 while (my ($ord, $name) = each(%ord2name)) {
132 455         1627 $name2ord{$name->[0]} = $ord;
133             }
134 7         31 while (my ($ord, $name) = each(%ord2alt)) {
135 28         5793 $alt2ord{$name->[0]} = $ord;
136             }
137             }
138              
139             =pod
140              
141             =head1 NAME
142              
143             Convert::ASCIInames - ASCII names for control characters
144              
145             =head1 SYNOPSIS
146              
147             use Convert::ASCIInames;
148              
149             Convert::ASCIInames::Configure(fallthrough => 1);
150             $name = ASCIIname($character_ordinal);
151             $name = ASCIIaltname($character_ordinal);
152             $name = ASCIIdescription($character_ordinal);
153             $name = ASCIIaltdescription($character_ordinal);
154             $character_ordinal = ASCIIordinal($name);
155              
156             =head1 DESCRIPTION
157              
158             Most if not all of the non-printing characters of the ASCII character set
159             had special significance in the days of teletypes and paper tapes.
160             For example, the character code 0x00 would be sent repeatedly in order
161             to give the receiving end a chance to catch up; it signified "no action"
162             and so was named C. The sending end might follow each line of text
163             with a number of C bytes in order to give the receiving end
164             a chance to return its print carriage to the left margin. The control
165             characters (so-called because they were used to control aspects of
166             communication or receiving devices) were given short 2-to-4 letter
167             names, like C, C, C, and C.
168              
169             Some of these special purposes have become obsolete, but some of them
170             are still in use. For example, character 0x07 (C) is used to
171             ring the feeper; 0x05 (C) is recognised by many terminals as
172             a trigger to report their status; and 0x08 (C) still means
173             "move the cursor back one space".
174              
175             This module will return the ASCII name for specified characters,
176             or the character code if given an ASCII name. In addition, the
177             full descriptive name ("Start of Heading" instead of C) is
178             available, although reverse translation of the descriptions isn't
179             provided.
180              
181             Some control characters have altername names. Character 0x13
182             is named C ("Device Control 3"), but is probably better
183             known by its alternate name of C. These alternate names
184             are also available through this module's functions.
185              
186             =head1 USAGE
187              
188             Each of the functions in this module is described below. They
189             are listed in lexical order, rather than functional.
190              
191             If you request the name (or alternate name) of a character that
192             doesn't have one, you'll either get the actual character itself,
193             or the name (if it has one) from the other list. For instance,
194             if you request the alternate name for 0x00, which doesn't have
195             one, the return value will either be C (the primary name)
196             or the value of C. The former is called "falling
197             through," and is controlled by the setting of the C
198             configuration option. If the option is set to a true value,
199             the module will attempt to give you the best name it can; if
200             it's set to a false value, you'll either get exactly what you
201             requested (such as the alternate name) or the character itself.
202              
203             If you provide an invalid character ordinal (such as a non-integer,
204             or one outside the range of 0-255), Convert::ASCIInames will
205             throw a message using C and use a standard substitute
206             value instead:
207              
208             =over 4
209              
210             =item o B
211              
212             The value 0x00 will be used.
213              
214             =item o B 0 or E 255>
215              
216             The value 255 (0xff) will be used instead.
217              
218             =item o B
219              
220             The ordinal of the first character of the argument will be used.
221             If option C is set, a warning message will be
222             issued.
223              
224             =back
225              
226             =cut
227              
228             =pod
229              
230             =head2 ASCIIaltdescription
231              
232             $text = ASCIIaltdescription($ordinal);
233              
234             This function returns the description for the alternate name, if any,
235             for the character with the specified ordinal. If there is no
236             altername name, the description of the primary name (if any) will be
237             returned if the C option is set; otherwise the value of
238             C will be returned.
239              
240             =cut
241              
242             sub ASCIIaltdescription {
243 6     6 1 2504 my ($ord) = is_ord(@_);
244 6         6 my $char;
245              
246 6   66     30 $char = ($ord2alt{$ord}->[1]
247             || ($config->{fallthrough} ? $ord2name{$ord}->[1] : 0)
248             || chr($ord));
249 6         12 return $char;
250             }
251              
252             =pod
253              
254             =head2 ASCIIaltname
255              
256             $text = ASCIIaltname($ordinal);
257              
258             This function returns the alternate name, if any, for the
259             character with the specified ordinal. If there is no altername
260             name, the primary name (if any) will be returned if the C
261             option is set; otherwise the value of C will be
262             returned.
263              
264             =cut
265              
266             sub ASCIIaltname {
267 512     512 1 56668 my ($ord) = is_ord(@_);
268 512         481 my $char;
269              
270 512   100     2879 $char = ($ord2alt{$ord}->[0]
271             || ($config->{fallthrough} ? $ord2name{$ord}->[0] : 0)
272             || chr($ord));
273 512         1120 return $char;
274             }
275              
276             =pod
277              
278             =head2 ASCIIdescription
279              
280             $text = ASCIIdescription($ordinal);
281              
282             This function returns the description for the primary name, if any,
283             for the character with the specified ordinal. If there is no
284             primary name, the description of the alternate name (if any) will be
285             returned if the C option is set; otherwise the value of
286             C will be returned.
287              
288             Note that it is unlikely that a character will have an alternate
289             name but not a primary one.
290              
291             =cut
292              
293             sub ASCIIdescription {
294 512     512 1 172623 my ($ord) = is_ord(@_);
295 512         572 my $char;
296              
297 512   100     3188 $char = ($ord2name{$ord}->[1]
298             || ($config->{fallthrough} ? $ord2alt{$ord}->[1] : 0)
299             || chr($ord));
300 512         1104 return $char;
301             }
302              
303             =pod
304              
305             =head2 ASCIIname
306              
307             This function returns the primary name, if any, for the
308             character with the specified ordinal. If there is no primary
309             name, the alternate name (if any) will be returned if the C
310             option is set; otherwise the value of C will be
311             returned.
312              
313             Note that it is unlikely that a character will have an alternate
314             name but not a primary one.
315              
316             =cut
317              
318             sub ASCIIname {
319 769     769 1 314933 my ($ord) = is_ord(@_);
320 769         879 my $char;
321              
322 769   100     6024 $char = ($ord2name{$ord}->[0]
323             || ($config->{fallthrough} ? $ord2alt{$ord}->[0] : 0)
324             || chr($ord));
325 769         1918 return $char;
326             }
327              
328             =pod
329              
330             =head2 ASCIIordinal
331              
332             $ordinal = ASCIIordinal($name)
333              
334             This function will attempt to look up the specified name in
335             the primary and alternate lists, and return the ordinal of
336             any match it finds. For example:
337              
338             my $ord = ASCIIordinal('xoff');
339             printf("xoff = 0x%02x\n", $ord);
340              
341             would print
342              
343             xoff = 0x13
344              
345             If the name does not appear in the primary or alternate list, the
346             ordinal of the first character of the string will be returned.
347              
348             The argument is not case-sensitive.
349              
350             =cut
351              
352             sub ASCIIordinal {
353 2     2 1 1127 my ($name) = is_char(@_);
354 2         4 my $char;
355              
356 2   33     25 $char = ($name2ord{uc($name)}
357             || ($config->{fallthrough} ? $alt2ord{uc($name)} : 0)
358             || ord(substr($name, 0, 1)));
359 2         5 return $char;
360             }
361              
362             =pod
363              
364             =head2 Convert::ASCIInames::Configure
365              
366             Convert::ASCIInames::Configure(..options..)
367              
368             This function sets the options controlling some details of
369             Convert::ASCIInames' operation. Options are specifed as either
370             a hash or a hashref:
371              
372             Convert::ASCIInames::Configure(fallback => 1);
373              
374             my $opts = { fallback => 1, strict_ordinals => 0};
375             Convert::ASCIInames::Configure($opts);
376              
377             The possible options are:
378              
379             =over 4
380              
381             =item o C
382              
383             If this option is set to a true value, Convert::ASCIInames will search
384             both the primary and the alternate (or I) lists for
385             the specified character or name. If set to a false value, only the
386             list you indicate will be searched.
387              
388             Default is true.
389              
390             =item o C
391              
392             When a function that takes a character ordinal is passed an argument
393             that is nominally invalid (I, not a positive integer between 0
394             and 255 inclusive), it will use the C value of the first byte
395             of the argument. If the C option is set to true,
396             a warning message will be generated, just in case this isn't
397             what you intended. If set to false, there is no message.
398              
399             The default value is false.
400              
401             =back
402              
403             =cut
404              
405             sub Configure {
406 14     14 1 4979 my (@opts) = @_;
407 14         21 my $prehash;
408 14 100       63 my (%ohash) = ((ref($opts[0]) eq 'HASH') ? %{$opts[0]} : @opts);
  1         4  
409              
410 14         19 for (keys(%{$config})) {
  14         56  
411 28         63 $prehash->{$_} = $config->{$_};
412 28 100       94 if (defined($ohash{$_})) {
413 11         28 $config->{$_} = $ohash{$_};
414             }
415             }
416 14         52 return $prehash;
417             }
418              
419             #
420             # Check that a value is really a valid character (or string).
421             #
422             sub is_char {
423 2     2 0 5 my ($val, $truncate) = @_;
424              
425 2 50 66     14 if ((! defined($val)) || (length($val) == 0)) {
426 2         281 carp('Null character; using NUL');
427 2         41 return chr(0x00);
428             }
429 0 0       0 return ($truncate ? substr($val, 0, 1) : $val);
430             }
431              
432             #
433             # Check that a value is really a valid ordinal.
434             #
435             sub is_ord {
436 1799     1799 0 3281 my ($val) = @_;
437              
438 1799 100 100     21482 if ((! defined($val)) || (length($val) == 0)) {
    100 100        
    100 66        
439 2         5266 carp('Null ordinal; using 0x00');
440 2         17 return 0x00;
441             }
442             elsif (($val =~ /^[-+]?\d+$/)
443             && (($val > 255)
444             || ($val < 0))) {
445 2         328 carp('Illegal ordinal value (< 0 or > 255); using 255');
446 2         13 return 0xff;
447             }
448             elsif ($val !~ /^\+?\d+$/) {
449 2 100       9 if ($config->{strict_ordinals}) {
450 1         168 carp('Ordinal is not a positive integer; '
451             . 'converting the first character');
452             }
453 2         11 return ord(substr($val, 0, 1));
454             }
455 1793         3281 return $val;
456             }
457              
458             1; #this line is important and will help the module return a true value
459              
460             __END__