/
perlpacktut.pod
2808 lines (1980 loc) · 108 KB
/
perlpacktut.pod
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
=encoding utf8
=head1 NAME
=begin original
perlpacktut - tutorial on C<pack> and C<unpack>
=end original
perlpacktut - C<pack> と C<unpack> のチュートリアル
=head1 DESCRIPTION
=begin original
C<pack> and C<unpack> are two functions for transforming data according
to a user-defined template, between the guarded way Perl stores values
and some well-defined representation as might be required in the
environment of a Perl program. Unfortunately, they're also two of
the most misunderstood and most often overlooked functions that Perl
provides. This tutorial will demystify them for you.
=end original
C<pack> と C<unpack> は、ユーザーが定義したテンプレートに従って、
Perl が値を保管する保護された方法と、Perl プログラムの環境で必要になる
かもしれないよく定義された表現の間を変換する二つの関数です。
残念ながら、これらは Perl が提供する関数の中でもっとも誤解され、
もっとも見落とされやすい関数でもあります。
このチュートリアルではこれらを分かりやすく説明します。
=head1 The Basic Principle
(基本原理)
=begin original
Most programming languages don't shelter the memory where variables are
stored. In C, for instance, you can take the address of some variable,
and the C<sizeof> operator tells you how many bytes are allocated to
the variable. Using the address and the size, you may access the storage
to your heart's content.
=end original
多くのプログラミング言語は変数が格納されているメモリを保護していません。
例えば、C では、ある変数のアドレスを取得できますし、
C<sizeof> 演算子は変数に何バイト割り当てられているかを返します。
アドレスとサイズを使って、心臓部にあるストレージにアクセスできます。
=begin original
In Perl, you just can't access memory at random, but the structural and
representational conversion provided by C<pack> and C<unpack> is an
excellent alternative. The C<pack> function converts values to a byte
sequence containing representations according to a given specification,
the so-called "template" argument. C<unpack> is the reverse process,
deriving some values from the contents of a string of bytes. (Be cautioned,
however, that not all that has been packed together can be neatly unpacked -
a very common experience as seasoned travellers are likely to confirm.)
=end original
Perl では、メモリにランダムにアクセスすることはできませんが、C<pack> と
C<unpack> によって提供される構造的および表現的な変換は素晴らしい
代替案です。
C<pack> 関数は、値を、「テンプレート」引数と呼ばれる使用に従った表現を含む
バイト列に変換します。
C<unpack> は逆処理で、バイトの並びから値を引き出します。
(しかし、pack された全てのデータがうまく unpack できるというわけでは
ないということは注意してください - 経験豊かな旅人が確認しそうな、とても
一般的な経験です。)
=begin original
Why, you may ask, would you need a chunk of memory containing some values
in binary representation? One good reason is input and output accessing
some file, a device, or a network connection, whereby this binary
representation is either forced on you or will give you some benefit
in processing. Another cause is passing data to some system call that
is not available as a Perl function: C<syscall> requires you to provide
parameters stored in the way it happens in a C program. Even text processing
(as shown in the next section) may be simplified with judicious usage
of these two functions.
=end original
あなたはどうしてバイナリ表現の中に値が含まれているメモリの塊が
必要なのか、と問うかもしれません。
よい理由の一つは、ファイル、デバイス、ネットワーク接続にアクセスする
入出力で、このバイナリ表現が強制されたものか、処理するためにいくらかの
利益がある場合です。
もう一つの原因は、Perl 関数として利用できないシステムコールにデータを
渡すときです: C<syscall> は C プログラムでのような形で保管された引数を
提供することを要求します。
(以下の章で示すように) テキスト処理ですら、これら 2 つの関数を賢明に
使うことで単純化できます。
=begin original
To see how (un)packing works, we'll start with a simple template
code where the conversion is in low gear: between the contents of a byte
sequence and a string of hexadecimal digits. Let's use C<unpack>, since
this is likely to remind you of a dump program, or some desperate last
message unfortunate programs are wont to throw at you before they expire
into the wild blue yonder. Assuming that the variable C<$mem> holds a
sequence of bytes that we'd like to inspect without assuming anything
about its meaning, we can write
=end original
(un)pack がどのように働くのかを見るために、変換がのろのろと行われる単純な
テンプレートコードから始めましょう: バイトシーケンスと 16 進数の文字列との
変換です。
C<unpack> を使いましょう; なぜならこれはダンププログラムや、
不幸なプログラムが息を引き取る前にあなたに投げかけることが常となっている
絶望的な最後のメッセージを思い出させそうだからです。
変数 C<$mem> に、その意味について何の仮定もおかずに調査したいバイト列が
入っていると仮定すると、以下のように書きます:
my( $hex ) = unpack( 'H*', $mem );
print "$hex\n";
=begin original
whereupon we might see something like this, with each pair of hex digits
corresponding to a byte:
=end original
するとすぐに、1 バイトに対応して 16 進数 2 文字が対応する、以下のような
ものが表示されます:
41204d414e204120504c414e20412043414e414c2050414e414d41
=begin original
What was in this chunk of memory? Numbers, characters, or a mixture of
both? Assuming that we're on a computer where ASCII (or some similar)
encoding is used: hexadecimal values in the range C<0x40> - C<0x5A>
indicate an uppercase letter, and C<0x20> encodes a space. So we might
assume it is a piece of text, which some are able to read like a tabloid;
but others will have to get hold of an ASCII table and relive that
firstgrader feeling. Not caring too much about which way to read this,
we note that C<unpack> with the template code C<H> converts the contents
of a sequence of bytes into the customary hexadecimal notation. Since
"a sequence of" is a pretty vague indication of quantity, C<H> has been
defined to convert just a single hexadecimal digit unless it is followed
by a repeat count. An asterisk for the repeat count means to use whatever
remains.
=end original
このメモリの塊はなんでしょう?
数値、文字、あるいはそれらの混合でしょうか?
使っているコンピュータが ASCII エンコーディング (あるいは似たようなもの) を
使っていると仮定します: C<0x40> - C<0x5A> 範囲の 16 進数は大文字を
示していて、C<0x20> は空白をエンコードしたものです。
それで、これは、タブロイドのように読むことのできるテキストの断片と
仮定できます; その他は ASCII テーブルを持って 1 年生の感覚を思い出す
必要があります。
これをどのようにして読むかについてはあまり気にしないことにして、
C<unpack> のテンプレートコード C<H> はバイト列の内容をいつもの 16 進表記に
変換することに注目します。
「列」というのは量についてあいまいなので、
C<H> は、引き続いて繰り返し回数がない場合は単に 1 つの 16 進数を
変換するように定義されています。
繰り返し数でのアスタリスクは、残っているもの全てを使うことを意味します。
=begin original
The inverse operation - packing byte contents from a string of hexadecimal
digits - is just as easily written. For instance:
=end original
逆操作 - 16 進数の文字列からバイトの内容に pack する - は簡単に書けます。
例えば:
my $s = pack( 'H2' x 10, 30..39 );
print "$s\n";
=begin original
Since we feed a list of ten 2-digit hexadecimal strings to C<pack>, the
pack template should contain ten pack codes. If this is run on a computer
with ASCII character coding, it will print C<0123456789>.
=end original
16 進で 2 桁の数値を示す文字列 10 個からなるリストを C<pack> に
渡しているので、pack テンプレートは 10 個の pack コードを含んでいる
必要があります。
これが ASCII 文字コードのコンピュータで実行されると、C<0123456789> を
表示します。
=head1 Packing Text
(テキストを pack する)
=begin original
Let's suppose you've got to read in a data file like this:
=end original
以下のようなデータファイルを読み込むことを考えます:
Date |Description | Income|Expenditure
01/24/2001 Zed's Camel Emporium 1147.99
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 235.00
=begin original
How do we do it? You might think first to use C<split>; however, since
C<split> collapses blank fields, you'll never know whether a record was
income or expenditure. Oops. Well, you could always use C<substr>:
=end original
どうすればいいでしょう?
最初に思いつくのは C<split> かもしれません;
しかし、C<split> は空白のフィールドを壊してしまうので、
そのレコードが収入だったか支出だったが分かりません。あらら。
では、C<substr> を使うとどうでしょう:
while (<>) {
my $date = substr($_, 0, 11);
my $desc = substr($_, 12, 27);
my $income = substr($_, 40, 7);
my $expend = substr($_, 52, 7);
...
}
=begin original
It's not really a barrel of laughs, is it? In fact, it's worse than it
may seem; the eagle-eyed may notice that the first field should only be
10 characters wide, and the error has propagated right through the other
numbers - which we've had to count by hand. So it's error-prone as well
as horribly unfriendly.
=end original
これはあまり愉快ではないですよね?
実際、これは思ったより悪いです; 注意深い人は最初のフィールドが 10 文字分しか
なく、エラーが他の数値に拡大してしまう - 手で数えなければなりません -
ことに気付くでしょう。
従って、これは恐ろしく不親切であると同様、間違いが発生しやすいです.
=begin original
Or maybe we could use regular expressions:
=end original
あるいは正規表現も使えます:
while (<>) {
my($date, $desc, $income, $expend) =
m|(\d\d/\d\d/\d{4}) (.{27}) (.{7})(.*)|;
...
}
=begin original
Urgh. Well, it's a bit better, but - well, would you want to maintain
that?
=end original
うわあ。
えーと、少しましです、しかし - えーと、これを保守したいと思います?
=begin original
Hey, isn't Perl supposed to make this sort of thing easy? Well, it does,
if you use the right tools. C<pack> and C<unpack> are designed to help
you out when dealing with fixed-width data like the above. Let's have a
look at a solution with C<unpack>:
=end original
ねえ、Perl はこの手のことを簡単にできないの?
ええ、できます、正しい道具を使えば。
C<pack> と C<unpack> は上記のような固定長データを扱う時の
助けになるように設計されています。
C<unpack> による解法を見てみましょう:
while (<>) {
my($date, $desc, $income, $expend) = unpack("A10xA27xA7A*", $_);
...
}
=begin original
That looks a bit nicer; but we've got to take apart that weird template.
Where did I pull that out of?
=end original
これはちょっとましに見えます;
でも変なテンプレートを分析しなければなりません。
これはどこから来たのでしょう?
=begin original
OK, let's have a look at some of our data again; in fact, we'll include
the headers, and a handy ruler so we can keep track of where we are.
=end original
よろしい、ここでデータをもう一度見てみましょう;
実際、ヘッダも含めて、何をしているかを追いかけるために
手書きの目盛りも付けています。
1 2 3 4 5
1234567890123456789012345678901234567890123456789012345678
Date |Description | Income|Expenditure
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 235.00
=begin original
From this, we can see that the date column stretches from column 1 to
column 10 - ten characters wide. The C<pack>-ese for "character" is
C<A>, and ten of them are C<A10>. So if we just wanted to extract the
dates, we could say this:
=end original
ここから、日付の桁は 1 桁目から 10 桁目まで - 10 文字の幅があることが
わかります。
「文字」のパックは C<A> で、10 文字の場合は C<A10> です。
それで、もし単に日付を展開したいだけなら、以下のように書けます:
my($date) = unpack("A10", $_);
=begin original
OK, what's next? Between the date and the description is a blank column;
we want to skip over that. The C<x> template means "skip forward", so we
want one of those. Next, we have another batch of characters, from 12 to
38. That's 27 more characters, hence C<A27>. (Don't make the fencepost
error - there are 27 characters between 12 and 38, not 26. Count 'em!)
=end original
よろしい、次は?
日付と説明の間には空白の桁があります;これは読み飛ばしたいです。
C<x> テンプレートは「読み飛ばす」ことを意味し、
これで 1 文字読み飛ばせます。
次に、別の文字の塊が 12 桁から 38 桁まであります。
これは 27 文字あるので、C<A27> です。
(数え間違えないように - 12 から 38 の間には 26 ではなく 27 文字あります。)
=begin original
Now we skip another character and pick up the next 7 characters:
=end original
次の文字は読み飛ばして、次の 7 文字を取り出します:
my($date,$description,$income) = unpack("A10xA27xA7", $_);
=begin original
Now comes the clever bit. Lines in our ledger which are just income and
not expenditure might end at column 46. Hence, we don't want to tell our
C<unpack> pattern that we B<need> to find another 12 characters; we'll
just say "if there's anything left, take it". As you might guess from
regular expressions, that's what the C<*> means: "use everything
remaining".
=end original
ここで少し賢くやりましょう。
台帳のうち、収入だけがあって支出がない行は 46 行目で終わっています。
従って、次の 12 文字を見つける B<必要がある> ということを
C<unpack> パターンに書きたくはありません;
単に次のようにします「もし何かが残っていれば、それを取ります」。
正規表現から推測したかもしれませんが、これが C<*> の意味することです:
「残っているもの全てを使います」。
=over 3
=item *
=begin original
Be warned, though, that unlike regular expressions, if the C<unpack>
template doesn't match the incoming data, Perl will scream and die.
=end original
但し、正規表現とは違うことに注意してください; もし C<unpack> テンプレートが
入力データと一致しない場合、Perl は悲鳴をあげて die します。
=back
=begin original
Hence, putting it all together:
=end original
従って、これを全部あわせると:
my ($date, $description, $income, $expend) =
unpack("A10xA27xA7xA*", $_);
=begin original
Now, that's our data parsed. I suppose what we might want to do now is
total up our income and expenditure, and add another line to the end of
our ledger - in the same format - saying how much we've brought in and
how much we've spent:
=end original
これで、データがパースできます。
今ほしいものが収入と支出をそれぞれ足し合わせて、台帳の最後に - 同じ形式で -
1 行付け加えることで、どれだけの収入と支出があったかを記すことだとします:
while (<>) {
my ($date, $desc, $income, $expend) =
unpack("A10xA27xA7xA*", $_);
$tot_income += $income;
$tot_expend += $expend;
}
$tot_income = sprintf("%.2f", $tot_income); # Get them into
$tot_expend = sprintf("%.2f", $tot_expend); # "financial" format
$date = POSIX::strftime("%m/%d/%Y", localtime);
# OK, let's go:
print pack("A10xA27xA7xA*", $date, "Totals",
$tot_income, $tot_expend);
=begin original
Oh, hmm. That didn't quite work. Let's see what happened:
=end original
あら、ふうむ。
これはうまく動きません。
何が起こったのか見てみましょう:
01/24/2001 Zed's Camel Emporium 1147.99
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 1235.00
03/23/2001Totals 1235.001172.98
=begin original
OK, it's a start, but what happened to the spaces? We put C<x>, didn't
we? Shouldn't it skip forward? Let's look at what L<perlfunc/pack> says:
=end original
まあ、これはスタートです; しかしスペースに何が起きたのでしょう?
C<x> を指定しましたよね?
これでは飛ばせない?
L<perlfunc/pack> に書いていることを見てみましょう:
x A null byte.
=begin original
Urgh. No wonder. There's a big difference between "a null byte",
character zero, and "a space", character 32. Perl's put something
between the date and the description - but unfortunately, we can't see
it!
=end original
うわあ。
当たり前です。
文字コード 0 の「ヌル文字」と、文字コード 32 の「空白」は全然違います。
Perl は日付と説明の間に何かを書いたのです - しかし残念ながら、
それは見えません!
=begin original
What we actually need to do is expand the width of the fields. The C<A>
format pads any non-existent characters with spaces, so we can use the
additional spaces to line up our fields, like this:
=end original
実際に必要なことはフィールドの幅を増やすことです。
C<A> フォーマットは存在しない文字を空白でパッディングするので、
以下のようにフィールドに空白の分だけ桁数を増やします:
print pack("A11 A28 A8 A*", $date, "Totals",
$tot_income, $tot_expend);
=begin original
(Note that you can put spaces in the template to make it more readable,
but they don't translate to spaces in the output.) Here's what we got
this time:
=end original
(テンプレートには読みやすくするために空白を入れることができますが、
出力には反映されないことに注意してください。)
これで得られたのは以下のものです:
01/24/2001 Zed's Camel Emporium 1147.99
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 1235.00
03/23/2001 Totals 1235.00 1172.98
=begin original
That's a bit better, but we still have that last column which needs to
be moved further over. There's an easy way to fix this up:
unfortunately, we can't get C<pack> to right-justify our fields, but we
can get C<sprintf> to do it:
=end original
これで少し良くなりましたが、まだ、最後の桁をもっと向こうに移動させる
必要があります。
これを修正する簡単な方法があります:
残念ながら C<pack> でフィールドを右寄せにすることは出来ませんが、
C<sprintf> を使えば出来ます:
$tot_income = sprintf("%.2f", $tot_income);
$tot_expend = sprintf("%12.2f", $tot_expend);
$date = POSIX::strftime("%m/%d/%Y", localtime);
print pack("A11 A28 A8 A*", $date, "Totals",
$tot_income, $tot_expend);
=begin original
This time we get the right answer:
=end original
今度は正しい答えを得られました:
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 1235.00
03/23/2001 Totals 1235.00 1172.98
=begin original
So that's how we consume and produce fixed-width data. Let's recap what
we've seen of C<pack> and C<unpack> so far:
=end original
ということで、これが固定長データを読み書きする方法です。
ここまでで C<pack> と C<unpack> について見たことを復習しましょう:
=over 3
=item *
=begin original
Use C<pack> to go from several pieces of data to one fixed-width
version; use C<unpack> to turn a fixed-width-format string into several
pieces of data.
=end original
複数のデータ片を一つの固定長データにするには C<pack> を使います;
固定長フォーマット文字列を複数のデータ片にするには C<unpack> を使います。
=item *
=begin original
The pack format C<A> means "any character"; if you're C<pack>ing and
you've run out of things to pack, C<pack> will fill the rest up with
spaces.
=end original
pack フォーマット C<A> は「任意の文字」を意味します; もし C<pack> 中に
pack するものがなくなったら、C<pack> は残りを空白で埋めます。
=item *
=begin original
C<x> means "skip a byte" when C<unpack>ing; when C<pack>ing, it means
"introduce a null byte" - that's probably not what you mean if you're
dealing with plain text.
=end original
C<unpack> での C<x> は「1 バイト読み飛ばす」ことを意味します;
C<pack> では、「ヌルバイトを生成する」ことを意味します -
これは、プレーンテキストを扱っている場合はおそらく望んでいるものでは
ないでしょう。
=item *
=begin original
You can follow the formats with numbers to say how many characters
should be affected by that format: C<A12> means "take 12 characters";
C<x6> means "skip 6 bytes" or "character 0, 6 times".
=end original
フォーマットの後に数値をつけることで、フォーマットに影響される文字数を
指定します: C<A12> は「12 文字取る」ことを意味します;
C<x6> は「6 バイト読み飛ばす」や「ヌルバイト 6 つ」を意味します。
=item *
=begin original
Instead of a number, you can use C<*> to mean "consume everything else
left".
=end original
数値の代わりに、C<*> で「残っているもの全てを使う」ことを指定できます。
=begin original
B<Warning>: when packing multiple pieces of data, C<*> only means
"consume all of the current piece of data". That's to say
=end original
B<警告>: 複数のデータ片を pack するとき、C<*> は「現在のデータ片を全て
含む」という意味だけです。
これは、以下のようにすると:
pack("A*A*", $one, $two)
=begin original
packs all of C<$one> into the first C<A*> and then all of C<$two> into
the second. This is a general principle: each format character
corresponds to one piece of data to be C<pack>ed.
=end original
C<$one> の全てを最初の C<A*> に pack し、それから C<$two> の全てを二番目に
pack します。
ここに一般的な原則があります: 各フォーマット文字は C<pack> されるデータ片
一つに対応します。
=back
=head1 Packing Numbers
(数値を pack する)
=begin original
So much for textual data. Let's get onto the meaty stuff that C<pack>
and C<unpack> are best at: handling binary formats for numbers. There is,
of course, not just one binary format - life would be too simple - but
Perl will do all the finicky labor for you.
=end original
テキストデータについてはこれくらいです。
C<pack> と C<unpack> が最良である、いやらしい代物: 数値のためのバイナリ
フォーマットに進みましょう。
もちろん、バイナリフォーマットはひとつではありません - 人生はそれほど
単純ではありません - が、Perl は全ての細かい作業を行います。
=head2 Integers
(整数)
=begin original
Packing and unpacking numbers implies conversion to and from some
I<specific> binary representation. Leaving floating point numbers
aside for the moment, the salient properties of any such representation
are:
=end original
数値を pack や unpack するということは、I<特定の> バイナリ表現との間で
変換するということを意味します。
今のところ浮動小数点数は脇にやっておくとすると、このような表現の
主要な性質としては:
=over 4
=item *
=begin original
the number of bytes used for storing the integer,
=end original
整数の保存に使うバイト数。
=item *
=begin original
whether the contents are interpreted as a signed or unsigned number,
=end original
内容を符号なし数として解釈するか符号付き数として解釈するか。
=item *
=begin original
the byte ordering: whether the first byte is the least or most
significant byte (or: little-endian or big-endian, respectively).
=end original
バイト順序:最初のバイトは最下位バイトか最上位バイトか
(言い換えると: それぞれリトルエンディアンかビッグエンディアンか)。
=back
=begin original
So, for instance, to pack 20302 to a signed 16 bit integer in your
computer's representation you write
=end original
それで、例えば、20302 をあなたのコンピュータの符号付き 16 ビット整数に
pack するとすると、以下のように書きます:
my $ps = pack( 's', 20302 );
=begin original
Again, the result is a string, now containing 2 bytes. If you print
this string (which is, generally, not recommended) you might see
C<ON> or C<NO> (depending on your system's byte ordering) - or something
entirely different if your computer doesn't use ASCII character encoding.
Unpacking C<$ps> with the same template returns the original integer value:
=end original
再び、結果は 2 バイトからなる文字列です。
もしこの文字列を表示する(これは一般的にはお勧めできません)と、
C<ON> か C<NO> (システムのバイト順に依存します) - または、もし
コンピューターが ASCII 文字エンコーディングを使っていないなら全く違う
文字列が表示されます。
C<$ps> を同じテンプレートで unpack すると、元の整数値が返ります:
my( $s ) = unpack( 's', $ps );
=begin original
This is true for all numeric template codes. But don't expect miracles:
if the packed value exceeds the allotted byte capacity, high order bits
are silently discarded, and unpack certainly won't be able to pull them
back out of some magic hat. And, when you pack using a signed template
code such as C<s>, an excess value may result in the sign bit
getting set, and unpacking this will smartly return a negative value.
=end original
これは全ての数値テンプレートコードに対して真です。
しかし奇跡を期待してはいけません:
もし pack された値が割り当てられたバイト容量を超えると、高位ビットは
黙って捨てられ、unpack は確実に魔法の帽子からデータを
取り出すことができません。
そして、C<s> のような符号付きテンプレートコードを使って pack すると、
超えた値が符号ビットをセットすることになり、unpack すると負の値が
返されることになるかもしれません。
=begin original
16 bits won't get you too far with integers, but there is C<l> and C<L>
for signed and unsigned 32-bit integers. And if this is not enough and
your system supports 64 bit integers you can push the limits much closer
to infinity with pack codes C<q> and C<Q>. A notable exception is provided
by pack codes C<i> and C<I> for signed and unsigned integers of the
"local custom" variety: Such an integer will take up as many bytes as
a local C compiler returns for C<sizeof(int)>, but it'll use I<at least>
32 bits.
=end original
16 ビットは整数に十分とは言えませんが、符号付きと符号なしの 32 ビット
整数のための C<l> と C<L> もあります。
そして、これで十分ではなく、システムが 64 ビット整数に対応しているなら、
pack コード C<q> と C<Q> を使って限界をほぼ無限にまで押しやることができます。
注目すべき例外は pack コード C<i> と C<I> で、「ローカルに特化した」
符号付きと符号なしの整数を提供します: このような整数は C<sizeof(int)> と
したときにローカルな C コンパイラが返す値と同じバイト数ですが、
I<少なくとも> 32 ビットを使います。
=begin original
Each of the integer pack codes C<sSlLqQ> results in a fixed number of bytes,
no matter where you execute your program. This may be useful for some
applications, but it does not provide for a portable way to pass data
structures between Perl and C programs (bound to happen when you call
XS extensions or the Perl function C<syscall>), or when you read or
write binary files. What you'll need in this case are template codes that
depend on what your local C compiler compiles when you code C<short> or
C<unsigned long>, for instance. These codes and their corresponding
byte lengths are shown in the table below. Since the C standard leaves
much leeway with respect to the relative sizes of these data types, actual
values may vary, and that's why the values are given as expressions in
C and Perl. (If you'd like to use values from C<%Config> in your program
you have to import it with C<use Config>.)
=end original
整数 pack コード C<sSlLqQ> のそれぞれは、どこでプログラムが
実行されたとしても固定長のバイト列となります。
これは一部のアプリケーションでは有用ですが、(XS エクステンションや
Perl 関数 C<syscall> を呼び出すときに必要となる)
Perl と C のプログラムの間でデータ構造を渡す場合や、バイナリファイルを
読み書きするときの、移植性のある手段は提供しません。
この場合に必要なものは、例えば、C<short> や C<unsigned long> と書いたときに
ローカルの C コンパイラがどのようにコンパイルするかに依存する
テンプレートコードです。
これらのコードと、それに対応するバイト長は以下のテーブルの様になります。
C 標準はそれぞれのデータ型の大きさの点で多くの自由裁量を残しているので、
実際の値は異なるかもしれず、そしてこれがなぜ値が C と Perl の式として
与えられているかの理由です。
(もしプログラムで C<%Config> の値を使いたい場合は、C<use Config> として
これをインポートする必要があります。)
=begin original
signed unsigned byte length in C byte length in Perl
s! S! sizeof(short) $Config{shortsize}
i! I! sizeof(int) $Config{intsize}
l! L! sizeof(long) $Config{longsize}
q! Q! sizeof(long long) $Config{longlongsize}
=end original
符号付き 符号なし C でのバイト長 Perl でのバイト長
s! S! sizeof(short) $Config{shortsize}
i! I! sizeof(int) $Config{intsize}
l! L! sizeof(long) $Config{longsize}
q! Q! sizeof(long long) $Config{longlongsize}
=begin original
The C<i!> and C<I!> codes aren't different from C<i> and C<I>; they are
tolerated for completeness' sake.
=end original
C<i!> および C<I!> は C<i> および C<I> と違いはありません; これらは
完全性のために許容されています。
=head2 Unpacking a Stack Frame
(スタックフレームを unpack する)
=begin original
Requesting a particular byte ordering may be necessary when you work with
binary data coming from some specific architecture whereas your program could
run on a totally different system. As an example, assume you have 24 bytes
containing a stack frame as it happens on an Intel 8086:
=end original
特定のアーキテクチャから来たバイナリに対して作業をする一方、プログラムが
全く違うシステムで動いている場合、特定のバイト順序の要求が必要になります。
例として、Intel 8086 のスタックフレームを含む 24 バイトを仮定します:
+---------+ +----+----+ +---------+
TOS: | IP | TOS+4:| FL | FH | FLAGS TOS+14:| SI |
+---------+ +----+----+ +---------+
| CS | | AL | AH | AX | DI |
+---------+ +----+----+ +---------+
| BL | BH | BX | BP |
+----+----+ +---------+
| CL | CH | CX | DS |
+----+----+ +---------+
| DL | DH | DX | ES |
+----+----+ +---------+
=begin original
First, we note that this time-honored 16-bit CPU uses little-endian order,
and that's why the low order byte is stored at the lower address. To
unpack such a (unsigned) short we'll have to use code C<v>. A repeat
count unpacks all 12 shorts:
=end original
まず、この伝統のある 16 ビット CPU はリトルエンディアンを使っていて、
それが低位バイトが低位アドレスに格納されている理由であることに
注意します。
このような(符号付き)short を unpack するには、コード C<v> を使う必要が
あるでしょう。
繰り返し数によって、12 全ての short を unpack します。
my( $ip, $cs, $flags, $ax, $bx, $cx, $dx, $si, $di, $bp, $ds, $es ) =
unpack( 'v12', $frame );
=begin original
Alternatively, we could have used C<C> to unpack the individually
accessible byte registers FL, FH, AL, AH, etc.:
=end original
あるいは、FL, FH, AL, AH といったバイトレジスタに個々にアクセスできるように
unpack するための C<C> もあります:
my( $fl, $fh, $al, $ah, $bl, $bh, $cl, $ch, $dl, $dh ) =
unpack( 'C10', substr( $frame, 4, 10 ) );
=begin original
It would be nice if we could do this in one fell swoop: unpack a short,
back up a little, and then unpack 2 bytes. Since Perl I<is> nice, it
proffers the template code C<X> to back up one byte. Putting this all
together, we may now write:
=end original
これを 1 回で行えたら素敵でしょう: short を unpack して、少し戻って、
それから 2 バイト unpack します。
Perl は I<素敵> なので、1 バイト戻るテンプレートコード C<X> を
提供しています。
これら全てを一緒にすると、以下のように書けます:
my( $ip, $cs,
$flags,$fl,$fh,
$ax,$al,$ah, $bx,$bl,$bh, $cx,$cl,$ch, $dx,$dl,$dh,
$si, $di, $bp, $ds, $es ) =
unpack( 'v2' . ('vXXCC' x 5) . 'v5', $frame );
=begin original
(The clumsy construction of the template can be avoided - just read on!)
=end original
(この不細工なテンプレート構造は避けられます - 読み進めてください!)
=begin original
We've taken some pains to construct the template so that it matches
the contents of our frame buffer. Otherwise we'd either get undefined values,
or C<unpack> could not unpack all. If C<pack> runs out of items, it will
supply null strings (which are coerced into zeroes whenever the pack code
says so).
=end original
テンプレートを構築するのに少し苦労したのは、フレームバッファの内容に
一致させるためです。
さもなければ未定義値を受け取ることになるか、あるいは
C<unpack> は何も unpack できなくなります。
もし C<pack> で要素がなくなったら、空文字列を補います
(pack コードがそうするように言っていれば、ゼロに強制されます)。
=head2 How to Eat an Egg on a Net
(インターネットの卵の食べ方)
=begin original
The pack code for big-endian (high order byte at the lowest address) is
C<n> for 16 bit and C<N> for 32 bit integers. You use these codes
if you know that your data comes from a compliant architecture, but,
surprisingly enough, you should also use these pack codes if you
exchange binary data, across the network, with some system that you
know next to nothing about. The simple reason is that this
order has been chosen as the I<network order>, and all standard-fearing
programs ought to follow this convention. (This is, of course, a stern
backing for one of the Lilliputian parties and may well influence the
political development there.) So, if the protocol expects you to send
a message by sending the length first, followed by just so many bytes,
you could write:
=end original
ビッグエンディアン(最下位アドレスが最上位バイト)での pack コードは、
16 ビット整数が C<n>、 32 ビット整数が C<N> です。
もし準拠したアーキテクチャからデータが来ることが分かっているなら
これらのコードを使います;
もしネットワークを通して何も知らない他のシステムとバイナリデータを
交換する場合にもこれらの pack コードを使うべきです。