root/NEWT0/trunk/src/newt_core/NewtNSOF.c

Revision 113, 26.3 kB (checked in by gnue, 17 months ago)

'#pragma mark' is invalidated by '#if 0'

  • Property svn:executable set to *
Line 
1/*------------------------------------------------------------------------*/
2/**
3 * @file    NewtNSOF.c
4 * @brief   Newton Streamed Object Format
5 *
6 * @author  M.Nukui
7 * @date    2005-04-01
8 *
9 * Copyright (C) 2005 M.Nukui All rights reserved.
10 */
11
12
13/* ヘッダファイル */
14#include <string.h>
15
16#include "NewtNSOF.h"
17#include "NewtErrs.h"
18#include "NewtObj.h"
19#include "NewtEnv.h"
20#include "NewtFns.h"
21#include "NewtVM.h"
22#include "NewtIconv.h"
23
24#include "utils/endian_utils.h"
25
26/* マクロ */
27#define NSOFIsNOS(verno)    ((verno == 1) || (verno == 2))  ///< Newton OS 互換の NSOF
28
29
30
31/* 型宣言 */
32
33/// NSOF変換に使用する iconv変換ディスクリプター
34#ifdef HAVE_LIBICONV
35typedef struct {
36    iconv_t     utf16be;    ///< iconv変換ディスクリプター(UTF16-BE)
37    iconv_t     macroman;   ///< iconv変換ディスクリプター(MACROMAN)
38} nsof_iconv_t;
39#endif /* HAVE_LIBICONV */
40
41/// NSOFストリーム構造体
42typedef struct {
43    int32_t     verno;          ///< NSOFバージョン番号
44    uint8_t *   data;           ///< データ
45    uint32_t    len;            ///< データの長さ
46    uint32_t    offset;         ///< 作業中の位置
47    newtRefVar  precedents;     ///< 出現済みオブジェクトのリスト
48    newtErr     lastErr;        ///< 最後のエラーコード
49
50#ifdef HAVE_LIBICONV
51    struct {
52        nsof_iconv_t    to;     ///< NSOFエンコーディングへの変換用
53        nsof_iconv_t    from;   ///< NSOFエンコーディングからの変換用
54    } cd; ///< iconv変換ディスクリプター
55#endif /* HAVE_LIBICONV */
56} nsof_stream_t;
57
58
59/* 関数プロトタイプ */
60static bool         NewtRefIsByte(newtRefArg r);
61static bool         NewtRefIsSmallRect(newtRefArg r);
62static int32_t      NewtArraySearch(newtRefArg array, newtRefArg r);
63
64static newtErr      NSOFWriteByte(nsof_stream_t * nsof, uint8_t value);
65static newtErr      NSOFWriteXlong(nsof_stream_t * nsof, int32_t value);
66static uint8_t      NSOFReadByte(nsof_stream_t * nsof);
67static int32_t      NSOFReadXlong(nsof_stream_t * nsof);
68
69static newtErr      NSOFWritePrecedent(nsof_stream_t * nsof, int32_t pos);
70static newtErr      NSOFWriteImmediate(nsof_stream_t * nsof, newtRefArg r);
71static newtErr      NSOFWriteCharacter(nsof_stream_t * nsof, newtRefArg r);
72static newtErr      NSOFWriteBinary(nsof_stream_t * nsof, newtRefArg r, uint16_t objtype);
73static newtErr      NSOFWriteSymbol(nsof_stream_t * nsof, newtRefArg r);
74static newtErr      NSOFWriteNamedMP(nsof_stream_t * nsof, newtRefArg r);
75static newtErr      NSOFWriteArray(nsof_stream_t * nsof, newtRefArg r);
76static newtErr      NSOFWriteFrame(nsof_stream_t * nsof, newtRefArg r);
77static newtErr      NSOFWriteSmallRect(nsof_stream_t * nsof, newtRefArg r);
78static newtErr      NewtWriteNSOF(nsof_stream_t * nsof, newtRefArg r);
79
80static newtRef      NSOFReadBinary(nsof_stream_t * nsof, int type);
81static newtRef      NSOFReadArray(nsof_stream_t * nsof, int type);
82static newtRef      NSOFReadFrame(nsof_stream_t * nsof);
83static newtRef      NSOFReadSymbol(nsof_stream_t * nsof);
84static newtRef      NSOFReadNamedMP(nsof_stream_t * nsof);
85static newtRef      NSOFReadSmallRect(nsof_stream_t * nsof);
86static newtRef      NSOFReadNSOF(nsof_stream_t * nsof);
87
88
89#if 0
90#pragma mark -
91#endif
92/*------------------------------------------------------------------------*/
93/** オブジェクトが 0〜255 の整数かチェックする
94 *
95 * @param r         [in] オブジェクト
96 *
97 * @retval          true    0〜255 の整数
98 * @retval          false   0〜255 の整数でない
99 */
100
101bool NewtRefIsByte(newtRefArg r)
102{
103    if (NewtRefIsInteger(r))
104    {
105        int32_t     n;
106
107        n = NewtRefToInteger(r);
108
109        if (0 <= n && n <= 255)
110            return true;
111    }
112
113    return false;
114}
115
116
117/*------------------------------------------------------------------------*/
118/** フレームが NSOF(smallRect) の条件を満たすかチェックする
119 *
120 * @param r         [in] フレームオブジェクト
121 *
122 * @retval          true    条件を満たす
123 * @retval          false   条件を満たさない
124 */
125
126bool NewtRefIsSmallRect(newtRefArg r)
127{
128    if (NewtFrameLength(r) == 4)
129    {
130        if (NewtRefIsByte(NcGetSlot(r, NSSYM(top))) &&
131            NewtRefIsByte(NcGetSlot(r, NSSYM(left))) &&
132            NewtRefIsByte(NcGetSlot(r, NSSYM(bottom))) &&
133            NewtRefIsByte(NcGetSlot(r, NSSYM(right))))
134        {
135            return true;
136        }
137    }
138
139    return false;
140}
141
142
143/*------------------------------------------------------------------------*/
144/** 配列からオブジェクトを探す
145 *
146 * @param array     [in] 配列
147 * @param r         [in] フレームオブジェクト
148 *
149 * @retval          0以上 見つかった位置
150 * @retval          -1      見つからなかった
151 */
152
153int32_t NewtArraySearch(newtRefArg array, newtRefArg r)
154{
155    newtRef *   slots;
156    uint32_t    len;
157    uint32_t    i;
158
159    len = NewtArrayLength(array);
160    slots = NewtRefToSlots(array);
161
162    for (i = 0; i < len; i++)
163    {
164        if (slots[i] == r)
165            return i;
166    }
167
168    return -1;
169}
170
171
172#if 0
173#pragma mark -
174#endif
175/*------------------------------------------------------------------------*/
176/** 1byte を NSOF でバッファに書込む
177 *
178 * @param nsof      [i/o]NSOFバッファ
179 * @param value     [in] 1byte データ
180 *
181 * @return          エラーコード
182 *
183 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
184 */
185 
186newtErr NSOFWriteByte(nsof_stream_t * nsof, uint8_t value)
187{
188    if (nsof->data)
189    {
190        if (nsof->len <= nsof->offset)
191        {   // バッファを越えた
192            nsof->lastErr = kNErrOutOfRange;
193            return nsof->lastErr;
194        }
195
196        nsof->data[nsof->offset] = value;
197    }
198
199    nsof->offset++;
200
201    return kNErrNone;
202}
203
204
205/*------------------------------------------------------------------------*/
206/** データを xlong 形式でバッファに書込む
207 *
208 * @param nsof      [i/o]NSOFバッファ
209 * @param value     [in] データ
210 *
211 * @return          エラーコード
212 *
213 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
214 */
215
216newtErr NSOFWriteXlong(nsof_stream_t * nsof, int32_t value)
217{
218    if (0 <= value && value <= 254)
219    {
220        NSOFWriteByte(nsof, value);
221    }
222    else
223    {
224        NSOFWriteByte(nsof, 0xff);
225        NSOFWriteByte(nsof, ((uint32_t)value >> 24) & 0xffff);
226        NSOFWriteByte(nsof, ((uint32_t)value >> 16) & 0xffff);
227        NSOFWriteByte(nsof, ((uint32_t)value >> 8) & 0xffff);
228        NSOFWriteByte(nsof, (uint32_t)value & 0xffff);
229    }
230
231    return nsof->lastErr;
232}
233
234
235/*------------------------------------------------------------------------*/
236/** NSOFバッファ からデータを 1byte 読込む
237 *
238 * @param nsof      [i/o]NSOFバッファ
239 *
240 * @return          1byte データ
241 */
242 
243uint8_t NSOFReadByte(nsof_stream_t * nsof)
244{
245    uint8_t     result;
246
247    if (nsof->len <= nsof->offset)
248    {   // バッファを越えた
249        nsof->lastErr = kNErrNotABinaryObject;
250        return 0;
251    }
252
253    result = nsof->data[nsof->offset];
254    nsof->offset++;
255
256    return result;
257}
258
259
260/*------------------------------------------------------------------------*/
261/** NSOFバッファ からデータを xlong 形式で読込む
262 *
263 * @param nsof      [i/o]NSOFバッファ
264 *
265 * @return          データ
266 */
267
268int32_t NSOFReadXlong(nsof_stream_t * nsof)
269{
270    int32_t     value;
271
272    value = NSOFReadByte(nsof);
273
274    if (value == 0xff)
275    {
276        value  = NSOFReadByte(nsof) << 24;
277        value |= NSOFReadByte(nsof) << 16;
278        value |= NSOFReadByte(nsof) << 8;
279        value |= NSOFReadByte(nsof);
280    }
281
282    return value;
283}
284
285
286#if 0
287#pragma mark -
288#endif
289/*------------------------------------------------------------------------*/
290/** 出現済みデータを NSOF でバッファに書込む
291 *
292 * @param nsof      [i/o]NSOFバッファ
293 * @param pos       [in] 出現位置
294 *
295 * @return          エラーコード
296 *
297 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
298 */
299 
300newtErr NSOFWritePrecedent(nsof_stream_t * nsof, int32_t pos)
301{
302    NSOFWriteByte(nsof, kNSOFPrecedent);
303    NSOFWriteXlong(nsof, pos);
304
305    return nsof->lastErr;
306}
307
308
309/*------------------------------------------------------------------------*/
310/** 即値データを NSOF でバッファに書込む
311 *
312 * @param nsof      [i/o]NSOFバッファ
313 * @param r         [in] 即値データ
314 *
315 * @return          エラーコード
316 *
317 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
318 */
319 
320newtErr NSOFWriteImmediate(nsof_stream_t * nsof, newtRefArg r)
321{
322    NSOFWriteByte(nsof, kNSOFImmediate);
323    NSOFWriteXlong(nsof, r);
324
325    return nsof->lastErr;
326}
327
328
329/*------------------------------------------------------------------------*/
330/** 文字データを NSOF でバッファに書込む
331 *
332 * @param nsof      [i/o]NSOFバッファ
333 * @param r         [in] 文字データ
334 *
335 * @return          エラーコード
336 *
337 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
338 */
339
340newtErr NSOFWriteCharacter(nsof_stream_t * nsof, newtRefArg r)
341{
342    int     c;
343
344    c = NewtRefToCharacter(r);
345
346    if (c < 0x100)
347    {
348        NSOFWriteByte(nsof, kNSOFCharacter);
349        NSOFWriteByte(nsof, c);
350    }
351    else
352    {
353        NSOFWriteByte(nsof, kNSOFUnicodeCharacter);
354        NSOFWriteByte(nsof, (c >> 8) & 0xff);
355        NSOFWriteByte(nsof, c & 0xff);
356    }
357
358    return nsof->lastErr;
359}
360
361
362/*------------------------------------------------------------------------*/
363/** バイナリデータを NSOF でバッファに書込む
364 *
365 * @param nsof      [i/o]NSOFバッファ
366 * @param r         [in] バイナリオブジェクト
367 * @param objtype   [in] オブジェクトタイプ
368 *
369 * @return          エラーコード
370 *
371 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
372 */
373
374newtErr NSOFWriteBinary(nsof_stream_t * nsof, newtRefArg r, uint16_t objtype)
375{
376    newtRefVar  klass;
377    uint32_t    size;
378    char *      buff = NULL;
379    int         type;
380
381    klass = NcClassOf(r);
382
383    if (klass == NSSYM0(string))
384        type = kNSOFString;
385    else
386        type = kNSOFBinaryObject;
387
388    size = NewtBinaryLength(r);
389
390#ifdef HAVE_LIBICONV
391    if (objtype == kNewtString)
392    {
393        size_t  bufflen;
394        char *  s;
395
396        s = NewtRefToString(r);
397        buff = NewtIconv(nsof->cd.to.utf16be, (char *)s, size, &bufflen);
398        if (buff) size = bufflen;
399    }
400#endif /* HAVE_LIBICONV */
401
402    NSOFWriteByte(nsof, type);
403    NSOFWriteXlong(nsof, size);
404
405    if (type == kNSOFBinaryObject)
406    {
407        NewtWriteNSOF(nsof, klass);
408    }
409
410    if (nsof->data)
411    {
412        uint8_t *   data;
413
414        data = nsof->data + nsof->offset;
415
416        switch (objtype)
417        {
418            case kNewtInt32:
419                if (NSOFIsNOS(nsof->verno))
420                {
421                    nsof->lastErr = kNErrNSOFWrite;
422                }
423                else
424                {
425                    int32_t n;
426
427                    n = NewtRefToInteger(r);
428                    n = htonl(n);
429                    memcpy(data, (uint8_t *)&n, sizeof(n));
430                }
431                break;
432
433            case kNewtReal:
434                {
435                    double  n;
436
437                    n = NewtRefToReal(r);
438                    n = htond(n);
439                    memcpy(data, (uint8_t *)&n, sizeof(n));
440                }
441                break;
442
443            default:
444                if (buff)
445                    memcpy(data, buff, size);
446                else
447                    memcpy(data, NewtRefToBinary(r), size);
448                break;
449        }
450    }
451
452    nsof->offset += size;
453    if (buff) free(buff);
454
455    return nsof->lastErr;
456}
457
458
459/*------------------------------------------------------------------------*/
460/** シンボルデータを NSOF でバッファに書込む
461 *
462 * @param nsof      [i/o]NSOFバッファ
463 * @param r         [in] シンボルオブジェクト
464 *
465 * @return          エラーコード
466 *
467 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
468 */
469
470newtErr NSOFWriteSymbol(nsof_stream_t * nsof, newtRefArg r)
471{
472    uint32_t    size;
473    char *      buff = NULL;
474    char *      name;
475
476    size = NewtSymbolLength(r);
477    name = NewtRefToSymbol(r)->name;
478
479#ifdef HAVE_LIBICONV
480    {
481        size_t      bufflen;
482
483        buff = NewtIconv(nsof->cd.to.macroman, (char *)name, size, &bufflen);
484
485        if (buff)
486        {
487            name = buff;
488            size = bufflen;
489        }
490    }
491#endif /* HAVE_LIBICONV */
492
493    NSOFWriteByte(nsof, kNSOFSymbol);
494    NSOFWriteXlong(nsof, size);
495
496    if (nsof->data) memcpy(nsof->data + nsof->offset, name, size);
497    nsof->offset += size;
498
499    if (buff) free(buff);
500
501    return nsof->lastErr;
502}
503
504
505#ifdef __NAMED_MAGIC_POINTER__
506/*------------------------------------------------------------------------*/
507/** 名前付マジックポインタを NSOF でバッファに書込む
508 *
509 * @param nsof      [i/o]NSOFバッファ
510 * @param r         [in] 名前付マジックポインタ
511 *
512 * @return          エラーコード
513 *
514 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
515 */
516
517newtErr NSOFWriteNamedMP(nsof_stream_t * nsof, newtRefArg r)
518{
519    newtRefVar  sym;
520
521    sym = NewtMPToSymbol(r);
522
523    if (NSOFIsNOS(nsof->verno))
524    {
525        // とりあえずシンボルを書込む
526        NSOFWriteSymbol(nsof, sym);
527        nsof->lastErr = kNErrNSOFWrite;
528    }
529    else
530    {
531        uint32_t    size;
532
533        size = NewtSymbolLength(sym);
534
535        NSOFWriteByte(nsof, kNSOFNamedMagicPointer);
536        NSOFWriteXlong(nsof, size);
537
538        if (nsof->data) memcpy(nsof->data + nsof->offset, NewtRefToSymbol(sym)->name, size);
539        nsof->offset += size;
540    }
541
542    return nsof->lastErr;
543}
544#endif /* __NAMED_MAGIC_POINTER__ */
545
546
547/*------------------------------------------------------------------------*/
548/** 配列データを NSOF でバッファに書込む
549 *
550 * @param nsof      [i/o]NSOFバッファ
551 * @param r         [in] 配列オブジェクト
552 *
553 * @return          エラーコード
554 *
555 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
556 */
557
558newtErr NSOFWriteArray(nsof_stream_t * nsof, newtRefArg r)
559{
560    newtRefVar  klass;
561    newtRef *   slots;
562    uint32_t    numSlots;
563    uint32_t    i;
564    int         type;
565
566    numSlots = NewtArrayLength(r);
567    klass = NcClassOf(r);
568
569    if (klass == NSSYM0(array))
570        type = kNSOFPlainArray;
571    else
572        type = kNSOFArray;
573
574    NSOFWriteByte(nsof, type);
575
576    NSOFWriteXlong(nsof, numSlots);
577
578    if (type == kNSOFArray)
579    {
580        NewtWriteNSOF(nsof, klass);
581        if (nsof->lastErr != kNErrNone) return nsof->lastErr;
582    }
583
584    slots = NewtRefToSlots(r);
585
586    for (i = 0; i < numSlots; i++)
587    {
588        NewtWriteNSOF(nsof, slots[i]);
589        if (nsof->lastErr != kNErrNone) return nsof->lastErr;
590    }
591
592    return nsof->lastErr;
593}
594
595
596/*------------------------------------------------------------------------*/
597/** フレームデータを NSOF でバッファに書込む
598 *
599 * @param nsof      [i/o]NSOFバッファ
600 * @param r         [in] フレームオブジェクト
601 *
602 * @return          エラーコード
603 *
604 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
605 */
606
607newtErr NSOFWriteFrame(nsof_stream_t * nsof, newtRefArg r)
608{
609    newtRefVar  map;
610    newtRef *   slots;
611    uint32_t    numSlots;
612    uint32_t    index;
613    uint32_t    i;
614
615    numSlots = NewtFrameLength(r);
616    map = NewtFrameMap(r);
617
618    NSOFWriteByte(nsof, kNSOFFrame);
619    NSOFWriteXlong(nsof, numSlots);
620
621    slots = NewtRefToSlots(r);
622
623    for (i = 0; i < numSlots; i++)
624    {
625        index = 0;
626        NewtWriteNSOF(nsof, NewtGetMapIndex(map, i, &index));
627        if (nsof->lastErr != kNErrNone) return nsof->lastErr;
628    }
629
630    for (i = 0; i < numSlots; i++)
631    {
632        NewtWriteNSOF(nsof, slots[i]);
633        if (nsof->lastErr != kNErrNone) return nsof->lastErr;
634    }
635
636    return nsof->lastErr;
637}
638
639
640/*------------------------------------------------------------------------*/
641/** フレームデータを NSOF(smallRect) でバッファに書込む
642 *
643 * @param nsof      [i/o]NSOFバッファ
644 * @param r         [in] フレームオブジェクト
645 *
646 * @return          エラーコード
647 *
648 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
649 */
650
651newtErr NSOFWriteSmallRect(nsof_stream_t * nsof, newtRefArg r)
652{
653    NSOFWriteByte(nsof, kNSOFSmallRect);
654    NSOFWriteByte(nsof, NewtRefToInteger(NcGetSlot(r, NSSYM(top))));
655    NSOFWriteByte(nsof, NewtRefToInteger(NcGetSlot(r, NSSYM(left))));
656    NSOFWriteByte(nsof, NewtRefToInteger(NcGetSlot(r, NSSYM(bottom))));
657    NSOFWriteByte(nsof, NewtRefToInteger(NcGetSlot(r, NSSYM(right))));
658
659    return nsof->lastErr;
660}
661
662
663/*------------------------------------------------------------------------*/
664/** オブジェクトを NSOFバイナリオブジェクトに変換して書込む
665 *
666 * @param nsof      [i/o]NSOFバッファ
667 * @param r         [in] オブジェクト
668 *
669 * @return          エラーコード
670 *
671 * @note            nsof->data が NULL の場合は nsof->offset のみ更新される
672 */
673
674newtErr NewtWriteNSOF(nsof_stream_t * nsof, newtRefArg r)
675{
676    if (NewtRefIsImmediate(r))
677    {
678        if (r == kNewtRefNIL)
679            NSOFWriteByte(nsof, kNSOFNIL);
680        else if (NewtRefIsCharacter(r))
681            NSOFWriteCharacter(nsof, r);
682        else
683            NSOFWriteImmediate(nsof, r);
684    }
685    else
686    {
687        int32_t foundPrecedent;
688
689        foundPrecedent = NewtArraySearch(nsof->precedents, r);
690
691        if (foundPrecedent < 0)
692        {
693            uint16_t    objtype;
694
695            NcAddArraySlot(nsof->precedents, r);
696            objtype = NewtGetRefType(r, true);
697
698            switch (objtype)
699            {
700                case kNewtArray:
701                    NSOFWriteArray(nsof, r);
702                    break;
703
704                case kNewtFrame:
705                    if (NewtRefIsSmallRect(r))
706                        NSOFWriteSmallRect(nsof, r);
707                    else
708                        NSOFWriteFrame(nsof, r);
709                    break;
710
711                case kNewtSymbol:
712                    NSOFWriteSymbol(nsof, r);
713                    break;
714
715#ifdef __NAMED_MAGIC_POINTER__
716                case kNewtMagicPointer:
717                    NSOFWriteNamedMP(nsof, r);
718                    break;
719#endif /* __NAMED_MAGIC_POINTER__ */
720
721                default:
722                    NSOFWriteBinary(nsof, r, objtype);
723                    break;
724            }
725        }
726        else
727        {
728            NSOFWritePrecedent(nsof, foundPrecedent);
729        }
730    }
731
732    return nsof->lastErr;
733}
734
735
736/*------------------------------------------------------------------------*/
737/** オブジェクトを NSOFバイナリオブジェクトに変換する
738 *
739 * @param rcvr      [in] レシーバ
740 * @param r         [in] オブジェクト
741 * @param ver       [in] バージョン
742 *
743 * @return          NSOFバイナリオブジェクト
744 */
745
746newtRef NsMakeNSOF(newtRefArg rcvr, newtRefArg r, newtRefArg ver)
747{
748    nsof_stream_t   nsof;
749    newtRefVar  result;
750
751    if (! NewtRefIsInteger(ver))
752        return NewtThrow(kNErrNotAnInteger, ver);
753
754    memset(&nsof, 0, sizeof(nsof));
755
756    nsof.verno = NewtRefToInteger(ver);
757    nsof.precedents = NewtMakeArray(kNewtRefUnbind, 0);
758    nsof.offset = 1;
759
760#ifdef HAVE_LIBICONV
761    if (NSOFIsNOS(nsof.verno))
762    {
763        char *      encoding;
764
765        encoding = NewtDefaultEncoding();
766        nsof.cd.to.utf16be = iconv_open("UTF-16BE", encoding);
767        nsof.cd.to.macroman = iconv_open("MACROMAN", encoding);
768    }
769    else
770    {
771        nsof.cd.to.utf16be = (iconv_t)-1;
772        nsof.cd.to.macroman = (iconv_t)-1;
773    }
774#endif /* HAVE_LIBICONV */
775
776    // 必要なサイズの計算
777    NewtWriteNSOF(&nsof, r);
778
779    if (nsof.lastErr == kNErrNone)
780    {
781        // バイナリオブジェクトの作成
782        result = NewtMakeBinary(NSSYM(NSOF), NULL, nsof.offset, false);
783
784        if (NewtRefIsNotNIL(result))
785        {   // 実際の書込み
786            NewtSetLength(nsof.precedents, 0);
787            nsof.data = NewtRefToBinary(result);
788            nsof.len = nsof.offset;
789            nsof.offset = 0;
790
791            NSOFWriteByte(&nsof, nsof.verno);
792            NewtWriteNSOF(&nsof, r);
793        }
794    }
795    else
796    {
797        result = NewtThrow(nsof.lastErr, r);
798    }
799
800#ifdef HAVE_LIBICONV
801    if (nsof.cd.to.utf16be != (iconv_t)-1) iconv_close(nsof.cd.to.utf16be);
802    if (nsof.cd.to.macroman != (iconv_t)-1) iconv_close(nsof.cd.to.macroman);
803#endif /* HAVE_LIBICONV */
804
805    return result;
806}
807
808
809#if 0
810#pragma mark -
811#endif
812/*------------------------------------------------------------------------*/
813/** NSOFバッファを読込んでバイナリオブジェクトに変換する
814 *
815 * @param nsof      [i/o]NSOFバッファ
816 * @param type      [in] NSOFのタイプ
817 *
818 * @return          バイナリオブジェクト
819 */
820
821newtRef NSOFReadBinary(nsof_stream_t * nsof, int type)
822{
823    newtRefVar  klass;
824    newtRefVar  r = kNewtRefUnbind;
825    int32_t     xlen;
826    uint8_t *   data;
827
828    xlen = NSOFReadXlong(nsof);
829
830    if (type == kNSOFString)
831    {
832        klass = NSSYM0(string);
833    }
834    else
835    {
836        klass = NSOFReadNSOF(nsof);
837        if (nsof->lastErr != kNErrNone) return kNewtRefUnbind;
838    }
839
840    data = nsof->data + nsof->offset;
841
842    if (klass == NSSYM0(int32))
843    {
844        if (NSOFIsNOS(nsof->verno))
845        {
846            nsof->lastErr = kNErrNSOFRead;
847        }
848        else
849        {
850            int32_t n;
851
852            memcpy(&n, data, sizeof(n));
853            n = ntohl(n);
854            r= NewtMakeInteger(n);
855        }
856    }
857    else if (klass == NSSYM0(real))
858    {
859        double  n;
860
861        memcpy(&n, data, sizeof(n));
862        n = ntohd(n);
863        r= NewtMakeReal(n);
864    }
865#ifdef HAVE_LIBICONV
866    else if (NewtIsSubclass(klass, NSSYM0(string)))
867    {
868        char *  buff;
869
870        buff = NewtIconv(nsof->cd.from.utf16be, (char *)data, xlen, NULL);
871
872        if (buff)
873        {
874            r = NewtMakeString(buff, false);
875            free(buff);
876        }
877        else
878        {
879            r = NewtMakeBinary(klass, data, xlen, false);
880        }
881    }
882#endif /* HAVE_LIBICONV */
883    else
884    {
885        r = NewtMakeBinary(klass, data, xlen, false);
886    }
887
888    nsof->offset += xlen;
889
890    return r;
891}
892
893
894/*------------------------------------------------------------------------*/
895/** NSOFバッファを読込んで配列オブジェクトに変換する
896 *
897 * @param nsof      [i/o]NSOFバッファ
898 * @param type      [in] NSOFのタイプ
899 *
900 * @return          配列オブジェクト
901 */
902
903newtRef NSOFReadArray(nsof_stream_t * nsof, int type)
904{
905    newtRefVar  klass = kNewtRefUnbind;
906    newtRefVar  r;
907    int32_t     xlen;
908
909    xlen = NSOFReadXlong(nsof);
910
911    if (type == kNSOFArray)
912    {
913        klass = NSOFReadNSOF(nsof);
914        if (nsof->lastErr != kNErrNone) return kNewtRefUnbind;
915    }
916
917    r = NewtMakeArray(klass, xlen);
918    NcAddArraySlot(nsof->precedents, r);
919
920    if (NewtRefIsNotNIL(r))
921    {
922        newtRef *   slots;
923        int32_t i;
924
925        slots = NewtRefToSlots(r);
926
927        for (i = 0; i < xlen; i++)
928        {
929            slots[i] = NSOFReadNSOF(nsof);
930            if (nsof->lastErr != kNErrNone) break;
931        }
932    }
933
934    return r;
935}
936
937
938/*------------------------------------------------------------------------*/
939/** NSOFバッファを読込んでフレームオブジェクトに変換する
940 *
941 * @param nsof      [i/o]NSOFバッファ
942 *
943 * @return          フレームオブジェクト
944 */
945
946newtRef NSOFReadFrame(nsof_stream_t * nsof)
947{
948    newtRefVar  map;
949    newtRefVar  r;
950    newtRef *   slots;
951    int32_t     xlen;
952    int32_t     i;
953
954    xlen = NSOFReadXlong(nsof);
955
956    if (xlen == 0)
957        return NcMakeFrame();
958
959    map = NewtMakeMap(kNewtRefNIL, xlen, NULL);
960    r = NewtMakeFrame(map, xlen);
961    NcAddArraySlot(nsof->precedents, r);
962
963    slots = NewtRefToSlots(map);
964
965    for (i = 1; i <= xlen; i++)
966    {
967        slots[i] = NSOFReadNSOF(nsof);
968        if (nsof->lastErr != kNErrNone) return kNewtRefUnbind;
969    }
970
971    slots = NewtRefToSlots(r);
972
973    for (i = 0; i < xlen; i++)
974    {
975        slots[i] = NSOFReadNSOF(nsof);
976        if (nsof->lastErr != kNErrNone) break;
977    }
978
979    return r;
980}
981
982
983/*------------------------------------------------------------------------*/
984/** NSOFバッファを読込んでシンボルオブジェクトに変換する
985 *
986 * @param nsof      [i/o]NSOFバッファ
987 *
988 * @return          シンボルオブジェクト
989 */
990
991newtRef NSOFReadSymbol(nsof_stream_t * nsof)
992{
993    newtRefVar  r = kNewtRefUnbind;
994    int32_t     xlen;
995    char *      name;
996
997    xlen = NSOFReadXlong(nsof);
998    name = malloc(xlen + 1);
999
1000    if (name)
1001    {
1002        memcpy(name, nsof->data + nsof->offset, xlen);
1003        name[xlen] = '\0';
1004
1005#ifdef HAVE_LIBICONV
1006        {
1007            char *  buff;
1008
1009            buff = NewtIconv(nsof->cd.from.macroman, name, xlen + 1, NULL);
1010
1011            if (buff)
1012            {   // 変換された
1013                r = NewtMakeSymbol(buff);
1014                free(buff);
1015            }
1016        }
1017#endif /* HAVE_LIBICONV */
1018
1019        if (r == kNewtRefUnbind)
1020            r = NewtMakeSymbol(name);
1021
1022        free(name);
1023    }
1024
1025    nsof->offset += xlen;
1026
1027    return r;
1028}
1029
1030
1031#ifdef __NAMED_MAGIC_POINTER__
1032/*------------------------------------------------------------------------*/
1033/** NSOFバッファを読込んで名前付マジックポインタに変換する
1034 *
1035 * @param nsof      [i/o]NSOFバッファ
1036 *
1037 * @return          名前付マジックポインタ
1038 */
1039
1040newtRef NSOFReadNamedMP(nsof_stream_t * nsof)
1041{
1042    newtRefVar  r;
1043
1044    r = NSOFReadSymbol(nsof);
1045
1046    if (NewtRefIsNotNIL(r))
1047    {
1048        if (NSOFIsNOS(nsof->verno))
1049        {
1050            nsof->lastErr = kNErrNSOFRead;
1051            // とりあえずシンボルのまま
1052        }
1053        else
1054        {
1055            r = NewtSymbolToMP(r);
1056        }
1057    }
1058
1059    return r;
1060}
1061#endif /* __NAMED_MAGIC_POINTER__ */
1062
1063
1064/*------------------------------------------------------------------------*/
1065/** NSOFバッファを読込んでフレームオブジェクト(smallRect)に変換する
1066 *
1067 * @param nsof      [i/o]NSOFバッファ
1068 *
1069 * @return          フレームオブジェクト(smallRect)
1070 */
1071
1072newtRef NSOFReadSmallRect(nsof_stream_t * nsof)
1073{
1074    newtRefVar  r;
1075
1076    r = NcMakeFrame();
1077    // 将来は map を共有すること
1078
1079    NcSetSlot(r, NSSYM(top), NewtMakeInteger(NSOFReadByte(nsof)));
1080    NcSetSlot(r, NSSYM(left), NewtMakeInteger(NSOFReadByte(nsof)));
1081    NcSetSlot(r, NSSYM(bottom), NewtMakeInteger(NSOFReadByte(nsof)));
1082    NcSetSlot(r, NSSYM(right), NewtMakeInteger(NSOFReadByte(nsof)));
1083
1084    return r;
1085}
1086
1087
1088/*------------------------------------------------------------------------*/
1089/** NSOFバイナリオブジェクトを読込んでオブジェクトに変換する
1090 *
1091 * @param nsof      [i/o]NSOFバッファ
1092 *
1093 * @return          オブジェクト
1094 */
1095
1096newtRef NSOFReadNSOF(nsof_stream_t * nsof)
1097{
1098    newtRefVar  r = kNewtRefUnbind;
1099    int32_t     xlen;
1100    int         type;
1101
1102    type = NSOFReadByte(nsof);
1103
1104    switch (type)
1105    {
1106        case kNSOFImmediate:
1107            r = (newtRef)NSOFReadXlong(nsof);
1108            break;
1109
1110        case kNSOFCharacter:
1111            r = NewtMakeCharacter(NSOFReadByte(nsof));
1112            break;
1113
1114        case kNSOFUnicodeCharacter:
1115            r = NewtMakeCharacter((uint32_t)NSOFReadByte(nsof) << 8 | NSOFReadByte(nsof));
1116            break;
1117
1118        case kNSOFBinaryObject:
1119        case kNSOFString:
1120            r = NSOFReadBinary(nsof, type);
1121            NcAddArraySlot(nsof->precedents, r);
1122            break;
1123
1124        case kNSOFArray:
1125        case kNSOFPlainArray:
1126            r = NSOFReadArray(nsof, type);
1127            break;
1128
1129        case kNSOFFrame:
1130            r = NSOFReadFrame(nsof);
1131            break;
1132
1133        case kNSOFSymbol:
1134            r = NSOFReadSymbol(nsof);
1135            NcAddArraySlot(nsof->precedents, r);
1136            break;
1137
1138        case