Unnamed Fossil Project

Check-in [fb3d7efd70]
Login

Check-in [fb3d7efd70]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:updated
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fb3d7efd70d6971128851b42da072f10436e650c
User & Date: monster 2012-07-24 17:23:02.606
Context
2012-07-24
17:26
updated check-in: ace7839bf1 user: monster tags: trunk
17:23
updated check-in: fb3d7efd70 user: monster tags: trunk
2012-07-23
07:39
CGI support check-in: c9b15f33ab user: monster tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to aes.hc.
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

*/

#ifndef C_once_88F44E4C_C507_47B8_A162_CBEC13D572DA
#define C_once_88F44E4C_C507_47B8_A162_CBEC13D572DA

#ifdef _LIBYOYO
#define _YOYO_AES_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"
#include "sha2.hc"

typedef struct _YOYO_AES
  {
    int nr;
    uint_t *rk;
    uint_t rawk[68];
  } YOYO_AES;

void Aes_Destruct(YOYO_AES *ctx)
#ifdef _YOYO_AES_BUILTIN
  {
    __Destruct(ctx);
  }
#endif
  ;

#ifdef _YOYO_AES_BUILTIN

  static byte_t YOYO_AES_FSb[256] =
    {
      0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
      0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
      0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
      0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
      0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
      0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,







|







|




|

|
|






|

|







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

*/

#ifndef C_once_88F44E4C_C507_47B8_A162_CBEC13D572DA
#define C_once_88F44E4C_C507_47B8_A162_CBEC13D572DA

#ifdef _LIBYOYO
#define _YO_AES_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"
#include "sha2.hc"

typedef struct _YO_AES
  {
    int nr;
    uint_t *rk;
    uint_t rawk[68];
  } YO_AES;

void Aes_Destruct(YO_AES *ctx)
#ifdef _YO_AES_BUILTIN
  {
    __Destruct(ctx);
  }
#endif
  ;

#ifdef _YO_AES_BUILTIN

  static byte_t YO_AES_FSb[256] =
    {
      0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
      0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
      0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
      0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
      0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
      0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
      0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
      0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
      0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
      0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
      0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
    };

  static uint_t YOYO_AES_FT0[256] =
    {
      0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
      0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
      0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
      0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
      0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
      0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,







|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
      0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
      0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
      0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
      0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
      0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
    };

  static uint_t YO_AES_FT0[256] =
    {
      0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
      0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
      0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
      0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
      0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
      0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
      0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
      0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
      0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
      0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
      0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
    };

  static uint_t YOYO_AES_FT1[256] =
    {
      0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
      0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
      0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
      0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
      0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
      0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,







|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
      0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
      0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
      0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
      0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
      0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
    };

  static uint_t YO_AES_FT1[256] =
    {
      0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
      0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
      0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
      0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
      0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
      0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
      0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
      0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
      0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
      0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
      0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a
    };

  static uint_t YOYO_AES_FT2[256] =
    {
      0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
      0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
      0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
      0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
      0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
      0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,







|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
      0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
      0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
      0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
      0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
      0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a
    };

  static uint_t YO_AES_FT2[256] =
    {
      0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
      0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
      0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
      0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
      0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
      0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
      0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
      0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
      0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
      0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
      0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16
    };

  static uint_t YOYO_AES_FT3[256] =
    {
      0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
      0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
      0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
      0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
      0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
      0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,







|







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
      0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
      0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
      0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
      0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
      0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16
    };

  static uint_t YO_AES_FT3[256] =
    {
      0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
      0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
      0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
      0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
      0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
      0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
      0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
      0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
      0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
      0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
      0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616
    };

  static byte_t YOYO_AES_RSb[256] =
    {
      0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
      0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
      0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
      0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
      0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
      0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,







|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
      0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
      0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
      0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
      0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
      0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616
    };

  static byte_t YO_AES_RSb[256] =
    {
      0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
      0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
      0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
      0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
      0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
      0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
      0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
      0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
      0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
      0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
      0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
    };

  static uint_t YOYO_AES_RT0[256] =
    {
      0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
      0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
      0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
      0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5,
      0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
      0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,







|







418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
      0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
      0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
      0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
      0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
      0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
    };

  static uint_t YO_AES_RT0[256] =
    {
      0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a,
      0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b,
      0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
      0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5,
      0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
      0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
      0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
      0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2,
      0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff,
      0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
      0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
    };

  static uint_t YOYO_AES_RT1[256] =
    {
      0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96,
      0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x03e34b93,
      0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525,
      0xd7e54ffc, 0xcb2ac5d7, 0x44352680, 0xa362b58f,
      0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
      0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6,







|







486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
      0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
      0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2,
      0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff,
      0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
      0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
    };

  static uint_t YO_AES_RT1[256] =
    {
      0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96,
      0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x03e34b93,
      0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525,
      0xd7e54ffc, 0xcb2ac5d7, 0x44352680, 0xa362b58f,
      0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
      0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6,
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
      0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
      0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f,
      0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41,
      0x01a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490,
      0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042
    };

  static uint_t YOYO_AES_RT2[256] =
    {
      0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e,
      0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303,
      0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c,
      0xe54ffcd7, 0x2ac5d7cb, 0x35268044, 0x62b58fa3,
      0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
      0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9,







|







554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
      0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
      0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f,
      0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41,
      0x01a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490,
      0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042
    };

  static uint_t YO_AES_RT2[256] =
    {
      0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e,
      0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303,
      0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c,
      0xe54ffcd7, 0x2ac5d7cb, 0x35268044, 0x62b58fa3,
      0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
      0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9,
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
      0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
      0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40,
      0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195,
      0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1,
      0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257
    };

  static uint_t YOYO_AES_RT3[256] =
    {
      0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27,
      0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3,
      0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02,
      0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362,
      0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
      0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3,







|







622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
      0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
      0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40,
      0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195,
      0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1,
      0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257
    };

  static uint_t YO_AES_RT3[256] =
    {
      0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27,
      0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3,
      0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02,
      0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362,
      0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
      0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3,
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
      0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
      0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3,
      0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d,
      0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156,
      0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8
    };

  static uint_t YOYO_AES_RCON[10] =
    {
      0x00000001, 0x00000002, 0x00000004, 0x00000008,
      0x00000010, 0x00000020, 0x00000040, 0x00000080,
      0x0000001b, 0x00000036
    };

#endif


#if defined _X86 || defined __i386 || defined __x86_64
  #define Aes_Internal_Encode memcpy
  #define Aes_Internal_Decode memcpy
#else
  void Aes_Internal_Encode(byte_t *output, uint_t *input, uint_t len)
  #ifdef _YOYO_AES_BUILTIN
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4)
        {
          output[j]   = (byte_t)(input[i] & 0xff);
          output[j+1] = (byte_t)((input[i] >> 8) & 0xff);
          output[j+2] = (byte_t)((input[i] >> 16) & 0xff);
          output[j+3] = (byte_t)((input[i] >> 24) & 0xff);
        }
    }
  #endif
    ;

  void Aes_Internal_Decode(uint_t *output, byte_t *input, uint_t len)
  #ifdef _YOYO_AES_BUILTIN
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4)
        output[i] = ((uint_t)input[j]) | (((uint_t)input[j+1]) << 8) |
          (((uint_t)input[j+2]) << 16) | (((uint_t)input[j+3]) << 24);
    }
  #endif
    ;

#endif

void *Aes_Init_Encipher_Static(YOYO_AES *ctx, void *key, int key_len_bits)
#ifdef _YOYO_AES_BUILTIN
  {
    int i;
    uint_t *RK;

    switch(key_len_bits)
      {
        case 128: ctx->nr = 10; break;
        case 192: ctx->nr = 12; break;
        case 256: ctx->nr = 14; break;
        default:
        __Raise_Format(YOYO_ERROR_UNSUPPORTED,("unsupported key length %d bit",key_len_bits));
      }

    RK = ctx->rk = ctx->rawk;
    Aes_Internal_Decode(RK,key,key_len_bits/8);

    switch( ctx->nr )
      {
        case 10:
          for( i = 0; i < 10; i++, RK += 4 )
            {
              RK[4]  = RK[0] ^ YOYO_AES_RCON[i] ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[3] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[3] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[3] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[3]       ) & 0x0ff ] << 24 );

              RK[5]  = RK[1] ^ RK[4];
              RK[6]  = RK[2] ^ RK[5];
              RK[7]  = RK[3] ^ RK[6];
            }
          break;

        case 12:
          for( i = 0; i < 8; i++, RK += 6 )
            {
              RK[6]  = RK[0] ^ YOYO_AES_RCON[i] ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[5] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[5] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[5] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[5]       ) & 0x0ff ] << 24 );

              RK[7]  = RK[1] ^ RK[6];
              RK[8]  = RK[2] ^ RK[7];
              RK[9]  = RK[3] ^ RK[8];
              RK[10] = RK[4] ^ RK[9];
              RK[11] = RK[5] ^ RK[10];
            }
          break;

        case 14:
          for( i = 0; i < 7; i++, RK += 8 )
            {
              RK[8]  = RK[0] ^ YOYO_AES_RCON[i] ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[7] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[7] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[7] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[7]       ) & 0x0ff ] << 24 );

              RK[9]  = RK[1] ^ RK[8];
              RK[10] = RK[2] ^ RK[9];
              RK[11] = RK[3] ^ RK[10];

              RK[12] = RK[4] ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[11]       ) & 0x0ff ]       ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[11] >>  8 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[11] >> 16 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YOYO_AES_FSb[ ( RK[11] >> 24 ) & 0x0ff ] << 24 );

              RK[13] = RK[5] ^ RK[12];
              RK[14] = RK[6] ^ RK[13];
              RK[15] = RK[7] ^ RK[14];
            }
          break;

        default:
          break;
      }

    return ctx;
  }
#endif
  ;

void *Aes_Init_Decipher_Static(YOYO_AES *ctx, void *key, int key_len_bits)
#ifdef _YOYO_AES_BUILTIN
  {
    int i,j;
    uint_t *RK, *SK;
    YOYO_AES cty = { 0, 0, {0} };
    Aes_Init_Encipher_Static(&cty,key,key_len_bits);
    RK = ctx->rk = ctx->rawk;
    ctx->nr = cty.nr;
    SK = cty.rk + cty.nr * 4;

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
    {
        for( j = 0; j < 4; j++, SK++ )
        {
            *RK++ = YOYO_AES_RT0[ YOYO_AES_FSb[ ( *SK       ) & 0x0ff ] ] ^
                    YOYO_AES_RT1[ YOYO_AES_FSb[ ( *SK >>  8 ) & 0x0ff ] ] ^
                    YOYO_AES_RT2[ YOYO_AES_FSb[ ( *SK >> 16 ) & 0x0ff ] ] ^
                    YOYO_AES_RT3[ YOYO_AES_FSb[ ( *SK >> 24 ) & 0x0ff ] ];
        }
    }

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    memset( &cty, 0, sizeof(cty) );
    return ctx;
  }
#endif
  ;

#define FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
  { \
    X0 = *RK++ ^ YOYO_AES_FT0[ ( Y0       ) & 0x0ff ] ^\
                 YOYO_AES_FT1[ ( Y1 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_FT2[ ( Y2 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_FT3[ ( Y3 >> 24 ) & 0x0ff ]; \
\
    X1 = *RK++ ^ YOYO_AES_FT0[ ( Y1       ) & 0x0ff ] ^\
                 YOYO_AES_FT1[ ( Y2 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_FT2[ ( Y3 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_FT3[ ( Y0 >> 24 ) & 0x0ff ]; \
\
    X2 = *RK++ ^ YOYO_AES_FT0[ ( Y2       ) & 0x0ff ] ^\
                 YOYO_AES_FT1[ ( Y3 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_FT2[ ( Y0 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_FT3[ ( Y1 >> 24 ) & 0x0ff ]; \
\
    X3 = *RK++ ^ YOYO_AES_FT0[ ( Y3       ) & 0x0ff ] ^\
                 YOYO_AES_FT1[ ( Y0 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_FT2[ ( Y1 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_FT3[ ( Y2 >> 24 ) & 0x0ff ]; \
  }

void Aes_Encrypt16( YOYO_AES *ctx, void *block16 )
#ifdef _YOYO_AES_BUILTIN
  {
    int i;
    uint_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
    RK = ctx->rk;

    X0 = Four_To_Unsigned((byte_t*)block16+0)  ^ *RK++;
    X1 = Four_To_Unsigned((byte_t*)block16+4)  ^ *RK++;
    X2 = Four_To_Unsigned((byte_t*)block16+8)  ^ *RK++;
    X3 = Four_To_Unsigned((byte_t*)block16+12) ^ *RK++;

    /* AES_ENCRYPT */
    for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
      {
        FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
        FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
      }

    FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );

    X0 = *RK++ ^ \
            ( (uint_t) YOYO_AES_FSb[ ( Y0       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y1 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y2 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y3 >> 24 ) & 0x0ff ] << 24 );

    X1 = *RK++ ^ \
            ( (uint_t) YOYO_AES_FSb[ ( Y1       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y2 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y3 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y0 >> 24 ) & 0x0ff ] << 24 );

    X2 = *RK++ ^ \
            ( (uint_t) YOYO_AES_FSb[ ( Y2       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y3 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y0 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y1 >> 24 ) & 0x0ff ] << 24 );

    X3 = *RK++ ^ \
            ( (uint_t) YOYO_AES_FSb[ ( Y3       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y0 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y1 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_FSb[ ( Y2 >> 24 ) & 0x0ff ] << 24 );

    Unsigned_To_Four( X0, (byte_t*)block16+0 );
    Unsigned_To_Four( X1, (byte_t*)block16+4 );
    Unsigned_To_Four( X2, (byte_t*)block16+8 );
    Unsigned_To_Four( X3, (byte_t*)block16+12 );
  }
#endif
  ;

#undef FROUND

#define RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
  { \
    X0 = *RK++ ^ YOYO_AES_RT0[ ( Y0       ) & 0x0ff ] ^\
                 YOYO_AES_RT1[ ( Y3 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_RT2[ ( Y2 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_RT3[ ( Y1 >> 24 ) & 0x0ff ]; \
\
    X1 = *RK++ ^ YOYO_AES_RT0[ ( Y1       ) & 0x0ff ] ^\
                 YOYO_AES_RT1[ ( Y0 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_RT2[ ( Y3 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_RT3[ ( Y2 >> 24 ) & 0x0ff ]; \
\
    X2 = *RK++ ^ YOYO_AES_RT0[ ( Y2       ) & 0x0ff ] ^\
                 YOYO_AES_RT1[ ( Y1 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_RT2[ ( Y0 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_RT3[ ( Y3 >> 24 ) & 0x0ff ]; \
\
    X3 = *RK++ ^ YOYO_AES_RT0[ ( Y3       ) & 0x0ff ] ^\
                 YOYO_AES_RT1[ ( Y2 >>  8 ) & 0x0ff ] ^\
                 YOYO_AES_RT2[ ( Y1 >> 16 ) & 0x0ff ] ^\
                 YOYO_AES_RT3[ ( Y0 >> 24 ) & 0x0ff ]; \
  }

void Aes_Decrypt16( YOYO_AES *ctx, void *block16 )
#ifdef _YOYO_AES_BUILTIN
  {
    int i;
    uint_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
    RK = ctx->rk;

    X0 = Four_To_Unsigned((byte_t*)block16+0)  ^ *RK++;
    X1 = Four_To_Unsigned((byte_t*)block16+4)  ^ *RK++;
    X2 = Four_To_Unsigned((byte_t*)block16+8)  ^ *RK++;
    X3 = Four_To_Unsigned((byte_t*)block16+12) ^ *RK++;

    for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
      {
        RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
        RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
      }

    RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );

    X0 = *RK++ ^ \
            ( (uint_t) YOYO_AES_RSb[ ( Y0       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y3 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y2 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y1 >> 24 ) & 0x0ff ] << 24 );

    X1 = *RK++ ^ \
            ( (uint_t) YOYO_AES_RSb[ ( Y1       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y0 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y3 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y2 >> 24 ) & 0x0ff ] << 24 );

    X2 = *RK++ ^ \
            ( (uint_t) YOYO_AES_RSb[ ( Y2       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y1 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y0 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y3 >> 24 ) & 0x0ff ] << 24 );

    X3 = *RK++ ^ \
            ( (uint_t) YOYO_AES_RSb[ ( Y3       ) & 0x0ff ]       ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y2 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y1 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YOYO_AES_RSb[ ( Y0 >> 24 ) & 0x0ff ] << 24 );

    Unsigned_To_Four( X0, (byte_t*)block16+0 );
    Unsigned_To_Four( X1, (byte_t*)block16+4 );
    Unsigned_To_Four( X2, (byte_t*)block16+8 );
    Unsigned_To_Four( X3, (byte_t*)block16+12 );
  }
#endif
  ;

#undef RROUND

void *Aes_Init_Encipher(void *key,int key_len)
#ifdef _YOYO_AES_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] =
      { {0},
        {Oj_Destruct_OjMID,  Aes_Destruct},
        {Oj_Encrypt16_OjMID, Aes_Encrypt16},
        {0}};

    YOYO_AES *ctx = __Object(sizeof(YOYO_AES),funcs);
    return Aes_Init_Encipher_Static(ctx,key,key_len);
  }
#endif
  ;

void *Aes_Encipher(char *S)
#ifdef _YOYO_AES_BUILTIN
  {
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    return Aes_Init_Encipher(key,256);
  }
#endif
  ;


void *Aes_Init_Decipher(void *key,int key_len)
#ifdef _YOYO_AES_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] =
      { {0},
        {Oj_Destruct_OjMID,  Aes_Destruct},
        {Oj_Decrypt16_OjMID, Aes_Decrypt16},
        {0}};

    YOYO_AES *ctx = __Object(sizeof(YOYO_AES),funcs);
    return Aes_Init_Decipher_Static(ctx,key,key_len);
  }
#endif
  ;

void *Aes_Decipher(char *S)
#ifdef _YOYO_AES_BUILTIN
  {
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    return Aes_Init_Decipher(key,256);
  }
#endif
  ;

void Aes_Encrypt(char *data, int len, char *S)
#ifdef _YOYO_AES_BUILTIN
  {
    int i;
    YOYO_AES actx = {0,0,{0}};
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    Aes_Init_Encipher_Static(&actx,key,256);

    for ( i = 0; i < len && len-i >= 16 ; i += 16 )
      {
        Aes_Encrypt16(&actx,data+i);
      }
  }
#endif
  ;

void Aes_Decrypt(char *data, int len, char *S)
#ifdef _YOYO_AES_BUILTIN
  {
    int i;
    YOYO_AES actx = {0,0,{0}};
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    Aes_Init_Decipher_Static(&actx,key,256);

    for ( i = 0; i < len && len-i >= 16 ; i += 16 )
      {
        Aes_Decrypt16(&actx,data+i);







|














|















|












|
|










|










|
|
|
|
|










|
|
|
|
|












|
|
|
|
|






|
|
|
|
















|
|



|














|
|
|
|
















|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|


|
|




















|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|













|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|


|
|



















|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|












|

|





|






|










|

|





|






|









|


|













|


|







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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
      0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
      0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3,
      0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d,
      0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156,
      0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8
    };

  static uint_t YO_AES_RCON[10] =
    {
      0x00000001, 0x00000002, 0x00000004, 0x00000008,
      0x00000010, 0x00000020, 0x00000040, 0x00000080,
      0x0000001b, 0x00000036
    };

#endif


#if defined _X86 || defined __i386 || defined __x86_64
  #define Aes_Internal_Encode memcpy
  #define Aes_Internal_Decode memcpy
#else
  void Aes_Internal_Encode(byte_t *output, uint_t *input, uint_t len)
  #ifdef _YO_AES_BUILTIN
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4)
        {
          output[j]   = (byte_t)(input[i] & 0xff);
          output[j+1] = (byte_t)((input[i] >> 8) & 0xff);
          output[j+2] = (byte_t)((input[i] >> 16) & 0xff);
          output[j+3] = (byte_t)((input[i] >> 24) & 0xff);
        }
    }
  #endif
    ;

  void Aes_Internal_Decode(uint_t *output, byte_t *input, uint_t len)
  #ifdef _YO_AES_BUILTIN
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4)
        output[i] = ((uint_t)input[j]) | (((uint_t)input[j+1]) << 8) |
          (((uint_t)input[j+2]) << 16) | (((uint_t)input[j+3]) << 24);
    }
  #endif
    ;

#endif

void *Aes_Init_Encipher_Static(YO_AES *ctx, void *key, int key_len_bits)
#ifdef _YO_AES_BUILTIN
  {
    int i;
    uint_t *RK;

    switch(key_len_bits)
      {
        case 128: ctx->nr = 10; break;
        case 192: ctx->nr = 12; break;
        case 256: ctx->nr = 14; break;
        default:
        __Raise_Format(YO_ERROR_UNSUPPORTED,("unsupported key length %d bit",key_len_bits));
      }

    RK = ctx->rk = ctx->rawk;
    Aes_Internal_Decode(RK,key,key_len_bits/8);

    switch( ctx->nr )
      {
        case 10:
          for( i = 0; i < 10; i++, RK += 4 )
            {
              RK[4]  = RK[0] ^ YO_AES_RCON[i] ^
              ( (uint_t) YO_AES_FSb[ ( RK[3] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[3] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[3] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[3]       ) & 0x0ff ] << 24 );

              RK[5]  = RK[1] ^ RK[4];
              RK[6]  = RK[2] ^ RK[5];
              RK[7]  = RK[3] ^ RK[6];
            }
          break;

        case 12:
          for( i = 0; i < 8; i++, RK += 6 )
            {
              RK[6]  = RK[0] ^ YO_AES_RCON[i] ^
              ( (uint_t) YO_AES_FSb[ ( RK[5] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[5] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[5] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[5]       ) & 0x0ff ] << 24 );

              RK[7]  = RK[1] ^ RK[6];
              RK[8]  = RK[2] ^ RK[7];
              RK[9]  = RK[3] ^ RK[8];
              RK[10] = RK[4] ^ RK[9];
              RK[11] = RK[5] ^ RK[10];
            }
          break;

        case 14:
          for( i = 0; i < 7; i++, RK += 8 )
            {
              RK[8]  = RK[0] ^ YO_AES_RCON[i] ^
              ( (uint_t) YO_AES_FSb[ ( RK[7] >>  8 ) & 0x0ff ]       ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[7] >> 16 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[7] >> 24 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[7]       ) & 0x0ff ] << 24 );

              RK[9]  = RK[1] ^ RK[8];
              RK[10] = RK[2] ^ RK[9];
              RK[11] = RK[3] ^ RK[10];

              RK[12] = RK[4] ^
              ( (uint_t) YO_AES_FSb[ ( RK[11]       ) & 0x0ff ]       ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[11] >>  8 ) & 0x0ff ] <<  8 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[11] >> 16 ) & 0x0ff ] << 16 ) ^
              ( (uint_t) YO_AES_FSb[ ( RK[11] >> 24 ) & 0x0ff ] << 24 );

              RK[13] = RK[5] ^ RK[12];
              RK[14] = RK[6] ^ RK[13];
              RK[15] = RK[7] ^ RK[14];
            }
          break;

        default:
          break;
      }

    return ctx;
  }
#endif
  ;

void *Aes_Init_Decipher_Static(YO_AES *ctx, void *key, int key_len_bits)
#ifdef _YO_AES_BUILTIN
  {
    int i,j;
    uint_t *RK, *SK;
    YO_AES cty = { 0, 0, {0} };
    Aes_Init_Encipher_Static(&cty,key,key_len_bits);
    RK = ctx->rk = ctx->rawk;
    ctx->nr = cty.nr;
    SK = cty.rk + cty.nr * 4;

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
    {
        for( j = 0; j < 4; j++, SK++ )
        {
            *RK++ = YO_AES_RT0[ YO_AES_FSb[ ( *SK       ) & 0x0ff ] ] ^
                    YO_AES_RT1[ YO_AES_FSb[ ( *SK >>  8 ) & 0x0ff ] ] ^
                    YO_AES_RT2[ YO_AES_FSb[ ( *SK >> 16 ) & 0x0ff ] ] ^
                    YO_AES_RT3[ YO_AES_FSb[ ( *SK >> 24 ) & 0x0ff ] ];
        }
    }

    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;
    *RK++ = *SK++;

    memset( &cty, 0, sizeof(cty) );
    return ctx;
  }
#endif
  ;

#define FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
  { \
    X0 = *RK++ ^ YO_AES_FT0[ ( Y0       ) & 0x0ff ] ^\
                 YO_AES_FT1[ ( Y1 >>  8 ) & 0x0ff ] ^\
                 YO_AES_FT2[ ( Y2 >> 16 ) & 0x0ff ] ^\
                 YO_AES_FT3[ ( Y3 >> 24 ) & 0x0ff ]; \
\
    X1 = *RK++ ^ YO_AES_FT0[ ( Y1       ) & 0x0ff ] ^\
                 YO_AES_FT1[ ( Y2 >>  8 ) & 0x0ff ] ^\
                 YO_AES_FT2[ ( Y3 >> 16 ) & 0x0ff ] ^\
                 YO_AES_FT3[ ( Y0 >> 24 ) & 0x0ff ]; \
\
    X2 = *RK++ ^ YO_AES_FT0[ ( Y2       ) & 0x0ff ] ^\
                 YO_AES_FT1[ ( Y3 >>  8 ) & 0x0ff ] ^\
                 YO_AES_FT2[ ( Y0 >> 16 ) & 0x0ff ] ^\
                 YO_AES_FT3[ ( Y1 >> 24 ) & 0x0ff ]; \
\
    X3 = *RK++ ^ YO_AES_FT0[ ( Y3       ) & 0x0ff ] ^\
                 YO_AES_FT1[ ( Y0 >>  8 ) & 0x0ff ] ^\
                 YO_AES_FT2[ ( Y1 >> 16 ) & 0x0ff ] ^\
                 YO_AES_FT3[ ( Y2 >> 24 ) & 0x0ff ]; \
  }

void Aes_Encrypt16( YO_AES *ctx, void *block16 )
#ifdef _YO_AES_BUILTIN
  {
    int i;
    uint_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
    RK = ctx->rk;

    X0 = Four_To_Unsigned((byte_t*)block16+0)  ^ *RK++;
    X1 = Four_To_Unsigned((byte_t*)block16+4)  ^ *RK++;
    X2 = Four_To_Unsigned((byte_t*)block16+8)  ^ *RK++;
    X3 = Four_To_Unsigned((byte_t*)block16+12) ^ *RK++;

    /* AES_ENCRYPT */
    for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
      {
        FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
        FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
      }

    FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );

    X0 = *RK++ ^ \
            ( (uint_t) YO_AES_FSb[ ( Y0       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_FSb[ ( Y1 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y2 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y3 >> 24 ) & 0x0ff ] << 24 );

    X1 = *RK++ ^ \
            ( (uint_t) YO_AES_FSb[ ( Y1       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_FSb[ ( Y2 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y3 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y0 >> 24 ) & 0x0ff ] << 24 );

    X2 = *RK++ ^ \
            ( (uint_t) YO_AES_FSb[ ( Y2       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_FSb[ ( Y3 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y0 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y1 >> 24 ) & 0x0ff ] << 24 );

    X3 = *RK++ ^ \
            ( (uint_t) YO_AES_FSb[ ( Y3       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_FSb[ ( Y0 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y1 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_FSb[ ( Y2 >> 24 ) & 0x0ff ] << 24 );

    Unsigned_To_Four( X0, (byte_t*)block16+0 );
    Unsigned_To_Four( X1, (byte_t*)block16+4 );
    Unsigned_To_Four( X2, (byte_t*)block16+8 );
    Unsigned_To_Four( X3, (byte_t*)block16+12 );
  }
#endif
  ;

#undef FROUND

#define RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
  { \
    X0 = *RK++ ^ YO_AES_RT0[ ( Y0       ) & 0x0ff ] ^\
                 YO_AES_RT1[ ( Y3 >>  8 ) & 0x0ff ] ^\
                 YO_AES_RT2[ ( Y2 >> 16 ) & 0x0ff ] ^\
                 YO_AES_RT3[ ( Y1 >> 24 ) & 0x0ff ]; \
\
    X1 = *RK++ ^ YO_AES_RT0[ ( Y1       ) & 0x0ff ] ^\
                 YO_AES_RT1[ ( Y0 >>  8 ) & 0x0ff ] ^\
                 YO_AES_RT2[ ( Y3 >> 16 ) & 0x0ff ] ^\
                 YO_AES_RT3[ ( Y2 >> 24 ) & 0x0ff ]; \
\
    X2 = *RK++ ^ YO_AES_RT0[ ( Y2       ) & 0x0ff ] ^\
                 YO_AES_RT1[ ( Y1 >>  8 ) & 0x0ff ] ^\
                 YO_AES_RT2[ ( Y0 >> 16 ) & 0x0ff ] ^\
                 YO_AES_RT3[ ( Y3 >> 24 ) & 0x0ff ]; \
\
    X3 = *RK++ ^ YO_AES_RT0[ ( Y3       ) & 0x0ff ] ^\
                 YO_AES_RT1[ ( Y2 >>  8 ) & 0x0ff ] ^\
                 YO_AES_RT2[ ( Y1 >> 16 ) & 0x0ff ] ^\
                 YO_AES_RT3[ ( Y0 >> 24 ) & 0x0ff ]; \
  }

void Aes_Decrypt16( YO_AES *ctx, void *block16 )
#ifdef _YO_AES_BUILTIN
  {
    int i;
    uint_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
    RK = ctx->rk;

    X0 = Four_To_Unsigned((byte_t*)block16+0)  ^ *RK++;
    X1 = Four_To_Unsigned((byte_t*)block16+4)  ^ *RK++;
    X2 = Four_To_Unsigned((byte_t*)block16+8)  ^ *RK++;
    X3 = Four_To_Unsigned((byte_t*)block16+12) ^ *RK++;

    for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
      {
        RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
        RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
      }

    RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );

    X0 = *RK++ ^ \
            ( (uint_t) YO_AES_RSb[ ( Y0       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_RSb[ ( Y3 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y2 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y1 >> 24 ) & 0x0ff ] << 24 );

    X1 = *RK++ ^ \
            ( (uint_t) YO_AES_RSb[ ( Y1       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_RSb[ ( Y0 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y3 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y2 >> 24 ) & 0x0ff ] << 24 );

    X2 = *RK++ ^ \
            ( (uint_t) YO_AES_RSb[ ( Y2       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_RSb[ ( Y1 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y0 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y3 >> 24 ) & 0x0ff ] << 24 );

    X3 = *RK++ ^ \
            ( (uint_t) YO_AES_RSb[ ( Y3       ) & 0x0ff ]       ) ^
            ( (uint_t) YO_AES_RSb[ ( Y2 >>  8 ) & 0x0ff ] <<  8 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y1 >> 16 ) & 0x0ff ] << 16 ) ^
            ( (uint_t) YO_AES_RSb[ ( Y0 >> 24 ) & 0x0ff ] << 24 );

    Unsigned_To_Four( X0, (byte_t*)block16+0 );
    Unsigned_To_Four( X1, (byte_t*)block16+4 );
    Unsigned_To_Four( X2, (byte_t*)block16+8 );
    Unsigned_To_Four( X3, (byte_t*)block16+12 );
  }
#endif
  ;

#undef RROUND

void *Aes_Init_Encipher(void *key,int key_len)
#ifdef _YO_AES_BUILTIN
  {
    static YO_FUNCTABLE funcs[] =
      { {0},
        {Oj_Destruct_OjMID,  Aes_Destruct},
        {Oj_Encrypt16_OjMID, Aes_Encrypt16},
        {0}};

    YO_AES *ctx = __Object(sizeof(YO_AES),funcs);
    return Aes_Init_Encipher_Static(ctx,key,key_len);
  }
#endif
  ;

void *Aes_Encipher(char *S)
#ifdef _YO_AES_BUILTIN
  {
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    return Aes_Init_Encipher(key,256);
  }
#endif
  ;


void *Aes_Init_Decipher(void *key,int key_len)
#ifdef _YO_AES_BUILTIN
  {
    static YO_FUNCTABLE funcs[] =
      { {0},
        {Oj_Destruct_OjMID,  Aes_Destruct},
        {Oj_Decrypt16_OjMID, Aes_Decrypt16},
        {0}};

    YO_AES *ctx = __Object(sizeof(YO_AES),funcs);
    return Aes_Init_Decipher_Static(ctx,key,key_len);
  }
#endif
  ;

void *Aes_Decipher(char *S)
#ifdef _YO_AES_BUILTIN
  {
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    return Aes_Init_Decipher(key,256);
  }
#endif
  ;

void Aes_Encrypt(char *data, int len, char *S)
#ifdef _YO_AES_BUILTIN
  {
    int i;
    YO_AES actx = {0,0,{0}};
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    Aes_Init_Encipher_Static(&actx,key,256);

    for ( i = 0; i < len && len-i >= 16 ; i += 16 )
      {
        Aes_Encrypt16(&actx,data+i);
      }
  }
#endif
  ;

void Aes_Decrypt(char *data, int len, char *S)
#ifdef _YO_AES_BUILTIN
  {
    int i;
    YO_AES actx = {0,0,{0}};
    byte_t key[32];
    Sha2_Digest_Digest(S,strlen(S),key);
    Aes_Init_Decipher_Static(&actx,key,256);

    for ( i = 0; i < len && len-i >= 16 ; i += 16 )
      {
        Aes_Decrypt16(&actx,data+i);
Changes to array.hc.
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

*/

#ifndef C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B
#define C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B

#ifdef _LIBYOYO
#define _YOYO_ARRAY_BUILTIN
#endif

#include "yoyo.hc"

#ifdef _YOYO_ARRAY_BUILTIN
# define _YOYO_ARRAY_BUILTIN_CODE(Code) Code
# define _YOYO_ARRAY_EXTERN 
#else
# define _YOYO_ARRAY_BUILTIN_CODE(Code)
# define _YOYO_ARRAY_EXTERN extern 
#endif

_YOYO_ARRAY_EXTERN char Oj_Sort_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = ">>>/@" );
_YOYO_ARRAY_EXTERN char Oj_Push_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "$+/@*" );
_YOYO_ARRAY_EXTERN char Oj_Pop_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "$-/@" );
_YOYO_ARRAY_EXTERN char Oj_Pop_Npl_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "`$-/@" );
_YOYO_ARRAY_EXTERN char Oj_Sorted_Insert_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = ">1>/@*" );
_YOYO_ARRAY_EXTERN char Oj_Sorted_Find_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = ">?>/@*" );
_YOYO_ARRAY_EXTERN char Oj_Push_Front_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "+$/@*" );
_YOYO_ARRAY_EXTERN char Oj_Pop_Front_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "-$/@" );
_YOYO_ARRAY_EXTERN char Oj_Pop_Front_Npl_OjMID[] _YOYO_ARRAY_BUILTIN_CODE ( = "`-$/@" );

void Oj_Sort(void *self)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void (*sort)(void *) = Yo_Find_Method_Of(&self,Oj_Sort_OjMID,YO_RAISE_ERROR);
    sort(self);
  }
#endif
  ;

void Oj_Sorted_Insert(void *self, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void (*insert)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Sorted_Insert_OjMID,YO_RAISE_ERROR);
    insert(self,val);
  }
#endif
  ;

void *Oj_Sorted_Find(void *self, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *(*find)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Sorted_Find_OjMID,YO_RAISE_ERROR);
    return find(self,val);
  }
#endif
  ;

void Oj_Push(void *self, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void (*push)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Push_OjMID,YO_RAISE_ERROR);
    push(self,val);
  }
#endif
  ;

void *Oj_Pop(void *self)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Oj_Pop_Npl(void *self)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Npl_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void Oj_Push_Front(void *self, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void (*push)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Push_Front_OjMID,YO_RAISE_ERROR);
    push(self,val);
  }
#endif
  ;

void *Oj_Pop_Front_Npl(void *self)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Front_Npl_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Oj_Pop_Front(void *self)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Front_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Lower_Boundary(void **S, int S_len, void *compare, void *val, int *found)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    typedef int (*Tcmp)(void *,void*);
    int cmp_r = 0;
    void **iS = S;
    void **middle = iS;
    int half;
    int len = S_len;







|




|
|
|

|
|


|
|
|
|
|
|
|
|
|


|








|








|








|








|








|








|








|








|








|







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

*/

#ifndef C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B
#define C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B

#ifdef _LIBYOYO
#define _YO_ARRAY_BUILTIN
#endif

#include "yoyo.hc"

#ifdef _YO_ARRAY_BUILTIN
# define _YO_ARRAY_BUILTIN_CODE(Code) Code
# define _YO_ARRAY_EXTERN 
#else
# define _YO_ARRAY_BUILTIN_CODE(Code)
# define _YO_ARRAY_EXTERN extern 
#endif

_YO_ARRAY_EXTERN char Oj_Sort_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = ">>>/@" );
_YO_ARRAY_EXTERN char Oj_Push_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "$+/@*" );
_YO_ARRAY_EXTERN char Oj_Pop_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "$-/@" );
_YO_ARRAY_EXTERN char Oj_Pop_Npl_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "`$-/@" );
_YO_ARRAY_EXTERN char Oj_Sorted_Insert_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = ">1>/@*" );
_YO_ARRAY_EXTERN char Oj_Sorted_Find_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = ">?>/@*" );
_YO_ARRAY_EXTERN char Oj_Push_Front_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "+$/@*" );
_YO_ARRAY_EXTERN char Oj_Pop_Front_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "-$/@" );
_YO_ARRAY_EXTERN char Oj_Pop_Front_Npl_OjMID[] _YO_ARRAY_BUILTIN_CODE ( = "`-$/@" );

void Oj_Sort(void *self)
#ifdef _YO_ARRAY_BUILTIN
  {
    void (*sort)(void *) = Yo_Find_Method_Of(&self,Oj_Sort_OjMID,YO_RAISE_ERROR);
    sort(self);
  }
#endif
  ;

void Oj_Sorted_Insert(void *self, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    void (*insert)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Sorted_Insert_OjMID,YO_RAISE_ERROR);
    insert(self,val);
  }
#endif
  ;

void *Oj_Sorted_Find(void *self, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *(*find)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Sorted_Find_OjMID,YO_RAISE_ERROR);
    return find(self,val);
  }
#endif
  ;

void Oj_Push(void *self, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    void (*push)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Push_OjMID,YO_RAISE_ERROR);
    push(self,val);
  }
#endif
  ;

void *Oj_Pop(void *self)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Oj_Pop_Npl(void *self)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Npl_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void Oj_Push_Front(void *self, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    void (*push)(void *, void *) = Yo_Find_Method_Of(&self,Oj_Push_Front_OjMID,YO_RAISE_ERROR);
    push(self,val);
  }
#endif
  ;

void *Oj_Pop_Front_Npl(void *self)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Front_Npl_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Oj_Pop_Front(void *self)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *(*pop)(void *) = Yo_Find_Method_Of(&self,Oj_Pop_Front_OjMID,YO_RAISE_ERROR);
    return pop(self);
  }
#endif
  ;

void *Lower_Boundary(void **S, int S_len, void *compare, void *val, int *found)
#ifdef _YO_ARRAY_BUILTIN
  {
    typedef int (*Tcmp)(void *,void*);
    int cmp_r = 0;
    void **iS = S;
    void **middle = iS;
    int half;
    int len = S_len;
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
      
    *found = !cmp_r;
    return iS;
  }
#endif
  ;

typedef struct _YOYO_ARRAY
  {
    void **at;
    int count;
    int capacity;
  } YOYO_ARRAY;

void Array_Del(YOYO_ARRAY *a,int pos,int n)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int i;
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);

    if ( pos < 0 ) pos = a->count + pos;
    if ( n < 0 || pos + n > a->count ) n = a->count-pos;
    if ( pos < 0 || pos+n > a->count ) 
      Yo_Raise(YOYO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);

    if ( destruct )
      for ( i = 0; i < n; ++i )
        destruct((a->at)[i+pos]);
    
    if ( pos != a->count-n )
      memmove(a->at+pos,a->at+(pos+n),(a->count-(pos+n))*sizeof(void*));
    a->count -= n;
  }
#endif
  ;

void *Array_Take_Npl(YOYO_ARRAY *a,int pos)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *Q = 0;
    
    if ( pos < 0 ) pos = a->count + pos;
    if ( pos < 0 || pos >= a->count ) 
      Yo_Raise(YOYO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);

    Q = (a->at)[pos];
    
    if ( pos != a->count-1 )
      memmove(a->at+pos,a->at+(pos+1),(a->count-(pos+1))*sizeof(void*));
    a->count -= 1;
    
    return Q;
  }
#endif
  ;

void *Array_Take(YOYO_ARRAY *a,int pos)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,YO_RAISE_ERROR);
    void *Q = Array_Take_Npl(a,pos);
    
    if ( Q )
      Yo_Pool_Ptr(Q,destruct);
    
    return Q;
  }
#endif
  ;

void Array_Grow(YOYO_ARRAY *a,int require)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int capacity = Min_Pow2(require*sizeof(void*));
    if ( !a->at || a->capacity < capacity )
      {
        a->at = Yo_Realloc_Npl(a->at,capacity);
        a->capacity = capacity;
      }
  }
#endif
  ;
  
void Array_Insert(YOYO_ARRAY *a,int pos,void *p)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( pos < 0 ) pos = a->count + pos + 1;
    if ( pos < 0 || pos > a->count ) 
      {
        void *self = a;
        void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
        if ( destruct ) destruct(p);
        Yo_Raise(YOYO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);
      }
    
    Array_Grow(a,a->count+1);
    if ( pos < a->count )
      memmove(a->at+pos+1,a->at+pos,(a->count-pos)*sizeof(void*));
    a->at[pos] = p;
    ++a->count;
  }
#endif
  ;

void Array_Fill(YOYO_ARRAY *a,int pos,void *p, int count)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int i;
    
    if ( !count ) return;
    else if ( count < 0 || pos < 0 ) 
      Yo_Raise(YOYO_ERROR_INVALID_PARAM,0,__Yo_FILE__,__LINE__);
    
    if ( !a->at || a->count-pos < count )
      {
        Array_Grow(a,a->count-pos+count);
        memset(a->at+pos,0,sizeof(void*)*count);
        a->count = a->count-pos+count;
      }







|




|

|
|








|












|
|





|












|
|













|
|











|
|







|











|
|





|







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
      
    *found = !cmp_r;
    return iS;
  }
#endif
  ;

typedef struct _YO_ARRAY
  {
    void **at;
    int count;
    int capacity;
  } YO_ARRAY;

void Array_Del(YO_ARRAY *a,int pos,int n)
#ifdef _YO_ARRAY_BUILTIN
  {
    int i;
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);

    if ( pos < 0 ) pos = a->count + pos;
    if ( n < 0 || pos + n > a->count ) n = a->count-pos;
    if ( pos < 0 || pos+n > a->count ) 
      Yo_Raise(YO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);

    if ( destruct )
      for ( i = 0; i < n; ++i )
        destruct((a->at)[i+pos]);
    
    if ( pos != a->count-n )
      memmove(a->at+pos,a->at+(pos+n),(a->count-(pos+n))*sizeof(void*));
    a->count -= n;
  }
#endif
  ;

void *Array_Take_Npl(YO_ARRAY *a,int pos)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *Q = 0;
    
    if ( pos < 0 ) pos = a->count + pos;
    if ( pos < 0 || pos >= a->count ) 
      Yo_Raise(YO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);

    Q = (a->at)[pos];
    
    if ( pos != a->count-1 )
      memmove(a->at+pos,a->at+(pos+1),(a->count-(pos+1))*sizeof(void*));
    a->count -= 1;
    
    return Q;
  }
#endif
  ;

void *Array_Take(YO_ARRAY *a,int pos)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,YO_RAISE_ERROR);
    void *Q = Array_Take_Npl(a,pos);
    
    if ( Q )
      Yo_Pool_Ptr(Q,destruct);
    
    return Q;
  }
#endif
  ;

void Array_Grow(YO_ARRAY *a,int require)
#ifdef _YO_ARRAY_BUILTIN
  {
    int capacity = Min_Pow2(require*sizeof(void*));
    if ( !a->at || a->capacity < capacity )
      {
        a->at = Yo_Realloc_Npl(a->at,capacity);
        a->capacity = capacity;
      }
  }
#endif
  ;
  
void Array_Insert(YO_ARRAY *a,int pos,void *p)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( pos < 0 ) pos = a->count + pos + 1;
    if ( pos < 0 || pos > a->count ) 
      {
        void *self = a;
        void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
        if ( destruct ) destruct(p);
        Yo_Raise(YO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);
      }
    
    Array_Grow(a,a->count+1);
    if ( pos < a->count )
      memmove(a->at+pos+1,a->at+pos,(a->count-pos)*sizeof(void*));
    a->at[pos] = p;
    ++a->count;
  }
#endif
  ;

void Array_Fill(YO_ARRAY *a,int pos,void *p, int count)
#ifdef _YO_ARRAY_BUILTIN
  {
    int i;
    
    if ( !count ) return;
    else if ( count < 0 || pos < 0 ) 
      Yo_Raise(YO_ERROR_INVALID_PARAM,0,__Yo_FILE__,__LINE__);
    
    if ( !a->at || a->count-pos < count )
      {
        Array_Grow(a,a->count-pos+count);
        memset(a->at+pos,0,sizeof(void*)*count);
        a->count = a->count-pos+count;
      }
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
          }
        a->at[pos+i] = p;
      }
  }
#endif
  ;

void Array_Set(YOYO_ARRAY *a,int pos,void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);

    if ( pos < 0 ) pos = a->count + pos;
    if ( pos < 0 || pos >= a->count ) 
      {
        if ( destruct ) destruct(val);
        __Raise(YOYO_ERROR_OUT_OF_RANGE,0);
      }
      
    if ( destruct )
      destruct((a->at)[pos]);

    a->at[pos] = val;
  }
#endif
  ;

int Array_Sorted_Lower_Boundary(YOYO_ARRAY *a,void *val,int *found,int except)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *self = a;
    int (*compare)(void *, void *);
    
    if ( !a->count ) 
      {
        *found = 0;
        return 0;
      }
    
    if ( 0 != (compare = Yo_Find_Method_Of(&self,Oj_Compare_Elements_OjMID,0)) )
      {
        void **p = Lower_Boundary(a->at,a->count,compare,val,found);
        return p - a->at;
      }
    else if (except)
      __Raise(YOYO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
    else
      return -1;
      
    return 0;
  }
#endif
  ;

void Array_Sorted_Insert(YOYO_ARRAY *a,void *p)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( !a->count )
      Array_Insert(a,-1,p);
    else
      {
        int found = 0;
        int pos ;
        
        pos = Array_Sorted_Lower_Boundary(a,p,&found,0);
        
        if ( pos < 0 )
          {
            void *self = a;
            void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              destructor(p);
            __Raise(YOYO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
          }
          
        if ( !found )
          Array_Insert(a,pos,p);
        else
          Array_Set(a,pos,p);
      }
  }
#endif
  ;

void *Array_Binary_Find(YOYO_ARRAY *a, void *p)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int found = 0;
    int pos = Array_Sorted_Lower_Boundary(a,p,&found,1);
    return found ? a->at[pos] : 0;
  }
#endif
  ;

#ifdef _YOYO_ARRAY_BUILTIN
int Array_Sort_Qsort_Compare(int (*compare)(void *a,void *b), void **a, void **b)
  {
    return compare(*a,*b);
  }
int (*Array_Sort_Qsort_Compare_Static_Compare)(void *a,void *b) = 0;
int Array_Sort_Qsort_Compare_Static(void **a, void **b)
  {
    return Array_Sort_Qsort_Compare_Static_Compare(*a,*b);
  }
#endif

void Array_Sort(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *self = a;
    void *compare;
    if ( a->at && a->count )
      {
        if ( 0 != (compare = Yo_Find_Method_Of(&self,Oj_Compare_Elements_OjMID,0)) )
          {
          #if !defined __windoze && !defined __NetBSD__ && !defined __linux__
            qsort_r(a->at,a->count,sizeof(void*),compare,(void*)Array_Sort_Qsort_Compare);
          #elif defined __windoze && _MSC_VER > 1400 
            qsort_s(a->at,a->count,sizeof(void*),compare,(void*)Array_Sort_Qsort_Compare);
          #else /* use global variable */
            __Xchg_Interlock
              {
                Array_Sort_Qsort_Compare_Static_Compare = compare;
                qsort(a->at,a->count,sizeof(void*),(void*)Array_Sort_Qsort_Compare_Static);
              }
          #endif
          }
        else
          __Raise(YOYO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
      }
  }
#endif
  ;

#define Array_COUNT(Arr)          ((int)((YOYO_ARRAY *)(Arr))->count+0)
#define Array_BEGIN(Arr)          (((YOYO_ARRAY *)(Arr))->at)
#define Array_END(Arr)            (Array_BEGIN(Arr)+Array_COUNT(Arr))
#define Array_AT(Arr,Idx)         ((((YOYO_ARRAY *)(Arr))->at)[Idx])
#define Array_Push(Arr,Val)       Array_Insert(Arr,-1,Val)
#define Array_Pop(Arr)            Array_Take(Arr,-1)
#define Array_Pop_Npl(Arr)        Array_Take_Npl(Arr,-1)
#define Array_Push_Front(Arr,Val) Array_Insert(Arr,0,Val)
#define Array_Pop_Front(Arr)      Array_Take(Arr,0)
#define Array_Pop_Front_Npl(Arr)  Array_Take_Npl(Arr,0)

void Array_Push_Oj(YOYO_ARRAY *a, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    Array_Push(a,val);
  }
#endif
  ;

void *Array_Pop_Oj(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    return Array_Pop(a);
  }
#endif
  ;

void *Array_Pop_Npl_Oj(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    return Array_Pop_Npl(a);
  }
#endif
  ;

void Array_Push_Front_Oj(YOYO_ARRAY *a, void *val)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    Array_Push_Front(a,val);
  }
#endif
  ;

void *Array_Pop_Front_Oj(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    return Array_Pop_Front(a);
  }
#endif
  ;

void *Array_Pop_Front_Npl_Oj(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    return Array_Pop_Front_Npl(a);
  }
#endif
  ;

int Array_Count(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_COUNT(a);
    return 0;
  }
#endif
  ;
  
void *Array_Begin(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_BEGIN(a);
    return 0;
  }
#endif
  ;

void *Array_End(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_END(a);
    return 0;
  }
#endif
  ;

void *Array_At(YOYO_ARRAY *a,int pos)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    if ( a )
      {
        if ( pos < 0 ) pos = a->count + pos;
        if ( pos < 0 || pos >= a->count ) 
          Yo_Raise(YOYO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);
        return Array_AT(a,pos);
      }
    return 0;
  }
#endif
  ;

void Array_Destruct(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int i = 0;
    void *self = a;
    void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    if ( destructor )
      for ( i = 0; i < a->count; ++i )
        if ( a->at[i] ) 
          destructor(a->at[i]);
    if ( a->at )
      free(a->at);
    Yo_Object_Destruct(a);
  }
#endif
  ;

void Array_Clear(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    int i = 0;
    void *self = a;
    void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    if ( destructor )
      for ( i = 0; i < a->count; ++i )
        destructor(a->at[i]);
    if ( a->at )
      memset(a->at,0,a->count*sizeof(a->at[0]));
    a->count = 0;
  }
#endif
  ;

#define Array_Init() Array_Void()
void *Array_Void(void)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YOYO_ARRAY *arr = Yo_Object(sizeof(YOYO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Refs(void)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, Yo_Unrefe},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YOYO_ARRAY *arr = Yo_Object(sizeof(YOYO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Refs_Copy(void *refs, int count)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    YOYO_ARRAY *arr = Array_Refs();
    int i;
    Array_Fill(arr,0,0,count);
    for ( i = 0; i < count; ++i )
      arr->at[i] = __Refe(((void**)refs)[i]);
    return arr;
  }
#endif
  ;
  
void *Array_Ptrs(void)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YOYO_ARRAY *arr = Yo_Object(sizeof(YOYO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Pchars(void)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Compare_Elements_OjMID, strcmp},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YOYO_ARRAY *arr = Yo_Object(sizeof(YOYO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

#ifdef _YOYO_ARRAY_BUILTIN
int __wcscmp(void *a, void *b) { return wcscmp(a,b); }
#endif

void *Array_Pwide(void)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Compare_Elements_OjMID, __wcscmp},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YOYO_ARRAY *arr = Yo_Object(sizeof(YOYO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Take_Data_Npl(YOYO_ARRAY *a)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *p = a->at;
    a->at = 0;
    a->capacity = a->count = 0;
    return p;
  }
#endif
  ;

#endif /* C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B */








|
|








|










|
|
















|








|
|
















|











|
|








|











|
|




















|





|
|

|







|
|






|
|






|
|






|
|






|
|






|
|






|
|








|
|








|
|








|
|





|







|
|















|
|
















|

|











|






|

|














|






|

|










|

|














|






|

|















|





|




|

|















|





|
|











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
          }
        a->at[pos+i] = p;
      }
  }
#endif
  ;

void Array_Set(YO_ARRAY *a,int pos,void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *self = a;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);

    if ( pos < 0 ) pos = a->count + pos;
    if ( pos < 0 || pos >= a->count ) 
      {
        if ( destruct ) destruct(val);
        __Raise(YO_ERROR_OUT_OF_RANGE,0);
      }
      
    if ( destruct )
      destruct((a->at)[pos]);

    a->at[pos] = val;
  }
#endif
  ;

int Array_Sorted_Lower_Boundary(YO_ARRAY *a,void *val,int *found,int except)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *self = a;
    int (*compare)(void *, void *);
    
    if ( !a->count ) 
      {
        *found = 0;
        return 0;
      }
    
    if ( 0 != (compare = Yo_Find_Method_Of(&self,Oj_Compare_Elements_OjMID,0)) )
      {
        void **p = Lower_Boundary(a->at,a->count,compare,val,found);
        return p - a->at;
      }
    else if (except)
      __Raise(YO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
    else
      return -1;
      
    return 0;
  }
#endif
  ;

void Array_Sorted_Insert(YO_ARRAY *a,void *p)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( !a->count )
      Array_Insert(a,-1,p);
    else
      {
        int found = 0;
        int pos ;
        
        pos = Array_Sorted_Lower_Boundary(a,p,&found,0);
        
        if ( pos < 0 )
          {
            void *self = a;
            void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              destructor(p);
            __Raise(YO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
          }
          
        if ( !found )
          Array_Insert(a,pos,p);
        else
          Array_Set(a,pos,p);
      }
  }
#endif
  ;

void *Array_Binary_Find(YO_ARRAY *a, void *p)
#ifdef _YO_ARRAY_BUILTIN
  {
    int found = 0;
    int pos = Array_Sorted_Lower_Boundary(a,p,&found,1);
    return found ? a->at[pos] : 0;
  }
#endif
  ;

#ifdef _YO_ARRAY_BUILTIN
int Array_Sort_Qsort_Compare(int (*compare)(void *a,void *b), void **a, void **b)
  {
    return compare(*a,*b);
  }
int (*Array_Sort_Qsort_Compare_Static_Compare)(void *a,void *b) = 0;
int Array_Sort_Qsort_Compare_Static(void **a, void **b)
  {
    return Array_Sort_Qsort_Compare_Static_Compare(*a,*b);
  }
#endif

void Array_Sort(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *self = a;
    void *compare;
    if ( a->at && a->count )
      {
        if ( 0 != (compare = Yo_Find_Method_Of(&self,Oj_Compare_Elements_OjMID,0)) )
          {
          #if !defined __windoze && !defined __NetBSD__ && !defined __linux__
            qsort_r(a->at,a->count,sizeof(void*),compare,(void*)Array_Sort_Qsort_Compare);
          #elif defined __windoze && _MSC_VER > 1400 
            qsort_s(a->at,a->count,sizeof(void*),compare,(void*)Array_Sort_Qsort_Compare);
          #else /* use global variable */
            __Xchg_Interlock
              {
                Array_Sort_Qsort_Compare_Static_Compare = compare;
                qsort(a->at,a->count,sizeof(void*),(void*)Array_Sort_Qsort_Compare_Static);
              }
          #endif
          }
        else
          __Raise(YO_ERROR_UNSORTABLE,__yoTa("array is unsortable",0));
      }
  }
#endif
  ;

#define Array_COUNT(Arr)          ((int)((YO_ARRAY *)(Arr))->count+0)
#define Array_BEGIN(Arr)          (((YO_ARRAY *)(Arr))->at)
#define Array_END(Arr)            (Array_BEGIN(Arr)+Array_COUNT(Arr))
#define Array_AT(Arr,Idx)         ((((YO_ARRAY *)(Arr))->at)[Idx])
#define Array_Push(Arr,Val)       Array_Insert(Arr,-1,Val)
#define Array_Pop(Arr)            Array_Take(Arr,-1)
#define Array_Pop_Npl(Arr)        Array_Take_Npl(Arr,-1)
#define Array_Push_Front(Arr,Val) Array_Insert(Arr,0,Val)
#define Array_Pop_Front(Arr)      Array_Take(Arr,0)
#define Array_Pop_Front_Npl(Arr)  Array_Take_Npl(Arr,0)

void Array_Push_Oj(YO_ARRAY *a, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    Array_Push(a,val);
  }
#endif
  ;

void *Array_Pop_Oj(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    return Array_Pop(a);
  }
#endif
  ;

void *Array_Pop_Npl_Oj(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    return Array_Pop_Npl(a);
  }
#endif
  ;

void Array_Push_Front_Oj(YO_ARRAY *a, void *val)
#ifdef _YO_ARRAY_BUILTIN
  {
    Array_Push_Front(a,val);
  }
#endif
  ;

void *Array_Pop_Front_Oj(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    return Array_Pop_Front(a);
  }
#endif
  ;

void *Array_Pop_Front_Npl_Oj(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    return Array_Pop_Front_Npl(a);
  }
#endif
  ;

int Array_Count(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_COUNT(a);
    return 0;
  }
#endif
  ;
  
void *Array_Begin(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_BEGIN(a);
    return 0;
  }
#endif
  ;

void *Array_End(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( a )
      return Array_END(a);
    return 0;
  }
#endif
  ;

void *Array_At(YO_ARRAY *a,int pos)
#ifdef _YO_ARRAY_BUILTIN
  {
    if ( a )
      {
        if ( pos < 0 ) pos = a->count + pos;
        if ( pos < 0 || pos >= a->count ) 
          Yo_Raise(YO_ERROR_OUT_OF_RANGE,0,__Yo_FILE__,__LINE__);
        return Array_AT(a,pos);
      }
    return 0;
  }
#endif
  ;

void Array_Destruct(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    int i = 0;
    void *self = a;
    void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    if ( destructor )
      for ( i = 0; i < a->count; ++i )
        if ( a->at[i] ) 
          destructor(a->at[i]);
    if ( a->at )
      free(a->at);
    Yo_Object_Destruct(a);
  }
#endif
  ;

void Array_Clear(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    int i = 0;
    void *self = a;
    void (*destructor)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    if ( destructor )
      for ( i = 0; i < a->count; ++i )
        destructor(a->at[i]);
    if ( a->at )
      memset(a->at,0,a->count*sizeof(a->at[0]));
    a->count = 0;
  }
#endif
  ;

#define Array_Init() Array_Void()
void *Array_Void(void)
#ifdef _YO_ARRAY_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YO_ARRAY *arr = Yo_Object(sizeof(YO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Refs(void)
#ifdef _YO_ARRAY_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, Yo_Unrefe},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YO_ARRAY *arr = Yo_Object(sizeof(YO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Refs_Copy(void *refs, int count)
#ifdef _YO_ARRAY_BUILTIN
  {
    YO_ARRAY *arr = Array_Refs();
    int i;
    Array_Fill(arr,0,0,count);
    for ( i = 0; i < count; ++i )
      arr->at[i] = __Refe(((void**)refs)[i]);
    return arr;
  }
#endif
  ;
  
void *Array_Ptrs(void)
#ifdef _YO_ARRAY_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YO_ARRAY *arr = Yo_Object(sizeof(YO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Pchars(void)
#ifdef _YO_ARRAY_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Compare_Elements_OjMID, strcmp},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YO_ARRAY *arr = Yo_Object(sizeof(YO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

#ifdef _YO_ARRAY_BUILTIN
int __wcscmp(void *a, void *b) { return wcscmp(a,b); }
#endif

void *Array_Pwide(void)
#ifdef _YO_ARRAY_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,         Array_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {Oj_Compare_Elements_OjMID, __wcscmp},
        {Oj_Sort_OjMID,             Array_Sort},
        {Oj_Sorted_Insert_OjMID,    Array_Sorted_Insert},
        {Oj_Sorted_Find_OjMID,      Array_Binary_Find},
        {Oj_Push_OjMID,             Array_Push_Oj},
        {Oj_Pop_OjMID,              Array_Pop_Oj},
        {Oj_Push_Front_OjMID,       Array_Push_Front_Oj},
        {Oj_Pop_Front_OjMID,        Array_Pop_Front_Oj},
        {Oj_Count_OjMID,            Array_Count},
        {Oj_Pop_Npl_OjMID,          Array_Pop_Npl_Oj},
        {Oj_Pop_Front_Npl_OjMID,    Array_Pop_Front_Npl_Oj},
        {0}};
    YO_ARRAY *arr = Yo_Object(sizeof(YO_ARRAY),funcs);
    return arr;
  }
#endif
  ;

void *Array_Take_Data_Npl(YO_ARRAY *a)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *p = a->at;
    a->at = 0;
    a->capacity = a->count = 0;
    return p;
  }
#endif
  ;

#endif /* C_once_44A7F9A5_269A_48D5_AABB_F08291F9087B */

Changes to bigint.hc.
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

*/

#ifndef C_once_B4220D86_3019_4E13_8682_D7F809F4E829
#define C_once_B4220D86_3019_4E13_8682_D7F809F4E829

#ifdef _LIBYOYO
#define _YOYO_BINGINT_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "random.hc"

typedef struct _YOYO_BIGINT
  {
    unsigned short digits;
    signed char sign;
    unsigned char capacity; /* extra blocks count */
    halflong_t value[1];
  } YOYO_BIGINT;
  
enum
  {
    YOYO_BIGINT_BLOCKSIZE   = 128,
    YOYO_BIGINT_BLOCKMASK   = YOYO_BIGINT_BLOCKSIZE-1,
    YOYO_BIGINT_MINDIGITS   = (YOYO_BIGINT_BLOCKSIZE-sizeof(YOYO_BIGINT))/sizeof(halflong_t)+1, 
    YOYO_BIGINT_BLKDIGITS   = YOYO_BIGINT_BLOCKSIZE/sizeof(halflong_t), 
    SizeOf_Min_YOYO_BIGINT  = sizeof(YOYO_BIGINT)+(YOYO_BIGINT_MINDIGITS-1)*sizeof(halflong_t),
    YOYO_BIGINT_DIGIT_SHIFT = sizeof(halflong_t)*8,
    YOYO_BIGINT_DIGIT_MASK  = (halflong_t)-1L,
  };

typedef struct _YOYO_BIGINT_STATIC
  {
    YOYO_BIGINT bint;
    halflong_t space[YOYO_BIGINT_MINDIGITS-1];
  } YOYO_BIGINT_STATIC;

#define Bigint_Size_Of_Digits(Digits) (((((Digits)-1)*sizeof(halflong_t)+sizeof(YOYO_BIGINT))+YOYO_BIGINT_BLOCKMASK)&~YOYO_BIGINT_BLOCKMASK)
#define Bigint_Digits_Of_Bits(Bits) (((Bits)+sizeof(halflong_t)*8-1)/(sizeof(halflong_t)*8))
#define Bigint_Digits_Of_Bytes(Bytes) (((Bytes)+sizeof(halflong_t)-1)/sizeof(halflong_t))

#define Bigint_Init(Value) Bigint_Init_Digits(Value,1)
YOYO_BIGINT *Bigint_Init_Digits(quad_t val, int digits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i = 0;
    YOYO_BIGINT *bint;
    if ( digits < YOYO_BIGINT_MINDIGITS ) digits = YOYO_BIGINT_MINDIGITS;
    bint = __Malloc(Bigint_Size_Of_Digits(digits));
    if ( val < 0 ) { bint->sign = -1; val = -val; } else bint->sign = 1;
    while ( val & YOYO_BIGINT_DIGIT_MASK )
     {
       bint->value[i++] = val & YOYO_BIGINT_DIGIT_MASK;
       val >>= YOYO_BIGINT_DIGIT_SHIFT; 
     }
    if ( i < digits )
      memset(bint->value+i,0,(digits-i)*sizeof(halflong_t));
    bint->digits = Yo_MAX(i,1);
    bint->capacity = ((digits-YOYO_BIGINT_MINDIGITS)+YOYO_BIGINT_BLKDIGITS-1)/YOYO_BIGINT_BLKDIGITS;
    return bint;
  }
#endif
  ;

int Bigint_Bitcount(YOYO_BIGINT *bint) 
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int bc,bcc;
    int i = bint->digits - 1;
    while ( i >= 0 && !bint->value[i] ) --i;
    if ( i < 0 ) return 0;
    bc = Bitcount_Of(bint->value[i]);
    bcc = bc + i*YOYO_BIGINT_DIGIT_SHIFT;   
    return bcc;
  }
#endif
  ;
  
int Bigint_Is_1(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i;
    if ( bint->value[0] != 1 )
      return 0;
    for ( i = 1; i < bint->digits; ++i )
      if ( bint->value[i] ) 
        return 0;
    return 1;
  }
#endif
  ;

int Bigint_Is_0(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i = 0;
    for ( ; i < bint->digits; ++i )
      if ( bint->value[i] ) 
        return 0;
    return 1;
  }
#endif
  ;

#define Bigint_Copy(Bint) Bigint_Copy_Expand(Bint,0)
YOYO_BIGINT *Bigint_Copy_Expand(YOYO_BIGINT *bint, int extra_digits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *out = 0;
    int digits, gap;
    
    STRICT_REQUIRE( extra_digits >= 0 );

    if ( bint )
      {
        digits = bint->digits+extra_digits;
        STRICT_REQUIRE( bint->digits > 0 );
      }
    else
      digits = extra_digits;
    
    if ( digits <= YOYO_BIGINT_MINDIGITS ) 
      gap = 0;
    else
      gap = digits-YOYO_BIGINT_MINDIGITS;
    
    out = __Malloc(Bigint_Size_Of_Digits(digits));
    memset(out,0,Bigint_Size_Of_Digits(digits));
    if ( bint )
      memcpy(out,bint,sizeof(*bint)+((bint->digits-1)*sizeof(halflong_t)));
    else
      out->sign = 1;
      
    out->digits = digits;
    out->capacity = (gap+YOYO_BIGINT_BLKDIGITS-1)/YOYO_BIGINT_BLKDIGITS;
    
    return out;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Expand(YOYO_BIGINT *bint, int extra_digits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( bint )
      {
        int digits = bint->digits+extra_digits;
    
        STRICT_REQUIRE( bint );
        STRICT_REQUIRE( bint->digits > 0 );
        STRICT_REQUIRE( extra_digits >= 0 );
    
        if ( bint->capacity*YOYO_BIGINT_BLKDIGITS + YOYO_BIGINT_MINDIGITS >= digits )
          {
            memset(bint->value+bint->digits,0,extra_digits*sizeof(halflong_t));
            bint->digits = digits;
            return bint;
          }
      }
    
    return Bigint_Copy_Expand(bint,extra_digits);
  }
#endif
  ;
  
YOYO_BIGINT *Bigint_Expand_If_Small(YOYO_BIGINT *bint, int required)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( !bint )
      return Bigint_Copy_Expand(0,required);
    else if ( bint->digits < required )
      return Bigint_Expand(bint,required - bint->digits);
    else
      return bint;
  }
#endif
  ;
  
#define Bigint_Alloca(Digits) Bigint_Setup_(alloca(Bigint_Size_Of_Digits(Digits)), Digits)
YOYO_BIGINT *Bigint_Setup_(YOYO_BIGINT *bint, int digits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    REQUIRE(bint);
    
    memset(bint,0,Bigint_Size_Of_Digits(digits));
    bint->digits = 1;
    bint->sign = 1;
    if ( digits > YOYO_BIGINT_MINDIGITS )
      bint->capacity =  ((digits-YOYO_BIGINT_MINDIGITS)+YOYO_BIGINT_BLKDIGITS-1)/YOYO_BIGINT_BLKDIGITS;
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Copy_To(YOYO_BIGINT *bint, YOYO_BIGINT *dst)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( dst->digits < bint->digits )
      dst = Bigint_Expand(dst,bint->digits-dst->digits);
    memcpy(dst->value,bint->value,sizeof(halflong_t)*bint->digits);
    dst->digits = bint->digits;
    dst->sign   = bint->sign;
    return dst;
  }
#endif
  ;

#define Bigint_Less(Bint,Q)  ( Bigint_Cmp(Bint,Q) <  0 )
#define Bigint_Equal(Bint,Q) ( Bigint_Cmp(Bint,Q) == 0 )
long Bigint_Cmp(YOYO_BIGINT *bint, YOYO_BIGINT *q)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( bint != q )
      {
        int ac  = bint->digits;
        int bc  = q->digits;
        halflong_t *a = bint->value+(ac-1); 
        halflong_t *b = q->value+(bc-1); 







|







|





|



|
|
|
|
|
|
|


|

|
|
|

|




|
|


|
|


|

|
|




|





|
|






|





|
|












|
|











|
|

|












|


|









|






|
|









|












|
|












|
|






|
|





|
|













|
|







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

*/

#ifndef C_once_B4220D86_3019_4E13_8682_D7F809F4E829
#define C_once_B4220D86_3019_4E13_8682_D7F809F4E829

#ifdef _LIBYOYO
#define _YO_BINGINT_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "random.hc"

typedef struct _YO_BIGINT
  {
    unsigned short digits;
    signed char sign;
    unsigned char capacity; /* extra blocks count */
    halflong_t value[1];
  } YO_BIGINT;
  
enum
  {
    YO_BIGINT_BLOCKSIZE   = 128,
    YO_BIGINT_BLOCKMASK   = YO_BIGINT_BLOCKSIZE-1,
    YO_BIGINT_MINDIGITS   = (YO_BIGINT_BLOCKSIZE-sizeof(YO_BIGINT))/sizeof(halflong_t)+1, 
    YO_BIGINT_BLKDIGITS   = YO_BIGINT_BLOCKSIZE/sizeof(halflong_t), 
    SizeOf_Min_YO_BIGINT  = sizeof(YO_BIGINT)+(YO_BIGINT_MINDIGITS-1)*sizeof(halflong_t),
    YO_BIGINT_DIGIT_SHIFT = sizeof(halflong_t)*8,
    YO_BIGINT_DIGIT_MASK  = (halflong_t)-1L,
  };

typedef struct _YO_BIGINT_STATIC
  {
    YO_BIGINT bint;
    halflong_t space[YO_BIGINT_MINDIGITS-1];
  } YO_BIGINT_STATIC;

#define Bigint_Size_Of_Digits(Digits) (((((Digits)-1)*sizeof(halflong_t)+sizeof(YO_BIGINT))+YO_BIGINT_BLOCKMASK)&~YO_BIGINT_BLOCKMASK)
#define Bigint_Digits_Of_Bits(Bits) (((Bits)+sizeof(halflong_t)*8-1)/(sizeof(halflong_t)*8))
#define Bigint_Digits_Of_Bytes(Bytes) (((Bytes)+sizeof(halflong_t)-1)/sizeof(halflong_t))

#define Bigint_Init(Value) Bigint_Init_Digits(Value,1)
YO_BIGINT *Bigint_Init_Digits(quad_t val, int digits)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i = 0;
    YO_BIGINT *bint;
    if ( digits < YO_BIGINT_MINDIGITS ) digits = YO_BIGINT_MINDIGITS;
    bint = __Malloc(Bigint_Size_Of_Digits(digits));
    if ( val < 0 ) { bint->sign = -1; val = -val; } else bint->sign = 1;
    while ( val & YO_BIGINT_DIGIT_MASK )
     {
       bint->value[i++] = val & YO_BIGINT_DIGIT_MASK;
       val >>= YO_BIGINT_DIGIT_SHIFT; 
     }
    if ( i < digits )
      memset(bint->value+i,0,(digits-i)*sizeof(halflong_t));
    bint->digits = Yo_MAX(i,1);
    bint->capacity = ((digits-YO_BIGINT_MINDIGITS)+YO_BIGINT_BLKDIGITS-1)/YO_BIGINT_BLKDIGITS;
    return bint;
  }
#endif
  ;

int Bigint_Bitcount(YO_BIGINT *bint) 
#ifdef _YO_BINGINT_BUILTIN
  {
    int bc,bcc;
    int i = bint->digits - 1;
    while ( i >= 0 && !bint->value[i] ) --i;
    if ( i < 0 ) return 0;
    bc = Bitcount_Of(bint->value[i]);
    bcc = bc + i*YO_BIGINT_DIGIT_SHIFT;   
    return bcc;
  }
#endif
  ;
  
int Bigint_Is_1(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i;
    if ( bint->value[0] != 1 )
      return 0;
    for ( i = 1; i < bint->digits; ++i )
      if ( bint->value[i] ) 
        return 0;
    return 1;
  }
#endif
  ;

int Bigint_Is_0(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i = 0;
    for ( ; i < bint->digits; ++i )
      if ( bint->value[i] ) 
        return 0;
    return 1;
  }
#endif
  ;

#define Bigint_Copy(Bint) Bigint_Copy_Expand(Bint,0)
YO_BIGINT *Bigint_Copy_Expand(YO_BIGINT *bint, int extra_digits)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *out = 0;
    int digits, gap;
    
    STRICT_REQUIRE( extra_digits >= 0 );

    if ( bint )
      {
        digits = bint->digits+extra_digits;
        STRICT_REQUIRE( bint->digits > 0 );
      }
    else
      digits = extra_digits;
    
    if ( digits <= YO_BIGINT_MINDIGITS ) 
      gap = 0;
    else
      gap = digits-YO_BIGINT_MINDIGITS;
    
    out = __Malloc(Bigint_Size_Of_Digits(digits));
    memset(out,0,Bigint_Size_Of_Digits(digits));
    if ( bint )
      memcpy(out,bint,sizeof(*bint)+((bint->digits-1)*sizeof(halflong_t)));
    else
      out->sign = 1;
      
    out->digits = digits;
    out->capacity = (gap+YO_BIGINT_BLKDIGITS-1)/YO_BIGINT_BLKDIGITS;
    
    return out;
  }
#endif
  ;

YO_BIGINT *Bigint_Expand(YO_BIGINT *bint, int extra_digits)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( bint )
      {
        int digits = bint->digits+extra_digits;
    
        STRICT_REQUIRE( bint );
        STRICT_REQUIRE( bint->digits > 0 );
        STRICT_REQUIRE( extra_digits >= 0 );
    
        if ( bint->capacity*YO_BIGINT_BLKDIGITS + YO_BIGINT_MINDIGITS >= digits )
          {
            memset(bint->value+bint->digits,0,extra_digits*sizeof(halflong_t));
            bint->digits = digits;
            return bint;
          }
      }
    
    return Bigint_Copy_Expand(bint,extra_digits);
  }
#endif
  ;
  
YO_BIGINT *Bigint_Expand_If_Small(YO_BIGINT *bint, int required)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( !bint )
      return Bigint_Copy_Expand(0,required);
    else if ( bint->digits < required )
      return Bigint_Expand(bint,required - bint->digits);
    else
      return bint;
  }
#endif
  ;
  
#define Bigint_Alloca(Digits) Bigint_Setup_(alloca(Bigint_Size_Of_Digits(Digits)), Digits)
YO_BIGINT *Bigint_Setup_(YO_BIGINT *bint, int digits)
#ifdef _YO_BINGINT_BUILTIN
  {
    REQUIRE(bint);
    
    memset(bint,0,Bigint_Size_Of_Digits(digits));
    bint->digits = 1;
    bint->sign = 1;
    if ( digits > YO_BIGINT_MINDIGITS )
      bint->capacity =  ((digits-YO_BIGINT_MINDIGITS)+YO_BIGINT_BLKDIGITS-1)/YO_BIGINT_BLKDIGITS;
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Copy_To(YO_BIGINT *bint, YO_BIGINT *dst)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( dst->digits < bint->digits )
      dst = Bigint_Expand(dst,bint->digits-dst->digits);
    memcpy(dst->value,bint->value,sizeof(halflong_t)*bint->digits);
    dst->digits = bint->digits;
    dst->sign   = bint->sign;
    return dst;
  }
#endif
  ;

#define Bigint_Less(Bint,Q)  ( Bigint_Cmp(Bint,Q) <  0 )
#define Bigint_Equal(Bint,Q) ( Bigint_Cmp(Bint,Q) == 0 )
long Bigint_Cmp(YO_BIGINT *bint, YO_BIGINT *q)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( bint != q )
      {
        int ac  = bint->digits;
        int bc  = q->digits;
        halflong_t *a = bint->value+(ac-1); 
        halflong_t *b = q->value+(bc-1); 
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
      }
      
    return 0;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Mul_Short(YOYO_BIGINT *bint,halflong_t d)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i,j;
    ulong_t Q = 0;
    ulong_t C = 0;

    for ( i = 0, j = bint->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] * (ulong_t)d + Q;
        C = (Q & YOYO_BIGINT_DIGIT_MASK) + C;
        bint->value[i] = (halflong_t)C;
        Q >>= YOYO_BIGINT_DIGIT_SHIFT;
        C >>= YOYO_BIGINT_DIGIT_SHIFT;
      }

    if ( Q )
      {
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }
      
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Add_Short(YOYO_BIGINT *bint,halflong_t d)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    ulong_t Q = (ulong_t)bint->value[0]+d;
    
    bint->value[0] = (halflong_t)Q;
    Q >>= YOYO_BIGINT_DIGIT_SHIFT;

    if ( Q )
      for ( i = bint->value+1, iE = bint->value+bint->digits; i < iE && Q; ++i )
        {
          Q += (ulong_t)*i;
          *i = (halflong_t)Q;
          Q >>= YOYO_BIGINT_DIGIT_SHIFT;
        }

    if ( Q )
      {
        int j = i-bint->value;
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Sub_Short(YOYO_BIGINT *bint,halflong_t d)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    ulong_t Q;
    
    if ( bint->sign < 1 ) return Bigint_Add_Short(bint,d);
    
    Q = (ulong_t)bint->value[0]-d;
    bint->value[0] = (halflong_t)Q;

    Q = ( Q >> YOYO_BIGINT_DIGIT_SHIFT ) & 1;

    if ( Q )
      for ( i = bint->value+1, iE = bint->value+bint->digits; i < iE && Q; ++i )
        {
          Q = (ulong_t)*i;
          --Q;
          *i = (halflong_t)Q;
          Q = ( Q >> YOYO_BIGINT_DIGIT_SHIFT ) & 1;
        }

    if ( Q )
      {
        int j;
        bint->sign = -bint->sign;
        for ( j = 0; j < bint->digits; ++j )
          bint->value[j] = ~bint->value[j];
        bint = Bigint_Add_Short(bint,1);
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Reset(YOYO_BIGINT *bint,int digits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( !bint )
      bint = Bigint_Expand(bint,digits);
    else
      {
        if ( digits > bint->digits && digits > YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,digits-bint->digits);
        else
          bint->digits = Yo_MAX(digits,1);
      }
    
    memset(bint->value,0,sizeof(halflong_t)*bint->digits);
    return bint;
  }
#endif
  ;

#define Bigint_Bit(Bint,i) \
  (((Bint)->value[i/YOYO_BIGINT_DIGIT_SHIFT] >> (i%YOYO_BIGINT_DIGIT_SHIFT)) & 1 )
#define Bigint_Setbit_(p,val) (p) = ((p)&~(val))|(val)
#define Bigint_Setbit(Bint,i,val) Bigint_Setbit_(\
    (Bint)->value[i/YOYO_BIGINT_DIGIT_SHIFT],\
    (val&1) << (i%YOYO_BIGINT_DIGIT_SHIFT))

YOYO_BIGINT *Bigint_Hishift_Q(YOYO_BIGINT *bint,YOYO_BIGINT *lo,int count,int *bits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i = *bits-1, j;
    bint = Bigint_Reset(bint,(count+YOYO_BIGINT_DIGIT_SHIFT-1)/YOYO_BIGINT_DIGIT_SHIFT);
    
    count = Yo_MIN(count,*bits);
    *bits -= count;
    
    for ( j = count-1 ; j >= 0 ; --j, --i ) 
      {
        halflong_t d = lo->value[i/YOYO_BIGINT_DIGIT_SHIFT];
        d >>= (i%YOYO_BIGINT_DIGIT_SHIFT);
        bint->value[j/YOYO_BIGINT_DIGIT_SHIFT] |= ( (d&1) << (j%YOYO_BIGINT_DIGIT_SHIFT));
      }
      
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Hishift_1(YOYO_BIGINT *bint, YOYO_BIGINT *lo,int *bits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    halflong_t Q = 0;
    halflong_t *i, *iE;
    
    if ( *bits )
      {
        --*bits;
        Q = Bigint_Bit(lo,*bits);
      }

    for ( i = bint->value, iE = bint->value+bint->digits; i != iE; ++i )
      {
        halflong_t S = *i;
        *i = ( S << 1 ) | Q;
        Q = S >> (YOYO_BIGINT_DIGIT_SHIFT-1);
      }

    if ( Q )
      {
        int j = bint->digits;
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Lshift_1(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    halflong_t Q = 0;

    for ( i = bint->value, iE = bint->value+bint->digits; i != iE; ++i )
      {
        halflong_t k = *i;
        *i = ( k << 1 ) | Q;
        Q = k >> (YOYO_BIGINT_DIGIT_SHIFT-1);
      }

    if ( Q )
      {
        int j = bint->digits;
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Rshift_1(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    halflong_t Q = 0;

    for ( i = bint->value+bint->digits-1, iE = bint->value-1; i != iE; --i )
      {
        halflong_t k = *i;
        *i = ( k >> 1 ) | Q;
        Q = k << (YOYO_BIGINT_DIGIT_SHIFT-1);
      }
    
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Lshift(YOYO_BIGINT *bint,unsigned count)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i, dif;
    int w = count%YOYO_BIGINT_DIGIT_SHIFT;
    ulong_t Q = 0;

    if ( w ) for ( i = 0; i < bint->digits; ++i )
      {
        Q |= ((ulong_t)bint->value[i]<<w);
        bint->value[i] = (halflong_t)Q;
        Q = (Q>>YOYO_BIGINT_DIGIT_SHIFT);
      }
      
    if ( Q )
      {
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }

    dif = count/YOYO_BIGINT_DIGIT_SHIFT;
    if ( dif ) 
      {
        int digits = bint->digits;
        if ( digits+dif > YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,dif);
        else bint->digits += dif;
        memmove(bint->value+dif,bint->value,digits*sizeof(halflong_t));
        memset(bint->value,0,dif*sizeof(halflong_t));
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Rshift(YOYO_BIGINT *bint,unsigned count)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i, dif;
    int w = count%YOYO_BIGINT_DIGIT_SHIFT;

    bint->value[0] = bint->value[0] >> w;
    
    if ( w ) for ( i = 1; i < bint->digits; ++i )
      {
        halflong_t Q = bint->value[i];
        bint->value[i-1] |= Q << (YOYO_BIGINT_DIGIT_SHIFT-w);
        bint->value[i] = Q >> w;
      }
        
    dif = count/YOYO_BIGINT_DIGIT_SHIFT;
    if ( dif )
      {
        int j = Yo_MAX(bint->digits-dif,0);
        if ( j )
          memmove(bint->value,bint->value+dif,j*sizeof(halflong_t));
        memset(bint->value+j,0,(bint->digits-j)*sizeof(halflong_t));
        bint->digits = Yo_MAX(j,1);
      }

    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Sub_Unsign(YOYO_BIGINT *bint,YOYO_BIGINT *q,int sign)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    ulong_t Q;
    int i,j;

    if ( bint->digits < q->digits )
      if ( q->digits > YOYO_BIGINT_MINDIGITS )
        bint = Bigint_Expand(bint,q->digits);
      else
        {
          memset(bint->value+bint->digits,0,sizeof(halflong_t)*(q->digits-bint->digits));
          bint->digits = q->digits;
        }
    
    Q = 0;
    for ( i = 0, j = q->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] - (ulong_t)q->value[i] - Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YOYO_BIGINT_DIGIT_SHIFT;
        Q &= 1;
      };

    for ( ; Q && i < bint->digits; ++i )
      {
        Q = (ulong_t)bint->value[i] - Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YOYO_BIGINT_DIGIT_SHIFT;
        Q &= 1;
      }
      
    if ( Q )
      {
        bint->sign = -sign;
        for ( i = 0, j = bint->digits; i < j; ++i )
          bint->value[i] = ~bint->value[i];
        Bigint_Add_Short(bint,1);
      }
    else
      bint->sign = sign;
      
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Add_Unsign(YOYO_BIGINT *bint,YOYO_BIGINT *q,int sign)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    ulong_t Q;
    int i,j;
    
    if ( bint->digits < q->digits )
      if ( q->digits > YOYO_BIGINT_MINDIGITS )
        bint = Bigint_Expand(bint,q->digits);
      else
        {
          memset(bint->value+bint->digits,0,sizeof(halflong_t)*(q->digits-bint->digits));
          bint->digits = q->digits;
        }
    
    Q = 0;
    for ( i = 0, j = q->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] + (ulong_t)q->value[i] + Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YOYO_BIGINT_DIGIT_SHIFT;
      };

    for ( ; Q && i < bint->digits; ++i )
      {
        Q = (ulong_t)bint->value[i] + Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YOYO_BIGINT_DIGIT_SHIFT;
      }
      
    if ( Q )
      {
        if ( bint->digits >= YOYO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }

    bint->sign = sign;
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Sub(YOYO_BIGINT *bint,YOYO_BIGINT *q)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( bint->sign != q->sign )
      return Bigint_Add_Unsign(bint,q,-q->sign);
    else
      return Bigint_Sub_Unsign(bint,q,q->sign);
  }
#endif
  ;

YOYO_BIGINT *Bigint_Add(YOYO_BIGINT *bint,YOYO_BIGINT *q)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    if ( bint->sign != q->sign )
      return Bigint_Sub_Unsign(bint,q,-q->sign);
    else
      return Bigint_Add_Unsign(bint,q,q->sign);
  }
#endif
  ;

#define Bigint_Div(Bint,Q) Bigint_Divrem(Bint,Q,0)
YOYO_BIGINT *Bigint_Divrem(YOYO_BIGINT *bint, YOYO_BIGINT *q, YOYO_BIGINT **rem)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *R, *Q = Bigint_Init(0);
    int bits    = Bigint_Bitcount(bint);
    int divbits = Bigint_Bitcount(q);
  
    if ( divbits > bits ) 
      {
        if ( rem ) *rem = Bigint_Copy(bint);
        return Q;
      }
  
    if ( !divbits ) 
      __Raise(YOYO_ERROR_ZERODIVIDE,0);
      
    R = Bigint_Init(0);
    Q = Bigint_Hishift_Q(Q,bint,divbits,&bits);
  
    for(;;) 
      {
        if ( !Bigint_Less(Q,q) )







|
|








|

|
|




|










|
|





|






|





|










|
|









|







|
















|
|





|












|


|
|

|
|


|






|
|
|







|
|














|





|










|
|








|





|










|
|








|







|
|


|






|




|





|



|











|
|


|






|



|














|
|





|












|







|


















|
|





|












|






|




|











|
|









|
|










|
|

|










|







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
      }
      
    return 0;
  }
#endif
  ;

YO_BIGINT *Bigint_Mul_Short(YO_BIGINT *bint,halflong_t d)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i,j;
    ulong_t Q = 0;
    ulong_t C = 0;

    for ( i = 0, j = bint->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] * (ulong_t)d + Q;
        C = (Q & YO_BIGINT_DIGIT_MASK) + C;
        bint->value[i] = (halflong_t)C;
        Q >>= YO_BIGINT_DIGIT_SHIFT;
        C >>= YO_BIGINT_DIGIT_SHIFT;
      }

    if ( Q )
      {
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }
      
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Add_Short(YO_BIGINT *bint,halflong_t d)
#ifdef _YO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    ulong_t Q = (ulong_t)bint->value[0]+d;
    
    bint->value[0] = (halflong_t)Q;
    Q >>= YO_BIGINT_DIGIT_SHIFT;

    if ( Q )
      for ( i = bint->value+1, iE = bint->value+bint->digits; i < iE && Q; ++i )
        {
          Q += (ulong_t)*i;
          *i = (halflong_t)Q;
          Q >>= YO_BIGINT_DIGIT_SHIFT;
        }

    if ( Q )
      {
        int j = i-bint->value;
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Sub_Short(YO_BIGINT *bint,halflong_t d)
#ifdef _YO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    ulong_t Q;
    
    if ( bint->sign < 1 ) return Bigint_Add_Short(bint,d);
    
    Q = (ulong_t)bint->value[0]-d;
    bint->value[0] = (halflong_t)Q;

    Q = ( Q >> YO_BIGINT_DIGIT_SHIFT ) & 1;

    if ( Q )
      for ( i = bint->value+1, iE = bint->value+bint->digits; i < iE && Q; ++i )
        {
          Q = (ulong_t)*i;
          --Q;
          *i = (halflong_t)Q;
          Q = ( Q >> YO_BIGINT_DIGIT_SHIFT ) & 1;
        }

    if ( Q )
      {
        int j;
        bint->sign = -bint->sign;
        for ( j = 0; j < bint->digits; ++j )
          bint->value[j] = ~bint->value[j];
        bint = Bigint_Add_Short(bint,1);
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Reset(YO_BIGINT *bint,int digits)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( !bint )
      bint = Bigint_Expand(bint,digits);
    else
      {
        if ( digits > bint->digits && digits > YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,digits-bint->digits);
        else
          bint->digits = Yo_MAX(digits,1);
      }
    
    memset(bint->value,0,sizeof(halflong_t)*bint->digits);
    return bint;
  }
#endif
  ;

#define Bigint_Bit(Bint,i) \
  (((Bint)->value[i/YO_BIGINT_DIGIT_SHIFT] >> (i%YO_BIGINT_DIGIT_SHIFT)) & 1 )
#define Bigint_Setbit_(p,val) (p) = ((p)&~(val))|(val)
#define Bigint_Setbit(Bint,i,val) Bigint_Setbit_(\
    (Bint)->value[i/YO_BIGINT_DIGIT_SHIFT],\
    (val&1) << (i%YO_BIGINT_DIGIT_SHIFT))

YO_BIGINT *Bigint_Hishift_Q(YO_BIGINT *bint,YO_BIGINT *lo,int count,int *bits)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i = *bits-1, j;
    bint = Bigint_Reset(bint,(count+YO_BIGINT_DIGIT_SHIFT-1)/YO_BIGINT_DIGIT_SHIFT);
    
    count = Yo_MIN(count,*bits);
    *bits -= count;
    
    for ( j = count-1 ; j >= 0 ; --j, --i ) 
      {
        halflong_t d = lo->value[i/YO_BIGINT_DIGIT_SHIFT];
        d >>= (i%YO_BIGINT_DIGIT_SHIFT);
        bint->value[j/YO_BIGINT_DIGIT_SHIFT] |= ( (d&1) << (j%YO_BIGINT_DIGIT_SHIFT));
      }
      
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Hishift_1(YO_BIGINT *bint, YO_BIGINT *lo,int *bits)
#ifdef _YO_BINGINT_BUILTIN
  {
    halflong_t Q = 0;
    halflong_t *i, *iE;
    
    if ( *bits )
      {
        --*bits;
        Q = Bigint_Bit(lo,*bits);
      }

    for ( i = bint->value, iE = bint->value+bint->digits; i != iE; ++i )
      {
        halflong_t S = *i;
        *i = ( S << 1 ) | Q;
        Q = S >> (YO_BIGINT_DIGIT_SHIFT-1);
      }

    if ( Q )
      {
        int j = bint->digits;
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Lshift_1(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    halflong_t Q = 0;

    for ( i = bint->value, iE = bint->value+bint->digits; i != iE; ++i )
      {
        halflong_t k = *i;
        *i = ( k << 1 ) | Q;
        Q = k >> (YO_BIGINT_DIGIT_SHIFT-1);
      }

    if ( Q )
      {
        int j = bint->digits;
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[j] = (halflong_t)Q;
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Rshift_1(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    halflong_t *i, *iE;
    halflong_t Q = 0;

    for ( i = bint->value+bint->digits-1, iE = bint->value-1; i != iE; --i )
      {
        halflong_t k = *i;
        *i = ( k >> 1 ) | Q;
        Q = k << (YO_BIGINT_DIGIT_SHIFT-1);
      }
    
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Lshift(YO_BIGINT *bint,unsigned count)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i, dif;
    int w = count%YO_BIGINT_DIGIT_SHIFT;
    ulong_t Q = 0;

    if ( w ) for ( i = 0; i < bint->digits; ++i )
      {
        Q |= ((ulong_t)bint->value[i]<<w);
        bint->value[i] = (halflong_t)Q;
        Q = (Q>>YO_BIGINT_DIGIT_SHIFT);
      }
      
    if ( Q )
      {
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }

    dif = count/YO_BIGINT_DIGIT_SHIFT;
    if ( dif ) 
      {
        int digits = bint->digits;
        if ( digits+dif > YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,dif);
        else bint->digits += dif;
        memmove(bint->value+dif,bint->value,digits*sizeof(halflong_t));
        memset(bint->value,0,dif*sizeof(halflong_t));
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Rshift(YO_BIGINT *bint,unsigned count)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i, dif;
    int w = count%YO_BIGINT_DIGIT_SHIFT;

    bint->value[0] = bint->value[0] >> w;
    
    if ( w ) for ( i = 1; i < bint->digits; ++i )
      {
        halflong_t Q = bint->value[i];
        bint->value[i-1] |= Q << (YO_BIGINT_DIGIT_SHIFT-w);
        bint->value[i] = Q >> w;
      }
        
    dif = count/YO_BIGINT_DIGIT_SHIFT;
    if ( dif )
      {
        int j = Yo_MAX(bint->digits-dif,0);
        if ( j )
          memmove(bint->value,bint->value+dif,j*sizeof(halflong_t));
        memset(bint->value+j,0,(bint->digits-j)*sizeof(halflong_t));
        bint->digits = Yo_MAX(j,1);
      }

    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Sub_Unsign(YO_BIGINT *bint,YO_BIGINT *q,int sign)
#ifdef _YO_BINGINT_BUILTIN
  {
    ulong_t Q;
    int i,j;

    if ( bint->digits < q->digits )
      if ( q->digits > YO_BIGINT_MINDIGITS )
        bint = Bigint_Expand(bint,q->digits);
      else
        {
          memset(bint->value+bint->digits,0,sizeof(halflong_t)*(q->digits-bint->digits));
          bint->digits = q->digits;
        }
    
    Q = 0;
    for ( i = 0, j = q->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] - (ulong_t)q->value[i] - Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YO_BIGINT_DIGIT_SHIFT;
        Q &= 1;
      };

    for ( ; Q && i < bint->digits; ++i )
      {
        Q = (ulong_t)bint->value[i] - Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YO_BIGINT_DIGIT_SHIFT;
        Q &= 1;
      }
      
    if ( Q )
      {
        bint->sign = -sign;
        for ( i = 0, j = bint->digits; i < j; ++i )
          bint->value[i] = ~bint->value[i];
        Bigint_Add_Short(bint,1);
      }
    else
      bint->sign = sign;
      
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Add_Unsign(YO_BIGINT *bint,YO_BIGINT *q,int sign)
#ifdef _YO_BINGINT_BUILTIN
  {
    ulong_t Q;
    int i,j;
    
    if ( bint->digits < q->digits )
      if ( q->digits > YO_BIGINT_MINDIGITS )
        bint = Bigint_Expand(bint,q->digits);
      else
        {
          memset(bint->value+bint->digits,0,sizeof(halflong_t)*(q->digits-bint->digits));
          bint->digits = q->digits;
        }
    
    Q = 0;
    for ( i = 0, j = q->digits; i < j; ++i )
      {
        Q = (ulong_t)bint->value[i] + (ulong_t)q->value[i] + Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YO_BIGINT_DIGIT_SHIFT;
      };

    for ( ; Q && i < bint->digits; ++i )
      {
        Q = (ulong_t)bint->value[i] + Q;
        bint->value[i] = (halflong_t)Q;
        Q >>= YO_BIGINT_DIGIT_SHIFT;
      }
      
    if ( Q )
      {
        if ( bint->digits >= YO_BIGINT_MINDIGITS )
          bint = Bigint_Expand(bint,1);
        else ++bint->digits;
        bint->value[i] = (halflong_t)Q;
      }

    bint->sign = sign;
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Sub(YO_BIGINT *bint,YO_BIGINT *q)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( bint->sign != q->sign )
      return Bigint_Add_Unsign(bint,q,-q->sign);
    else
      return Bigint_Sub_Unsign(bint,q,q->sign);
  }
#endif
  ;

YO_BIGINT *Bigint_Add(YO_BIGINT *bint,YO_BIGINT *q)
#ifdef _YO_BINGINT_BUILTIN
  {
    if ( bint->sign != q->sign )
      return Bigint_Sub_Unsign(bint,q,-q->sign);
    else
      return Bigint_Add_Unsign(bint,q,q->sign);
  }
#endif
  ;

#define Bigint_Div(Bint,Q) Bigint_Divrem(Bint,Q,0)
YO_BIGINT *Bigint_Divrem(YO_BIGINT *bint, YO_BIGINT *q, YO_BIGINT **rem)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *R, *Q = Bigint_Init(0);
    int bits    = Bigint_Bitcount(bint);
    int divbits = Bigint_Bitcount(q);
  
    if ( divbits > bits ) 
      {
        if ( rem ) *rem = Bigint_Copy(bint);
        return Q;
      }
  
    if ( !divbits ) 
      __Raise(YO_ERROR_ZERODIVIDE,0);
      
    R = Bigint_Init(0);
    Q = Bigint_Hishift_Q(Q,bint,divbits,&bits);
  
    for(;;) 
      {
        if ( !Bigint_Less(Q,q) )
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

    if ( rem ) *rem = Q;
    return R;
  }
#endif
  ;
  
YOYO_BIGINT *Bigint_Divrem_Short(YOYO_BIGINT *bint, halflong_t q, halflong_t *rem)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i;
    ulong_t Q = 0;
    for ( i = bint->digits-1; i >= 0; --i )
      {
        Q <<= YOYO_BIGINT_DIGIT_SHIFT;
        Q |= bint->value[i];
        bint->value[i] = (halflong_t)(Q/q);
        Q = Q%q;
      }
    if ( rem ) *rem = (halflong_t)Q;
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Decode_2(char *S)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          for ( ;*p; ++p )
            {
              if ( *p != '0' && *p != '1' ) __Raise_Format(YOYO_ERROR_ILLFORMED,("invalid binary number %s",S));
              bint = Bigint_Lshift_1(bint);
              bint->value[0] |= (byte_t)(*p-'0');
            }
        }
    
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Decode_10(char *S)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          if ( *p == '-' ) { bint->sign = -1; ++p; }
          else if ( *p == '+' ) ++p;
          
          for ( ;*p; ++p )
            {
              if ( !Isdigit(*p) ) __Raise_Format(YOYO_ERROR_ILLFORMED,("invalid decimal number %s",S));
              bint = Bigint_Mul_Short(bint,10);
              bint = Bigint_Add_Short(bint,*p-'0');
            }
        }
    
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Decode_16(char *S)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          for ( ;*p; ++p )
            {
              if ( !Isxdigit(*p) || !Isxdigit(p[1]) ) 
                __Raise_Format(YOYO_ERROR_ILLFORMED,("invalid hexadecimal number %s",S));
              bint = Bigint_Lshift(bint,8);
              bint->value[0] |= Str_Unhex_Byte(p,0,0);
              ++p;
            }
        }
    
    return bint;
  }
#endif
  ;

char *Bigint_Encode_2(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        int i = 0, bc = Bigint_Bitcount(bint);
        char *S = __Malloc(bc+1);
        
        S[bc] = 0;
        
        if ( bc ) for ( ; i < bc; ++i )
          S[i] = Bigint_Bit(bint,i) ? '1' : '0';
        
        ret = Str_Reverse(S,bc);
      }
    return ret;
  }
#endif
  ;

char *Bigint_Encode_10(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YOYO_BUFFER *bf = Buffer_Init(0);
        YOYO_BIGINT *R = Bigint_Copy(bint);

        if ( !Bigint_Is_0(R) )
          {
            do
              {
                halflong_t rem;
                R = Bigint_Divrem_Short(R,10,&rem);







|
|





|










|
|

|







|










|
|

|










|










|
|

|








|











|
|



















|
|




|
|







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

    if ( rem ) *rem = Q;
    return R;
  }
#endif
  ;
  
YO_BIGINT *Bigint_Divrem_Short(YO_BIGINT *bint, halflong_t q, halflong_t *rem)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i;
    ulong_t Q = 0;
    for ( i = bint->digits-1; i >= 0; --i )
      {
        Q <<= YO_BIGINT_DIGIT_SHIFT;
        Q |= bint->value[i];
        bint->value[i] = (halflong_t)(Q/q);
        Q = Q%q;
      }
    if ( rem ) *rem = (halflong_t)Q;
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Decode_2(char *S)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          for ( ;*p; ++p )
            {
              if ( *p != '0' && *p != '1' ) __Raise_Format(YO_ERROR_ILLFORMED,("invalid binary number %s",S));
              bint = Bigint_Lshift_1(bint);
              bint->value[0] |= (byte_t)(*p-'0');
            }
        }
    
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Decode_10(char *S)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          if ( *p == '-' ) { bint->sign = -1; ++p; }
          else if ( *p == '+' ) ++p;
          
          for ( ;*p; ++p )
            {
              if ( !Isdigit(*p) ) __Raise_Format(YO_ERROR_ILLFORMED,("invalid decimal number %s",S));
              bint = Bigint_Mul_Short(bint,10);
              bint = Bigint_Add_Short(bint,*p-'0');
            }
        }
    
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Decode_16(char *S)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *bint = Bigint_Init(0);
    char *p = S;
    
    __Auto_Ptr(bint)
      if ( p )
        {
          for ( ;*p; ++p )
            {
              if ( !Isxdigit(*p) || !Isxdigit(p[1]) ) 
                __Raise_Format(YO_ERROR_ILLFORMED,("invalid hexadecimal number %s",S));
              bint = Bigint_Lshift(bint,8);
              bint->value[0] |= Str_Unhex_Byte(p,0,0);
              ++p;
            }
        }
    
    return bint;
  }
#endif
  ;

char *Bigint_Encode_2(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        int i = 0, bc = Bigint_Bitcount(bint);
        char *S = __Malloc(bc+1);
        
        S[bc] = 0;
        
        if ( bc ) for ( ; i < bc; ++i )
          S[i] = Bigint_Bit(bint,i) ? '1' : '0';
        
        ret = Str_Reverse(S,bc);
      }
    return ret;
  }
#endif
  ;

char *Bigint_Encode_10(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YO_BUFFER *bf = Buffer_Init(0);
        YO_BIGINT *R = Bigint_Copy(bint);

        if ( !Bigint_Is_0(R) )
          {
            do
              {
                halflong_t rem;
                R = Bigint_Divrem_Short(R,10,&rem);
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
        ret = Str_Reverse(bf->at,bf->count);
      }
    return ret;
  }
#endif
  ;

char *Bigint_Encode_16(YOYO_BIGINT *bint)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        int bc = (Bigint_Bitcount(bint)+7)/8;
        char *S = Str_Hex_Encode(bint->value,bc);
        ret = Str_Reverse(S,bc*2);
      }
    return ret;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Mul(YOYO_BIGINT *bint, YOYO_BIGINT *d)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *R = Bigint_Alloca(bint->digits+d->digits+1);
    int i, Qdigi, j, Tdigi;

    R->digits = bint->digits+d->digits+1;

    for ( i = 0, Qdigi = d->digits, Tdigi = bint->digits; i < Qdigi; ++i )
      {
        ulong_t Q = 0;
        ulong_t C = 0;
        for ( j = 0; j < Tdigi; ++j )
          {
            Q = (ulong_t)d->value[i] * (ulong_t)bint->value[j] + Q;
            C = (ulong_t)R->value[j+i] + (Q & YOYO_BIGINT_DIGIT_MASK) + C;
            R->value[j+i] = (halflong_t)C;
            Q >>=YOYO_BIGINT_DIGIT_SHIFT;
            C >>= YOYO_BIGINT_DIGIT_SHIFT;
          }
        do 
          {
            C = (ulong_t)R->value[Tdigi+i] + (Q & YOYO_BIGINT_DIGIT_MASK) + C;
            R->value[Tdigi+i] = (halflong_t)C;
            Q >>= YOYO_BIGINT_DIGIT_SHIFT;
            C >>= YOYO_BIGINT_DIGIT_SHIFT;
          }
        while ( i < Qdigi && C ); 
      }

    while ( R->digits > 1 && !R->value[R->digits-1] ) --R->digits;
    if ( d->sign != bint->sign ) R->sign = -1;
    return Bigint_Copy_To(R,bint);
  }
#endif
  ;
  
YOYO_BIGINT *Bigint_Modulo(YOYO_BIGINT *bint, YOYO_BIGINT *mod)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int bits = Bigint_Bitcount(bint);
    int modbits = Bigint_Bitcount(mod);
    YOYO_BIGINT *R = Bigint_Alloca(mod->digits+1);
    
    if ( modbits > bits ) return bint;
    
    R = Bigint_Hishift_Q(R,bint,modbits,&bits);
    
    for(;;) 
      {







|
|













|
|

|











|

|
|



|

|
|











|
|



|







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
        ret = Str_Reverse(bf->at,bf->count);
      }
    return ret;
  }
#endif
  ;

char *Bigint_Encode_16(YO_BIGINT *bint)
#ifdef _YO_BINGINT_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        int bc = (Bigint_Bitcount(bint)+7)/8;
        char *S = Str_Hex_Encode(bint->value,bc);
        ret = Str_Reverse(S,bc*2);
      }
    return ret;
  }
#endif
  ;

YO_BIGINT *Bigint_Mul(YO_BIGINT *bint, YO_BIGINT *d)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *R = Bigint_Alloca(bint->digits+d->digits+1);
    int i, Qdigi, j, Tdigi;

    R->digits = bint->digits+d->digits+1;

    for ( i = 0, Qdigi = d->digits, Tdigi = bint->digits; i < Qdigi; ++i )
      {
        ulong_t Q = 0;
        ulong_t C = 0;
        for ( j = 0; j < Tdigi; ++j )
          {
            Q = (ulong_t)d->value[i] * (ulong_t)bint->value[j] + Q;
            C = (ulong_t)R->value[j+i] + (Q & YO_BIGINT_DIGIT_MASK) + C;
            R->value[j+i] = (halflong_t)C;
            Q >>=YO_BIGINT_DIGIT_SHIFT;
            C >>= YO_BIGINT_DIGIT_SHIFT;
          }
        do 
          {
            C = (ulong_t)R->value[Tdigi+i] + (Q & YO_BIGINT_DIGIT_MASK) + C;
            R->value[Tdigi+i] = (halflong_t)C;
            Q >>= YO_BIGINT_DIGIT_SHIFT;
            C >>= YO_BIGINT_DIGIT_SHIFT;
          }
        while ( i < Qdigi && C ); 
      }

    while ( R->digits > 1 && !R->value[R->digits-1] ) --R->digits;
    if ( d->sign != bint->sign ) R->sign = -1;
    return Bigint_Copy_To(R,bint);
  }
#endif
  ;
  
YO_BIGINT *Bigint_Modulo(YO_BIGINT *bint, YO_BIGINT *mod)
#ifdef _YO_BINGINT_BUILTIN
  {
    int bits = Bigint_Bitcount(bint);
    int modbits = Bigint_Bitcount(mod);
    YO_BIGINT *R = Bigint_Alloca(mod->digits+1);
    
    if ( modbits > bits ) return bint;
    
    R = Bigint_Hishift_Q(R,bint,modbits,&bits);
    
    for(;;) 
      {
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
      }
    
    return Bigint_Copy_To(R,bint);
  }
#endif
  ;

YOYO_BIGINT *Bigint_Modmul(YOYO_BIGINT *bint, YOYO_BIGINT *d, YOYO_BIGINT *mod)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *R = Bigint_Alloca(bint->digits+d->digits+1);
    int i, Qdigi, j, Tdigi;
    int bits, modbits;
    R->digits = bint->digits+d->digits+1;

    for ( i = 0, Qdigi = d->digits, Tdigi = bint->digits; i < Qdigi; ++i )
      {
        ulong_t Q = 0;
        ulong_t C = 0;
        for ( j = 0; j < Tdigi; ++j )
          {
            Q = (ulong_t)d->value[i] * (ulong_t)bint->value[j] + Q;
            C = (ulong_t)R->value[j+i] + (Q & YOYO_BIGINT_DIGIT_MASK) + C;
            R->value[j+i] = (halflong_t)C;
            Q >>=YOYO_BIGINT_DIGIT_SHIFT;
            C >>= YOYO_BIGINT_DIGIT_SHIFT;
          }
        do 
          {
            C = (ulong_t)R->value[Tdigi+i] + (Q & YOYO_BIGINT_DIGIT_MASK) + C;
            R->value[Tdigi+i] = (halflong_t)C;
            Q >>= YOYO_BIGINT_DIGIT_SHIFT;
            C >>= YOYO_BIGINT_DIGIT_SHIFT;
          }
        while ( i < Qdigi && C ); 
      }

    while ( R->digits > 1 && !R->value[R->digits-1] ) --R->digits;
    if ( d->sign != bint->sign ) R->sign = -1;








|
|

|











|

|
|



|

|
|







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
      }
    
    return Bigint_Copy_To(R,bint);
  }
#endif
  ;

YO_BIGINT *Bigint_Modmul(YO_BIGINT *bint, YO_BIGINT *d, YO_BIGINT *mod)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *R = Bigint_Alloca(bint->digits+d->digits+1);
    int i, Qdigi, j, Tdigi;
    int bits, modbits;
    R->digits = bint->digits+d->digits+1;

    for ( i = 0, Qdigi = d->digits, Tdigi = bint->digits; i < Qdigi; ++i )
      {
        ulong_t Q = 0;
        ulong_t C = 0;
        for ( j = 0; j < Tdigi; ++j )
          {
            Q = (ulong_t)d->value[i] * (ulong_t)bint->value[j] + Q;
            C = (ulong_t)R->value[j+i] + (Q & YO_BIGINT_DIGIT_MASK) + C;
            R->value[j+i] = (halflong_t)C;
            Q >>=YO_BIGINT_DIGIT_SHIFT;
            C >>= YO_BIGINT_DIGIT_SHIFT;
          }
        do 
          {
            C = (ulong_t)R->value[Tdigi+i] + (Q & YO_BIGINT_DIGIT_MASK) + C;
            R->value[Tdigi+i] = (halflong_t)C;
            Q >>= YO_BIGINT_DIGIT_SHIFT;
            C >>= YO_BIGINT_DIGIT_SHIFT;
          }
        while ( i < Qdigi && C ); 
      }

    while ( R->digits > 1 && !R->value[R->digits-1] ) --R->digits;
    if ( d->sign != bint->sign ) R->sign = -1;

998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
      }
    
    return bint;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Expmod(YOYO_BIGINT *bint, YOYO_BIGINT *e,YOYO_BIGINT *mod)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *E = Bigint_Alloca(e->digits);
    YOYO_BIGINT *t = Bigint_Alloca(mod->digits);
    YOYO_BIGINT *R = 0;
    
    __Auto_Ptr(R)
      {
        E = Bigint_Copy_To(e,E);
        t = Bigint_Modulo(Bigint_Copy_To(bint,t),mod);
        R = bint;
        R->value[0] = 1;







|
|

|
|
|







998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
      }
    
    return bint;
  }
#endif
  ;

YO_BIGINT *Bigint_Expmod(YO_BIGINT *bint, YO_BIGINT *e,YO_BIGINT *mod)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *E = Bigint_Alloca(e->digits);
    YO_BIGINT *t = Bigint_Alloca(mod->digits);
    YO_BIGINT *R = 0;
    
    __Auto_Ptr(R)
      {
        E = Bigint_Copy_To(e,E);
        t = Bigint_Modulo(Bigint_Copy_To(bint,t),mod);
        R = bint;
        R->value[0] = 1;
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
      }
      
    return R;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Invmod(YOYO_BIGINT *bint, YOYO_BIGINT *mod)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *i = 0;
    
    __Auto_Ptr(i)
      {
        YOYO_BIGINT *b = Bigint_Copy(mod);
        YOYO_BIGINT *j = Bigint_Init(1);
        YOYO_BIGINT *c = Bigint_Copy(bint);
        i = Bigint_Init(0);
    
        while ( c->value[0] || !Bigint_Is_0(c) )
          {
            YOYO_BIGINT *y;
            YOYO_BIGINT *q;
            YOYO_BIGINT *x;
            x = Bigint_Divrem(b,c,&y);
            b = c;
            c = y;
            q = Bigint_Sub(i,Bigint_Mul(Bigint_Copy(j),x));
            i = j;
            j = q;
          }
      
        if ( i->sign < 0 ) i = Bigint_Add(i,mod);
      }
    
    return i;
  }
#endif
  ;

#ifndef _YOYO_BINGINT_BUILTIN
extern
#endif
unsigned short First_Prime_Values[]
#ifdef _YOYO_BINGINT_BUILTIN
= {
#include "prime_values.inc"        
}
#endif
  ;

#ifndef _YOYO_BINGINT_BUILTIN
extern
#endif
int First_Prime_Values_Count
#ifdef _YOYO_BINGINT_BUILTIN
= sizeof(First_Prime_Values)/sizeof(First_Prime_Values[0])
#endif
  ;

#ifdef _YOYO_BINGINT_BUILTIN
enum 
  { 
    YOYO_PRIME_MAX_COUNT = /*1229*/ sizeof(First_Prime_Values)/sizeof(First_Prime_Values[0]),
    YOYO_PRIME_RSAPUBLIC_MIN = 256, 
    YOYO_PRIME_RSAPUBLIC_MAX = YOYO_PRIME_MAX_COUNT,
    YOYO_PRIME_TEST_Q = 32,
  };
#endif

halflong_t First_Prime(int no)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    STRICT_REQUIRE(no >= 0 && no < YOYO_PRIME_MAX_COUNT);
    return First_Prime_Values[no];
  }
#endif
  ;

int Bigint_Ferma_Prime_Test(YOYO_BIGINT *bint, int q)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int is_prime = 1;
    __Auto_Release
      {
        int i;
        YOYO_BIGINT *p   = Bigint_Alloca(bint->digits);
        YOYO_BIGINT *p_1 = Bigint_Alloca(bint->digits);
        YOYO_BIGINT *t   = Bigint_Alloca(1);
    
        if ( !q ) q = YOYO_PRIME_TEST_Q;
        STRICT_REQUIRE( q > 0 && q < YOYO_PRIME_MAX_COUNT );

        p = Bigint_Copy_To(bint,p);
        p_1 = Bigint_Sub_Short(Bigint_Copy_To(bint,p_1),1);

        for ( i =0; is_prime && i < q; ++i )
          {
            t->value[0] = First_Prime_Values[i];
            t->digits = 1;
            if ( ! Bigint_Is_1(Bigint_Expmod(t,p_1,p)) )
              is_prime = 0;
          }
      }
      
    return is_prime;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Prime(int bits, int q, int maxcount,YOYO_BIGINT *tmp)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i,n;
    YOYO_BIGINT *ret = 0;
    YOYO_BIGINT *r = tmp;
    
    if ( !q ) q = YOYO_PRIME_TEST_Q;
    if ( !maxcount ) maxcount = 101;
    
    STRICT_REQUIRE( maxcount > 0 );
    STRICT_REQUIRE( bits > 8 );
    STRICT_REQUIRE( q > 0 && q < 500 );

    n = Yo_MIN(128,bits-3);







|
|

|



|
|
|




|
|
|
















|



|






|



|




|


|
|
|
|




|

|





|
|





|
|
|

|
|


















|
|


|
|

|







1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
      }
      
    return R;
  }
#endif
  ;

YO_BIGINT *Bigint_Invmod(YO_BIGINT *bint, YO_BIGINT *mod)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *i = 0;
    
    __Auto_Ptr(i)
      {
        YO_BIGINT *b = Bigint_Copy(mod);
        YO_BIGINT *j = Bigint_Init(1);
        YO_BIGINT *c = Bigint_Copy(bint);
        i = Bigint_Init(0);
    
        while ( c->value[0] || !Bigint_Is_0(c) )
          {
            YO_BIGINT *y;
            YO_BIGINT *q;
            YO_BIGINT *x;
            x = Bigint_Divrem(b,c,&y);
            b = c;
            c = y;
            q = Bigint_Sub(i,Bigint_Mul(Bigint_Copy(j),x));
            i = j;
            j = q;
          }
      
        if ( i->sign < 0 ) i = Bigint_Add(i,mod);
      }
    
    return i;
  }
#endif
  ;

#ifndef _YO_BINGINT_BUILTIN
extern
#endif
unsigned short First_Prime_Values[]
#ifdef _YO_BINGINT_BUILTIN
= {
#include "prime_values.inc"        
}
#endif
  ;

#ifndef _YO_BINGINT_BUILTIN
extern
#endif
int First_Prime_Values_Count
#ifdef _YO_BINGINT_BUILTIN
= sizeof(First_Prime_Values)/sizeof(First_Prime_Values[0])
#endif
  ;

#ifdef _YO_BINGINT_BUILTIN
enum 
  { 
    YO_PRIME_MAX_COUNT = /*1229*/ sizeof(First_Prime_Values)/sizeof(First_Prime_Values[0]),
    YO_PRIME_RSAPUBLIC_MIN = 256, 
    YO_PRIME_RSAPUBLIC_MAX = YO_PRIME_MAX_COUNT,
    YO_PRIME_TEST_Q = 32,
  };
#endif

halflong_t First_Prime(int no)
#ifdef _YO_BINGINT_BUILTIN
  {
    STRICT_REQUIRE(no >= 0 && no < YO_PRIME_MAX_COUNT);
    return First_Prime_Values[no];
  }
#endif
  ;

int Bigint_Ferma_Prime_Test(YO_BIGINT *bint, int q)
#ifdef _YO_BINGINT_BUILTIN
  {
    int is_prime = 1;
    __Auto_Release
      {
        int i;
        YO_BIGINT *p   = Bigint_Alloca(bint->digits);
        YO_BIGINT *p_1 = Bigint_Alloca(bint->digits);
        YO_BIGINT *t   = Bigint_Alloca(1);
    
        if ( !q ) q = YO_PRIME_TEST_Q;
        STRICT_REQUIRE( q > 0 && q < YO_PRIME_MAX_COUNT );

        p = Bigint_Copy_To(bint,p);
        p_1 = Bigint_Sub_Short(Bigint_Copy_To(bint,p_1),1);

        for ( i =0; is_prime && i < q; ++i )
          {
            t->value[0] = First_Prime_Values[i];
            t->digits = 1;
            if ( ! Bigint_Is_1(Bigint_Expmod(t,p_1,p)) )
              is_prime = 0;
          }
      }
      
    return is_prime;
  }
#endif
  ;

YO_BIGINT *Bigint_Prime(int bits, int q, int maxcount,YO_BIGINT *tmp)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i,n;
    YO_BIGINT *ret = 0;
    YO_BIGINT *r = tmp;
    
    if ( !q ) q = YO_PRIME_TEST_Q;
    if ( !maxcount ) maxcount = 101;
    
    STRICT_REQUIRE( maxcount > 0 );
    STRICT_REQUIRE( bits > 8 );
    STRICT_REQUIRE( q > 0 && q < 500 );

    n = Yo_MIN(128,bits-3);
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
                break;
              }
            r = Bigint_Add_Short(r,2);
          }
       }
     
    if ( !ret )
      __Raise(YOYO_ERROR_LIMIT_REACHED,"failed to generate prime");
    return ret;
  }
#endif
  ;
  
void Bigint_Generate_Rsa_PQ(
  YOYO_BIGINT /*out*/ **rsa_P, int pBits,
  YOYO_BIGINT /*out*/ **rsa_Q, int qBits,
  YOYO_BIGINT /*out*/ **rsa_N)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int lt = 0;
    int bits = qBits+pBits-1;
    YOYO_BIGINT *nMax = Bigint_Init(1);
    YOYO_BIGINT *nMin = Bigint_Init(1);
    YOYO_BIGINT *n, *p, *q;
    YOYO_BIGINT *pr = Bigint_Alloca(Bigint_Digits_Of_Bits(pBits)+1);
    YOYO_BIGINT *qr = Bigint_Alloca(Bigint_Digits_Of_Bits(qBits)+1);
    YOYO_BIGINT *nr = Bigint_Alloca(Bigint_Digits_Of_Bits(bits)+1);

    nMax = Bigint_Sub_Short(Bigint_Lshift(nMax,bits),1);
    nMin = Bigint_Lshift(nMin,bits-1);

    REQUIRE(bits >= 33);
    STRICT_REQUIRE(pBits > 0);
    STRICT_REQUIRE(qBits > 0);







|






|
|
|
|



|
|
|
|
|
|







1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
                break;
              }
            r = Bigint_Add_Short(r,2);
          }
       }
     
    if ( !ret )
      __Raise(YO_ERROR_LIMIT_REACHED,"failed to generate prime");
    return ret;
  }
#endif
  ;
  
void Bigint_Generate_Rsa_PQ(
  YO_BIGINT /*out*/ **rsa_P, int pBits,
  YO_BIGINT /*out*/ **rsa_Q, int qBits,
  YO_BIGINT /*out*/ **rsa_N)
#ifdef _YO_BINGINT_BUILTIN
  {
    int lt = 0;
    int bits = qBits+pBits-1;
    YO_BIGINT *nMax = Bigint_Init(1);
    YO_BIGINT *nMin = Bigint_Init(1);
    YO_BIGINT *n, *p, *q;
    YO_BIGINT *pr = Bigint_Alloca(Bigint_Digits_Of_Bits(pBits)+1);
    YO_BIGINT *qr = Bigint_Alloca(Bigint_Digits_Of_Bits(qBits)+1);
    YO_BIGINT *nr = Bigint_Alloca(Bigint_Digits_Of_Bits(bits)+1);

    nMax = Bigint_Sub_Short(Bigint_Lshift(nMax,bits),1);
    nMin = Bigint_Lshift(nMin,bits-1);

    REQUIRE(bits >= 33);
    STRICT_REQUIRE(pBits > 0);
    STRICT_REQUIRE(qBits > 0);
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
    *rsa_P = (p == pr) ? Bigint_Copy(p) : p;
    *rsa_Q = (q == qr) ? Bigint_Copy(q) : q; 
    *rsa_N = (n == nr) ? Bigint_Copy(n) : n;
  }
#endif
  ;

YOYO_BIGINT *Bigint_Mutal_Prime(YOYO_BIGINT *bint, int bits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    YOYO_BIGINT *ret = 0;
    YOYO_BIGINT *r = Bigint_Alloca(Bigint_Digits_Of_Bits(bits)+1);
    YOYO_BIGINT *d = Bigint_Alloca(bint->digits);
    while (!ret) __Auto_Ptr(ret)
      {
        YOYO_BIGINT *x = Bigint_Prime(bits,0,0,r);
        Bigint_Copy_To(bint,d);
        if ( !Bigint_Is_0(Bigint_Modulo(d,x)) )
          ret = (x == r) ? Bigint_Copy(x) : x;
      }
    return ret;
  }
#endif
  ;
  
YOYO_BIGINT *Bigint_First_Mutal_Prime(YOYO_BIGINT *bint, int skip_primes)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    int i;
    halflong_t rem = 0;
    halflong_t prime;
    YOYO_BIGINT *r = Bigint_Alloca(bint->digits);
    
    REQUIRE(skip_primes > 0 && skip_primes < YOYO_PRIME_MAX_COUNT/2 );
    
    for ( i = skip_primes; !rem && i < YOYO_PRIME_MAX_COUNT; ++i )
      {
        YOYO_BIGINT *x = Bigint_Copy_To(bint,r);
        prime = First_Prime_Values[i];
        Bigint_Divrem_Short(x,prime,&rem);
      }
    
    if ( rem )         
      return Bigint_Init(prime);
    
    return 0;      
  }
#endif
  ;

void Bigint_Generate_Rsa_Key_Pair(
  YOYO_BIGINT /*out*/ **rsa_pub, 
  YOYO_BIGINT /*out*/ **rsa_priv, 
  YOYO_BIGINT /*out*/ **rsa_mod,
  int bits)
#ifdef _YOYO_BINGINT_BUILTIN
  {
    __Auto_Ptr(*rsa_mod)
      {
        YOYO_BIGINT *p, *q, *n, *phi;
        int pBits = Get_Random(bits/5,bits/2);
        int qBits = (bits+1)-pBits;

        STRICT_REQUIRE(pBits < bits/2 && pBits > 0 );
        STRICT_REQUIRE(pBits+qBits == bits+1);

        n = 0;







|
|

|
|
|


|









|
|




|

|

|

|













|
|
|

|



|







1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
    *rsa_P = (p == pr) ? Bigint_Copy(p) : p;
    *rsa_Q = (q == qr) ? Bigint_Copy(q) : q; 
    *rsa_N = (n == nr) ? Bigint_Copy(n) : n;
  }
#endif
  ;

YO_BIGINT *Bigint_Mutal_Prime(YO_BIGINT *bint, int bits)
#ifdef _YO_BINGINT_BUILTIN
  {
    YO_BIGINT *ret = 0;
    YO_BIGINT *r = Bigint_Alloca(Bigint_Digits_Of_Bits(bits)+1);
    YO_BIGINT *d = Bigint_Alloca(bint->digits);
    while (!ret) __Auto_Ptr(ret)
      {
        YO_BIGINT *x = Bigint_Prime(bits,0,0,r);
        Bigint_Copy_To(bint,d);
        if ( !Bigint_Is_0(Bigint_Modulo(d,x)) )
          ret = (x == r) ? Bigint_Copy(x) : x;
      }
    return ret;
  }
#endif
  ;
  
YO_BIGINT *Bigint_First_Mutal_Prime(YO_BIGINT *bint, int skip_primes)
#ifdef _YO_BINGINT_BUILTIN
  {
    int i;
    halflong_t rem = 0;
    halflong_t prime;
    YO_BIGINT *r = Bigint_Alloca(bint->digits);
    
    REQUIRE(skip_primes > 0 && skip_primes < YO_PRIME_MAX_COUNT/2 );
    
    for ( i = skip_primes; !rem && i < YO_PRIME_MAX_COUNT; ++i )
      {
        YO_BIGINT *x = Bigint_Copy_To(bint,r);
        prime = First_Prime_Values[i];
        Bigint_Divrem_Short(x,prime,&rem);
      }
    
    if ( rem )         
      return Bigint_Init(prime);
    
    return 0;      
  }
#endif
  ;

void Bigint_Generate_Rsa_Key_Pair(
  YO_BIGINT /*out*/ **rsa_pub, 
  YO_BIGINT /*out*/ **rsa_priv, 
  YO_BIGINT /*out*/ **rsa_mod,
  int bits)
#ifdef _YO_BINGINT_BUILTIN
  {
    __Auto_Ptr(*rsa_mod)
      {
        YO_BIGINT *p, *q, *n, *phi;
        int pBits = Get_Random(bits/5,bits/2);
        int qBits = (bits+1)-pBits;

        STRICT_REQUIRE(pBits < bits/2 && pBits > 0 );
        STRICT_REQUIRE(pBits+qBits == bits+1);

        n = 0;
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
    
    __Pool(*rsa_pub);
    __Pool(*rsa_priv);
  }
#endif
  ;

YOYO_BIGINT *Bigint_From_Bytes(YOYO_BIGINT *bint, void *data, int len)
#ifdef _YOYO_BINGINT_BUILTIN
  {
#if defined __i386 || defined __x86_64
    int digits = Bigint_Digits_Of_Bytes(len);
    bint = Bigint_Expand_If_Small(bint,digits);
    memset(bint->value,0,bint->digits*sizeof(halflong_t));
    memcpy(bint->value,data,len);
    return bint;
#else
  #error fixme!
#endif
  }
#endif
  ;
  
int Bigint_To_Bytes(YOYO_BIGINT *bint, void *out, int maxlen)
#ifdef _YOYO_BINGINT_BUILTIN
  {
#if defined __i386 || defined __x86_64
    int l = sizeof(halflong_t)*bint->digits;
    byte_t *p = (byte_t*)(bint->value+bint->digits) - 1;
    while ( p != (byte_t*)bint->value && !*p ) --l;
    if ( l > maxlen )
      __Raise(YOYO_ERROR_NO_ENOUGH,"raw bigint outbuffer to small!");
    memcpy(out,bint->value,l);
    return l;
#else
    #error fixme!
#endif
  }
#endif
  ;
  
#endif /* C_once_B4220D86_3019_4E13_8682_D7F809F4E829 */









|
|














|
|






|












1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
    
    __Pool(*rsa_pub);
    __Pool(*rsa_priv);
  }
#endif
  ;

YO_BIGINT *Bigint_From_Bytes(YO_BIGINT *bint, void *data, int len)
#ifdef _YO_BINGINT_BUILTIN
  {
#if defined __i386 || defined __x86_64
    int digits = Bigint_Digits_Of_Bytes(len);
    bint = Bigint_Expand_If_Small(bint,digits);
    memset(bint->value,0,bint->digits*sizeof(halflong_t));
    memcpy(bint->value,data,len);
    return bint;
#else
  #error fixme!
#endif
  }
#endif
  ;
  
int Bigint_To_Bytes(YO_BIGINT *bint, void *out, int maxlen)
#ifdef _YO_BINGINT_BUILTIN
  {
#if defined __i386 || defined __x86_64
    int l = sizeof(halflong_t)*bint->digits;
    byte_t *p = (byte_t*)(bint->value+bint->digits) - 1;
    while ( p != (byte_t*)bint->value && !*p ) --l;
    if ( l > maxlen )
      __Raise(YO_ERROR_NO_ENOUGH,"raw bigint outbuffer to small!");
    memcpy(out,bint->value,l);
    return l;
#else
    #error fixme!
#endif
  }
#endif
  ;
  
#endif /* C_once_B4220D86_3019_4E13_8682_D7F809F4E829 */


Changes to bio.hc.
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

*/

#ifndef C_once_91A90154_CD39_414F_9D05_4B45029B172F
#define C_once_91A90154_CD39_414F_9D05_4B45029B172F

#ifdef _LIBYOYO
#define _YOYO_BIO_BUILTIN
#endif

enum 
  { 
    YOYO_BIO_BUFFER_SIZE = 512,
    YOYO_BIO_WRITE = __FOUR_CHARS('W','R','I','T'), 
    YOYO_BIO_READ  = __FOUR_CHARS('R','E','A','D'),
  };

typedef struct _YOYO_BIO_BUFFER
  {
    int    start, end;
    byte_t data[YOYO_BIO_BUFFER_SIZE];
  } YOYO_BIO_BUFFER;

typedef struct _YOYO_BIO
  {
    YOYO_BIO_BUFFER bf;
    int (*inout)(void*,void*,int,int);
    void *strm;
    int  direction;
  } YOYO_BIO;

YOYO_BIO *Bio_Input(void *strm)
#ifdef _YOYO_BIO_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YOYO_BIO_Destruct},
        {Oj_Read_OjMID,        Buffer_File_Read},
      };
    YOYO_BIO *bio = __Object(sizeof(YOYO_BIO),funcs);
    bio->direction = YOYO_BIO_READ;
    bio->inout = (int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Read_OjMID,YO_RAISE_ERROR)
    bio->strm = __Refe(strm);
    return bio;
  }
#endif  
  ;
  
YOYO_BIO *Bio_Output(void *strm)
#ifdef _YOYO_BIO_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YOYO_BIO_Destruct},
        {Oj_Write_OjMID,       Bio_Write},
        {Oj_Flush_OjMID,       Bio_Flush},
      };
      
    YOYO_BIO *bio = __Object(sizeof(YOYO_BIO),funcs);
    bio->direction = YOYO_BIO_WRITE;
    bio->inout = (int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Write_OjMID,YO_RAISE_ERROR)
    bio->strm  = __Refe(strm);
    return bio;
  }
#endif  
  ;

void Bio_Flush(YOYO_BIO *bio)
#ifdef _YOYO_BIO_BUILTIN
  {
    /* output bio doesn´t use bf.start */
    if ( bio->direction != YOYO_BIO_WRITE )
      __Raise(YOYO_ERROR_UNSUPPORTED,__yoTa("input BIO doesn't support Flush"));
    if ( bio->bf.data )
      bio->inout(bio->strm,bio->bf.data,bio->bf.end);
    bio->bf.end = 0;
    Oj_Flush(bio->strm);
  }
#endif
  ;
  
int Bio_Write(YOYO_BIO *bio,void *dta,int count,int mincount)
#ifdef _YOYO_BIO_BUILTIN
  {
    /* output bio doesn´t use bf.start */
    int q,cc=0;
    
    if ( bio->direction != YOYO_BIO_WRITE )
      __Raise(YOYO_ERROR_UNSUPPORTED,__yoTa("input BIO doesn't support Write"));
    
    while ( cc != count )
      {
        q = Yo_MIN(count-cc,(sizeof(bio->bf.data)-bio->bf.end));
        
        if ( q )
          {







|




|
|
|


|


|
|

|

|



|

|
|

|

|


|
|







|
|

|

|




|
|







|
|


|
|








|
|




|
|







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

*/

#ifndef C_once_91A90154_CD39_414F_9D05_4B45029B172F
#define C_once_91A90154_CD39_414F_9D05_4B45029B172F

#ifdef _LIBYOYO
#define _YO_BIO_BUILTIN
#endif

enum 
  { 
    YO_BIO_BUFFER_SIZE = 512,
    YO_BIO_WRITE = __FOUR_CHARS('W','R','I','T'), 
    YO_BIO_READ  = __FOUR_CHARS('R','E','A','D'),
  };

typedef struct _YO_BIO_BUFFER
  {
    int    start, end;
    byte_t data[YO_BIO_BUFFER_SIZE];
  } YO_BIO_BUFFER;

typedef struct _YO_BIO
  {
    YO_BIO_BUFFER bf;
    int (*inout)(void*,void*,int,int);
    void *strm;
    int  direction;
  } YO_BIO;

YO_BIO *Bio_Input(void *strm)
#ifdef _YO_BIO_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YO_BIO_Destruct},
        {Oj_Read_OjMID,        Buffer_File_Read},
      };
    YO_BIO *bio = __Object(sizeof(YO_BIO),funcs);
    bio->direction = YO_BIO_READ;
    bio->inout = (int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Read_OjMID,YO_RAISE_ERROR)
    bio->strm = __Refe(strm);
    return bio;
  }
#endif  
  ;
  
YO_BIO *Bio_Output(void *strm)
#ifdef _YO_BIO_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YO_BIO_Destruct},
        {Oj_Write_OjMID,       Bio_Write},
        {Oj_Flush_OjMID,       Bio_Flush},
      };
      
    YO_BIO *bio = __Object(sizeof(YO_BIO),funcs);
    bio->direction = YO_BIO_WRITE;
    bio->inout = (int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Write_OjMID,YO_RAISE_ERROR)
    bio->strm  = __Refe(strm);
    return bio;
  }
#endif  
  ;

void Bio_Flush(YO_BIO *bio)
#ifdef _YO_BIO_BUILTIN
  {
    /* output bio doesn´t use bf.start */
    if ( bio->direction != YO_BIO_WRITE )
      __Raise(YO_ERROR_UNSUPPORTED,__yoTa("input BIO doesn't support Flush"));
    if ( bio->bf.data )
      bio->inout(bio->strm,bio->bf.data,bio->bf.end);
    bio->bf.end = 0;
    Oj_Flush(bio->strm);
  }
#endif
  ;
  
int Bio_Write(YO_BIO *bio,void *dta,int count,int mincount)
#ifdef _YO_BIO_BUILTIN
  {
    /* output bio doesn´t use bf.start */
    int q,cc=0;
    
    if ( bio->direction != YO_BIO_WRITE )
      __Raise(YO_ERROR_UNSUPPORTED,__yoTa("input BIO doesn't support Write"));
    
    while ( cc != count )
      {
        q = Yo_MIN(count-cc,(sizeof(bio->bf.data)-bio->bf.end));
        
        if ( q )
          {
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
      }
       
    return cc;
  }
#endif
  ;

int _Bio_Fill_Buffer(YOYO_BIO *bio, int read_or_die)
#ifdef _YOYO_BIO_BUILTIN
  {
    bio->bf.start = 0;
    bio->bf.end = 0;
    q = bio->inout(bio->strm,bio->bf.data,sizeof(bio->bf.data),read_or_die?1:0);
    bio->bf.end = q;

    if ( !q && read_or_die ) 
      __Raise(YOYO_ERROR_UNEXPECTED,__yoTa("chained read should return least 1 byte or die!",0))
  }
#endif
  ;
  
int Bio_Read(YOYO_BIO *bio,void *out,int count,int mincount)
#ifdef _YOYO_BIO_BUILTIN
  {
    int q,cc = 0;
    if ( bio->direction != YOYO_BIO_READ )
      __Raise(YOYO_ERROR_UNSUPPORTED,__yoTa("output BIO doesn't support Read"));
    
    if ( !count ) return 0;
    
    while ( cc != count )
      {
        q = Yo_MIN(count-cc,(bio->bf.end-bio->bf.start));








|
|







|




|
|


|
|







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
      }
       
    return cc;
  }
#endif
  ;

int _Bio_Fill_Buffer(YO_BIO *bio, int read_or_die)
#ifdef _YO_BIO_BUILTIN
  {
    bio->bf.start = 0;
    bio->bf.end = 0;
    q = bio->inout(bio->strm,bio->bf.data,sizeof(bio->bf.data),read_or_die?1:0);
    bio->bf.end = q;

    if ( !q && read_or_die ) 
      __Raise(YO_ERROR_UNEXPECTED,__yoTa("chained read should return least 1 byte or die!",0))
  }
#endif
  ;
  
int Bio_Read(YO_BIO *bio,void *out,int count,int mincount)
#ifdef _YO_BIO_BUILTIN
  {
    int q,cc = 0;
    if ( bio->direction != YO_BIO_READ )
      __Raise(YO_ERROR_UNSUPPORTED,__yoTa("output BIO doesn't support Read"));
    
    if ( !count ) return 0;
    
    while ( cc != count )
      {
        q = Yo_MIN(count-cc,(bio->bf.end-bio->bf.start));

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
      }
    
    return cc;
  }
#endif
  ;

char *Bio_Read_Line(YOYO_BIO *bio, YOYO_BUFFER *bf)
#ifdef _YOYO_BIO_BUILTIN
  {
    int i, E;
    YOYO_BUFFER *out = bf;
    if ( !out ) out  = Buffer_Init(0);
    out->count = 0;
    
    for(;;)
      {
        char *p;
        if ( bio->bf.end == bio->bf.start )







|
|


|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
      }
    
    return cc;
  }
#endif
  ;

char *Bio_Read_Line(YO_BIO *bio, YO_BUFFER *bf)
#ifdef _YO_BIO_BUILTIN
  {
    int i, E;
    YO_BUFFER *out = bf;
    if ( !out ) out  = Buffer_Init(0);
    out->count = 0;
    
    for(;;)
      {
        char *p;
        if ( bio->bf.end == bio->bf.start )
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
      }
    else
      return bf->at;
  }
#endif 
  ;

int Bio_Copy_Into(YOYO_BIO *bio, void *strm, int count)
#ifdef _YOYO_BIO_BUILTIN
  {
    byte_t bf[512];
    int i;
    int (*oj_read)(void*,void*,int,int) = 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Read_OjMID,YO_RAISE_ERROR));
    for ( i = 0; i < count || count < 0; )
      {
        int l = oj_read(strm,bf,sizeof(bf),0);
        if ( l ) 
          {
            Bio_Write(bio,bf,l,l);
            i += l;
          }
        else if ( count < 0 )
          break;
        else
          __Raise(YOYO_ERROR_IO_EOF,__yoTa("stream out of data",0));
      }
    return i;
  }
#endif 
  ;

int Bio_Copy_From(YOYO_BIO *bio, void *strm, int count)
#ifdef _YOYO_BIO_BUILTIN
  {
    byte_t bf[512];
    int i;
    int (*oj_write)(void*,void*,int,int) = 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Write_OjMID,YO_RAISE_ERROR));
    for ( i = 0; i < count || count < 0; )
      {
        int l = Bio_Read(bio,bf,sizeof(bf),0);
        if ( l ) 
          {
            oj_write(strm,bf,l,l);
            i += l;
          }
        else if ( count < 0 )
          break;
        else
          __Raise(YOYO_ERROR_IO_EOF,__yoTa("stream out of data",0));
      }
    return i;
  }
#endif 
  ;

void Bio_Reset(YOYO_BIO *bio)
#ifdef _YOYO_BIO_BUILTIN
  {
    bio->bf.start = bio->bf.end = 0;
  }
#endif 
  ;

#endif /* C_once_91A90154_CD39_414F_9D05_4B45029B172F */







|
|
















|






|
|
















|






|
|







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
      }
    else
      return bf->at;
  }
#endif 
  ;

int Bio_Copy_Into(YO_BIO *bio, void *strm, int count)
#ifdef _YO_BIO_BUILTIN
  {
    byte_t bf[512];
    int i;
    int (*oj_read)(void*,void*,int,int) = 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Read_OjMID,YO_RAISE_ERROR));
    for ( i = 0; i < count || count < 0; )
      {
        int l = oj_read(strm,bf,sizeof(bf),0);
        if ( l ) 
          {
            Bio_Write(bio,bf,l,l);
            i += l;
          }
        else if ( count < 0 )
          break;
        else
          __Raise(YO_ERROR_IO_EOF,__yoTa("stream out of data",0));
      }
    return i;
  }
#endif 
  ;

int Bio_Copy_From(YO_BIO *bio, void *strm, int count)
#ifdef _YO_BIO_BUILTIN
  {
    byte_t bf[512];
    int i;
    int (*oj_write)(void*,void*,int,int) = 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&strm,Oj_Write_OjMID,YO_RAISE_ERROR));
    for ( i = 0; i < count || count < 0; )
      {
        int l = Bio_Read(bio,bf,sizeof(bf),0);
        if ( l ) 
          {
            oj_write(strm,bf,l,l);
            i += l;
          }
        else if ( count < 0 )
          break;
        else
          __Raise(YO_ERROR_IO_EOF,__yoTa("stream out of data",0));
      }
    return i;
  }
#endif 
  ;

void Bio_Reset(YO_BIO *bio)
#ifdef _YO_BIO_BUILTIN
  {
    bio->bf.start = bio->bf.end = 0;
  }
#endif 
  ;

#endif /* C_once_91A90154_CD39_414F_9D05_4B45029B172F */
Changes to blowfish.hc.
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

*/

#ifndef C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD
#define C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD

#ifdef _LIBYOYO
#define _YOYO_BLOWFISH_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"

typedef struct _YOYO_BLOWFISH
  {
    uint_t P[16 + 2];
    uint_t S[4][256];
  } YOYO_BLOWFISH;

#ifdef _YOYO_BLOWFISH_BUILTIN

static uint_t Blowfish_P[16 + 2] = 
  {
    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,







|






|



|

|







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

*/

#ifndef C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD
#define C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD

#ifdef _LIBYOYO
#define _YO_BLOWFISH_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"

typedef struct _YO_BLOWFISH
  {
    uint_t P[16 + 2];
    uint_t S[4][256];
  } YO_BLOWFISH;

#ifdef _YO_BLOWFISH_BUILTIN

static uint_t Blowfish_P[16 + 2] = 
  {
    0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
    0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
    0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
    0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
      0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
      0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
      0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
      0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }
  };
#endif

#ifdef _YOYO_BLOWFISH_BUILTIN
#define F(S,X) \
      ((( (S)[0][((X) >> 24)] + (S)[1][(((X) >> 16)&0x0ff)] ) \
       ^ (S)[2][((X) >> 8)&0x0ff] ) \
       + (S)[3][(X) & 0x0ff])
#endif

void Blowfish_Encrypt8_(YOYO_BLOWFISH *self, uint_t *Lx, uint_t *Rx)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    uint_t  L = *Lx;
    uint_t  R = *Rx;
    uint_t  temp;
    int     i;
  
    for (i = 0; i < 16; ++i) 







|






|
|







336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
      0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
      0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
      0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
      0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }
  };
#endif

#ifdef _YO_BLOWFISH_BUILTIN
#define F(S,X) \
      ((( (S)[0][((X) >> 24)] + (S)[1][(((X) >> 16)&0x0ff)] ) \
       ^ (S)[2][((X) >> 8)&0x0ff] ) \
       + (S)[3][(X) & 0x0ff])
#endif

void Blowfish_Encrypt8_(YO_BLOWFISH *self, uint_t *Lx, uint_t *Rx)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    uint_t  L = *Lx;
    uint_t  R = *Rx;
    uint_t  temp;
    int     i;
  
    for (i = 0; i < 16; ++i) 
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

    *Rx = R ^ self->P[16];
    *Lx = L ^ self->P[16 + 1];
  }
#endif
  ;

void Blowfish_Encrypt8(YOYO_BLOWFISH *self,void *block8)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    uint_t L = Four_To_Unsigned_BE((byte_t*)block8+0);
    uint_t R = Four_To_Unsigned_BE((byte_t*)block8+4);
    Blowfish_Encrypt8_(self,&L,&R);
    Unsigned_To_Four_BE(L,(byte_t*)block8+0);
    Unsigned_To_Four_BE(R,(byte_t*)block8+4);
  }
#endif
  ;

void Blowfish_Decrypt8_(YOYO_BLOWFISH *self, uint_t *Lx, uint_t *Rx)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    uint_t  L = *Lx;
    uint_t  R = *Rx;
    uint_t  temp;
    int     i;
    
    for (i = 16 + 1; i > 1; --i) 







|
|










|
|







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

    *Rx = R ^ self->P[16];
    *Lx = L ^ self->P[16 + 1];
  }
#endif
  ;

void Blowfish_Encrypt8(YO_BLOWFISH *self,void *block8)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    uint_t L = Four_To_Unsigned_BE((byte_t*)block8+0);
    uint_t R = Four_To_Unsigned_BE((byte_t*)block8+4);
    Blowfish_Encrypt8_(self,&L,&R);
    Unsigned_To_Four_BE(L,(byte_t*)block8+0);
    Unsigned_To_Four_BE(R,(byte_t*)block8+4);
  }
#endif
  ;

void Blowfish_Decrypt8_(YO_BLOWFISH *self, uint_t *Lx, uint_t *Rx)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    uint_t  L = *Lx;
    uint_t  R = *Rx;
    uint_t  temp;
    int     i;
    
    for (i = 16 + 1; i > 1; --i) 
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

    *Rx = R ^ self->P[1];
    *Lx = L ^ self->P[0];
  }
#endif
  ;

void Blowfish_Decrypt8(YOYO_BLOWFISH *self,void *block8)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    uint_t L = Four_To_Unsigned_BE((byte_t*)block8+0);
    uint_t R = Four_To_Unsigned_BE((byte_t*)block8+4);
    Blowfish_Decrypt8_(self,&L,&R);
    Unsigned_To_Four_BE(L,(byte_t*)block8+0);
    Unsigned_To_Four_BE(R,(byte_t*)block8+4);
  }
#endif
  ;

#ifdef _YOYO_BLOWFISH_BUILTIN
#undef F
#endif

void Blowfish_Destruct(YOYO_BLOWFISH *self)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    __Destruct(self);
  }
#endif
  ;

void *Blowfish_Init_Static(YOYO_BLOWFISH *self, void *key, int key_len) 
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    int i, j, k;
    uint_t data;
    uint_t L = 0, R = 0;

    key_len = Yo_MIN(key_len,56);








|
|










|



|
|






|
|







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

    *Rx = R ^ self->P[1];
    *Lx = L ^ self->P[0];
  }
#endif
  ;

void Blowfish_Decrypt8(YO_BLOWFISH *self,void *block8)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    uint_t L = Four_To_Unsigned_BE((byte_t*)block8+0);
    uint_t R = Four_To_Unsigned_BE((byte_t*)block8+4);
    Blowfish_Decrypt8_(self,&L,&R);
    Unsigned_To_Four_BE(L,(byte_t*)block8+0);
    Unsigned_To_Four_BE(R,(byte_t*)block8+4);
  }
#endif
  ;

#ifdef _YO_BLOWFISH_BUILTIN
#undef F
#endif

void Blowfish_Destruct(YO_BLOWFISH *self)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    __Destruct(self);
  }
#endif
  ;

void *Blowfish_Init_Static(YO_BLOWFISH *self, void *key, int key_len) 
#ifdef _YO_BLOWFISH_BUILTIN
  {
    int i, j, k;
    uint_t data;
    uint_t L = 0, R = 0;

    key_len = Yo_MIN(key_len,56);

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
      
    return self;
  }
#endif
  ;

void *Blowfish_Init(void *key,int key_len) 
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Blowfish_Destruct},
        {Oj_Encrypt8_OjMID, Blowfish_Encrypt8},
        {Oj_Decrypt8_OjMID, Blowfish_Decrypt8},
        {0}};
    
    YOYO_BLOWFISH *self = Yo_Object(sizeof(YOYO_BLOWFISH),funcs);

    return Blowfish_Init_Static(self,key,key_len);
  }
#endif
  ;

void *Blowfish_Object_Init_With_Text_Key(char *Skey)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    byte_t key[16] = {0};
    Md5_Digest(Skey,strlen(Skey),key);
    return Blowfish_Init(key,16);
  }
#endif
  ;

#define Blowfish_Decipher(Skey) Blowfish_Object_Init_With_Text_Key(Skey)
#define Blowfish_Encipher(Skey) Blowfish_Object_Init_With_Text_Key(Skey)

void Blowfish_Encrypt(char *data, int len, char *passwd)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    int i;
    YOYO_BLOWFISH bfctx = {{0},{{0},{0}}};
    Blowfish_Init_Static(&bfctx,passwd,strlen(passwd));
    
    for ( i = 0; i < len && len-i >= 8 ; i += 8 )
      {
        Blowfish_Encrypt8(&bfctx,data+i);
      }
  }
#endif
  ;

void Blowfish_Decrypt(char *data, int len, char *passwd)
#ifdef _YOYO_BLOWFISH_BUILTIN
  {
    int i;
    YOYO_BLOWFISH bfctx = {{0},{{0},{0}}};
    Blowfish_Init_Static(&bfctx,passwd,strlen(passwd));
    
    for ( i = 0; i < len && len-i >= 8 ; i += 8 )
      {
        Blowfish_Decrypt8(&bfctx,data+i);
      }
  }
#endif
  ;

#endif /* C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD */








|

|






|







|












|


|











|


|












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
      
    return self;
  }
#endif
  ;

void *Blowfish_Init(void *key,int key_len) 
#ifdef _YO_BLOWFISH_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Blowfish_Destruct},
        {Oj_Encrypt8_OjMID, Blowfish_Encrypt8},
        {Oj_Decrypt8_OjMID, Blowfish_Decrypt8},
        {0}};
    
    YO_BLOWFISH *self = Yo_Object(sizeof(YO_BLOWFISH),funcs);

    return Blowfish_Init_Static(self,key,key_len);
  }
#endif
  ;

void *Blowfish_Object_Init_With_Text_Key(char *Skey)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    byte_t key[16] = {0};
    Md5_Digest(Skey,strlen(Skey),key);
    return Blowfish_Init(key,16);
  }
#endif
  ;

#define Blowfish_Decipher(Skey) Blowfish_Object_Init_With_Text_Key(Skey)
#define Blowfish_Encipher(Skey) Blowfish_Object_Init_With_Text_Key(Skey)

void Blowfish_Encrypt(char *data, int len, char *passwd)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    int i;
    YO_BLOWFISH bfctx = {{0},{{0},{0}}};
    Blowfish_Init_Static(&bfctx,passwd,strlen(passwd));
    
    for ( i = 0; i < len && len-i >= 8 ; i += 8 )
      {
        Blowfish_Encrypt8(&bfctx,data+i);
      }
  }
#endif
  ;

void Blowfish_Decrypt(char *data, int len, char *passwd)
#ifdef _YO_BLOWFISH_BUILTIN
  {
    int i;
    YO_BLOWFISH bfctx = {{0},{{0},{0}}};
    Blowfish_Init_Static(&bfctx,passwd,strlen(passwd));
    
    for ( i = 0; i < len && len-i >= 8 ; i += 8 )
      {
        Blowfish_Decrypt8(&bfctx,data+i);
      }
  }
#endif
  ;

#endif /* C_once_A87E119A_8C55_442C_94CE_F1B2DF0121AD */

Changes to buffer.hc.
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

*/

#ifndef C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120
#define C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120

#ifdef _LIBYOYO
#define _YOYO_BUFFER_BUILTIN
#endif

#include "yoyo.hc"

/* string.hc */
char *Str_Hex_Byte(byte_t val,char pfx,void *out);

typedef struct _YOYO_BUFFER
  { 
    byte_t *at; 
    int count;
    int capacity;
  } YOYO_BUFFER;

void Buffer_Clear(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    free(bf->at);
    bf->at = 0;
    bf->count = 0;
    bf->capacity = 0;
  }
#endif
  ;
  
void *Buffer_Init(int count);
YOYO_BUFFER *Buffer_Reserve(YOYO_BUFFER *bf,int capacity)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( capacity < 0 )
      __Raise(YOYO_ERROR_OUT_OF_RANGE,0);

    if ( !bf ) bf = Buffer_Init(0);

    if ( bf->capacity < capacity )
      {
        bf->at = __Realloc_Npl(bf->at,capacity+1);
        bf->capacity = capacity;
      }
      
    return bf;
  }
#endif
  ;

YOYO_BUFFER *Buffer_Grow_Reserve(YOYO_BUFFER *bf,int capacity)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( capacity < 0 )
      __Raise(YOYO_ERROR_OUT_OF_RANGE,0);

    if ( !bf ) bf = Buffer_Init(0);

    if ( bf->capacity < capacity )
      {
        capacity = Min_Pow2(capacity);
        bf->at = __Realloc_Npl(bf->at,capacity+1);
        bf->capacity = capacity;
      }
      
    return bf;
  }
#endif
  ;

void Buffer_Resize(YOYO_BUFFER *bf,int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Reserve(bf,count);
    bf->count = count;
    if ( bf->at ) bf->at[bf->count] = 0;
  }
#endif
  ;

void Buffer_Grow(YOYO_BUFFER *bf,int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Grow_Reserve(bf,count);
    bf->count = count;
    bf->at[bf->count] = 0;
  }
#endif
  ;
void Buffer_Append(YOYO_BUFFER *bf,void *S,int len)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( len && S )
      {
        Buffer_Grow_Reserve(bf,bf->count+len);
        memcpy(bf->at+bf->count,S,len);
        bf->count += len;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Fill_Append(YOYO_BUFFER *bf,int c,int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    STRICT_REQUIRE( count >= 0 );

    if ( count > 0 )
      {
        Buffer_Grow_Reserve(bf,bf->count+count);
        memset(bf->at+bf->count,c,count);
        bf->count += count;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Print(YOYO_BUFFER *bf, char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);
  }
#endif
  ;

void Buffer_Puts(YOYO_BUFFER *bf, char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);
    Buffer_Fill_Append(bf,'\n',1);
  }
#endif
  ;
  
void Buffer_Set(YOYO_BUFFER *bf, char *S, int L)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    Buffer_Resize(bf,0);    
    Buffer_Append(bf,S,L);
  }
#endif
  ;

void Buffer_Printf_Va(YOYO_BUFFER *bf, char *fmt, va_list va)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    int q, rq_len;
    
    rq_len = Yo_Detect_Required_Buffer_Size(fmt,va)+1;
    Buffer_Grow_Reserve(bf,bf->count+rq_len);
    
  #ifdef __windoze







|







|




|

|
|










|
|


|














|
|


|















|
|








|
|







|
|















|
|














|
|






|
|







|
|







|
|







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

*/

#ifndef C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120
#define C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120

#ifdef _LIBYOYO
#define _YO_BUFFER_BUILTIN
#endif

#include "yoyo.hc"

/* string.hc */
char *Str_Hex_Byte(byte_t val,char pfx,void *out);

typedef struct _YO_BUFFER
  { 
    byte_t *at; 
    int count;
    int capacity;
  } YO_BUFFER;

void Buffer_Clear(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    free(bf->at);
    bf->at = 0;
    bf->count = 0;
    bf->capacity = 0;
  }
#endif
  ;
  
void *Buffer_Init(int count);
YO_BUFFER *Buffer_Reserve(YO_BUFFER *bf,int capacity)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( capacity < 0 )
      __Raise(YO_ERROR_OUT_OF_RANGE,0);

    if ( !bf ) bf = Buffer_Init(0);

    if ( bf->capacity < capacity )
      {
        bf->at = __Realloc_Npl(bf->at,capacity+1);
        bf->capacity = capacity;
      }
      
    return bf;
  }
#endif
  ;

YO_BUFFER *Buffer_Grow_Reserve(YO_BUFFER *bf,int capacity)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( capacity < 0 )
      __Raise(YO_ERROR_OUT_OF_RANGE,0);

    if ( !bf ) bf = Buffer_Init(0);

    if ( bf->capacity < capacity )
      {
        capacity = Min_Pow2(capacity);
        bf->at = __Realloc_Npl(bf->at,capacity+1);
        bf->capacity = capacity;
      }
      
    return bf;
  }
#endif
  ;

void Buffer_Resize(YO_BUFFER *bf,int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    Buffer_Reserve(bf,count);
    bf->count = count;
    if ( bf->at ) bf->at[bf->count] = 0;
  }
#endif
  ;

void Buffer_Grow(YO_BUFFER *bf,int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    Buffer_Grow_Reserve(bf,count);
    bf->count = count;
    bf->at[bf->count] = 0;
  }
#endif
  ;
void Buffer_Append(YO_BUFFER *bf,void *S,int len)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( len && S )
      {
        Buffer_Grow_Reserve(bf,bf->count+len);
        memcpy(bf->at+bf->count,S,len);
        bf->count += len;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Fill_Append(YO_BUFFER *bf,int c,int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    STRICT_REQUIRE( count >= 0 );

    if ( count > 0 )
      {
        Buffer_Grow_Reserve(bf,bf->count+count);
        memset(bf->at+bf->count,c,count);
        bf->count += count;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Print(YO_BUFFER *bf, char *S)
#ifdef _YO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);
  }
#endif
  ;

void Buffer_Puts(YO_BUFFER *bf, char *S)
#ifdef _YO_BUFFER_BUILTIN
  {
    Buffer_Append(bf,S,-1);
    Buffer_Fill_Append(bf,'\n',1);
  }
#endif
  ;
  
void Buffer_Set(YO_BUFFER *bf, char *S, int L)
#ifdef _YO_BUFFER_BUILTIN
  {
    Buffer_Resize(bf,0);    
    Buffer_Append(bf,S,L);
  }
#endif
  ;

void Buffer_Printf_Va(YO_BUFFER *bf, char *fmt, va_list va)
#ifdef _YO_BUFFER_BUILTIN
  {
    int q, rq_len;
    
    rq_len = Yo_Detect_Required_Buffer_Size(fmt,va)+1;
    Buffer_Grow_Reserve(bf,bf->count+rq_len);
    
  #ifdef __windoze
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
    STRICT_REQUIRE(bf->count >= 0 && bf->count <= bf->capacity);
  
    bf->at[bf->count] = 0;
  }
#endif
  ;

void Buffer_Printf(YOYO_BUFFER *bf, char *fmt, ...)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    va_list va;
    va_start(va,fmt);
    Buffer_Printf_Va(bf,fmt,va);
    va_end(va);
  }
#endif
  ;

void Buffer_Hex_Append(YOYO_BUFFER *bf, void *S, int len)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( len && S )
      {
        int i;
        Buffer_Grow_Reserve(bf,bf->count+len*2);
        for ( i = 0; i < len; ++i )
          Str_Hex_Byte( ((byte_t*)S)[i], 0, bf->at+bf->count+i*2 );

        bf->count += len*2;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Quote_Append(YOYO_BUFFER *bf, void *S, int len, int brk)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    byte_t *q = S;
    byte_t *p = q;
    byte_t *E;
    
    if ( len < 0 ) 
      len = S?strlen(S):0;







|
|









|
|


















|
|







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
    STRICT_REQUIRE(bf->count >= 0 && bf->count <= bf->capacity);
  
    bf->at[bf->count] = 0;
  }
#endif
  ;

void Buffer_Printf(YO_BUFFER *bf, char *fmt, ...)
#ifdef _YO_BUFFER_BUILTIN
  {
    va_list va;
    va_start(va,fmt);
    Buffer_Printf_Va(bf,fmt,va);
    va_end(va);
  }
#endif
  ;

void Buffer_Hex_Append(YO_BUFFER *bf, void *S, int len)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( len && S )
      {
        int i;
        Buffer_Grow_Reserve(bf,bf->count+len*2);
        for ( i = 0; i < len; ++i )
          Str_Hex_Byte( ((byte_t*)S)[i], 0, bf->at+bf->count+i*2 );

        bf->count += len*2;
        bf->at[bf->count] = 0;
      }
  }
#endif
  ;

void Buffer_Quote_Append(YO_BUFFER *bf, void *S, int len, int brk)
#ifdef _YO_BUFFER_BUILTIN
  {
    byte_t *q = S;
    byte_t *p = q;
    byte_t *E;
    
    if ( len < 0 ) 
      len = S?strlen(S):0;
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
          
        q = p;
      }
  }
#endif
  ;

void Buffer_Html_Quote_Append(YOYO_BUFFER *bf, void *S, int len)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    byte_t *q = S;
    byte_t *p = q;
    byte_t *E;
    
    if ( len < 0 ) 
      len = S?strlen(S):0;







|
|







293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
          
        q = p;
      }
  }
#endif
  ;

void Buffer_Html_Quote_Append(YO_BUFFER *bf, void *S, int len)
#ifdef _YO_BUFFER_BUILTIN
  {
    byte_t *q = S;
    byte_t *p = q;
    byte_t *E;
    
    if ( len < 0 ) 
      len = S?strlen(S):0;
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
          
        q = p;
      }
  }
#endif
  ;

void Buffer_Insert(YOYO_BUFFER *bf,int pos,void *S,int len)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( pos < 0 ) pos = bf->count + pos + 1;
    if ( pos < 0 || pos > bf->count ) 
      __Raise(YOYO_ERROR_OUT_OF_RANGE,0);
    
    Buffer_Grow_Reserve(bf,bf->count+len);
    if ( pos < bf->count )
      memmove(bf->at+pos+len,bf->at+pos,bf->count-pos);
    memcpy(bf->at+pos,S,len);
    bf->count += len;
    bf->at[bf->count] = 0;
  }
#endif
  ;


#define Buffer_Take_Data(Bf) __Pool(Buffer_Take_Data_Npl(Bf))
void *Buffer_Take_Data_Npl(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    void *R = bf->at;
    bf->count = 0;
    bf->at = 0;
    bf->capacity = 0;
    return R;
  }
#endif
  ;
  
void *Buffer_Take_Data_Non(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    void *n = Buffer_Take_Data(bf);
    if ( !n ) 
      { 
        n = Yo_Malloc(1);
        *((char*)n) = 0;
      }
    return n;
  }
#endif
  ;
  
#define Buffer_COUNT(Bf)    ((int)((YOYO_BUFFER *)(Bf))->count)
#define Buffer_CAPACITY(Bf) ((int)((YOYO_BUFFER *)(Bf))->capacity)
#define Buffer_BEGIN(Bf)    (((YOYO_BUFFER *)(Bf))->at)
#define Buffer_END(Bf)      (Buffer_BEGIN(Bf)+Buffer_COUNT(Bf))

int Buffer_Count(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_COUNT(bf);
    return 0;
  }
#endif
  ;
  
int Buffer_Capacity(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_CAPACITY(bf);
    return 0;
  }
#endif
  ;
 void *Buffer_Begin(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_BEGIN(bf);
    return 0;
  }
#endif
  ;

void *Buffer_End(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_END(bf);
    return 0;
  }
#endif
  ;

void Buffer_Destruct(YOYO_BUFFER *bf)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    if ( bf->at )
      free(bf->at);
    __Destruct(bf);
  }
#endif
  ;

void *Buffer_Init(int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    YOYO_BUFFER *bf = Yo_Object_Dtor(sizeof(YOYO_BUFFER),Buffer_Destruct);
    if ( count )
      Buffer_Resize(bf,count);
    return bf;
  }
#endif
  ;
  
void *Buffer_Acquire(char *S)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    YOYO_BUFFER *bf = Yo_Object_Dtor(sizeof(YOYO_BUFFER),Buffer_Destruct);
    int L = strlen(S);
    bf->at = S;
    bf->count = L;
    bf->capacity = L;
    return bf;
  }
#endif
  ;

void *Buffer_Zero(int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    YOYO_BUFFER *bf = Buffer_Init(count);
    if ( bf->count ) 
      memset(bf->at,0,bf->count);
    return bf;
  }
#endif
  ;

void *Buffer_Copy(void *S, int count)
#ifdef _YOYO_BUFFER_BUILTIN
  {
    YOYO_BUFFER *bf = Buffer_Init(count);
    if ( count )
      memcpy(bf->at,S,count);
    return bf;
  }
#endif
  ;

#endif /* C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120 */








|
|






|













|
|










|
|












|
|
|


|
|








|
|







|
|








|
|








|
|









|

|








|

|










|

|








|

|









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
          
        q = p;
      }
  }
#endif
  ;

void Buffer_Insert(YO_BUFFER *bf,int pos,void *S,int len)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( len < 0 ) /* appending C string */
      len = S?strlen(S):0;

    if ( pos < 0 ) pos = bf->count + pos + 1;
    if ( pos < 0 || pos > bf->count ) 
      __Raise(YO_ERROR_OUT_OF_RANGE,0);
    
    Buffer_Grow_Reserve(bf,bf->count+len);
    if ( pos < bf->count )
      memmove(bf->at+pos+len,bf->at+pos,bf->count-pos);
    memcpy(bf->at+pos,S,len);
    bf->count += len;
    bf->at[bf->count] = 0;
  }
#endif
  ;


#define Buffer_Take_Data(Bf) __Pool(Buffer_Take_Data_Npl(Bf))
void *Buffer_Take_Data_Npl(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    void *R = bf->at;
    bf->count = 0;
    bf->at = 0;
    bf->capacity = 0;
    return R;
  }
#endif
  ;
  
void *Buffer_Take_Data_Non(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    void *n = Buffer_Take_Data(bf);
    if ( !n ) 
      { 
        n = Yo_Malloc(1);
        *((char*)n) = 0;
      }
    return n;
  }
#endif
  ;
  
#define Buffer_COUNT(Bf)    ((int)((YO_BUFFER *)(Bf))->count)
#define Buffer_CAPACITY(Bf) ((int)((YO_BUFFER *)(Bf))->capacity)
#define Buffer_BEGIN(Bf)    (((YO_BUFFER *)(Bf))->at)
#define Buffer_END(Bf)      (Buffer_BEGIN(Bf)+Buffer_COUNT(Bf))

int Buffer_Count(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_COUNT(bf);
    return 0;
  }
#endif
  ;
  
int Buffer_Capacity(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_CAPACITY(bf);
    return 0;
  }
#endif
  ;
 void *Buffer_Begin(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_BEGIN(bf);
    return 0;
  }
#endif
  ;

void *Buffer_End(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( bf )
      return Buffer_END(bf);
    return 0;
  }
#endif
  ;

void Buffer_Destruct(YO_BUFFER *bf)
#ifdef _YO_BUFFER_BUILTIN
  {
    if ( bf->at )
      free(bf->at);
    __Destruct(bf);
  }
#endif
  ;

void *Buffer_Init(int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    YO_BUFFER *bf = Yo_Object_Dtor(sizeof(YO_BUFFER),Buffer_Destruct);
    if ( count )
      Buffer_Resize(bf,count);
    return bf;
  }
#endif
  ;
  
void *Buffer_Acquire(char *S)
#ifdef _YO_BUFFER_BUILTIN
  {
    YO_BUFFER *bf = Yo_Object_Dtor(sizeof(YO_BUFFER),Buffer_Destruct);
    int L = strlen(S);
    bf->at = S;
    bf->count = L;
    bf->capacity = L;
    return bf;
  }
#endif
  ;

void *Buffer_Zero(int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    YO_BUFFER *bf = Buffer_Init(count);
    if ( bf->count ) 
      memset(bf->at,0,bf->count);
    return bf;
  }
#endif
  ;

void *Buffer_Copy(void *S, int count)
#ifdef _YO_BUFFER_BUILTIN
  {
    YO_BUFFER *bf = Buffer_Init(count);
    if ( count )
      memcpy(bf->at,S,count);
    return bf;
  }
#endif
  ;

#endif /* C_once_29A1C0D6_2792_4035_8D0E_9DB1797A4120 */

Changes to cgi.hc.
39
40
41
42
43
44
45





















































































































































































































































































































































































































































































































































































































































































































































































































Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/




























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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

Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

*/

#ifndef C_once_C02CA609_3FE5_45AB_B64B_15A73FD72214
#define C_once_C02CA609_3FE5_45AB_B64B_15A73FD72214

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "stdf.hc" 
#include "mime.hc"
#include "xdata.hc"
#include "xdef.hc"
#include "logout.hc"

#ifdef _LIBYOYO
#define _YO_CGI_BUILTIN
#endif

extern char **environ;

enum 
  {
    YO_CGI_BAD_METHOD     = 0,
    YO_CGI_GET            = 1,
    YO_CGI_POST           = 2,
    YO_CGI_HTTP_X_X       = 300000,
    YO_CGI_HTTP_1_0       = 300100,
    YO_CGI_HTTP_1_1       = 300101,
    YO_CGI_CGI_GW         = 100000,
    YO_CGI_CGI_X_X        = 100000,
    YO_CGI_CGI_1_0        = 100100,
    YO_CGI_CGI_1_1        = 100101,
    YO_CGI_FAST_CGI_GW    = 200000,
    YO_CGI_FAST_CGI_X_X   = 200000,
    YO_CGI_FAST_CGI_1_0   = 200100,
    YO_CGI_FAST_CGI_1_1   = 200101,
    YO_CGI_NO_CONTENT     = 0,
    YO_CGI_URLENCODED     = 1,
    YO_CGI_OCTETSTREAM    = 2,
    YO_CGI_MULTIPART      = 3,
    YO_CGI_POST_MAX_PAYLOAD = 64*KILOBYTE,
    YO_CGI_OUT_TEXTHTML = 200,
    YO_CGI_OUT_REDIRECT = 301,
    YO_CGI_OUT_DATASTREAM = 299,
    YO_CGI_OUT_NOTFOUND = 404,
  };

/* YO_CGI_COOKIE does not require specific destructor, use free */
typedef struct _YO_CGI_COOKIE
  {
    struct _YO_CGI_COOKIE *next;
    char *value;
    time_t expire;
    int  secure;
    char name[1];
  } YO_CGI_COOKIE;

typedef struct _YO_CGI_UPLOAD
  {
    struct _YO_CGI_UPLOAD *next;
    char *path;
    char *mimetype;
    char *original;
    int length;
    int status;
    char name[1];
  } YO_CGI_UPLOAD;

typedef struct _YO_CGI
  {
    YO_XNODE *params;
    char *server_software;
    char *server_name;
    char *request_uri;
    char *remote_addr;
    char *referer;
    char *query_string;
    char *path_info;
    char *content_boundary; /* can be null */
    char **langlist;
    int gateway_interface;
    int server_protocol;
    int server_port;
    int request_method;
    int content_length;
    int content_type;
    YO_CGI_COOKIE *cookie_in;
    YO_CGI_COOKIE *cookie_out;
    YO_CGI_UPLOAD *upload;
    YO_BUFFER *out;
    void *dstrm;
    char *dstrm_mimetype;
  } YO_CGI;

#define Cgi_Langlist(Cgir) ((Cgir)->langlist)

void Cgi_Destruct(YO_CGI *self)
#ifdef _YO_CGI_BUILTIN
  {
    __Gogo
      {
        YO_CGI_COOKIE *qoo;
        for ( qoo = self->cookie_in; qoo; ) { void *q = qoo->next; free(qoo); qoo = q; }
        for ( qoo = self->cookie_out; qoo; ) { void *q = qoo->next; free(qoo); qoo = q; }
      }
    
    __Gogo
      {
        YO_CGI_UPLOAD *qoo, *qoo1;
        for ( qoo = self->upload; qoo; )
          {
            qoo1 = qoo->next;
            if ( qoo->path && File_Exists(qoo->path) ) 
              __Try_Except
                File_Unlink(qoo->path,0);
              __Except
                Log_Error("when unlink uploaded file `%s`, occured: %s",
                                         qoo->path, __Format_Error());
            free(qoo);
            qoo = qoo1;
          }
      }
    
    if (self->langlist) 
      {
        char **qoo;
        for ( qoo = self->langlist; *qoo; ++qoo )
          free(*qoo);
        free(self->langlist);
      }
    
    free(self->server_software);
    free(self->server_name);
    free(self->request_uri);
    free(self->remote_addr);
    free(self->referer);
    free(self->query_string);
    free(self->path_info);
    free(self->content_boundary);
    free(self->dstrm_mimetype);
    __Unrefe(self->params);
    __Unrefe(self->out);
    __Unrefe(self->dstrm);
    memset(self,0xfe,sizeof(*self)); /* !!! */
    __Destruct(self);
  }
#endif
  ;
  
YO_CGI_COOKIE **Cgi_Find_Cookie_(YO_CGI_COOKIE **qoo,char *name, int name_len)
#ifdef _YO_CGI_BUILTIN
  {
    while ( *qoo )
      {
        int i;
        char *Q = (*qoo)->name;
        char *N = name;
        for ( i = 0; i < name_len; ++i )
          if ( Q[i] != N[i] )
            break;
        if ( i == name_len && !Q[i] )
          break;
        qoo = &(*qoo)->next;
      }
    return qoo;
  }
#endif
  ;

#define Cgi_Set_Cookie(Cgir,Name,Value,Expire) Cgi_Set_Cookie_(&(Cgir)->cookie_out,(Name),-1,(Value),-1,0,(Expire));
#define Cgi_Set_Secure_Cookie(Cgir,Name,Value,Expire) Cgi_Set_Cookie_(&(Cgir)->cookie_out,(Name),-1,(Value),-1,1,(Expire));
void Cgi_Set_Cookie_(YO_CGI_COOKIE **qoo, char *name, int name_len, char *value, int value_len, int secure, time_t expire)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_COOKIE **cookie;
    
    if ( name_len < 0 ) name_len = name?strlen(name):0;
    if ( value_len < 0 ) value_len = value?strlen(value):0;
    
    cookie = Cgi_Find_Cookie_(qoo,name,name_len);
    if ( *cookie )
      {
        free(*cookie);
        *cookie = 0;
      }
      
    *cookie = __Malloc_Npl(sizeof(YO_CGI_COOKIE)+(name_len+value_len+1));
    (*cookie)->value = (*cookie)->name+name_len+1;
    memcpy((*cookie)->name,name,name_len);
    (*cookie)->name[name_len] = 0;
    memcpy((*cookie)->value,value,value_len);
    (*cookie)->value[value_len] = 0;
    (*cookie)->secure = secure;
    (*cookie)->expire = expire;
    (*cookie)->next = 0;
  }
#endif
  ;
  
char *Cgi_Get_Cookie(YO_CGI *cgir,char *name)
#ifdef _YO_CGI_BUILTIN
  {
    if ( name )
      {
        YO_CGI_COOKIE **q = Cgi_Find_Cookie_(&cgir->cookie_in,name,strlen(name));
        if ( *q )
          return (*q)->value;
      }
    return 0;
  }
#endif
  ;

YO_CGI_UPLOAD *Cgi_Find_Upload(YO_CGI *cgir, char *upload_name)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_UPLOAD *up = cgir->upload;
    for ( ; up ; up = up->next )
      if ( Str_Equal_Nocase(up->name,upload_name) )
        break;
    return up;
  }
#endif
  ;

char *Cgi_Mime_Of_Upload(YO_CGI *cgir, char *upload_name)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_UPLOAD *up = Cgi_Find_Upload(cgir,upload_name);
    if ( up )
      return up->mimetype;
    return 0;
  }
#endif
  ;

char *Cgi_Get_Upload_Path(YO_CGI *cgir, char *upload_name)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_UPLOAD *up = Cgi_Find_Upload(cgir,upload_name);
    if ( up )
      return up->path;
    else
      __Raise_Format(YO_ERROR_INVALID_PARAM,
        ("CGI request does not have upload with name '%s'",upload_name));
    return 0;
  }
#endif
  ;

void *Cgi_Open_Upload(YO_CGI *cgir, char *upload_name)
#ifdef _YO_CGI_BUILTIN
  {
    return Cfile_Open(Cgi_Get_Upload_Path(cgir,upload_name),"r");
  }
#endif
  ;

YO_CGI_UPLOAD *Cgi_Attach_Upload(YO_CGI_UPLOAD **upload, char *path, char *mimetype, char *name, char *original, int len)
#ifdef _YO_CGI_BUILTIN
  {
    int path_len = path?strlen(path):0;
    int mime_len = mimetype?strlen(mimetype):0;
    int name_len = name?strlen(name):0;
    int orig_len = original?strlen(original):0;
    int mem_len = path_len+1+mime_len+1+orig_len+1+name_len+sizeof(YO_CGI_UPLOAD);
    YO_CGI_UPLOAD *u = __Malloc_Npl(mem_len);
    memset(u,0,mem_len);
    u->path = u->name+name_len+1;
    u->mimetype = u->path+path_len+1;
    u->original = u->mimetype+mime_len+1;
    if ( name_len ) memcpy(u->name,name,name_len);
    if ( path_len ) memcpy(u->path,path,path_len);
    if ( mime_len ) memcpy(u->mimetype,mimetype,mime_len);
    if ( orig_len ) memcpy(u->original,original,orig_len);
    u->length = len;
    
    while ( *upload ) upload = &(*upload)->next;
    *upload = u;
    return u;
  }
#endif
  ;

int Cgi_Recognize_Request_Method(char *method)
#ifdef _YO_CGI_BUILTIN
  {
    if ( method )
      {
        if ( !strcmp_I(method,"get") )
          return YO_CGI_GET;
        if ( !strcmp_I(method,"post") )
          return YO_CGI_POST;
      }
    return 0;
  } 
#endif
  ;
  
int Cgi_Recognize_Content_Type(char *cont_type)
#ifdef _YO_CGI_BUILTIN
  {
    if ( cont_type )
      {
        while ( Isspace(*cont_type) ) ++cont_type;
        if ( !strncmp_I(cont_type,"multipart/form-data;",20) )
          return YO_CGI_MULTIPART;
        if ( !strcmp_I(cont_type,"application/x-www-form-urlencoded") )
          return YO_CGI_URLENCODED;
        if ( !strcmp_I(cont_type,"application/octet-stream") )
          return YO_CGI_OCTETSTREAM;
      }
    return 0;
  }
#endif
  ;
  
int Cgi_Recognize_Gateway_Ifs(char *gwifs)
#ifdef _YO_CGI_BUILTIN
  {
    if ( gwifs )
      {
        while ( Isspace(*gwifs) ) ++gwifs;
        if ( !strncmp_I(gwifs,"cgi/1.1",9) )
          return YO_CGI_CGI_1_1;
        if ( !strncmp_I(gwifs,"cgi/1.0",9) )
          return YO_CGI_CGI_1_0;
      }
    return YO_CGI_CGI_X_X;
  }
#endif
  ;
  
int Cgi_Recognize_Protocol(char *proto)
#ifdef _YO_CGI_BUILTIN
  {
    if ( proto )
      {
        while ( Isspace(*proto) ) ++proto;
        if ( !strncmp_I(proto,"http/1.1",10) )
          return YO_CGI_HTTP_1_1;
        if ( !strncmp_I(proto,"http/1.0",10) )
          return YO_CGI_HTTP_1_0;
      }
    return 0;
  }
#endif
  ;
  
YO_CGI *Cgi_Init()
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI *self = __Object_Dtor(sizeof(YO_CGI),Cgi_Destruct);

    setlocale(LC_NUMERIC,"C");
    setlocale(LC_TIME,"C");

    self->server_software = Str_Copy_Npl(getenv("SERVER_SOFTWARE"),-1);
    self->gateway_interface = Cgi_Recognize_Gateway_Ifs(getenv("GATEWAY_INTERFACE"));
    self->server_protocol = Cgi_Recognize_Protocol(getenv("SERVER_PROTOCOL"));

    self->server_name = Str_Copy_Npl(getenv("SERVER_NAME"),-1);
    self->server_port = Str_To_Int_Dflt(getenv("SERVER_PORT"),80);

    self->request_uri = Str_Copy_Npl(getenv("REQUEST_URI"),-1);
    self->remote_addr = Str_Copy_Npl(getenv("REMOTE_ADDR"),-1);
    self->referer = Str_Copy_Npl(getenv("HTTP_REFERER"),-1);

    self->request_method = Cgi_Recognize_Request_Method(getenv("REQUEST_METHOD"));
    self->query_string = Str_Copy_Npl(getenv("QUERY_STRING"),-1);
    self->path_info = Str_Copy_Npl(getenv("PATH_INFO"),-1);    
    self->content_length = Str_To_Int_Dflt(getenv("CONTENT_LENGTH"),0);
    
    __Gogo
      {
        char *S = getenv("CONTENT_TYPE");
        self->content_type = Cgi_Recognize_Content_Type(S);
        if ( self->content_type == YO_CGI_MULTIPART )
          {
            char *bndr = strchr(S,';');
            if ( bndr )
              {
                ++bndr;
                while ( Isspace(*bndr) ) ++bndr;
                if ( Str_Starts_With(bndr,"boundary=") )
                  self->content_boundary = Str_Concat_Npl("--",bndr+9);
              }
          }
      }
     
     __Gogo
      {
        char *S = getenv("HTTP_COOKIE");
        if ( S ) while (*S)
          {
            int nam_len,val_len;
            char *nam;
            char *val;
            while ( Isspace(*S) ) ++S;
            nam = S;
            while ( *S && *S != '=' && *S != ';' ) ++S;
            if ( *S == '=' )
              {
                nam_len = S - nam;
                ++S;
                val = S;
                while ( *S && *S != ';' ) ++S;
              }
            else
              {
                val = nam;
                nam_len = 0;
              }
            val_len = S-val;
            if ( *S == ';' ) ++S;
            Cgi_Set_Cookie_(&self->cookie_in,nam,nam_len,val,val_len,0,0);
          }
      }
      
    __Gogo
      {
        YO_ARRAY *arr = 0;
        char *S1, *S2, *S = getenv("HTTP_ACCEPT_LANGUAGE");
        if ( S )
          {
            arr = Array_Pchars();
            while ( *S )
              {
                S1 = S;
                S2 = S;
                while ( *S && *S != ',' ) ++S;
                while ( S2 < S && *S2 != ';' ) ++S2;
                Array_Push(arr,Str_Copy_Npl(S1,S2-S1));
                while ( *S == ',' ) ++S;
              }
            Array_Push(arr,0);
            self->langlist = Array_Take_Data_Npl(arr);
          }
      }
    
    self->out = __Refe(Buffer_Init(0));
    return self;
  }
#endif
  ;
  
void Cgi_Format_Bf(YO_CGI *self, YO_BUFFER *bf)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_COOKIE *q;
    YO_CGI_UPLOAD *u;
    
    Buffer_Printf(bf,"YO_CGI(%08x){\n",self);
    Buffer_Printf(bf,"  server_software = '%s'\n",self->server_software);
    Buffer_Printf(bf,"  server_name = '%s'\n",self->server_name);
    Buffer_Printf(bf,"  request_uri = '%s'\n",self->request_uri);
    Buffer_Printf(bf,"  remote_addr = '%s'\n",self->remote_addr);
    Buffer_Printf(bf,"  referer = '%s'\n",self->referer);
    Buffer_Printf(bf,"  query_string = '%s'\n",self->query_string);
    Buffer_Printf(bf,"  path_info = '%s'\n",self->path_info);
    Buffer_Printf(bf,"  content_boundary = '%s'\n",self->content_boundary?self->content_boundary:"");
    Buffer_Printf(bf,"  gateway_interface = %d\n",self->gateway_interface);
    Buffer_Printf(bf,"  server_protocol = %d\n",self->server_protocol);
    Buffer_Printf(bf,"  server_port = %d\n",self->server_port);
    Buffer_Printf(bf,"  request_method = %d\n",self->request_method);
    Buffer_Printf(bf,"  content_length = %d\n",self->content_length);
    Buffer_Printf(bf,"  content_type = %d\n",self->content_type);
    Buffer_Append(bf,"  params:\n",-1);
    if (self->params) Def_Format_Into(bf,self->params,2);
    Buffer_Append(bf,"  cookie-in:\n",-1);
    for ( q = self->cookie_in; q; q = q->next ) 
      Buffer_Printf(bf,"    %s => %s\n",q->name,q->value);
    Buffer_Append(bf,"  cookie-out:\n",-1);
    for ( q = self->cookie_out; q; q = q->next ) 
      Buffer_Printf(bf,"    %s => %s  ((%sexpire:%ld))\n",q->name,q->value,q->secure?"SECURED ":"",q->expire);
    Buffer_Append(bf,"  upload:\n",-1);
    for ( u = self->upload; u; u = u->next )
      Buffer_Printf(bf,"    %s => %s (%d bytes) %s `%s`\n",u->name,u->path,u->length,u->mimetype,u->original);
    Buffer_Printf(bf,"}\n");
  }
#endif
  ;
  
char *Cgi_Format_Str(YO_CGI *self)
#ifdef _YO_CGI_BUILTIN
  {
    YO_BUFFER *bf = Buffer_Init(0);
    Cgi_Format_Bf(self,bf);
    return Buffer_Take_Data(bf);
  }
#endif
  ;

char *Cgi_Format_Cookies_Out(YO_CGI *self)
#ifdef _YO_CGI_BUILTIN
  {
    YO_CGI_COOKIE *q;
    YO_BUFFER bf = {0};
    for ( q = self->cookie_out; q; q = q->next ) 
      {
        Buffer_Append(&bf,"Set-Cookie: ",-1);
        Buffer_Append(&bf,q->name,-1);
        Buffer_Fill_Append(&bf,'=',1);
        Buffer_Append(&bf,q->value,-1);
        if ( q->expire )
          {
            //time_t gmt_time;
            static char *wday [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
            static char *mon  [] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
            struct tm *tm = gmtime(&q->expire);
            Buffer_Printf(&bf,"; expires=%s, %02d-%s-%04d %02d:%02d:%02d GMT",
              wday[tm->tm_wday%7],
              tm->tm_mday,
              mon[tm->tm_mon%12],
              tm->tm_year+1900,
              tm->tm_hour,tm->tm_min,tm->tm_sec);
          }
        if ( q->secure )
          Buffer_Append(&bf,"; secure",-1);

        Buffer_Append(&bf,"; HttpOnly",-1);
        if ( q->next )
          Buffer_Fill_Append(&bf,'\n',1);
      }
    if ( bf.at )
      return Buffer_Take_Data(&bf);
    else
      return "";
  }
#endif
  ;

char *Cgi_Upload_Part(
  YO_CGI *cgir, longptr_t out, Unknown_Write_Proc xwrite, 
  char *S, char *bf, int *L, int maxlen)
#ifdef _YO_CGI_BUILTIN
  {
    int count = 0;
    int cb_l = strlen(cgir->content_boundary);
    
    while (S && *L)
      {
        int j = 0, k = 0;
        if ( strncmp(S,cgir->content_boundary,cb_l) == 0 )
          break;
        
        //++j;
        
        while ( *L-j >= cb_l+2 )
          {
            k = 0;
            if ( S[j] == '\r' ) ++k;
            if ( S[j+k] == '\n' ) ++k;
            if ( 0 == strncmp(S+j+k,cgir->content_boundary,cb_l) )
              break;
            ++j;
          }
        
        if ( count + j > maxlen )
          __Raise(YO_ERROR_TO_BIG,__yoTa("payload size out of limit",0));
        Unknown_Write(out,S,j,xwrite);
        count += j;
        S = Stdin_Pump_Part(bf,S+j+k,L);
        if ( *L < cb_l ) 
          __Raise(YO_ERROR_IO,__yoTa("uncomplete request",0));
      }

    return S;
  }
#endif
  ;
  
char *Cgi_Strip(char *S)
#ifdef _YO_CGI_BUILTIN
  {
    if ( S && *S == '"' )
      {
        int L = strlen(S);
        if ( S[L-1] == '"' ) S[L-1] = 0;
        return S+1;
      }
    return S;
  }
#endif
  ;
  
char *Cgi_Multipart_Next(
  YO_CGI *cgir, char *upload_dir, int upload_maxsize, char *bf,char *S, int *L)
#ifdef _YO_CGI_BUILTIN
  {
    char *SE;
    char *name, *filename, *ctype;
    int cb_l = strlen(cgir->content_boundary);
     
    while ( *S && Isspace(*S) ) ++S;
    
    if ( 0 == strncmp(S,cgir->content_boundary,cb_l) )
      {
        S = Stdin_Pump_Part(bf,S,L);
        SE = S+1;
        while ( *SE )
          {
            if ( *SE == '\n' && SE[1] == '\n' ) 
              { SE += 2; break; }
            if ( *SE == '\n' && SE[1] == '\r' && SE[2] == '\n') 
              { SE += 3; break; }
            ++SE;
          }
        if ( *SE )
          {
            SE[-1] = 0;
            name = Cgi_Strip(Str_Fetch_Substr(S,"name=",0,";\n\r"));
            filename = Cgi_Strip(Str_Fetch_Substr(S,"filename=",0,";\n\r"));
            ctype = Cgi_Strip(Str_Fetch_Substr(S,"Content-Type:"," ",";\n\r"));
            S = Stdin_Pump_Part(bf,SE,L);
            if ( ctype || filename )
              {
                char *tmpfname = Path_Unique_Name(upload_dir,"cgi-",".upl");
                YO_CFILE *f = Cfile_Open(tmpfname,"w+P");
                YO_CGI_UPLOAD *u = Cgi_Attach_Upload(&cgir->upload,tmpfname,ctype,name,filename,0);
                S = Cgi_Upload_Part(cgir,(longptr_t)f,&Cf_Write,S,bf,L,upload_maxsize);
                Cfile_Flush(f);
                u->length = Cfile_Length(f);
                Cfile_Close(f);
              }
            else
              {
                YO_BUFFER *val = Buffer_Init(0);
                S = Cgi_Upload_Part(cgir,(longptr_t)val,&Bf_Write,S,bf,L,YO_CGI_POST_MAX_PAYLOAD);
                Xvalue_Set_Str(Xnode_Deep_Value(cgir->params,name),val->at,val->count);
              }
            return S;
          }
      }
    return 0;
  }
#endif
  ;
  
void Cgi_Process_Multipart_Content(YO_CGI *cgir, char *upload_dir, int upload_maxsize)
#ifdef _YO_CGI_BUILTIN
  {
    char bf[YO_STDF_PUMP_BUFFER];
    int L = Stdin_Pump(bf);
    char *S = bf;
    while ( S && L )
      __Auto_Release
        S = Cgi_Multipart_Next(cgir,upload_dir,upload_maxsize,bf,S,&L);
  }
#endif
  ;
  
YO_XNODE *Cgi_Query_Params(YO_CGI *cgir, char *upload_dir, int upload_maxsize)
#ifdef _YO_CGI_BUILTIN
  {
    if ( !cgir->params ) __Auto_Release
      {
        char lbuf[1024], c;
        char *q, *key, *value, *qE = lbuf+(sizeof(lbuf)-1);
        char *S = 0;
        cgir->params = __Refe(Xdata_Init());
        if ( !upload_dir ) upload_dir = Temp_Directory();
        if ( cgir->request_method == YO_CGI_GET )
          {
            S = cgir->query_string;
          }
        else if ( cgir->request_method == YO_CGI_POST )
          {
            if ( cgir->content_type == YO_CGI_MULTIPART )
              {
                if ( cgir->content_boundary )
                  Cgi_Process_Multipart_Content(cgir,upload_dir,upload_maxsize);
              }
            else if ( cgir->content_length < YO_CGI_POST_MAX_PAYLOAD )
              {
                int count = cgir->content_length;
                int l = 0;
                S = __Malloc(count+1);
                while ( l < count )
                  {
                    int q = fread(S+l,1,count-l,stdin);
                    if ( q < 0 )
                      __Raise_Format(YO_ERROR_IO,
                        (__yoTa("failed to read request content: %s",0),strerror(ferror(stdin))));
                    l += q;
                  }
                S[count] = 0;
              }
            else
              __Raise(YO_ERROR_TO_BIG,__yoTa("payload size out of limit",0));
          }
        if ( S && (cgir->request_method == YO_CGI_GET || cgir->content_type == YO_CGI_URLENCODED) )
          {
            while ( *S )
              {
                value = 0;
                key = q = lbuf;
                while ( *S && *S == '&' ) ++S;
                while ( *S && *S != '=' && *S != '&' )
                  {
                    c = ( *S != '%' && *S != '+' ) ? *S++ : Str_Urldecode_Char(&S);
                    if ( q >= lbuf && q < qE ) *q++ = c;
                  }
                if ( q >= lbuf && q < qE ) *q++ = 0;
                value = q; *q = 0; /* if (q == qE) there is one more char for final zero */
                if ( *S == '=' ) 
                  {
                    ++S;
                    while ( *S && *S != '&' )
                      {
                        c = ( *S != '%' && *S != '+' ) ? *S++ : Str_Urldecode_Char(&S);
                        if ( q >= lbuf && q < qE ) *q++ = c;
                      }
                  }
                *q = 0; /* if (q == qE) there is one more char for final zero */
                Xvalue_Set_Str(Xnode_Deep_Value(cgir->params,key),value,q-value);
              }
          }
      }
    return cgir->params;
  }
#endif
  ;
  
#define Cgi_Get_Outbuf(Cgir) ((Cgir)->out)
#define Cgi_Get_Len(Cgir) ((Cgir)->out->count)
#define Cgi_Get_Cstr(Cgir) ((Cgir)->out->at)
#define Cgi_Puts(Cgir,S) Buffer_Puts(Cgir->out,S)
#define Cgi_Fill(Cgir,C,N) Buffer_Fill_Append(Cgir->out,C,N)
#define Cgi_Append(Cgir,S,L) Buffer_Append(Cgir->out,S,L)

void Cgi_Printf(YO_CGI *cgir, char *fmt, ...)
#ifdef _YO_CGI_BUILTIN
  {
    va_list va;
    va_start(va,fmt);
    Buffer_Printf_Va(cgir->out,fmt,va);
    va_end(va);
  }
#endif
  ;

void Cgi_Write_Out(YO_CGI *cgir, int out_status)
#ifdef _YO_CGI_BUILTIN
  {
    if ( out_status == YO_CGI_OUT_TEXTHTML )
      {
        Stdout_Put("Content-Type: text/html; charset=utf-8\r\n");
        printf("Content-Length: %d\r\n\r\n",Cgi_Get_Len(cgir));
        Stdout_Put(cgir->out->at);
      }
    else if ( out_status == YO_CGI_OUT_REDIRECT )
      {
        Stdout_Put("Location: ");
        Stdout_Put(cgir->out->at);
        Stdout_Put("\r\n");
        Stdout_Put(Cgi_Format_Cookies_Out(cgir));
        Stdout_Put("\r\n\r\n");
      }
    else if ( out_status == YO_CGI_OUT_DATASTREAM )
      {
        char bf[YO_FILE_COPY_BUFFER_SIZE];
        int count = 0;
        void *src = cgir->dstrm;
        int (*xread)(void*,void*,int,int) = Yo_Find_Method_Of(&src,Oj_Read_OjMID,YO_RAISE_ERROR);
        int len = Oj_Available(cgir->dstrm);
        Stdout_Put("Content-Type: ");
        Stdout_Put(cgir->dstrm_mimetype);
        Stdout_Put("\r\n");
        printf("Content-Length: %d\r\n\r\n",len);
        for ( ;; )
          {
            int i = xread(src,bf,YO_FILE_COPY_BUFFER_SIZE,0);
            if ( !i ) break;
            fwrite(bf,1,i,stdout);
            count += i;
          }
      }
    else /* empty page */
      {
        Stdout_Put("Content-Type: text/html; charset=utf-8\n");
        Stdout_Put("Content-Length: 0\n\n");
      }
    fflush(stdout);
  }
#endif
  ;

#endif /* C_once_C02CA609_3FE5_45AB_B64B_15A73FD72214 */
Changes to cipher.hc.
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

*/

#ifndef C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219
#define C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219

#ifdef _LIBYOYO
#define _YOYO_CIPHER_BUILTIN
#endif

#include "yoyo.hc"
#include "md5.hc"
#include "sha2.hc"

#ifdef _YOYO_CIPHER_BUILTIN
# define _YOYO_CIPHER_BUILTIN_CODE(Code) Code
# define _YOYO_CIPHER_EXTERN 
#else
# define _YOYO_CIPHER_BUILTIN_CODE(Code)
# define _YOYO_CIPHER_EXTERN extern 
#endif

_YOYO_CIPHER_EXTERN char Oj_Encrypt8_OjMID[] _YOYO_CIPHER_BUILTIN_CODE ( = "encrypt8/@*" );
_YOYO_CIPHER_EXTERN char Oj_Decrypt8_OjMID[] _YOYO_CIPHER_BUILTIN_CODE ( = "decrypt8/@*" );
_YOYO_CIPHER_EXTERN char Oj_Encrypt16_OjMID[] _YOYO_CIPHER_BUILTIN_CODE ( = "encrypt16/@*" );
_YOYO_CIPHER_EXTERN char Oj_Decrypt16_OjMID[] _YOYO_CIPHER_BUILTIN_CODE ( = "decrypt16/@*" );

void Oj_Encrypt8(void *cipher,void *block8) _YOYO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Encrypt8_OjMID,YO_RAISE_ERROR))
        (cipher,block8); });

void Oj_Decrypt8(void *cipher,void *block8) _YOYO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Decrypt8_OjMID,YO_RAISE_ERROR))
        (cipher,block8); });
        
void Oj_Encrypt16(void *cipher,void *block16) _YOYO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Encrypt16_OjMID,YO_RAISE_ERROR))
        (cipher,block16); });

void Oj_Decrypt16(void *cipher,void *block16) _YOYO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Decrypt16_OjMID,YO_RAISE_ERROR))
        (cipher,block16); });

void _Oj_Check_Buffer_Size_N_Alignment_8(int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    if ( S_len < 8 ) 
      __Raise(YOYO_ERROR_NO_ENOUGH,__yoTa("data buffer to small",0));
    
    if ( S_len % 8 )
      __Raise(YOYO_ERROR_UNALIGNED,__yoTa("size of data buffer should be aligned to 8 bytes",0));
  }
#endif
  ;

void _Oj_Check_Buffer_Size_N_Alignment_16(int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    if ( S_len < 16 ) 
      __Raise(YOYO_ERROR_NO_ENOUGH,__yoTa("data buffer to small",0));
    
    if ( S_len % 16 )
      __Raise(YOYO_ERROR_UNALIGNED,__yoTa("size of data buffer should be aligned to 16 bytes",0));
  }
#endif
  ;

void _Oj_Encrypt_Decrypt_ECB_8(void *cipher, void (*f8)(void*,void*), void *S, int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    int i;
    
    _Oj_Check_Buffer_Size_N_Alignment_8(S_len);
    
    for ( i = 0; i < S_len/8; ++i )
      {
        byte_t *p = (byte_t*)S+i*8;
        f8(cipher,p);
      }
  }
#endif
  ;

void _Oj_Encrypt_Decrypt_ECB_16(void *cipher, void (*f16)(void*,void*), void *S, int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    int i;
    
    _Oj_Check_Buffer_Size_N_Alignment_16(S_len);
    
    for ( i = 0; i < S_len/16; ++i )
      {
        byte_t *p = (byte_t*)S+i*16;
        f16(cipher,p);
      }
  }
#endif
  ;

void Oj_Encrypt_ECB(void *cipher, void *S, int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    void (*f)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Encrypt8_OjMID,0);
    
    if ( f )
      _Oj_Encrypt_Decrypt_ECB_8(cipher,f,S,S_len);
    else if ( 0 != (f = Yo_Find_Method_Of(&cipher,Oj_Encrypt16_OjMID,0)) )
      _Oj_Encrypt_Decrypt_ECB_16(cipher,f,S,S_len);
    else
      __Raise(YOYO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Encrypt8_OjMID or Oj_Encrypt16_OjMID mothod",0));
  }
#endif
  ;

void Oj_Decrypt_ECB(void *cipher, void *S, int S_len)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    void (*f)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Decrypt8_OjMID,0);
    
    if ( f )
      _Oj_Encrypt_Decrypt_ECB_8(cipher,f,S,S_len);
    else if ( 0 != (f = Yo_Find_Method_Of(&cipher,Oj_Decrypt16_OjMID,0)) )
      _Oj_Encrypt_Decrypt_ECB_16(cipher,f,S,S_len);
    else
      __Raise(YOYO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Decrypt8_OjMID or Oj_Decrypt16_OjMID mothod",0));
  }
#endif
  ;

quad_t _Oj_Encrypt_Decrypt_XEX_8(void *cipher, void (*f8)(void*,void*), void *cipher2, void (*xex)(void*,void*), void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    int i,j, n = xex?8:16;
    byte_t q16[16] = {0};
    
    _Oj_Check_Buffer_Size_N_Alignment_8(S_len);
    
    for ( i = 0; i < S_len/8; ++i )







|






|
|
|

|
|


|
|
|
|

|



|



|



|




|


|


|





|


|


|





|















|















|








|






|








|






|







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

*/

#ifndef C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219
#define C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219

#ifdef _LIBYOYO
#define _YO_CIPHER_BUILTIN
#endif

#include "yoyo.hc"
#include "md5.hc"
#include "sha2.hc"

#ifdef _YO_CIPHER_BUILTIN
# define _YO_CIPHER_BUILTIN_CODE(Code) Code
# define _YO_CIPHER_EXTERN 
#else
# define _YO_CIPHER_BUILTIN_CODE(Code)
# define _YO_CIPHER_EXTERN extern 
#endif

_YO_CIPHER_EXTERN char Oj_Encrypt8_OjMID[] _YO_CIPHER_BUILTIN_CODE ( = "encrypt8/@*" );
_YO_CIPHER_EXTERN char Oj_Decrypt8_OjMID[] _YO_CIPHER_BUILTIN_CODE ( = "decrypt8/@*" );
_YO_CIPHER_EXTERN char Oj_Encrypt16_OjMID[] _YO_CIPHER_BUILTIN_CODE ( = "encrypt16/@*" );
_YO_CIPHER_EXTERN char Oj_Decrypt16_OjMID[] _YO_CIPHER_BUILTIN_CODE ( = "decrypt16/@*" );

void Oj_Encrypt8(void *cipher,void *block8) _YO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Encrypt8_OjMID,YO_RAISE_ERROR))
        (cipher,block8); });

void Oj_Decrypt8(void *cipher,void *block8) _YO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Decrypt8_OjMID,YO_RAISE_ERROR))
        (cipher,block8); });
        
void Oj_Encrypt16(void *cipher,void *block16) _YO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Encrypt16_OjMID,YO_RAISE_ERROR))
        (cipher,block16); });

void Oj_Decrypt16(void *cipher,void *block16) _YO_CIPHER_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(cipher,Oj_Decrypt16_OjMID,YO_RAISE_ERROR))
        (cipher,block16); });

void _Oj_Check_Buffer_Size_N_Alignment_8(int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    if ( S_len < 8 ) 
      __Raise(YO_ERROR_NO_ENOUGH,__yoTa("data buffer to small",0));
    
    if ( S_len % 8 )
      __Raise(YO_ERROR_UNALIGNED,__yoTa("size of data buffer should be aligned to 8 bytes",0));
  }
#endif
  ;

void _Oj_Check_Buffer_Size_N_Alignment_16(int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    if ( S_len < 16 ) 
      __Raise(YO_ERROR_NO_ENOUGH,__yoTa("data buffer to small",0));
    
    if ( S_len % 16 )
      __Raise(YO_ERROR_UNALIGNED,__yoTa("size of data buffer should be aligned to 16 bytes",0));
  }
#endif
  ;

void _Oj_Encrypt_Decrypt_ECB_8(void *cipher, void (*f8)(void*,void*), void *S, int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    int i;
    
    _Oj_Check_Buffer_Size_N_Alignment_8(S_len);
    
    for ( i = 0; i < S_len/8; ++i )
      {
        byte_t *p = (byte_t*)S+i*8;
        f8(cipher,p);
      }
  }
#endif
  ;

void _Oj_Encrypt_Decrypt_ECB_16(void *cipher, void (*f16)(void*,void*), void *S, int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    int i;
    
    _Oj_Check_Buffer_Size_N_Alignment_16(S_len);
    
    for ( i = 0; i < S_len/16; ++i )
      {
        byte_t *p = (byte_t*)S+i*16;
        f16(cipher,p);
      }
  }
#endif
  ;

void Oj_Encrypt_ECB(void *cipher, void *S, int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    void (*f)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Encrypt8_OjMID,0);
    
    if ( f )
      _Oj_Encrypt_Decrypt_ECB_8(cipher,f,S,S_len);
    else if ( 0 != (f = Yo_Find_Method_Of(&cipher,Oj_Encrypt16_OjMID,0)) )
      _Oj_Encrypt_Decrypt_ECB_16(cipher,f,S,S_len);
    else
      __Raise(YO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Encrypt8_OjMID or Oj_Encrypt16_OjMID mothod",0));
  }
#endif
  ;

void Oj_Decrypt_ECB(void *cipher, void *S, int S_len)
#ifdef _YO_CIPHER_BUILTIN
  {
    void (*f)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Decrypt8_OjMID,0);
    
    if ( f )
      _Oj_Encrypt_Decrypt_ECB_8(cipher,f,S,S_len);
    else if ( 0 != (f = Yo_Find_Method_Of(&cipher,Oj_Decrypt16_OjMID,0)) )
      _Oj_Encrypt_Decrypt_ECB_16(cipher,f,S,S_len);
    else
      __Raise(YO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Decrypt8_OjMID or Oj_Decrypt16_OjMID mothod",0));
  }
#endif
  ;

quad_t _Oj_Encrypt_Decrypt_XEX_8(void *cipher, void (*f8)(void*,void*), void *cipher2, void (*xex)(void*,void*), void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    int i,j, n = xex?8:16;
    byte_t q16[16] = {0};
    
    _Oj_Check_Buffer_Size_N_Alignment_8(S_len);
    
    for ( i = 0; i < S_len/8; ++i )
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    
    return st;
  }
#endif
  ;

quad_t _Oj_Encrypt_Decrypt_XEX_16(void *cipher, void (*f16)(void*,void*), void *cipher2, void (*xex)(void*,void*), void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    int i,j, n = xex?16:32;
    byte_t q32[32] = {0};
    
    _Oj_Check_Buffer_Size_N_Alignment_16(S_len);
    
    for ( i = 0; i < S_len/16; ++i )







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    
    return st;
  }
#endif
  ;

quad_t _Oj_Encrypt_Decrypt_XEX_16(void *cipher, void (*f16)(void*,void*), void *cipher2, void (*xex)(void*,void*), void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    int i,j, n = xex?16:32;
    byte_t q32[32] = {0};
    
    _Oj_Check_Buffer_Size_N_Alignment_16(S_len);
    
    for ( i = 0; i < S_len/16; ++i )
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    
    return st;
  }
#endif
  ;

quad_t Oj_Encrypt_XEX_2(void *cipher, void *cipher2, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    void (*encrypt)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Encrypt8_OjMID,0);
    if ( encrypt ) 
      {
        if ( !cipher2 )
          return _Oj_Encrypt_Decrypt_XEX_8(cipher,encrypt,0,0,S,S_len,st);
        else







|







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    
    return st;
  }
#endif
  ;

quad_t Oj_Encrypt_XEX_2(void *cipher, void *cipher2, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    void (*encrypt)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Encrypt8_OjMID,0);
    if ( encrypt ) 
      {
        if ( !cipher2 )
          return _Oj_Encrypt_Decrypt_XEX_8(cipher,encrypt,0,0,S,S_len,st);
        else
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
        else
          {
            void (*encrypt2)(void*,void*) = Yo_Find_Method_Of(&cipher2,Oj_Encrypt16_OjMID,YO_RAISE_ERROR);
            return _Oj_Encrypt_Decrypt_XEX_16(cipher,encrypt,cipher2,encrypt2,S,S_len,st);
          }
      }
    else
      __Raise(YOYO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Encrypt8_OjMID or Oj_Encrypt16_OjMID mothod",0));
    return 0;
  }
#endif
  ;

quad_t Oj_Decrypt_XEX_2(void *cipher, void *cipher2, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    void (*decrypt)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Decrypt8_OjMID,0);
    if ( decrypt )
      {
        if ( !cipher2 )
          return _Oj_Encrypt_Decrypt_XEX_8(cipher,decrypt,0,0,S,S_len,st);
        else







|







|







256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
        else
          {
            void (*encrypt2)(void*,void*) = Yo_Find_Method_Of(&cipher2,Oj_Encrypt16_OjMID,YO_RAISE_ERROR);
            return _Oj_Encrypt_Decrypt_XEX_16(cipher,encrypt,cipher2,encrypt2,S,S_len,st);
          }
      }
    else
      __Raise(YO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Encrypt8_OjMID or Oj_Encrypt16_OjMID mothod",0));
    return 0;
  }
#endif
  ;

quad_t Oj_Decrypt_XEX_2(void *cipher, void *cipher2, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    void (*decrypt)(void*,void*) = Yo_Find_Method_Of(&cipher,Oj_Decrypt8_OjMID,0);
    if ( decrypt )
      {
        if ( !cipher2 )
          return _Oj_Encrypt_Decrypt_XEX_8(cipher,decrypt,0,0,S,S_len,st);
        else
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
        else
          {
            void (*encrypt)(void*,void*) = Yo_Find_Method_Of(&cipher2,Oj_Encrypt16_OjMID,YO_RAISE_ERROR);
            return _Oj_Encrypt_Decrypt_XEX_16(cipher,decrypt,cipher2,encrypt,S,S_len,st);
          }
      }
    else
      __Raise(YOYO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Decrypt8_OjMID or Oj_Decrypt16_OjMID mothod",0));
    return 0;
  }
#endif
  ;

quad_t Oj_Encrypt_XEX(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    return Oj_Encrypt_XEX_2(cipher,cipher,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Decrypt_XEX(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,cipher,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Encrypt_XEX_MDSH(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,0,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Decrypt_XEX_MDSH(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YOYO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,0,S,S_len,st);
  }
#endif
  ;

#endif /* C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219 */








|







|







|







|







|








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
        else
          {
            void (*encrypt)(void*,void*) = Yo_Find_Method_Of(&cipher2,Oj_Encrypt16_OjMID,YO_RAISE_ERROR);
            return _Oj_Encrypt_Decrypt_XEX_16(cipher,decrypt,cipher2,encrypt,S,S_len,st);
          }
      }
    else
      __Raise(YO_ERROR_METHOD_NOT_FOUND,
              __yoTa("cipher does not contain Oj_Decrypt8_OjMID or Oj_Decrypt16_OjMID mothod",0));
    return 0;
  }
#endif
  ;

quad_t Oj_Encrypt_XEX(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    return Oj_Encrypt_XEX_2(cipher,cipher,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Decrypt_XEX(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,cipher,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Encrypt_XEX_MDSH(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,0,S,S_len,st);
  }
#endif
  ;

quad_t Oj_Decrypt_XEX_MDSH(void *cipher, void *S, int S_len, quad_t st)
#ifdef _YO_CIPHER_BUILTIN
  {
    return Oj_Decrypt_XEX_2(cipher,0,S,S_len,st);
  }
#endif
  ;

#endif /* C_once_1F19AF84_9BBE_46CC_87A4_8252243D7219 */

Changes to crc.hc.
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

*/

#ifndef C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6
#define C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6

#ifdef _LIBYOYO
#define _YOYO_CRC_BUILTIN
#endif

#include "yoyo.hc"

#ifdef _YOYO_CRC_BUILTIN
# define _YOYO_CRC_BUILTIN_CODE(Code) Code
# define _YOYO_CRC_EXTERN 
#else
# define _YOYO_CRC_BUILTIN_CODE(Code)
# define _YOYO_CRC_EXTERN extern 
#endif

_YOYO_CRC_EXTERN char Oj_Digest_Update_OjMID[] _YOYO_CRC_BUILTIN_CODE( = "digest-update/@*i"); 
void Oj_Digest_Update(void *dgst,void *buf,int L) _YOYO_CRC_BUILTIN_CODE(
  { ((void(*)(void*,void*,int))Yo_Find_Method_Of(&dgst,Oj_Digest_Update_OjMID,YO_RAISE_ERROR))
        (dgst,buf,L); });

uint_t    Crc_32(uint_t crc, void *, int len);
ushort_t  Crc_16(ushort_t crc, void *, int len);
byte_t    Crc_8(byte_t crc, void *, int len);
byte_t    Crc_8_Of_Cstr(char *S);
uint_t    Adler_32(uint_t adler, void *, int len);

#define Digest_Crc_32(Data,Len) Crc_32(0,Data,Len)
#define Digest_Crc_16(Data,Len) Crc_16(0,Data,Len)
#define Digest_Crc_8(Data,Len)  Crc_8(0,Data,Len)
#define Crc32_Digest(Data,Len,Buf)  Unsigned_To_Four(Crc_32(0,Data,Len),(Buf))
#define Crc16_Digest(Data,Len,Buf)  Unsigned_To_Two(Crc_16(0,Data,Len),(Buf))
#define Crc8_Digest(Data,Len,Buf)   (*(byte_t*)(Buf) = Crc_8(0,Data,Len))

byte_t Crc_8_32(byte_t start, uint_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_8(start,q,4); 
  }
#endif
  ;
  
ushort_t Crc_16_32(ushort_t start, uint_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_16(start,q,4); 
  }
#endif
  ;

uint_t Crc_32_32(uint_t start, uint_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_32(start,q,4); 
  }
#endif
  ;
  
byte_t Crc_8_16(byte_t start, ushort_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_8(start,q,2); 
  }
#endif
  ;

ushort_t Crc_16_16(ushort_t start, ushort_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_16(start,q,2); 
  }
#endif
  ;
  
uint_t Crc_32_16(uint_t start, ushort_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_32(start,q,2); 
  }
#endif
  ;
  
byte_t Crc_8_64(byte_t start, uquad_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    byte_t C = Crc_8_32(start,(uint_t)(val>>32)); 
    return Crc_8_32(C,(uint_t)val); 
  }
#endif
  ;

ushort_t Crc_16_64(ushort_t start, uquad_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    ushort_t C = Crc_16_32(start,(uint_t)(val>>32)); 
    return Crc_16_32(C,(uint_t)val); 
  }
#endif
  ;
  
uint_t Crc_32_64(uint_t start, uquad_t val) 
#ifdef _YOYO_CRC_BUILTIN
  { 
    uint_t C = Crc_32_32(start,(uint_t)(val>>32)); 
    return Crc_32_32(C,(uint_t)val); 
  }
#endif
  ;

#ifdef _YOYO_CRC_BUILTIN

  #define CRC32_MCRO_DO1(buf)  crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
  #define CRC32_MCRO_DO2(buf)  CRC32_MCRO_DO1(buf); CRC32_MCRO_DO1(buf);
  #define CRC32_MCRO_DO4(buf)  CRC32_MCRO_DO2(buf); CRC32_MCRO_DO2(buf);
  #define CRC32_MCRO_DO8(buf)  CRC32_MCRO_DO4(buf); CRC32_MCRO_DO4(buf);

  uint_t Crc_32(uint_t crc, void *_buf, int len)







|




|
|
|

|
|


|
|

















|








|








|








|








|








|








|








|








|







|







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

*/

#ifndef C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6
#define C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6

#ifdef _LIBYOYO
#define _YO_CRC_BUILTIN
#endif

#include "yoyo.hc"

#ifdef _YO_CRC_BUILTIN
# define _YO_CRC_BUILTIN_CODE(Code) Code
# define _YO_CRC_EXTERN 
#else
# define _YO_CRC_BUILTIN_CODE(Code)
# define _YO_CRC_EXTERN extern 
#endif

_YO_CRC_EXTERN char Oj_Digest_Update_OjMID[] _YO_CRC_BUILTIN_CODE( = "digest-update/@*i"); 
void Oj_Digest_Update(void *dgst,void *buf,int L) _YO_CRC_BUILTIN_CODE(
  { ((void(*)(void*,void*,int))Yo_Find_Method_Of(&dgst,Oj_Digest_Update_OjMID,YO_RAISE_ERROR))
        (dgst,buf,L); });

uint_t    Crc_32(uint_t crc, void *, int len);
ushort_t  Crc_16(ushort_t crc, void *, int len);
byte_t    Crc_8(byte_t crc, void *, int len);
byte_t    Crc_8_Of_Cstr(char *S);
uint_t    Adler_32(uint_t adler, void *, int len);

#define Digest_Crc_32(Data,Len) Crc_32(0,Data,Len)
#define Digest_Crc_16(Data,Len) Crc_16(0,Data,Len)
#define Digest_Crc_8(Data,Len)  Crc_8(0,Data,Len)
#define Crc32_Digest(Data,Len,Buf)  Unsigned_To_Four(Crc_32(0,Data,Len),(Buf))
#define Crc16_Digest(Data,Len,Buf)  Unsigned_To_Two(Crc_16(0,Data,Len),(Buf))
#define Crc8_Digest(Data,Len,Buf)   (*(byte_t*)(Buf) = Crc_8(0,Data,Len))

byte_t Crc_8_32(byte_t start, uint_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_8(start,q,4); 
  }
#endif
  ;
  
ushort_t Crc_16_32(ushort_t start, uint_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_16(start,q,4); 
  }
#endif
  ;

uint_t Crc_32_32(uint_t start, uint_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>24), (byte_t)(val>>16), (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_32(start,q,4); 
  }
#endif
  ;
  
byte_t Crc_8_16(byte_t start, ushort_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_8(start,q,2); 
  }
#endif
  ;

ushort_t Crc_16_16(ushort_t start, ushort_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_16(start,q,2); 
  }
#endif
  ;
  
uint_t Crc_32_16(uint_t start, ushort_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t q[] = { (byte_t)(val>>8), (byte_t)(val) }; 
    return Crc_32(start,q,2); 
  }
#endif
  ;
  
byte_t Crc_8_64(byte_t start, uquad_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    byte_t C = Crc_8_32(start,(uint_t)(val>>32)); 
    return Crc_8_32(C,(uint_t)val); 
  }
#endif
  ;

ushort_t Crc_16_64(ushort_t start, uquad_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    ushort_t C = Crc_16_32(start,(uint_t)(val>>32)); 
    return Crc_16_32(C,(uint_t)val); 
  }
#endif
  ;
  
uint_t Crc_32_64(uint_t start, uquad_t val) 
#ifdef _YO_CRC_BUILTIN
  { 
    uint_t C = Crc_32_32(start,(uint_t)(val>>32)); 
    return Crc_32_32(C,(uint_t)val); 
  }
#endif
  ;

#ifdef _YO_CRC_BUILTIN

  #define CRC32_MCRO_DO1(buf)  crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
  #define CRC32_MCRO_DO2(buf)  CRC32_MCRO_DO1(buf); CRC32_MCRO_DO1(buf);
  #define CRC32_MCRO_DO4(buf)  CRC32_MCRO_DO2(buf); CRC32_MCRO_DO2(buf);
  #define CRC32_MCRO_DO8(buf)  CRC32_MCRO_DO4(buf); CRC32_MCRO_DO4(buf);

  uint_t Crc_32(uint_t crc, void *_buf, int len)
391
392
393
394
395
396
397
398
399
400
401

#undef _ADLER32_DO1
#undef _ADLER32_DO2
#undef _ADLER32_DO4
#undef _ADLER32_DO8
#undef _ADLER32_DO16

#endif /* _YOYO_CRC_BUILTIN */

#endif /* C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6 */








|



391
392
393
394
395
396
397
398
399
400
401

#undef _ADLER32_DO1
#undef _ADLER32_DO2
#undef _ADLER32_DO4
#undef _ADLER32_DO8
#undef _ADLER32_DO16

#endif /* _YO_CRC_BUILTIN */

#endif /* C_once_A1549AAE_F443_4982_AFD4_F5BE02C14DE6 */

Changes to ctoken.hc.
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#define C_once_DD56FBFA_631C_47CD_B2A4_E6C8932594C8

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"

#ifdef _LIBYOYO
#define _YOYO_CTOKEN_BUILTIN
#endif

enum
  {
      YO_CTOKEN_ERR         = -2,
      YO_CTOKEN_END         = -1,
      YO_CTOKEN_DIGITS      = __FOUR_CHARS('D','I','G','T'),







|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#define C_once_DD56FBFA_631C_47CD_B2A4_E6C8932594C8

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"

#ifdef _LIBYOYO
#define _YO_CTOKEN_BUILTIN
#endif

enum
  {
      YO_CTOKEN_ERR         = -2,
      YO_CTOKEN_END         = -1,
      YO_CTOKEN_DIGITS      = __FOUR_CHARS('D','I','G','T'),
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
      YO_CTOKEN_ELS         = __FOUR_CHARS(' ','.','.','.'),
      YO_CTOKEN_EQUAL       = __FOUR_CHARS(' ',' ','=','='),
      YO_CTOKEN_NSPACE      = __FOUR_CHARS(' ',' ',':',':'),
      YO_CTOKEN_NEG_SET     = __FOUR_CHARS(' ',' ','~','='),
      YO_CTOKEN_NOT_SET     = __FOUR_CHARS(' ',' ','!','='),
  };

typedef struct _YOYO_CTOKMR
  {
    char *m;
    int lineno;
    int charno;
  } YOYO_CTOKMR;
  
typedef struct _YOYO_CTOKST
  {
    char *pS;
    char *pE;
    char *pI;
    char *source;
    int lineno;
    int charno;

    YOYO_CTOKMR last;
    YOYO_CTOKMR prelast;
  } YOYO_CTOKST;

void Ctok_Init(YOYO_CTOKST *a, char *S, char *E, char *source)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    memset(a,0,sizeof(*a));
    a->pI = a->pS = S;
    a->pE = E;
    a->source = source;
    a->lineno = 0;
    a->charno = 0;
  }  
#endif
  ;
  
int Ctok_GetXchr(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pI != a->pE )
      {
        if ( *a->pI == '\n' ) 
          { ++a->lineno; a->charno = 1; } 
        else 
          ++a->charno;
        return *a->pI++;
      }
    return -1;
  }
#endif
  ;
  
int Ctok_SkipXchrUntil(char c, YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    for (;;)
      {
        STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
        if ( a->pE == a->pI )
          return 0;
        if ( *a->pI != c )







|




|

|








|
|
|

|
|











|
|















|
|







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
      YO_CTOKEN_ELS         = __FOUR_CHARS(' ','.','.','.'),
      YO_CTOKEN_EQUAL       = __FOUR_CHARS(' ',' ','=','='),
      YO_CTOKEN_NSPACE      = __FOUR_CHARS(' ',' ',':',':'),
      YO_CTOKEN_NEG_SET     = __FOUR_CHARS(' ',' ','~','='),
      YO_CTOKEN_NOT_SET     = __FOUR_CHARS(' ',' ','!','='),
  };

typedef struct _YO_CTOKMR
  {
    char *m;
    int lineno;
    int charno;
  } YO_CTOKMR;
  
typedef struct _YO_CTOKST
  {
    char *pS;
    char *pE;
    char *pI;
    char *source;
    int lineno;
    int charno;

    YO_CTOKMR last;
    YO_CTOKMR prelast;
  } YO_CTOKST;

void Ctok_Init(YO_CTOKST *a, char *S, char *E, char *source)
#ifdef _YO_CTOKEN_BUILTIN
  {
    memset(a,0,sizeof(*a));
    a->pI = a->pS = S;
    a->pE = E;
    a->source = source;
    a->lineno = 0;
    a->charno = 0;
  }  
#endif
  ;
  
int Ctok_GetXchr(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pI != a->pE )
      {
        if ( *a->pI == '\n' ) 
          { ++a->lineno; a->charno = 1; } 
        else 
          ++a->charno;
        return *a->pI++;
      }
    return -1;
  }
#endif
  ;
  
int Ctok_SkipXchrUntil(char c, YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    for (;;)
      {
        STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
        if ( a->pE == a->pI )
          return 0;
        if ( *a->pI != c )
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
        else
          return c;
      }
  }
#endif
  ;
  
int Ctok_GetXchrIfIs(char c, YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pE == a->pI || *a->pI != c )
      return 0;
    ++a->pI;
    return c;
  }
#endif
  ;
  
int Ctok_GetXchrIfIs_Rep(char c, YOYO_CTOKST *a, int no)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    int i;
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pE-a->pI < no )
      return 0;
    for ( i = 0; i < no; ++i )
      if ( a->pI[i] != c ) 
        return 0;
    a->pI += no;
    return c;
  }
#endif
  ;
  
void Ctok_Stepback(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pI != a->pS ) 
      {
        --a->pI;
        if ( *a->pI == '\n' ) --a->lineno;
      }
  }
#endif
  ;
    
int Ctok_Hasmore(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    return a->pE - a->pI;
  }
#endif
  ;
    
void Ctok_Skip_Spaces(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    while ( a->pI != a->pE && ( *a->pI == ' ' || *a->pI == '\t' || *a->pI == '\n' || *a->pI == '\r' ) )
      Ctok_GetXchr(a);
  }
#endif
  ;
  
void Ctok_Mark(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  { 
    Ctok_Skip_Spaces(a);
    a->prelast = a->last;
    a->last.lineno = a->lineno;
    a->last.charno = a->charno;
    a->last.m = a->pI;
  }
#endif
  ;
  
void Ctok_Backmark(YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  { 
    if ( a->last.m )
     {
       a->pI = a->last.m;
       a->charno = a->last.charno;
       a->lineno = a->last.lineno;
      }
    a->last = a->prelast;
    memset(&a->prelast,0,sizeof(a->prelast));
  }
#endif
  ;
  
#define Ctok_Token(Area,Buf) Ctok_Token_(Area,Buf,0,0)
#define Ctok_Token_Local(Area,Buf,Plen) Ctok_Token_(Area,Buf,Plen,1)
#define Ctok_Token_Srcref(Area,Pptr,Plen) Ctok_Token_(Area,Pptr,Plen,2)

int Ctok_Token_(YOYO_CTOKST *a, void *dst, void *opt, int srccp)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    int tk;
    char *S;
    int c;
    STRICT_REQUIRE(a != 0);    
  
  l_repeat:  







|
|










|
|














|
|











|
|







|
|







|
|










|
|

















|
|







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
        else
          return c;
      }
  }
#endif
  ;
  
int Ctok_GetXchrIfIs(char c, YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pE == a->pI || *a->pI != c )
      return 0;
    ++a->pI;
    return c;
  }
#endif
  ;
  
int Ctok_GetXchrIfIs_Rep(char c, YO_CTOKST *a, int no)
#ifdef _YO_CTOKEN_BUILTIN
  {
    int i;
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pE-a->pI < no )
      return 0;
    for ( i = 0; i < no; ++i )
      if ( a->pI[i] != c ) 
        return 0;
    a->pI += no;
    return c;
  }
#endif
  ;
  
void Ctok_Stepback(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    if ( a->pI != a->pS ) 
      {
        --a->pI;
        if ( *a->pI == '\n' ) --a->lineno;
      }
  }
#endif
  ;
    
int Ctok_Hasmore(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    STRICT_REQUIRE( a->pI <= a->pE && a->pI >= a->pS );
    return a->pE - a->pI;
  }
#endif
  ;
    
void Ctok_Skip_Spaces(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    while ( a->pI != a->pE && ( *a->pI == ' ' || *a->pI == '\t' || *a->pI == '\n' || *a->pI == '\r' ) )
      Ctok_GetXchr(a);
  }
#endif
  ;
  
void Ctok_Mark(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  { 
    Ctok_Skip_Spaces(a);
    a->prelast = a->last;
    a->last.lineno = a->lineno;
    a->last.charno = a->charno;
    a->last.m = a->pI;
  }
#endif
  ;
  
void Ctok_Backmark(YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  { 
    if ( a->last.m )
     {
       a->pI = a->last.m;
       a->charno = a->last.charno;
       a->lineno = a->last.lineno;
      }
    a->last = a->prelast;
    memset(&a->prelast,0,sizeof(a->prelast));
  }
#endif
  ;
  
#define Ctok_Token(Area,Buf) Ctok_Token_(Area,Buf,0,0)
#define Ctok_Token_Local(Area,Buf,Plen) Ctok_Token_(Area,Buf,Plen,1)
#define Ctok_Token_Srcref(Area,Pptr,Plen) Ctok_Token_(Area,Pptr,Plen,2)

int Ctok_Token_(YO_CTOKST *a, void *dst, void *opt, int srccp)
#ifdef _YO_CTOKEN_BUILTIN
  {
    int tk;
    char *S;
    int c;
    STRICT_REQUIRE(a != 0);    
  
  l_repeat:  
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
      {
      }
    return tk;     
  }
#endif
  ;
  
void Ctok_Expect_Error(char *text,YOYO_CTOKST *a)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    __Raise_Format(YOYO_ERROR_SYNTAX,("synax error: %s at %s:%d:%d"
                          ,text ,a->source ,a->lineno ,a->charno) );
  }
#endif
  ;
  
char *Ctok_To_String(int tok)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    if ( tok > 30 && tok < 128 ) return Str_Copy_L((char*)&tok,1);
    return __Format("token(%4s)",&tok);
  }
#endif
  ;
  
void Ctok_Expect(int comp, char *p, YOYO_CTOKST *a, YOYO_BUFFER *r)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    int t;
    Ctok_Mark(a);
    t = Ctok_Token(a,r);
    if ( t != comp || ( p && !!strcmp(r->at,p) ) ) 
      {
        Ctok_Backmark(a);
        Ctok_Expect_Error(__Format("expected %s",Ctok_To_String(comp)),a);
      }
  }
#endif
  ;
  
int Ctok_GetIfIs(int comp, char *p, YOYO_CTOKST *a, YOYO_BUFFER *r)
#ifdef _YOYO_CTOKEN_BUILTIN
  {
    int t;
    Ctok_Mark(a);
    t = Ctok_Token(a,r);
    if ( t != comp || ( p && !!strcmp(r->at,p) ) ) 
      {
        Ctok_Backmark(a);







|
|

|






|







|
|













|
|







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
      {
      }
    return tk;     
  }
#endif
  ;
  
void Ctok_Expect_Error(char *text,YO_CTOKST *a)
#ifdef _YO_CTOKEN_BUILTIN
  {
    __Raise_Format(YO_ERROR_SYNTAX,("synax error: %s at %s:%d:%d"
                          ,text ,a->source ,a->lineno ,a->charno) );
  }
#endif
  ;
  
char *Ctok_To_String(int tok)
#ifdef _YO_CTOKEN_BUILTIN
  {
    if ( tok > 30 && tok < 128 ) return Str_Copy_L((char*)&tok,1);
    return __Format("token(%4s)",&tok);
  }
#endif
  ;
  
void Ctok_Expect(int comp, char *p, YO_CTOKST *a, YO_BUFFER *r)
#ifdef _YO_CTOKEN_BUILTIN
  {
    int t;
    Ctok_Mark(a);
    t = Ctok_Token(a,r);
    if ( t != comp || ( p && !!strcmp(r->at,p) ) ) 
      {
        Ctok_Backmark(a);
        Ctok_Expect_Error(__Format("expected %s",Ctok_To_String(comp)),a);
      }
  }
#endif
  ;
  
int Ctok_GetIfIs(int comp, char *p, YO_CTOKST *a, YO_BUFFER *r)
#ifdef _YO_CTOKEN_BUILTIN
  {
    int t;
    Ctok_Mark(a);
    t = Ctok_Token(a,r);
    if ( t != comp || ( p && !!strcmp(r->at,p) ) ) 
      {
        Ctok_Backmark(a);
Changes to datetime.hc.
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

*/

#ifndef C_once_A998DD5F_3579_4977_B115_DCCE42423C49
#define C_once_A998DD5F_3579_4977_B115_DCCE42423C49

#ifdef _LIBYOYO
#define _YOYO_DATETIME_BUILTIN
#endif

#include "yoyo.hc"

typedef quad_t datetime_t;

#define Get_Curr_Date()        ((uint_t)(Current_Gmt_Datetime()>>32))
#define Get_Curr_Datetime()    Current_Gmt_Datetime()
#define Get_Posix_Datetime(Dt) Timet_Of_Datetime(Dt)
#define Get_Gmtime_Datetime(T) Gmtime_Datetime(T)
#define Get_System_Useconds()  System_Useconds()
#define Get_System_Millis()    (Get_System_Useconds()/1000)

#define System_Millis() (System_Useconds()/1000)
quad_t System_Useconds()
#ifdef _YOYO_DATETIME_BUILTIN
  {
  #ifdef __windoze
    SYSTEMTIME systime = {0};
    FILETIME   ftime;
    quad_t Q;
    GetSystemTime(&systime);
    SystemTimeToFileTime(&systime,&ftime);
    Q = ((quad_t)ftime.dwHighDateTime << 32) + (quad_t)ftime.dwLowDateTime;
    Q -= 116444736000000000LL; /* posix epoche */
    return Q/10;
  #else
    struct timeval tv = {0};
    gettimeofday(&tv,0);
    return  ( (quad_t)tv.tv_sec * 1000*1000 + (quad_t)tv.tv_usec );
  #endif
  }
#endif
  ;
  
uint_t Get_Mclocks()
#ifdef _YOYO_DATETIME_BUILTIN
  {
    double c = clock();
    return (uint_t)((c/CLOCKS_PER_SEC)*1000);
  }
#endif
  ;

double Get_Sclocks()
#ifdef _YOYO_DATETIME_BUILTIN
  {
    double c = clock();
    return c/CLOCKS_PER_SEC;
  }
#endif
  ;

quad_t Tm_To_Datetime(struct tm *tm,int msec)
#ifdef _YOYO_DATETIME_BUILTIN
  {
    uint_t dt = (((uint_t)tm->tm_year+1900)<<16)|(((uint_t)tm->tm_mon+1)<<8)|tm->tm_mday;
    uint_t mt = ((uint_t)tm->tm_hour<<24)|(uint_t)(tm->tm_min<<16)|((uint_t)tm->tm_sec<<8)|((msec/10)%100);
    return ((quad_t)dt << 32)|(quad_t)mt;
  }
#endif
  ;

#define Gmtime_Datetime(T) _Gmtime_Datetime(T,0)
quad_t _Gmtime_Datetime(time_t t, int ms)
#ifdef _YOYO_DATETIME_BUILTIN
  {
    struct tm *tm;
    tm = gmtime(&t);
    return Tm_To_Datetime(tm,ms);
  }
#endif
  ;

#define Local_Datetime(T) _Local_Datetime(T,0)
quad_t _Local_Datetime(time_t t, int ms)
#ifdef _YOYO_DATETIME_BUILTIN
  {
    struct tm *tm;
    tm = localtime(&t);
    return Tm_To_Datetime(tm,ms);
  }
#endif
  ;

quad_t Current_Gmt_Datetime()
#ifdef _YOYO_DATETIME_BUILTIN
  {
    quad_t usec = Get_System_Useconds();
    return _Gmtime_Datetime((time_t)(usec/1000000),(int)((usec/1000)%1000));
  }
#endif
  ;

quad_t Current_Local_Datetime()
#ifdef _YOYO_DATETIME_BUILTIN
  {
    quad_t usec = Get_System_Useconds();
    return _Local_Datetime((time_t)(usec/1000000),(int)((usec/1000)%1000));
  }
#endif
  ;

#define Dt_Hour(Dt) ((int)((Dt)>>24)&0x0ff)
#define Dt_Min(Dt)  ((int)((Dt)>>16)&0x0ff)
#define Dt_Sec(Dt)  ((int)((Dt)>> 8)&0x0ff)
#define Dt_Msec(Dt) ((int)((Dt)>> 0)&0x0ff)
#define Dt_Year(Dt) ((int)((Dt)>>(32+16))&0x0ffff)
#define Dt_Mon(Dt)  ((int)((Dt)>>(32+ 8))&0x0ff)
#define Dt_Mday(Dt) ((int)((Dt)>>(32+ 0))&0x0ff)

quad_t Get_Datetime(uint_t year, uint_t month, uint_t day, uint_t hour, uint_t minute, uint_t segundo )
#ifdef _YOYO_DATETIME_BUILTIN
  {
    uint_t dt = ((year%0x0ffff)<<16)|((month%13)<<8)|(day%32);
    uint_t mt = ((hour%24)<<24)|((minute%60)<<16)|((segundo%60)<<8);
    return ((quad_t)dt << 32)|(quad_t)mt;
  }
#endif
  ;

time_t Timet_Of_Datetime(quad_t dtime)
#ifdef _YOYO_DATETIME_BUILTIN
  {
    struct tm tm;
    memset(&tm,0,sizeof(tm));
    tm.tm_year = Dt_Year(dtime)-1900;
    tm.tm_mon  = Dt_Mon(dtime)-1;
    tm.tm_mday = Dt_Mday(dtime);
    tm.tm_hour = Dt_Hour(dtime);
    tm.tm_min  = Dt_Min(dtime);
    return mktime(&tm);
  }
#endif
  ;

#ifdef __windoze
  void Timet_To_Filetime(time_t t, FILETIME *pft)
# ifdef _YOYO_DATETIME_BUILTIN
    {
      quad_t ll = (quad_t)t * 10000000 + 116444736000000000LL;
      pft->dwLowDateTime = (DWORD)ll;
      pft->dwHighDateTime = (DWORD)(ll >> 32);
    }
# endif
    ;
  #define Timet_To_Largetime(T,Li) Timet_To_Filetime(T,(FILETIME*)(Li))
#endif /*__windoze*/

#endif /* C_once_A998DD5F_3579_4977_B115_DCCE42423C49 */








|















|




















|








|








|










|










|









|








|
















|









|















|












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

*/

#ifndef C_once_A998DD5F_3579_4977_B115_DCCE42423C49
#define C_once_A998DD5F_3579_4977_B115_DCCE42423C49

#ifdef _LIBYOYO
#define _YO_DATETIME_BUILTIN
#endif

#include "yoyo.hc"

typedef quad_t datetime_t;

#define Get_Curr_Date()        ((uint_t)(Current_Gmt_Datetime()>>32))
#define Get_Curr_Datetime()    Current_Gmt_Datetime()
#define Get_Posix_Datetime(Dt) Timet_Of_Datetime(Dt)
#define Get_Gmtime_Datetime(T) Gmtime_Datetime(T)
#define Get_System_Useconds()  System_Useconds()
#define Get_System_Millis()    (Get_System_Useconds()/1000)

#define System_Millis() (System_Useconds()/1000)
quad_t System_Useconds()
#ifdef _YO_DATETIME_BUILTIN
  {
  #ifdef __windoze
    SYSTEMTIME systime = {0};
    FILETIME   ftime;
    quad_t Q;
    GetSystemTime(&systime);
    SystemTimeToFileTime(&systime,&ftime);
    Q = ((quad_t)ftime.dwHighDateTime << 32) + (quad_t)ftime.dwLowDateTime;
    Q -= 116444736000000000LL; /* posix epoche */
    return Q/10;
  #else
    struct timeval tv = {0};
    gettimeofday(&tv,0);
    return  ( (quad_t)tv.tv_sec * 1000*1000 + (quad_t)tv.tv_usec );
  #endif
  }
#endif
  ;
  
uint_t Get_Mclocks()
#ifdef _YO_DATETIME_BUILTIN
  {
    double c = clock();
    return (uint_t)((c/CLOCKS_PER_SEC)*1000);
  }
#endif
  ;

double Get_Sclocks()
#ifdef _YO_DATETIME_BUILTIN
  {
    double c = clock();
    return c/CLOCKS_PER_SEC;
  }
#endif
  ;

quad_t Tm_To_Datetime(struct tm *tm,int msec)
#ifdef _YO_DATETIME_BUILTIN
  {
    uint_t dt = (((uint_t)tm->tm_year+1900)<<16)|(((uint_t)tm->tm_mon+1)<<8)|tm->tm_mday;
    uint_t mt = ((uint_t)tm->tm_hour<<24)|(uint_t)(tm->tm_min<<16)|((uint_t)tm->tm_sec<<8)|((msec/10)%100);
    return ((quad_t)dt << 32)|(quad_t)mt;
  }
#endif
  ;

#define Gmtime_Datetime(T) _Gmtime_Datetime(T,0)
quad_t _Gmtime_Datetime(time_t t, int ms)
#ifdef _YO_DATETIME_BUILTIN
  {
    struct tm *tm;
    tm = gmtime(&t);
    return Tm_To_Datetime(tm,ms);
  }
#endif
  ;

#define Local_Datetime(T) _Local_Datetime(T,0)
quad_t _Local_Datetime(time_t t, int ms)
#ifdef _YO_DATETIME_BUILTIN
  {
    struct tm *tm;
    tm = localtime(&t);
    return Tm_To_Datetime(tm,ms);
  }
#endif
  ;

quad_t Current_Gmt_Datetime()
#ifdef _YO_DATETIME_BUILTIN
  {
    quad_t usec = Get_System_Useconds();
    return _Gmtime_Datetime((time_t)(usec/1000000),(int)((usec/1000)%1000));
  }
#endif
  ;

quad_t Current_Local_Datetime()
#ifdef _YO_DATETIME_BUILTIN
  {
    quad_t usec = Get_System_Useconds();
    return _Local_Datetime((time_t)(usec/1000000),(int)((usec/1000)%1000));
  }
#endif
  ;

#define Dt_Hour(Dt) ((int)((Dt)>>24)&0x0ff)
#define Dt_Min(Dt)  ((int)((Dt)>>16)&0x0ff)
#define Dt_Sec(Dt)  ((int)((Dt)>> 8)&0x0ff)
#define Dt_Msec(Dt) ((int)((Dt)>> 0)&0x0ff)
#define Dt_Year(Dt) ((int)((Dt)>>(32+16))&0x0ffff)
#define Dt_Mon(Dt)  ((int)((Dt)>>(32+ 8))&0x0ff)
#define Dt_Mday(Dt) ((int)((Dt)>>(32+ 0))&0x0ff)

quad_t Get_Datetime(uint_t year, uint_t month, uint_t day, uint_t hour, uint_t minute, uint_t segundo )
#ifdef _YO_DATETIME_BUILTIN
  {
    uint_t dt = ((year%0x0ffff)<<16)|((month%13)<<8)|(day%32);
    uint_t mt = ((hour%24)<<24)|((minute%60)<<16)|((segundo%60)<<8);
    return ((quad_t)dt << 32)|(quad_t)mt;
  }
#endif
  ;

time_t Timet_Of_Datetime(quad_t dtime)
#ifdef _YO_DATETIME_BUILTIN
  {
    struct tm tm;
    memset(&tm,0,sizeof(tm));
    tm.tm_year = Dt_Year(dtime)-1900;
    tm.tm_mon  = Dt_Mon(dtime)-1;
    tm.tm_mday = Dt_Mday(dtime);
    tm.tm_hour = Dt_Hour(dtime);
    tm.tm_min  = Dt_Min(dtime);
    return mktime(&tm);
  }
#endif
  ;

#ifdef __windoze
  void Timet_To_Filetime(time_t t, FILETIME *pft)
# ifdef _YO_DATETIME_BUILTIN
    {
      quad_t ll = (quad_t)t * 10000000 + 116444736000000000LL;
      pft->dwLowDateTime = (DWORD)ll;
      pft->dwHighDateTime = (DWORD)(ll >> 32);
    }
# endif
    ;
  #define Timet_To_Largetime(T,Li) Timet_To_Filetime(T,(FILETIME*)(Li))
#endif /*__windoze*/

#endif /* C_once_A998DD5F_3579_4977_B115_DCCE42423C49 */

Changes to debugit.hc.
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

*/

#ifndef C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4
#define C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4

#ifdef _LIBYOYO
#define _YOYO_DEBUGIT_BUILTIN
#endif

#include "yoyo.hc"
#include "winreg.hc"

#ifdef _MSC_VER
# define Debug_Break() __debugbreak()    
#elif defined __GNUC__
# define Debug_Break() __builtin_trap()    
#else
# define Debug_Break() raise(SIGTRAP)
#endif

void Debug_It()
#ifdef _YOYO_DEBUGIT_BUILTIN
  {
#ifdef __windoze
    char ae[128] = {0};
    __Auto_Release
      {
        YOYO_WINREG *h = Open_Local_Machine_Subkey("Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
        char *S = WinReg_Query_String(h,"Debugger");
        snprintf(ae,127,S,GetCurrentProcessId(),0);
      }
    WinExec(ae,0);
    Sleep(3000);
#endif
    Debug_Break();    
  }
#endif
  ;
  
#endif /*C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4*/








|














|





|













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

*/

#ifndef C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4
#define C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4

#ifdef _LIBYOYO
#define _YO_DEBUGIT_BUILTIN
#endif

#include "yoyo.hc"
#include "winreg.hc"

#ifdef _MSC_VER
# define Debug_Break() __debugbreak()    
#elif defined __GNUC__
# define Debug_Break() __builtin_trap()    
#else
# define Debug_Break() raise(SIGTRAP)
#endif

void Debug_It()
#ifdef _YO_DEBUGIT_BUILTIN
  {
#ifdef __windoze
    char ae[128] = {0};
    __Auto_Release
      {
        YO_WINREG *h = Open_Local_Machine_Subkey("Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug");
        char *S = WinReg_Query_String(h,"Debugger");
        snprintf(ae,127,S,GetCurrentProcessId(),0);
      }
    WinExec(ae,0);
    Sleep(3000);
#endif
    Debug_Break();    
  }
#endif
  ;
  
#endif /*C_once_1ABAFC81_AD6E_4869_8891_EEE28BC64BF4*/

Changes to dicto.hc.
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

*/

#ifndef C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203
#define C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203

#ifdef _LIBYOYO
#define _YOYO_DICTO_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"
#include "buffer.hc"
#include "array.hc"

typedef struct _YOYO_DICTO_REC
  {
    struct _YOYO_DICTO_REC *next;
    void *ptr;
    byte_t hashcode;
    char key[1];
  } YOYO_DICTO_REC;

typedef struct _YOYO_DICTO
  {
    struct _YOYO_DICTO_REC **table; 
    int count;
    int width;
  } YOYO_DICTO;


#define Dicto_Hash_1(Key) Crc_8_Of_Cstr(Key)
#define Dicto_Count(Dicto) ((int)((YOYO_DICTO*)(Dicto))->count+0)

void Dicto_Rehash(YOYO_DICTO *o);

#ifdef _YOYO_DICTO_BUILTIN  
int Dicto_Width_Values[] = {5,11,23,47,97,181,256};
#endif

YOYO_DICTO_REC **Dicto_Backet(YOYO_DICTO *o, byte_t hashcode, char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    YOYO_DICTO_REC **nrec;
    
    if ( !o->table )
      {
        o->width = Dicto_Width_Values[0];
        o->table = Yo_Malloc_Npl(o->width*sizeof(void*));
        memset(o->table,0,o->width*sizeof(void*));
      }







|







|

|



|

|

|


|



|

|

|



|
|

|







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

*/

#ifndef C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203
#define C_once_38B1FFE7_1462_42EB_BABE_AA8E0BE62203

#ifdef _LIBYOYO
#define _YO_DICTO_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"
#include "buffer.hc"
#include "array.hc"

typedef struct _YO_DICTO_REC
  {
    struct _YO_DICTO_REC *next;
    void *ptr;
    byte_t hashcode;
    char key[1];
  } YO_DICTO_REC;

typedef struct _YO_DICTO
  {
    struct _YO_DICTO_REC **table; 
    int count;
    int width;
  } YO_DICTO;


#define Dicto_Hash_1(Key) Crc_8_Of_Cstr(Key)
#define Dicto_Count(Dicto) ((int)((YO_DICTO*)(Dicto))->count+0)

void Dicto_Rehash(YO_DICTO *o);

#ifdef _YO_DICTO_BUILTIN  
int Dicto_Width_Values[] = {5,11,23,47,97,181,256};
#endif

YO_DICTO_REC **Dicto_Backet(YO_DICTO *o, byte_t hashcode, char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    YO_DICTO_REC **nrec;
    
    if ( !o->table )
      {
        o->width = Dicto_Width_Values[0];
        o->table = Yo_Malloc_Npl(o->width*sizeof(void*));
        memset(o->table,0,o->width*sizeof(void*));
      }
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
      }
    
    return nrec;
  }
#endif
  ;

YOYO_DICTO_REC *Dicto_Allocate(char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    int keylen = strlen(key);
    YOYO_DICTO_REC *Q = Yo_Malloc_Npl(sizeof(YOYO_DICTO_REC) + keylen);
    memcpy(Q->key,key,keylen+1);
    Q->hashcode = Dicto_Hash_1(key);
    Q->next = 0;
    Q->ptr = 0;
    return Q;
  }
#endif
  ;

void *Dicto_Get(YOYO_DICTO *o, char *key, void *dflt)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YOYO_DICTO_REC *Q = *Dicto_Backet(o,hashcode,key);
        if ( Q )
          return Q->ptr;
      }
    return dflt;
  }
#endif
  ;

void *Dicto_Get_Key_Ptr(YOYO_DICTO *o, char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YOYO_DICTO_REC *Q = *Dicto_Backet(o,hashcode,key);
        if ( Q )
          return Q->key;
      }
    return 0;
  }
#endif
  ;

int Dicto_Has(YOYO_DICTO *o, char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        if ( *Dicto_Backet(o,hashcode,key) )
          return 1;
      }
    return 0;
  }
#endif
  ;

void *Dicto_Put(YOYO_DICTO *o, char *key, void *val)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YOYO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YOYO_DICTO_REC *p = *Q;
            void *self = o;
            void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              (*destructor)(p->ptr);
            p->ptr = val;
            key = (*Q)->key;
          }







|
|


|









|
|




|








|
|




|








|
|












|
|




|


|







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
      }
    
    return nrec;
  }
#endif
  ;

YO_DICTO_REC *Dicto_Allocate(char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    int keylen = strlen(key);
    YO_DICTO_REC *Q = Yo_Malloc_Npl(sizeof(YO_DICTO_REC) + keylen);
    memcpy(Q->key,key,keylen+1);
    Q->hashcode = Dicto_Hash_1(key);
    Q->next = 0;
    Q->ptr = 0;
    return Q;
  }
#endif
  ;

void *Dicto_Get(YO_DICTO *o, char *key, void *dflt)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YO_DICTO_REC *Q = *Dicto_Backet(o,hashcode,key);
        if ( Q )
          return Q->ptr;
      }
    return dflt;
  }
#endif
  ;

void *Dicto_Get_Key_Ptr(YO_DICTO *o, char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YO_DICTO_REC *Q = *Dicto_Backet(o,hashcode,key);
        if ( Q )
          return Q->key;
      }
    return 0;
  }
#endif
  ;

int Dicto_Has(YO_DICTO *o, char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        if ( *Dicto_Backet(o,hashcode,key) )
          return 1;
      }
    return 0;
  }
#endif
  ;

void *Dicto_Put(YO_DICTO *o, char *key, void *val)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YO_DICTO_REC *p = *Q;
            void *self = o;
            void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              (*destructor)(p->ptr);
            p->ptr = val;
            key = (*Q)->key;
          }
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
      }
    else
      return 0;
  }
#endif
  ;

void Dicto_Del(YOYO_DICTO *o, char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YOYO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YOYO_DICTO_REC *p = *Q;
            void *self = o;
            void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              (*destructor)(p->ptr);
            *Q = (*Q)->next;
            free(p);
            STRICT_REQUIRE ( o->count >= 1 );
            --o->count;
          }
      }
  }
#endif
  ;

/* returns unmanaged value */
void *Dicto_Take_Npl(YOYO_DICTO *o, char *key)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YOYO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YOYO_DICTO_REC *p = *Q;
            void *ret = p->ptr;
            *Q = (*Q)->next;
            free(p);
            STRICT_REQUIRE ( o->count >= 1 );
            --o->count;
            return ret;
          }
      }
    return 0;
  }
#endif
  ;

void *Dicto_Take(YOYO_DICTO *o, char *key)
#ifdef _YOYO_ARRAY_BUILTIN
  {
    void *self = o;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,YO_RAISE_ERROR);
    void *Q = Dicto_Take_Npl(o,key);
    
    if ( Q )
      Yo_Pool_Ptr(Q,destruct);
      
    return Q;
  }
#endif
  ;

void Dicto_Clear(YOYO_DICTO *o)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    int i;
    void *self = o;
    void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    
    if ( o->table )
      for ( i = 0; i < o->width; ++i )
        while ( o->table[i] )
          {
            YOYO_DICTO_REC *Q = o->table[i];
            o->table[i] = Q->next;
            if ( destructor )
              (*destructor)(Q->ptr);
            free(Q);
          }

    if ( o->table ) free( o->table );
    o->table = 0;
    o->width = 0;
    o->count = 0;      
  }
#endif
  ;

#ifdef _YOYO_DICTO_BUILTIN  
void Dicto_Rehash(YOYO_DICTO *o)
  {
    if ( o->table && o->count )
      {
        int i;
        int width = 256;
        YOYO_DICTO_REC **table;
        
        for ( i = 0; Dicto_Width_Values[i] < 256; ++i )
          if ( o->count <= Dicto_Width_Values[i] + Dicto_Width_Values[i]/2  )
            {
              width = Dicto_Width_Values[i]; 
              break;
            }
        
        if ( width > o->width ) 
          {
            table = Yo_Malloc_Npl(width*sizeof(void*));
            memset(table,0,width*sizeof(void*));
        
            for ( i = 0; i < o->width; ++i )
              while ( o->table[i] )
                {
                  YOYO_DICTO_REC *Q = o->table[i];
                  o->table[i] = Q->next;
                  Q->next = table[Q->hashcode%width];
                  table[Q->hashcode%width] = Q;
                }
      
            free(o->table);
            o->width = width;
            o->table = table;    
          }
      }
  }
#endif
  ;

void Dicto_Destruct(YOYO_DICTO *o)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    Dicto_Clear(o);
    Yo_Object_Destruct(o);
  }
#endif
  ;

void *Dicto_Refs(void)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Dicto_Destruct},
        {Oj_Destruct_Element_OjMID, Yo_Unrefe},
        {0}};
    YOYO_DICTO *dicto = Yo_Object(sizeof(YOYO_DICTO),funcs);
    return dicto;
  }
#endif
  ;

void *Dicto_Ptrs(void)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Dicto_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {0}};
    YOYO_DICTO *dicto = Yo_Object(sizeof(YOYO_DICTO),funcs);
    return dicto;
  }
#endif
  ;

void *Dicto_Init(void)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    YOYO_DICTO *dicto = Yo_Object_Dtor(sizeof(YOYO_DICTO),Dicto_Destruct);
    return dicto;
  }
#endif
  ;

void Dicto_Apply(YOYO_DICTO *o,void (*filter)(char *,void *,void *),void *state)  
#ifdef _YOYO_DICTO_BUILTIN  
  {
    int i;
    YOYO_DICTO_REC *nrec;
    if ( o && o->table ) 
      for ( i = 0; i < o->width; ++i )
        {      
          nrec = o->table[i];
          while ( nrec )
            {
              filter(nrec->key,nrec->ptr,state);
              nrec = nrec->next;
            }  
        }
  }
#endif
  ;

void _Dicto_Filter_Push_Value(char *key, void *value, YOYO_ARRAY *a)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    Array_Push(a,value);
  }
#endif
  ;
    
YOYO_ARRAY *Dicto_Values(YOYO_DICTO *o)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    YOYO_ARRAY *a = Array_Void();
    Dicto_Apply(o,_Dicto_Filter_Push_Value,a);
    return a;
  }
#endif
  ;
    
void _Dicto_Filter_Push_Key(char *key, void *value, YOYO_ARRAY *a)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    Array_Push(a,key);
  }
#endif
  ;
    
YOYO_ARRAY *Dicto_Keys(YOYO_DICTO *o)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    YOYO_ARRAY *a = Array_Void();
    Dicto_Apply(o,_Dicto_Filter_Push_Key,a);
    return a;
  }
#endif
  ;
  
typedef void (*dicto_format_printer_t)(YOYO_BUFFER *bf,void *S);

char *Dicto_Format(YOYO_DICTO *o, dicto_format_printer_t print, YOYO_BUFFER *_bf, int pretty)
#ifdef _YOYO_DICTO_BUILTIN  
  {
    int start = 0, i, j=0;
    YOYO_BUFFER *bf = _bf;
    YOYO_DICTO_REC *nrec;

    if ( !bf ) bf = Buffer_Init(0);
    start = bf->count;
    
    Buffer_Fill_Append(bf,'{',1);
    if ( pretty )
      Buffer_Fill_Append(bf,'\n',1); 







|
|




|


|















|
|




|


|













|
|













|
|









|














|
|





|
















|














|
|








|

|




|






|

|




|






|

|





|
|


|














|
|






|
|

|






|
|






|
|

|






|

|
|


|
|







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
      }
    else
      return 0;
  }
#endif
  ;

void Dicto_Del(YO_DICTO *o, char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YO_DICTO_REC *p = *Q;
            void *self = o;
            void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
            if ( destructor )
              (*destructor)(p->ptr);
            *Q = (*Q)->next;
            free(p);
            STRICT_REQUIRE ( o->count >= 1 );
            --o->count;
          }
      }
  }
#endif
  ;

/* returns unmanaged value */
void *Dicto_Take_Npl(YO_DICTO *o, char *key)
#ifdef _YO_DICTO_BUILTIN  
  {
    if ( key )
      {
        byte_t hashcode = Dicto_Hash_1(key);
        YO_DICTO_REC **Q = Dicto_Backet(o,hashcode,key);
        if ( *Q )
          {
            YO_DICTO_REC *p = *Q;
            void *ret = p->ptr;
            *Q = (*Q)->next;
            free(p);
            STRICT_REQUIRE ( o->count >= 1 );
            --o->count;
            return ret;
          }
      }
    return 0;
  }
#endif
  ;

void *Dicto_Take(YO_DICTO *o, char *key)
#ifdef _YO_ARRAY_BUILTIN
  {
    void *self = o;
    void (*destruct)(void *) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,YO_RAISE_ERROR);
    void *Q = Dicto_Take_Npl(o,key);
    
    if ( Q )
      Yo_Pool_Ptr(Q,destruct);
      
    return Q;
  }
#endif
  ;

void Dicto_Clear(YO_DICTO *o)
#ifdef _YO_DICTO_BUILTIN  
  {
    int i;
    void *self = o;
    void (*destructor)(void*) = Yo_Find_Method_Of(&self,Oj_Destruct_Element_OjMID,0);
    
    if ( o->table )
      for ( i = 0; i < o->width; ++i )
        while ( o->table[i] )
          {
            YO_DICTO_REC *Q = o->table[i];
            o->table[i] = Q->next;
            if ( destructor )
              (*destructor)(Q->ptr);
            free(Q);
          }

    if ( o->table ) free( o->table );
    o->table = 0;
    o->width = 0;
    o->count = 0;      
  }
#endif
  ;

#ifdef _YO_DICTO_BUILTIN  
void Dicto_Rehash(YO_DICTO *o)
  {
    if ( o->table && o->count )
      {
        int i;
        int width = 256;
        YO_DICTO_REC **table;
        
        for ( i = 0; Dicto_Width_Values[i] < 256; ++i )
          if ( o->count <= Dicto_Width_Values[i] + Dicto_Width_Values[i]/2  )
            {
              width = Dicto_Width_Values[i]; 
              break;
            }
        
        if ( width > o->width ) 
          {
            table = Yo_Malloc_Npl(width*sizeof(void*));
            memset(table,0,width*sizeof(void*));
        
            for ( i = 0; i < o->width; ++i )
              while ( o->table[i] )
                {
                  YO_DICTO_REC *Q = o->table[i];
                  o->table[i] = Q->next;
                  Q->next = table[Q->hashcode%width];
                  table[Q->hashcode%width] = Q;
                }
      
            free(o->table);
            o->width = width;
            o->table = table;    
          }
      }
  }
#endif
  ;

void Dicto_Destruct(YO_DICTO *o)
#ifdef _YO_DICTO_BUILTIN  
  {
    Dicto_Clear(o);
    Yo_Object_Destruct(o);
  }
#endif
  ;

void *Dicto_Refs(void)
#ifdef _YO_DICTO_BUILTIN  
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Dicto_Destruct},
        {Oj_Destruct_Element_OjMID, Yo_Unrefe},
        {0}};
    YO_DICTO *dicto = Yo_Object(sizeof(YO_DICTO),funcs);
    return dicto;
  }
#endif
  ;

void *Dicto_Ptrs(void)
#ifdef _YO_DICTO_BUILTIN  
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, Dicto_Destruct},
        {Oj_Destruct_Element_OjMID, free},
        {0}};
    YO_DICTO *dicto = Yo_Object(sizeof(YO_DICTO),funcs);
    return dicto;
  }
#endif
  ;

void *Dicto_Init(void)
#ifdef _YO_DICTO_BUILTIN  
  {
    YO_DICTO *dicto = Yo_Object_Dtor(sizeof(YO_DICTO),Dicto_Destruct);
    return dicto;
  }
#endif
  ;

void Dicto_Apply(YO_DICTO *o,void (*filter)(char *,void *,void *),void *state)  
#ifdef _YO_DICTO_BUILTIN  
  {
    int i;
    YO_DICTO_REC *nrec;
    if ( o && o->table ) 
      for ( i = 0; i < o->width; ++i )
        {      
          nrec = o->table[i];
          while ( nrec )
            {
              filter(nrec->key,nrec->ptr,state);
              nrec = nrec->next;
            }  
        }
  }
#endif
  ;

void _Dicto_Filter_Push_Value(char *key, void *value, YO_ARRAY *a)
#ifdef _YO_DICTO_BUILTIN  
  {
    Array_Push(a,value);
  }
#endif
  ;
    
YO_ARRAY *Dicto_Values(YO_DICTO *o)
#ifdef _YO_DICTO_BUILTIN  
  {
    YO_ARRAY *a = Array_Void();
    Dicto_Apply(o,_Dicto_Filter_Push_Value,a);
    return a;
  }
#endif
  ;
    
void _Dicto_Filter_Push_Key(char *key, void *value, YO_ARRAY *a)
#ifdef _YO_DICTO_BUILTIN  
  {
    Array_Push(a,key);
  }
#endif
  ;
    
YO_ARRAY *Dicto_Keys(YO_DICTO *o)
#ifdef _YO_DICTO_BUILTIN  
  {
    YO_ARRAY *a = Array_Void();
    Dicto_Apply(o,_Dicto_Filter_Push_Key,a);
    return a;
  }
#endif
  ;
  
typedef void (*dicto_format_printer_t)(YO_BUFFER *bf,void *S);

char *Dicto_Format(YO_DICTO *o, dicto_format_printer_t print, YO_BUFFER *_bf, int pretty)
#ifdef _YO_DICTO_BUILTIN  
  {
    int start = 0, i, j=0;
    YO_BUFFER *bf = _bf;
    YO_DICTO_REC *nrec;

    if ( !bf ) bf = Buffer_Init(0);
    start = bf->count;
    
    Buffer_Fill_Append(bf,'{',1);
    if ( pretty )
      Buffer_Fill_Append(bf,'\n',1); 
Changes to file.hc.
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

*/

#ifndef C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B
#define C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B

#ifdef _LIBYOYO
#define _YOYO_FILE_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "random.hc"

#ifndef __windoze
# include <dirent.h>
# include <sys/file.h>
#endif

#ifdef _FILEi32
  typedef long file_offset_t;
#else
  typedef quad_t file_offset_t;
#endif

enum { YOYO_FILE_COPY_BUFFER_SIZE = 4096, };

#ifdef _YOYO_FILE_BUILTIN
# define _YOYO_FILE_BUILTIN_CODE(Code) Code
# define _YOYO_FILE_EXTERN
#else
# define _YOYO_FILE_BUILTIN_CODE(Code)
# define _YOYO_FILE_EXTERN extern
#endif

#ifdef __windoze
enum { YOYO_PATH_SEPARATOR = '\\' };
#else
enum { YOYO_PATH_SEPARATOR = '/' };
#endif

void File_Check_Error(char *op, FILE *f, char *fname, int look_to_errno)
#ifdef _YOYO_FILE_BUILTIN
  {
    int err = 0;
    char *errS = 0;
    
    if ( look_to_errno )
      {
        if ( (err = errno) ) 
          errS = strerror(err);
      }
    else if ( f && !feof(f) && ( err = ferror(f) ) )
      {
        errS = strerror(err);
        clearerr(f);
      }
    
    if (err)
      __Raise_Format(YOYO_ERROR_IO,("%s failed on file '%s': %s",op,fname,errS));
  }
#endif
  ;

#define Raise_If_File_Error(Op,Fname) File_Check_Error(Op,0,Fname,1)

char *Path_Basename(char *path)
#ifdef _YOYO_FILE_BUILTIN
  {
    char *ret = path;
    if ( path )
      {
        char *p = strrchr(path,'/');
      #ifdef __windoze
        char *p2 = strrchr(path,'\\');
        if ( !p || p < p2 ) p = p2;
      #endif
        if ( p )
          ret = Str_Copy(p+1);
      }
    return ret;
  }
#endif
  ;

char *Path_Dirname(char *path)
#ifdef _YOYO_FILE_BUILTIN
  {
    char *ret = 0;
    if ( path )
      {
        char *p = strrchr(path,'/');
      #ifdef __windoze
        char *p2 = strrchr(path,'\\');







|


















|

|
|
|

|
|



|

|



|
















|







|


















|







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

*/

#ifndef C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B
#define C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B

#ifdef _LIBYOYO
#define _YO_FILE_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "random.hc"

#ifndef __windoze
# include <dirent.h>
# include <sys/file.h>
#endif

#ifdef _FILEi32
  typedef long file_offset_t;
#else
  typedef quad_t file_offset_t;
#endif

enum { YO_FILE_COPY_BUFFER_SIZE = 4096, };

#ifdef _YO_FILE_BUILTIN
# define _YO_FILE_BUILTIN_CODE(Code) Code
# define _YO_FILE_EXTERN
#else
# define _YO_FILE_BUILTIN_CODE(Code)
# define _YO_FILE_EXTERN extern
#endif

#ifdef __windoze
enum { YO_PATH_SEPARATOR = '\\' };
#else
enum { YO_PATH_SEPARATOR = '/' };
#endif

void File_Check_Error(char *op, FILE *f, char *fname, int look_to_errno)
#ifdef _YO_FILE_BUILTIN
  {
    int err = 0;
    char *errS = 0;
    
    if ( look_to_errno )
      {
        if ( (err = errno) ) 
          errS = strerror(err);
      }
    else if ( f && !feof(f) && ( err = ferror(f) ) )
      {
        errS = strerror(err);
        clearerr(f);
      }
    
    if (err)
      __Raise_Format(YO_ERROR_IO,("%s failed on file '%s': %s",op,fname,errS));
  }
#endif
  ;

#define Raise_If_File_Error(Op,Fname) File_Check_Error(Op,0,Fname,1)

char *Path_Basename(char *path)
#ifdef _YO_FILE_BUILTIN
  {
    char *ret = path;
    if ( path )
      {
        char *p = strrchr(path,'/');
      #ifdef __windoze
        char *p2 = strrchr(path,'\\');
        if ( !p || p < p2 ) p = p2;
      #endif
        if ( p )
          ret = Str_Copy(p+1);
      }
    return ret;
  }
#endif
  ;

char *Path_Dirname(char *path)
#ifdef _YO_FILE_BUILTIN
  {
    char *ret = 0;
    if ( path )
      {
        char *p = strrchr(path,'/');
      #ifdef __windoze
        char *p2 = strrchr(path,'\\');
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
          }
      }
    return ret;
  }
#endif
  ;























char *Current_Directory()
#ifdef _YOYO_FILE_BUILTIN
  {
    enum { tmp_len = 512 };
    char *ptr = 0;
    __Auto_Ptr(ptr)
      {
      #ifdef __windoze
        wchar_t *tmp = __Malloc((tmp_len+1)*sizeof(wchar_t));
        ptr = Str_Unicode_To_Utf8(_wgetcwd(tmp,tmp_len));
      #else
        char *tmp = __Malloc(tmp_len+1);
        ptr = Str_Copy(getcwd(tmp,tmp_len),-1);
      #endif
      }
    return ptr;
  }
#endif
  ;

void Change_Directory(char *dirname)
#ifdef _YOYO_FILE_BUILTIN
  {
    __Auto_Release
      {
        int err;
      #ifdef __windoze
        wchar_t *tmp = Str_Utf8_To_Unicode(dirname);
        err = _wchdir(tmp);
      #else
        err = chdir(dirname);
      #endif
        if ( err == - 1 )
          Raise_If_File_Error("chdir",dirname);
      }
  }
#endif
  ;
  
char *Path_Normilize_Npl_(char *path, int sep)
#ifdef _YOYO_FILE_BUILTIN
  {
    int i = 0, ln = strlen(path);
    char *S = __Malloc_Npl(ln+1);
    *S = 0;
    
    while ( *path )
      {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



















|


















|







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
          }
      }
    return ret;
  }
#endif
  ;

char *Temp_Directory()
#ifdef _YO_FILE_BUILTIN
  {
    enum { tmp_len = 512 };
    char *ptr = 0;
    __Auto_Ptr(ptr)
      {
      #ifdef __windoze
        wchar_t *tmp = __Malloc((tmp_len+1)*sizeof(wchar_t));
        GetTempPathW(tmp_len+1,tmp);
        ptr = Str_Unicode_To_Utf8(tmp);
      #else
        char *tmp = getenv("TEMP");
        if ( !tmp ) tmp = "/tmp"
        ptr = Str_Copy(tmp);
      #endif
      }
    return ptr;
  }
#endif
  ;
    
char *Current_Directory()
#ifdef _YO_FILE_BUILTIN
  {
    enum { tmp_len = 512 };
    char *ptr = 0;
    __Auto_Ptr(ptr)
      {
      #ifdef __windoze
        wchar_t *tmp = __Malloc((tmp_len+1)*sizeof(wchar_t));
        ptr = Str_Unicode_To_Utf8(_wgetcwd(tmp,tmp_len));
      #else
        char *tmp = __Malloc(tmp_len+1);
        ptr = Str_Copy(getcwd(tmp,tmp_len),-1);
      #endif
      }
    return ptr;
  }
#endif
  ;

void Change_Directory(char *dirname)
#ifdef _YO_FILE_BUILTIN
  {
    __Auto_Release
      {
        int err;
      #ifdef __windoze
        wchar_t *tmp = Str_Utf8_To_Unicode(dirname);
        err = _wchdir(tmp);
      #else
        err = chdir(dirname);
      #endif
        if ( err == - 1 )
          Raise_If_File_Error("chdir",dirname);
      }
  }
#endif
  ;
  
char *Path_Normilize_Npl_(char *path, int sep)
#ifdef _YO_FILE_BUILTIN
  {
    int i = 0, ln = strlen(path);
    char *S = __Malloc_Npl(ln+1);
    *S = 0;
    
    while ( *path )
      {
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    if ( i && S[i-1] == sep ) S[--i] = 0;
    
    return S;
  }
#endif
  ;

#define Path_Normilize_Npl(S) Path_Normilize_Npl_(S,YOYO_PATH_SEPARATOR)
#define Path_Normilize(S) __Pool(Path_Normilize_Npl(S))
#define Path_Normposix_Npl(S) Path_Normilize_Npl_(S,'/')
#define Path_Normposix(S) __Pool(Path_Normilize_Npl(S))

char *Path_Unique_Name(char *dirname,char *pfx, char *sfx)
#ifdef _YOYO_FILE_BUILTIN
  {
  #ifdef __windoze
    char DELIMITER[] = "\\";
  #else
    char DELIMITER[] = "/";
  #endif
    char unique[2+4+6] = {0};







|





|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
    if ( i && S[i-1] == sep ) S[--i] = 0;
    
    return S;
  }
#endif
  ;

#define Path_Normilize_Npl(S) Path_Normilize_Npl_(S,YO_PATH_SEPARATOR)
#define Path_Normilize(S) __Pool(Path_Normilize_Npl(S))
#define Path_Normposix_Npl(S) Path_Normilize_Npl_(S,'/')
#define Path_Normposix(S) __Pool(Path_Normilize_Npl(S))

char *Path_Unique_Name(char *dirname,char *pfx, char *sfx)
#ifdef _YO_FILE_BUILTIN
  {
  #ifdef __windoze
    char DELIMITER[] = "\\";
  #else
    char DELIMITER[] = "/";
  #endif
    char unique[2+4+6] = {0};
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    else
      return Str_Join_3(0,(pfx?pfx:""),out,(sfx?sfx:""));
  }
#endif
  ;

char *Path_Join(char *dir, char *name)
#ifdef _YOYO_FILE_BUILTIN
  {
  #ifdef __windoze
    enum { DELIMITER = '\\' };
  #else
    enum { DELIMITER = '/' };
  #endif
    if ( dir && *dir )







|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    else
      return Str_Join_3(0,(pfx?pfx:""),out,(sfx?sfx:""));
  }
#endif
  ;

char *Path_Join(char *dir, char *name)
#ifdef _YO_FILE_BUILTIN
  {
  #ifdef __windoze
    enum { DELIMITER = '\\' };
  #else
    enum { DELIMITER = '/' };
  #endif
    if ( dir && *dir )
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
    else
      return Str_Copy(name);
  }
#endif
  ;

char *Path_Suffix(char *path)
#ifdef _YOYO_FILE_BUILTIN
  {
    char *ret = 0;
    char *p = strrchr(path,'.');
    if ( p )
      {
        char *p1 = strrchr(path,'/');
        if ( p1 && p1 > p ) p = p1;







|







289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    else
      return Str_Copy(name);
  }
#endif
  ;

char *Path_Suffix(char *path)
#ifdef _YO_FILE_BUILTIN
  {
    char *ret = 0;
    char *p = strrchr(path,'.');
    if ( p )
      {
        char *p1 = strrchr(path,'/');
        if ( p1 && p1 > p ) p = p1;
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
      ret = Str_Copy(p);
    return ret;
  }
#endif
  ;

char *Path_Unsuffix(char *path)
#ifdef _YOYO_FILE_BUILTIN
  {
    char *ret = 0;
    char *p = strrchr(path,'.');
    if ( p )
      {
        char *p1 = strrchr(path,'/');
        if ( p1 && p1 > p ) p = p1;







|







313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
      ret = Str_Copy(p);
    return ret;
  }
#endif
  ;

char *Path_Unsuffix(char *path)
#ifdef _YO_FILE_BUILTIN
  {
    char *ret = 0;
    char *p = strrchr(path,'.');
    if ( p )
      {
        char *p1 = strrchr(path,'/');
        if ( p1 && p1 > p ) p = p1;
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
      ret = Str_Copy_L(path,p-path);
    return ret;
  }
#endif
  ;
  
char *Path_Fullname(char *path)
#ifdef _YOYO_FILE_BUILTIN
  {
  #ifdef __windoze
    if ( path )
      {
        wchar_t *foo;
        char *ret = 0;
        __Auto_Ptr(ret)







|







337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
      ret = Str_Copy_L(path,p-path);
    return ret;
  }
#endif
  ;
  
char *Path_Fullname(char *path)
#ifdef _YO_FILE_BUILTIN
  {
  #ifdef __windoze
    if ( path )
      {
        wchar_t *foo;
        char *ret = 0;
        __Auto_Ptr(ret)
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
      }
  #endif
    return Str_Copy(path);
  }
#endif
  ;

typedef struct _YOYO_FILE_STATS
  {
    time_t ctime;
    time_t mtime;
    quad_t length;
    
    struct {
      int exists: 1;
      int is_regular: 1;
      int is_tty: 1;
      int is_symlink: 1;
      int is_unisok: 1;
      int is_directory: 1;
      int is_writable: 1;
      int is_readable: 1;
      int is_executable: 1;
    } f;
  
  } YOYO_FILE_STATS;

#ifdef __windoze
  #if !defined _FILEi32  
    typedef struct __stat64 _YOYO_stat;
  #else
    typedef struct _stat _YOYO_stat;
  #endif
  #if !defined S_IWUSR 
    enum 
      { 
        S_IWUSR = _S_IWRITE,
        S_IRUSR = _S_IREAD,
        S_IXUSR = _S_IEXEC,
      };
  #endif  
#else
  typedef struct stat _YOYO_stat;
#endif        

YOYO_FILE_STATS *File_Translate_Filestats(_YOYO_stat *fst,YOYO_FILE_STATS *st,int exists)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( !st ) st = __Malloc(sizeof(YOYO_FILE_STATS));
    memset(st,0,sizeof(*st));
    st->f.exists       = exists;
    st->f.is_regular   = !!((fst->st_mode&S_IFMT) & S_IFREG);
    st->f.is_directory = !!((fst->st_mode&S_IFMT) & S_IFDIR);
  #ifndef __windoze  
    st->f.is_symlink   = !!((fst->st_mode&S_IFMT) & S_IFLNK);    
    st->f.is_unisok    = !!((fst->st_mode&S_IFMT) & S_IFSOCK);
  #endif  
    st->f.is_writable  = (fst->st_mode&S_IWUSR) != 0;
    st->f.is_readable  = (fst->st_mode&S_IRUSR) != 0;
    st->f.is_executable = (fst->st_mode&S_IXUSR) != 0;
    st->length = fst->st_size;
    st->ctime  = fst->st_ctime;
    st->mtime  = fst->st_mtime;
    
    return st;
  }
#endif
  ;

YOYO_FILE_STATS *File_Get_Stats(char *name,YOYO_FILE_STATS *st,int ignorerr)
#ifdef _YOYO_FILE_BUILTIN
  {
    _YOYO_stat fst = {0};
    int err;
  #ifdef __windoze
    wchar_t *uni_name = Str_Utf8_To_Unicode(name);
    #ifndef _FILEi32  
      err = _wstat64(uni_name,&fst);
    #else
      err = _wstat(uni_name,&fst);







|

















|



|

|










|


|
|

|




















|
|

|







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
      }
  #endif
    return Str_Copy(path);
  }
#endif
  ;

typedef struct _YO_FILE_STATS
  {
    time_t ctime;
    time_t mtime;
    quad_t length;
    
    struct {
      int exists: 1;
      int is_regular: 1;
      int is_tty: 1;
      int is_symlink: 1;
      int is_unisok: 1;
      int is_directory: 1;
      int is_writable: 1;
      int is_readable: 1;
      int is_executable: 1;
    } f;
  
  } YO_FILE_STATS;

#ifdef __windoze
  #if !defined _FILEi32  
    typedef struct __stat64 _YO_stat;
  #else
    typedef struct _stat _YO_stat;
  #endif
  #if !defined S_IWUSR 
    enum 
      { 
        S_IWUSR = _S_IWRITE,
        S_IRUSR = _S_IREAD,
        S_IXUSR = _S_IEXEC,
      };
  #endif  
#else
  typedef struct stat _YO_stat;
#endif        

YO_FILE_STATS *File_Translate_Filestats(_YO_stat *fst,YO_FILE_STATS *st,int exists)
#ifdef _YO_FILE_BUILTIN
  {
    if ( !st ) st = __Malloc(sizeof(YO_FILE_STATS));
    memset(st,0,sizeof(*st));
    st->f.exists       = exists;
    st->f.is_regular   = !!((fst->st_mode&S_IFMT) & S_IFREG);
    st->f.is_directory = !!((fst->st_mode&S_IFMT) & S_IFDIR);
  #ifndef __windoze  
    st->f.is_symlink   = !!((fst->st_mode&S_IFMT) & S_IFLNK);    
    st->f.is_unisok    = !!((fst->st_mode&S_IFMT) & S_IFSOCK);
  #endif  
    st->f.is_writable  = (fst->st_mode&S_IWUSR) != 0;
    st->f.is_readable  = (fst->st_mode&S_IRUSR) != 0;
    st->f.is_executable = (fst->st_mode&S_IXUSR) != 0;
    st->length = fst->st_size;
    st->ctime  = fst->st_ctime;
    st->mtime  = fst->st_mtime;
    
    return st;
  }
#endif
  ;

YO_FILE_STATS *File_Get_Stats(char *name,YO_FILE_STATS *st,int ignorerr)
#ifdef _YO_FILE_BUILTIN
  {
    _YO_stat fst = {0};
    int err;
  #ifdef __windoze
    wchar_t *uni_name = Str_Utf8_To_Unicode(name);
    #ifndef _FILEi32  
      err = _wstat64(uni_name,&fst);
    #else
      err = _wstat(uni_name,&fst);
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
        st = File_Translate_Filestats(&fst,st,!err);
      }
    else if ( err && !ignorerr )              
      {
        int eno = errno;
        if ( st ) memset(st,0,sizeof(*st));
        if ( eno == ENOENT || eno == ENOTDIR )
          __Raise_Format(YOYO_ERROR_DOESNT_EXIST,("file '%s' does not exist",name));
        File_Check_Error("getting stats",0,name,1); 
      }
    return st;
  }
#endif
  ;

YOYO_FILE_STATS *File_Get_Stats_Reuse(char *name, YOYO_FILE_STATS **stp)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( stp && *stp ) 
      return *stp;
    else
      {
        YOYO_FILE_STATS *st = File_Get_Stats(name,0,0);
        if ( stp ) *stp = st;
        return st;
      }
  }
#endif
  ;

time_t File_Ctime(char *name) 
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->ctime;});
time_t File_Mtime(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->mtime;});
quad_t File_Length(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->length;});
int File_Exists(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,1)->f.exists;});
int File_Is_Regular(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_regular;});
int File_Is_Directory(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_directory;});
int File_Is_Writable(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_writable;});
int File_Is_Readable(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_readable;});
int File_Is_Executable(char *name)
  _YOYO_FILE_BUILTIN_CODE({YOYO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_executable;});

void Delete_Directory(char *name)
#ifdef _YOYO_FILE_BUILTIN
  {
    YOYO_FILE_STATS st;
    if ( File_Get_Stats(name,&st,1)->f.is_directory )
      {
      #ifdef __windoze
        if ( _wrmdir(Str_Utf8_To_Unicode(name)) < 0 )
      #else
        if ( rmdir(name) < 0 )
      #endif  
          File_Check_Error("rmdir",0,name,1);
      }
  }
#endif
  ;

void Create_Directory(char *name)
#ifdef _YOYO_FILE_BUILTIN
  {
    YOYO_FILE_STATS st;
    if ( !File_Get_Stats(name,&st,1)->f.is_directory )
      {
      #ifdef __windoze
        if ( _wmkdir(Str_Utf8_To_Unicode(name)) < 0 )
      #else
        if ( mkdir(name,0755) < 0 )
      #endif  
          File_Check_Error("mkdir",0,name,1);
      }
  }
#endif
  ;

void Create_Directory_In_Depth(char *name)
#ifdef _YOYO_FILE_BUILTIN
  {
    int nL = name ? strlen(name) : 0;
    if ( nL 
        && !(nL == 2 && name[1] == ':')  
        && !(nL == 1 && (name[0] == '/' || name[0] == '\\') ))
      {
        Create_Directory_In_Depth(Path_Dirname(name));
        Create_Directory(name);
      }
  }
#endif
  ;

void Create_Required_Dirs(char *name)
#ifdef _YOYO_FILE_BUILTIN
  {
    __Auto_Release
      {
        char *dirpath = Path_Dirname(name);
        Create_Directory_In_Depth(dirpath);
      }
  }
#endif
  ;

enum _YOYO_DIRLIST_FLAGS
  {
    FILE_LIST_ALL = 0,
    FILE_LIST_DIRECTORIES = 1,
    FILE_LIST_FILES = 2,
  };

YOYO_ARRAY *File_List_Directory(char *dirname, unsigned flags)
#ifdef _YOYO_FILE_BUILTIN
  {
  #ifdef __windoze
    WIN32_FIND_DATAW fdtw;
    HANDLE hfnd;
  #else
    DIR *dir;
  #endif







|







|
|





|








|

|

|

|

|

|

|

|

|


|

|














|

|














|














|










|






|
|







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
        st = File_Translate_Filestats(&fst,st,!err);
      }
    else if ( err && !ignorerr )              
      {
        int eno = errno;
        if ( st ) memset(st,0,sizeof(*st));
        if ( eno == ENOENT || eno == ENOTDIR )
          __Raise_Format(YO_ERROR_DOESNT_EXIST,("file '%s' does not exist",name));
        File_Check_Error("getting stats",0,name,1); 
      }
    return st;
  }
#endif
  ;

YO_FILE_STATS *File_Get_Stats_Reuse(char *name, YO_FILE_STATS **stp)
#ifdef _YO_FILE_BUILTIN
  {
    if ( stp && *stp ) 
      return *stp;
    else
      {
        YO_FILE_STATS *st = File_Get_Stats(name,0,0);
        if ( stp ) *stp = st;
        return st;
      }
  }
#endif
  ;

time_t File_Ctime(char *name) 
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->ctime;});
time_t File_Mtime(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->mtime;});
quad_t File_Length(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->length;});
int File_Exists(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,1)->f.exists;});
int File_Is_Regular(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_regular;});
int File_Is_Directory(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_directory;});
int File_Is_Writable(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_writable;});
int File_Is_Readable(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_readable;});
int File_Is_Executable(char *name)
  _YO_FILE_BUILTIN_CODE({YO_FILE_STATS st={0}; return File_Get_Stats(name,&st,0)->f.is_executable;});

void Delete_Directory(char *name)
#ifdef _YO_FILE_BUILTIN
  {
    YO_FILE_STATS st;
    if ( File_Get_Stats(name,&st,1)->f.is_directory )
      {
      #ifdef __windoze
        if ( _wrmdir(Str_Utf8_To_Unicode(name)) < 0 )
      #else
        if ( rmdir(name) < 0 )
      #endif  
          File_Check_Error("rmdir",0,name,1);
      }
  }
#endif
  ;

void Create_Directory(char *name)
#ifdef _YO_FILE_BUILTIN
  {
    YO_FILE_STATS st;
    if ( !File_Get_Stats(name,&st,1)->f.is_directory )
      {
      #ifdef __windoze
        if ( _wmkdir(Str_Utf8_To_Unicode(name)) < 0 )
      #else
        if ( mkdir(name,0755) < 0 )
      #endif  
          File_Check_Error("mkdir",0,name,1);
      }
  }
#endif
  ;

void Create_Directory_In_Depth(char *name)
#ifdef _YO_FILE_BUILTIN
  {
    int nL = name ? strlen(name) : 0;
    if ( nL 
        && !(nL == 2 && name[1] == ':')  
        && !(nL == 1 && (name[0] == '/' || name[0] == '\\') ))
      {
        Create_Directory_In_Depth(Path_Dirname(name));
        Create_Directory(name);
      }
  }
#endif
  ;

void Create_Required_Dirs(char *name)
#ifdef _YO_FILE_BUILTIN
  {
    __Auto_Release
      {
        char *dirpath = Path_Dirname(name);
        Create_Directory_In_Depth(dirpath);
      }
  }
#endif
  ;

enum _YO_DIRLIST_FLAGS
  {
    FILE_LIST_ALL = 0,
    FILE_LIST_DIRECTORIES = 1,
    FILE_LIST_FILES = 2,
  };

YO_ARRAY *File_List_Directory(char *dirname, unsigned flags)
#ifdef _YO_FILE_BUILTIN
  {
  #ifdef __windoze
    WIN32_FIND_DATAW fdtw;
    HANDLE hfnd;
  #else
    DIR *dir;
  #endif
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
#ifdef __windoze
#define utf8_unlink(S) _wunlink(Str_Utf8_To_Unicode(S));
#else
#define utf8_unlink(S) unlink(S)
#endif

void File_Unlink(char *name, int force)
#ifdef _YOYO_FILE_BUILTIN
  {
    YOYO_FILE_STATS st;
    int i, err = 0;
    
    __Auto_Release
      {
        File_Get_Stats(name,&st,0);
    
        if ( st.f.exists )
          {
            if ( st.f.is_directory && force )
              {
                YOYO_ARRAY *L = File_List_Directory(name,0);
                for ( i = 0; i < L->count; ++i )
                  File_Unlink(Path_Join(name,L->at[i]),force);
                Delete_Directory(name);
              }
            else
              err = utf8_unlink(name);
          }
      
        if ( err < 0 )
          File_Check_Error("unlink",0,name,1); 
      }
  }
#endif
  ;

void File_Rename(char *old_name, char *new_name)
#ifdef _YOYO_FILE_BUILTIN
  {
    int err = 0;
  #ifdef __windoze
    wchar_t *So = Str_Utf8_To_Unicode(old_name);
    wchar_t *Sn = Str_Utf8_To_Unicode(new_name);
    err = _wrename(So,Sn);
    Yo_Release(Sn);
    Yo_Release(So);
  #else
    err = rename(old_name,new_name);
  #endif
    if ( err < 0 )
      File_Check_Error("rename",0,old_name,1); 
  }
#endif
  ;
  
typedef struct _YOYO_CFILE
  {
    FILE *fd;
    char *name;
    int shared;
  } YOYO_CFILE;

int Raise_If_Cfile_Is_Not_Opened(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( !f || !f->fd )
      Yo_Raise(YOYO_ERROR_IO,
        Yo_Format("file '%s' is already closed",(f?f->name:""))
        ,__Yo_FILE__,__LINE__);
    return 1;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Close_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "close/@"); 
int Oj_Close(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return ((int(*)(void*))Yo_Find_Method_Of(&f,Oj_Close_OjMID,YO_RAISE_ERROR))
        (f); });

int Cfile_Close(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( f->fd )
      {
        fclose(f->fd);
        f->fd = 0;
      }
    return 0;
  }
#endif
  ;

int Pfile_Close(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    int ret = 0;
    if ( f->fd )
      {
      #ifdef __windoze
        ret = _pclose(f->fd);
      #else
        ret = pclose(f->fd);
      #endif
        f->fd = 0;
      }
    return ret;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Flush_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "flush/@"); 
void Oj_Flush(void *f) _YOYO_FILE_BUILTIN_CODE(
  { ((void(*)(void*))Yo_Find_Method_Of(&f,Oj_Flush_OjMID,YO_RAISE_ERROR))
        (f); });

void Cfile_Flush(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( f->fd )
      if ( fflush(f->fd) )
        {
          File_Check_Error("flush",0,f->name,1); 
        }
  }
#endif
  ;

void Cfile_Destruct(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    Cfile_Close(f);
    free(f->name);
    __Destruct(f);
  }
#endif
  ;

void Pfile_Destruct(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    Pfile_Close(f);
    free(f->name);
    __Destruct(f);
  }
#endif
  ;

YOYO_FILE_STATS *Cfile_Stats(YOYO_CFILE *f,YOYO_FILE_STATS *st)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        _YOYO_stat fst = {0};
        int err;

      #ifdef __windoze
        #if !defined _FILEi32  
          err = _fstat64(fileno(f->fd),&fst);
        #else
          err = _fstat(fileno(f->fd),&fst);
        #endif
      #else
        err = fstat(fileno(f->fd),&fst);
      #endif        
        if ( err )
          File_Check_Error("getting stats",f->fd,f->name,0); 
        return File_Translate_Filestats(&fst,st,!err);
      }
    return 0;
  };
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Eof_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "eof/@"); 
int Oj_Eof(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*))Yo_Find_Method_Of(&f,Oj_Eof_OjMID,YO_RAISE_ERROR))
        (f); });

int Cfile_Eof(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( f->fd )
      {
        return feof(f->fd);
      }
    return 1;
  }
#endif
  ;

#define Oj_Read_Full(File,Buf,Count) Oj_Read(File,Buf,Count,-1)
_YOYO_FILE_EXTERN char Oj_Read_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "read/@*ii"); 
int Oj_Read(void *f,void *buf,int count,int min_count) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&f,Oj_Read_OjMID,YO_RAISE_ERROR))
        (f,buf,count,min_count); });

int Cfile_Read(YOYO_CFILE *f, void *buf, int count, int min_count)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int cc = 0;
        byte_t *d = (byte_t *)buf;
        if ( min_count < 0 ) min_count = count; 
        for ( ; cc < count ; )
          {
            int q = fread(d,1,count-cc,f->fd);
            if ( q <= 0 )
              {
                if ( feof(f->fd) )
                  {
                    if ( cc >= min_count ) 
                      break;
                    else 
                      Yo_Raise(YOYO_ERROR_IO,
                        Yo_Format("end of file '%s'",f->name), __FILE__,__LINE__);
                  }
                else 
                  File_Check_Error("read",f->fd,f->name,0);
              }
            if ( !q && cc >= min_count) break;
            cc += q;
            d += q;
          }
        return cc;
      }
    return 0;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Read_Line_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "readline/@"); 
char *Oj_Read_Line(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((void *(*)(void*))Yo_Find_Method_Of(&f,Oj_Read_Line_OjMID,YO_RAISE_ERROR))
        (f); });

char *Cfile_Read_Line(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int S_len = 0;
        char *S = 0;
        for(;;)
          {







|

|










|
















|

















|




|

|
|


|







|
|



|
|











|
|
















|
|



|
|










|
|








|
|








|
|



|




















|
|




|
|











|
|




|
|
















|
















|
|




|
|







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
#ifdef __windoze
#define utf8_unlink(S) _wunlink(Str_Utf8_To_Unicode(S));
#else
#define utf8_unlink(S) unlink(S)
#endif

void File_Unlink(char *name, int force)
#ifdef _YO_FILE_BUILTIN
  {
    YO_FILE_STATS st;
    int i, err = 0;
    
    __Auto_Release
      {
        File_Get_Stats(name,&st,0);
    
        if ( st.f.exists )
          {
            if ( st.f.is_directory && force )
              {
                YO_ARRAY *L = File_List_Directory(name,0);
                for ( i = 0; i < L->count; ++i )
                  File_Unlink(Path_Join(name,L->at[i]),force);
                Delete_Directory(name);
              }
            else
              err = utf8_unlink(name);
          }
      
        if ( err < 0 )
          File_Check_Error("unlink",0,name,1); 
      }
  }
#endif
  ;

void File_Rename(char *old_name, char *new_name)
#ifdef _YO_FILE_BUILTIN
  {
    int err = 0;
  #ifdef __windoze
    wchar_t *So = Str_Utf8_To_Unicode(old_name);
    wchar_t *Sn = Str_Utf8_To_Unicode(new_name);
    err = _wrename(So,Sn);
    Yo_Release(Sn);
    Yo_Release(So);
  #else
    err = rename(old_name,new_name);
  #endif
    if ( err < 0 )
      File_Check_Error("rename",0,old_name,1); 
  }
#endif
  ;
  
typedef struct _YO_CFILE
  {
    FILE *fd;
    char *name;
    int shared;
  } YO_CFILE;

int Raise_If_Cfile_Is_Not_Opened(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( !f || !f->fd )
      Yo_Raise(YO_ERROR_IO,
        Yo_Format("file '%s' is already closed",(f?f->name:""))
        ,__Yo_FILE__,__LINE__);
    return 1;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Close_OjMID[] _YO_FILE_BUILTIN_CODE( = "close/@"); 
int Oj_Close(void *f) _YO_FILE_BUILTIN_CODE(
  { return ((int(*)(void*))Yo_Find_Method_Of(&f,Oj_Close_OjMID,YO_RAISE_ERROR))
        (f); });

int Cfile_Close(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( f->fd )
      {
        fclose(f->fd);
        f->fd = 0;
      }
    return 0;
  }
#endif
  ;

int Pfile_Close(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    int ret = 0;
    if ( f->fd )
      {
      #ifdef __windoze
        ret = _pclose(f->fd);
      #else
        ret = pclose(f->fd);
      #endif
        f->fd = 0;
      }
    return ret;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Flush_OjMID[] _YO_FILE_BUILTIN_CODE( = "flush/@"); 
void Oj_Flush(void *f) _YO_FILE_BUILTIN_CODE(
  { ((void(*)(void*))Yo_Find_Method_Of(&f,Oj_Flush_OjMID,YO_RAISE_ERROR))
        (f); });

void Cfile_Flush(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( f->fd )
      if ( fflush(f->fd) )
        {
          File_Check_Error("flush",0,f->name,1); 
        }
  }
#endif
  ;

void Cfile_Destruct(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    Cfile_Close(f);
    free(f->name);
    __Destruct(f);
  }
#endif
  ;

void Pfile_Destruct(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    Pfile_Close(f);
    free(f->name);
    __Destruct(f);
  }
#endif
  ;

YO_FILE_STATS *Cfile_Stats(YO_CFILE *f,YO_FILE_STATS *st)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        _YO_stat fst = {0};
        int err;

      #ifdef __windoze
        #if !defined _FILEi32  
          err = _fstat64(fileno(f->fd),&fst);
        #else
          err = _fstat(fileno(f->fd),&fst);
        #endif
      #else
        err = fstat(fileno(f->fd),&fst);
      #endif        
        if ( err )
          File_Check_Error("getting stats",f->fd,f->name,0); 
        return File_Translate_Filestats(&fst,st,!err);
      }
    return 0;
  };
#endif
  ;

_YO_FILE_EXTERN char Oj_Eof_OjMID[] _YO_FILE_BUILTIN_CODE( = "eof/@"); 
int Oj_Eof(void *f) _YO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*))Yo_Find_Method_Of(&f,Oj_Eof_OjMID,YO_RAISE_ERROR))
        (f); });

int Cfile_Eof(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( f->fd )
      {
        return feof(f->fd);
      }
    return 1;
  }
#endif
  ;

#define Oj_Read_Full(File,Buf,Count) Oj_Read(File,Buf,Count,-1)
_YO_FILE_EXTERN char Oj_Read_OjMID[] _YO_FILE_BUILTIN_CODE( = "read/@*ii"); 
int Oj_Read(void *f,void *buf,int count,int min_count) _YO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&f,Oj_Read_OjMID,YO_RAISE_ERROR))
        (f,buf,count,min_count); });

int Cfile_Read(YO_CFILE *f, void *buf, int count, int min_count)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int cc = 0;
        byte_t *d = (byte_t *)buf;
        if ( min_count < 0 ) min_count = count; 
        for ( ; cc < count ; )
          {
            int q = fread(d,1,count-cc,f->fd);
            if ( q <= 0 )
              {
                if ( feof(f->fd) )
                  {
                    if ( cc >= min_count ) 
                      break;
                    else 
                      Yo_Raise(YO_ERROR_IO,
                        Yo_Format("end of file '%s'",f->name), __FILE__,__LINE__);
                  }
                else 
                  File_Check_Error("read",f->fd,f->name,0);
              }
            if ( !q && cc >= min_count) break;
            cc += q;
            d += q;
          }
        return cc;
      }
    return 0;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Read_Line_OjMID[] _YO_FILE_BUILTIN_CODE( = "readline/@"); 
char *Oj_Read_Line(void *f) _YO_FILE_BUILTIN_CODE(
  { return 
      ((void *(*)(void*))Yo_Find_Method_Of(&f,Oj_Read_Line_OjMID,YO_RAISE_ERROR))
        (f); });

char *Cfile_Read_Line(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int S_len = 0;
        char *S = 0;
        for(;;)
          {
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
      }
    return 0;
  }
#endif
  ;

#define Oj_Write_Full(File,Buf,Count) Oj_Write(File,Buf,Count,-1)
_YOYO_FILE_EXTERN char Oj_Write_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "write/@*ii"); 
int Oj_Write(void *f,void *buf,int count,int min_count) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&f,Oj_Write_OjMID,YO_RAISE_ERROR))
        (f,buf,count,min_count); });

int Cfile_Write(YOYO_CFILE *f, void *buf, int count, int min_count)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int cc = 0;
        char *d = buf;
        for ( ; cc < count ; )
          {







|
|




|
|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
      }
    return 0;
  }
#endif
  ;

#define Oj_Write_Full(File,Buf,Count) Oj_Write(File,Buf,Count,-1)
_YO_FILE_EXTERN char Oj_Write_OjMID[] _YO_FILE_BUILTIN_CODE( = "write/@*ii"); 
int Oj_Write(void *f,void *buf,int count,int min_count) _YO_FILE_BUILTIN_CODE(
  { return 
      ((int(*)(void*,void*,int,int))Yo_Find_Method_Of(&f,Oj_Write_OjMID,YO_RAISE_ERROR))
        (f,buf,count,min_count); });

int Cfile_Write(YO_CFILE *f, void *buf, int count, int min_count)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int cc = 0;
        char *d = buf;
        for ( ; cc < count ; )
          {
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
        return cc;
      }
    return 0;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Write_Line_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "writeline/@*"); 
void Oj_Write_Line(void *f,char *text) _YOYO_FILE_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&f,Oj_Write_Line_OjMID,YO_RAISE_ERROR))
        (f,text); });

void Cfile_Write_Line(YOYO_CFILE *f, char *text)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int Ln = text?strlen(text):0;
        if ( Ln )
          Cfile_Write(f,text,Ln,Ln);
        Cfile_Write(f,"\n",1,1);
        Cfile_Flush(f);
      }
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Tell_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "tell/@"); 
quad_t Oj_Tell(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Tell_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Tell(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        quad_t q = 
        #ifdef __windoze 
          #if !defined _FILEi32  
            _ftelli64(f->fd);







|
|



|
|













|
|




|
|







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
        return cc;
      }
    return 0;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Write_Line_OjMID[] _YO_FILE_BUILTIN_CODE( = "writeline/@*"); 
void Oj_Write_Line(void *f,char *text) _YO_FILE_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&f,Oj_Write_Line_OjMID,YO_RAISE_ERROR))
        (f,text); });

void Cfile_Write_Line(YO_CFILE *f, char *text)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int Ln = text?strlen(text):0;
        if ( Ln )
          Cfile_Write(f,text,Ln,Ln);
        Cfile_Write(f,"\n",1,1);
        Cfile_Flush(f);
      }
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Tell_OjMID[] _YO_FILE_BUILTIN_CODE( = "tell/@"); 
quad_t Oj_Tell(void *f) _YO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Tell_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Tell(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        quad_t q = 
        #ifdef __windoze 
          #if !defined _FILEi32  
            _ftelli64(f->fd);
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
        return q;
      }
    return 0;
  }
#endif
  ;
  
_YOYO_FILE_EXTERN char Oj_Length_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "length/@"); 
quad_t Oj_Length(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Length_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Length(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YOYO_FILE_STATS st = {0};
        return Cfile_Stats(f,&st)->length; 
      }
    return 0;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Available_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "available/@"); 
quad_t Oj_Available(void *f) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Available_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Available(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YOYO_FILE_STATS st;
        return Cfile_Stats(f,&st)->length - Cfile_Tell(f); 
      }
    return 0;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Read_All_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "readall/@"); 
YOYO_BUFFER *Oj_Read_All(void *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    void *(*readall)(void*) = Yo_Find_Method_Of(&f,Oj_Read_All_OjMID,0);
    if ( readall )
      return readall(f);
    else
      {
        quad_t (*available)(void*) = Yo_Find_Method_Of(&f,Oj_Available_OjMID,0);
        int (*read)(void*,void*,int,int) = Yo_Find_Method_Of(&f,Oj_Read_OjMID,YO_RAISE_ERROR);
        void *L;
        if ( available )
          {
            quad_t len = available(f);
            if ( len > INT_MAX )
              __Raise(YOYO_ERROR_IO,"file to big to be read in one pass");
            L = Buffer_Init((int)len);
            if ( len )
              read(f,Buffer_Begin(L),(int)len,(int)len);
          }
        else
          {
            int (*eof)(void*) = Yo_Find_Method_Of(&f,Oj_Eof_OjMID,YO_RAISE_ERROR);







|
|




|
|



|







|
|




|
|



|







|
|
|













|







977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
        return q;
      }
    return 0;
  }
#endif
  ;
  
_YO_FILE_EXTERN char Oj_Length_OjMID[] _YO_FILE_BUILTIN_CODE( = "length/@"); 
quad_t Oj_Length(void *f) _YO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Length_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Length(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YO_FILE_STATS st = {0};
        return Cfile_Stats(f,&st)->length; 
      }
    return 0;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Available_OjMID[] _YO_FILE_BUILTIN_CODE( = "available/@"); 
quad_t Oj_Available(void *f) _YO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t(*)(void*))Yo_Find_Method_Of(&f,Oj_Available_OjMID,YO_RAISE_ERROR))
        (f); });

quad_t Cfile_Available(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YO_FILE_STATS st;
        return Cfile_Stats(f,&st)->length - Cfile_Tell(f); 
      }
    return 0;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Read_All_OjMID[] _YO_FILE_BUILTIN_CODE( = "readall/@"); 
YO_BUFFER *Oj_Read_All(void *f)
#ifdef _YO_FILE_BUILTIN
  {
    void *(*readall)(void*) = Yo_Find_Method_Of(&f,Oj_Read_All_OjMID,0);
    if ( readall )
      return readall(f);
    else
      {
        quad_t (*available)(void*) = Yo_Find_Method_Of(&f,Oj_Available_OjMID,0);
        int (*read)(void*,void*,int,int) = Yo_Find_Method_Of(&f,Oj_Read_OjMID,YO_RAISE_ERROR);
        void *L;
        if ( available )
          {
            quad_t len = available(f);
            if ( len > INT_MAX )
              __Raise(YO_ERROR_IO,"file to big to be read in one pass");
            L = Buffer_Init((int)len);
            if ( len )
              read(f,Buffer_Begin(L),(int)len,(int)len);
          }
        else
          {
            int (*eof)(void*) = Yo_Find_Method_Of(&f,Oj_Eof_OjMID,YO_RAISE_ERROR);
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
          }
        return L;
      }
  }
#endif
  ;

YOYO_BUFFER *Cfile_Read_All(YOYO_CFILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YOYO_BUFFER *L;
        quad_t len = Cfile_Available(f);
        if ( len > INT_MAX )
          Yo_Raise(YOYO_ERROR_IO,
            "file to big to be read in one pass",__Yo_FILE__,__LINE__);
        L = Buffer_Init(0);
        while ( len ) 
          /* windoze text mode reads less then available, so we need to read carefully*/
          {
            Buffer_Grow_Reserve(L,L->count+(int)len);
            L->count += Cfile_Read(f,L->at+L->count,(int)len,0);
            L->at[L->count] = 0;
            len = Cfile_Available(f);
          }
        return L;
      }
    return 0;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Seek_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "seek/@qi"); 
quad_t Oj_Seek(void *f, quad_t pos, int whence) _YOYO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t (*)(void*,quad_t,int whence))Yo_Find_Method_Of(&f,Oj_Seek_OjMID,YO_RAISE_ERROR))
        (f,pos,whence); });

quad_t Cfile_Seek(YOYO_CFILE *f, quad_t pos, int whence)
#ifdef _YOYO_FILE_BUILTIN
  {
    quad_t old = Cfile_Tell(f);
    if ( old < 0 ) return -1;
    
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int q = 







|
|



|


|

















|
|




|
|







1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
          }
        return L;
      }
  }
#endif
  ;

YO_BUFFER *Cfile_Read_All(YO_CFILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        YO_BUFFER *L;
        quad_t len = Cfile_Available(f);
        if ( len > INT_MAX )
          Yo_Raise(YO_ERROR_IO,
            "file to big to be read in one pass",__Yo_FILE__,__LINE__);
        L = Buffer_Init(0);
        while ( len ) 
          /* windoze text mode reads less then available, so we need to read carefully*/
          {
            Buffer_Grow_Reserve(L,L->count+(int)len);
            L->count += Cfile_Read(f,L->at+L->count,(int)len,0);
            L->at[L->count] = 0;
            len = Cfile_Available(f);
          }
        return L;
      }
    return 0;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Seek_OjMID[] _YO_FILE_BUILTIN_CODE( = "seek/@qi"); 
quad_t Oj_Seek(void *f, quad_t pos, int whence) _YO_FILE_BUILTIN_CODE(
  { return 
      ((quad_t (*)(void*,quad_t,int whence))Yo_Find_Method_Of(&f,Oj_Seek_OjMID,YO_RAISE_ERROR))
        (f,pos,whence); });

quad_t Cfile_Seek(YO_CFILE *f, quad_t pos, int whence)
#ifdef _YO_FILE_BUILTIN
  {
    quad_t old = Cfile_Tell(f);
    if ( old < 0 ) return -1;
    
    if ( Raise_If_Cfile_Is_Not_Opened(f) )
      {
        int q = 
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
        return old;
      }
    return 0;
  }
#endif
  ;

YOYO_CFILE *Cfile_Object(FILE *fd, char *name, int share)
#ifdef _YOYO_FILE_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    Cfile_Destruct},
        {Oj_Close_OjMID,       Cfile_Close},
        {Oj_Read_OjMID,        Cfile_Read},
        {Oj_Write_OjMID,       Cfile_Write},
        {Oj_Read_Line_OjMID,   Cfile_Read_Line},
        {Oj_Write_Line_OjMID,  Cfile_Write_Line},
        {Oj_Read_All_OjMID,    Cfile_Read_All},
        {Oj_Seek_OjMID,        Cfile_Seek},
        {Oj_Tell_OjMID,        Cfile_Tell},
        {Oj_Length_OjMID,      Cfile_Length},
        {Oj_Available_OjMID,   Cfile_Available},
        {Oj_Eof_OjMID,         Cfile_Eof},
        {Oj_Flush_OjMID,       Cfile_Flush},
        {0}};
    YOYO_CFILE *f = Yo_Object(sizeof(YOYO_CFILE),funcs);
    f->fd = fd;
    f->shared = share;
    f->name = name?Str_Copy_Npl(name,-1):__yoTa("<file>",0);
    return f;
  }
#endif
  ;

YOYO_CFILE *Pfile_Object(FILE *fd, char *cmd, int share)
#ifdef _YOYO_FILE_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    Pfile_Destruct},
        {Oj_Close_OjMID,       Pfile_Close},
        {Oj_Read_OjMID,        Cfile_Read},
        {Oj_Write_OjMID,       Cfile_Write},
        {Oj_Read_Line_OjMID,   Cfile_Read_Line},
        {Oj_Write_Line_OjMID,  Cfile_Write_Line},
        {Oj_Eof_OjMID,         Cfile_Eof},
        {Oj_Flush_OjMID,       Cfile_Flush},
        {0}};
    YOYO_CFILE *f = Yo_Object(sizeof(YOYO_CFILE),funcs);
    f->fd = fd;
    f->shared = share;
    f->name = cmd?Str_Copy_Npl(cmd,-1):__yoTa("<command>",0);
    return f;
  }
#endif
  ;

enum _YOYO_FILE_ACCESS_FLAGS
  {
    YOYO_FILE_READ        = 1,
    YOYO_FILE_WRITE       = 2,
    YOYO_FILE_READWRITE   = YOYO_FILE_READ|YOYO_FILE_WRITE,
    YOYO_FILE_FORWARD     = 32,
    YOYO_FILE_TEXT        = 64, // by default is binary mode
    YOYO_FILE_CREATE_PATH = 128, // create expected path if doesn't exists
    YOYO_FILE_APPEND      = 256,
    
    //_YOYO_FILE_NEED_EXITENT_FILE = 0x080000,
    YOYO_FILE_OPENEXISTS  = 0x000000, // open if exists
    YOYO_FILE_CREATENEW   = 0x010000, // error if exists
    YOYO_FILE_OPENALWAYS  = 0x020000, // if not exists create new
    YOYO_FILE_CREATEALWAYS= 0x030000, // if exists unlink and create new
    YOYO_FILE_OVERWRITE   = 0x040000, // if exists truncate
    YOYO_FILE_CREATE_MASK = 0x0f0000,
    
    YOYO_FILE_CREATE      = YOYO_FILE_READWRITE|YOYO_FILE_CREATE_PATH|YOYO_FILE_CREATEALWAYS,
    YOYO_FILE_REUSE       = YOYO_FILE_READWRITE|YOYO_FILE_OPENALWAYS,
    YOYO_FILE_CONSTANT    = YOYO_FILE_READ|YOYO_FILE_OPENEXISTS,
    YOYO_FILE_MODIFY      = YOYO_FILE_READWRITE|YOYO_FILE_OPENEXISTS, 
  };

void File_Check_Access_Is_Satisfied(char *path, uint_t access)
#ifdef _YOYO_FILE_BUILTIN
  {
    YOYO_FILE_STATS st = {0};
    File_Get_Stats(path,&st,1);
    
    if ( (access & YOYO_FILE_CREATE_PATH) && !st.f.exists )
      Create_Required_Dirs(path);
    
    if ( st.f.exists )
      if (st.f.is_directory )
        __Raise_Format(YOYO_ERROR_IO,("file '%s' is directory",path));
      else if ( (access & YOYO_FILE_CREATE_MASK) == YOYO_FILE_CREATENEW  )
        __Raise_Format(YOYO_ERROR_IO,("file '%s' already exists",path));
      else if ( (access & YOYO_FILE_CREATE_MASK) == YOYO_FILE_CREATEALWAYS )
        File_Unlink(path,0);
      else;
    else if ( (access & YOYO_FILE_CREATE_MASK) == YOYO_FILE_OPENEXISTS )
      __Raise_Format(YOYO_ERROR_DOESNT_EXIST,("file '%s' does not exist",path));
  }
#endif
  ;

uint_t File_Access_From_Str(char *S)
#ifdef _YOYO_FILE_BUILTIN
  {
    uint_t access = 0;
    for ( ;*S; ++S )
      switch (*S)
        {
          case '+': access |= YOYO_FILE_WRITE; /*falldown*/
          case 'r': access |= YOYO_FILE_READ; break;
          case 'a': access |= 
            YOYO_FILE_WRITE
            |YOYO_FILE_APPEND
            |YOYO_FILE_FORWARD
            |YOYO_FILE_OPENALWAYS;
          case 'w': access |= YOYO_FILE_WRITE|YOYO_FILE_OVERWRITE; break;
          case 'c': access |= YOYO_FILE_WRITE|YOYO_FILE_CREATEALWAYS; break;
          case 'n': access |= YOYO_FILE_WRITE|YOYO_FILE_CREATENEW; break;
          case 't': access |= YOYO_FILE_TEXT; break;
          case 'P': access |= YOYO_FILE_CREATE_PATH; break;
          default: break;
        }
    return access;
  }
#endif
  ;

#define File_Open(Name,Access) Cfile_Open(Name,Access)

void Cfile_Remove_Nonstandard_AC(char *nonst, char *ac)
#ifdef _YOYO_FILE_BUILTIN
  {
    int ac_r = 0;
    int ac_w = 0;
    int ac_plus = 0;
    int ac_t = 0;
/*  int ac_a = 0;
    int ac_b = 0; */







|
|

|















|








|
|

|










|








|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|



|

|


|




|
|
|
|


|
|





|





|
|

|
|
|
|
|
|
|
|
|










|







1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
        return old;
      }
    return 0;
  }
#endif
  ;

YO_CFILE *Cfile_Object(FILE *fd, char *name, int share)
#ifdef _YO_FILE_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    Cfile_Destruct},
        {Oj_Close_OjMID,       Cfile_Close},
        {Oj_Read_OjMID,        Cfile_Read},
        {Oj_Write_OjMID,       Cfile_Write},
        {Oj_Read_Line_OjMID,   Cfile_Read_Line},
        {Oj_Write_Line_OjMID,  Cfile_Write_Line},
        {Oj_Read_All_OjMID,    Cfile_Read_All},
        {Oj_Seek_OjMID,        Cfile_Seek},
        {Oj_Tell_OjMID,        Cfile_Tell},
        {Oj_Length_OjMID,      Cfile_Length},
        {Oj_Available_OjMID,   Cfile_Available},
        {Oj_Eof_OjMID,         Cfile_Eof},
        {Oj_Flush_OjMID,       Cfile_Flush},
        {0}};
    YO_CFILE *f = Yo_Object(sizeof(YO_CFILE),funcs);
    f->fd = fd;
    f->shared = share;
    f->name = name?Str_Copy_Npl(name,-1):__yoTa("<file>",0);
    return f;
  }
#endif
  ;

YO_CFILE *Pfile_Object(FILE *fd, char *cmd, int share)
#ifdef _YO_FILE_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    Pfile_Destruct},
        {Oj_Close_OjMID,       Pfile_Close},
        {Oj_Read_OjMID,        Cfile_Read},
        {Oj_Write_OjMID,       Cfile_Write},
        {Oj_Read_Line_OjMID,   Cfile_Read_Line},
        {Oj_Write_Line_OjMID,  Cfile_Write_Line},
        {Oj_Eof_OjMID,         Cfile_Eof},
        {Oj_Flush_OjMID,       Cfile_Flush},
        {0}};
    YO_CFILE *f = Yo_Object(sizeof(YO_CFILE),funcs);
    f->fd = fd;
    f->shared = share;
    f->name = cmd?Str_Copy_Npl(cmd,-1):__yoTa("<command>",0);
    return f;
  }
#endif
  ;

enum _YO_FILE_ACCESS_FLAGS
  {
    YO_FILE_READ        = 1,
    YO_FILE_WRITE       = 2,
    YO_FILE_READWRITE   = YO_FILE_READ|YO_FILE_WRITE,
    YO_FILE_FORWARD     = 32,
    YO_FILE_TEXT        = 64, // by default is binary mode
    YO_FILE_CREATE_PATH = 128, // create expected path if doesn't exists
    YO_FILE_APPEND      = 256,
    
    //_YO_FILE_NEED_EXITENT_FILE = 0x080000,
    YO_FILE_OPENEXISTS  = 0x000000, // open if exists
    YO_FILE_CREATENEW   = 0x010000, // error if exists
    YO_FILE_OPENALWAYS  = 0x020000, // if not exists create new
    YO_FILE_CREATEALWAYS= 0x030000, // if exists unlink and create new
    YO_FILE_OVERWRITE   = 0x040000, // if exists truncate
    YO_FILE_CREATE_MASK = 0x0f0000,
    
    YO_FILE_CREATE      = YO_FILE_READWRITE|YO_FILE_CREATE_PATH|YO_FILE_CREATEALWAYS,
    YO_FILE_REUSE       = YO_FILE_READWRITE|YO_FILE_OPENALWAYS,
    YO_FILE_CONSTANT    = YO_FILE_READ|YO_FILE_OPENEXISTS,
    YO_FILE_MODIFY      = YO_FILE_READWRITE|YO_FILE_OPENEXISTS, 
  };

void File_Check_Access_Is_Satisfied(char *path, uint_t access)
#ifdef _YO_FILE_BUILTIN
  {
    YO_FILE_STATS st = {0};
    File_Get_Stats(path,&st,1);
    
    if ( (access & YO_FILE_CREATE_PATH) && !st.f.exists )
      Create_Required_Dirs(path);
    
    if ( st.f.exists )
      if (st.f.is_directory )
        __Raise_Format(YO_ERROR_IO,("file '%s' is directory",path));
      else if ( (access & YO_FILE_CREATE_MASK) == YO_FILE_CREATENEW  )
        __Raise_Format(YO_ERROR_IO,("file '%s' already exists",path));
      else if ( (access & YO_FILE_CREATE_MASK) == YO_FILE_CREATEALWAYS )
        File_Unlink(path,0);
      else;
    else if ( (access & YO_FILE_CREATE_MASK) == YO_FILE_OPENEXISTS )
      __Raise_Format(YO_ERROR_DOESNT_EXIST,("file '%s' does not exist",path));
  }
#endif
  ;

uint_t File_Access_From_Str(char *S)
#ifdef _YO_FILE_BUILTIN
  {
    uint_t access = 0;
    for ( ;*S; ++S )
      switch (*S)
        {
          case '+': access |= YO_FILE_WRITE; /*falldown*/
          case 'r': access |= YO_FILE_READ; break;
          case 'a': access |= 
            YO_FILE_WRITE
            |YO_FILE_APPEND
            |YO_FILE_FORWARD
            |YO_FILE_OPENALWAYS;
          case 'w': access |= YO_FILE_WRITE|YO_FILE_OVERWRITE; break;
          case 'c': access |= YO_FILE_WRITE|YO_FILE_CREATEALWAYS; break;
          case 'n': access |= YO_FILE_WRITE|YO_FILE_CREATENEW; break;
          case 't': access |= YO_FILE_TEXT; break;
          case 'P': access |= YO_FILE_CREATE_PATH; break;
          default: break;
        }
    return access;
  }
#endif
  ;

#define File_Open(Name,Access) Cfile_Open(Name,Access)

void Cfile_Remove_Nonstandard_AC(char *nonst, char *ac)
#ifdef _YO_FILE_BUILTIN
  {
    int ac_r = 0;
    int ac_w = 0;
    int ac_plus = 0;
    int ac_t = 0;
/*  int ac_a = 0;
    int ac_b = 0; */
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
    else *ac++ = 'b';    
    *ac = 0;
  }
#endif
  ;

void *Cfile_Open_Raw(char *name, char *access)
#ifdef _YOYO_FILE_BUILTIN
  {
    char ac[9];
    void *f = 0;
    
    // always binary mode if 't' not declared manualy
    Cfile_Remove_Nonstandard_AC(access,ac);
    
    #ifdef __windoze
      if ( 0 != (f = _wfopen(Str_Utf8_To_Unicode(name),Str_Utf8_To_Unicode(ac))) )
    #else
      if ( 0 != (f = fopen(name,ac)) )
    #endif
        f = Cfile_Object(f,name,0);
        
    return f;
  }
#endif
  ;

void *Pfile_Open(char *command, char *access)
#ifdef _YOYO_FILE_BUILTIN
  {
    void *f = 0;
    #ifdef __windoze
      int text = 0, i;
      wchar_t ac[9] = {0};
      for ( i = 0; access[i] && i < sizeof(ac)-1; ++i )
        {







|




















|







1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
    else *ac++ = 'b';    
    *ac = 0;
  }
#endif
  ;

void *Cfile_Open_Raw(char *name, char *access)
#ifdef _YO_FILE_BUILTIN
  {
    char ac[9];
    void *f = 0;
    
    // always binary mode if 't' not declared manualy
    Cfile_Remove_Nonstandard_AC(access,ac);
    
    #ifdef __windoze
      if ( 0 != (f = _wfopen(Str_Utf8_To_Unicode(name),Str_Utf8_To_Unicode(ac))) )
    #else
      if ( 0 != (f = fopen(name,ac)) )
    #endif
        f = Cfile_Object(f,name,0);
        
    return f;
  }
#endif
  ;

void *Pfile_Open(char *command, char *access)
#ifdef _YO_FILE_BUILTIN
  {
    void *f = 0;
    #ifdef __windoze
      int text = 0, i;
      wchar_t ac[9] = {0};
      for ( i = 0; access[i] && i < sizeof(ac)-1; ++i )
        {
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
        f = Pfile_Object(f,command,0);
    return f;
  }
#endif
  ;

void *Cfile_Open(char *name, char *access)
#ifdef _YOYO_FILE_BUILTIN
  {
    void *f = 0;
    __Auto_Ptr(f)
      {
        File_Check_Access_Is_Satisfied(name,File_Access_From_Str(access));
        f = Cfile_Open_Raw(name,access);
        if ( !f )
          File_Check_Error("open file",0,name,1);
      }
    return f;
  }
#endif
  ;

#define Cfile_Acquire(Name,Fd) Cfile_Object(Fd,Name,0)
#define Cfile_Share(Name,Fd)   Cfile_Object(Fd,Name,1)

void *Cfile_Temp()
#ifdef _YOYO_FILE_BUILTIN
  {
    FILE *f = tmpfile();
    if ( !f )
      File_Check_Error("open file",0,"tmpfile",1);
    return Cfile_Object(f,"tmpfile",0);
  }
#endif
  ;

int Oj_Write_BOM(void *f,int bom)
#ifdef _YOYO_FILE_BUILTIN
  {
    switch( bom )
      {
        case YOYO_BOM_DOESNT_PRESENT:
          return 0; // none
        case YOYO_BOM_UTF16_LE:
          return Oj_Write(f,"\xff\xfe",2,2);
        case YOYO_BOM_UTF16_BE:
          return Oj_Write(f,"\xfe\xff",2,2);
        case YOYO_BOM_UTF8:
          return Oj_Write(f,"\xef\xbb\xbf",3,3);
        default:
          __Raise(YOYO_ERROR_INVALID_PARAM,__yoTa("bad BOM identifier",0));
      }
      
    return 0; /*fake*/
  }
#endif
  ;

#define __Pfd_Lock(Pfd) __Interlock_Opt( (void)0, Pfd, __Pfd_Lock_In, __Pfd_Lock_Out, __Pfd_Lock_Out )

#ifdef __windoze

#define   LOCK_SH   1    /* shared lock */
#define   LOCK_EX   2    /* exclusive lock */
#define   LOCK_NB   4    /* don't block when locking */
#define   LOCK_UN   8    /* unlock */

int flock(int fd, int opt)
#ifdef _YOYO_FILE_BUILTIN
  {
    return 0;
  }
#endif
  ;

#endif /* __windoze */

void __Pfd_Lock_In(int *pfd) 
#ifdef _YOYO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( flock(*pfd,LOCK_EX) )
      __Raise_Format(YOYO_ERROR_IO,("failed to lock fd %d: %s",*pfd,strerror(errno)));
  }
#endif
  ;

void __Pfd_Lock_Out(int *pfd) 
#ifdef _YOYO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( flock(*pfd,LOCK_UN) )
      if ( errno != EBADF )
        __Fatal("failed to unlock file");
  }
#endif
  ;

#define __Pfd_Guard(Pfd) __Interlock_Opt( (void)0, Pfd, (void), __Pfd_Guard_Out, __Pfd_Guard_Out )
void __Pfd_Guard_Out(int *pfd) 
#ifdef _YOYO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( *pfd >= 0 )
      {
        close(*pfd);
        *pfd = -1;
      }
  }
#endif
  ;

int Oj_Copy_File(void *src, void *dst)
#ifdef _YOYO_FILE_BUILTIN
  {
    char bf[YOYO_FILE_COPY_BUFFER_SIZE];
    int count = 0;
    int (*xread)(void*,void*,int,int) = Yo_Find_Method_Of(&src,Oj_Read_OjMID,YO_RAISE_ERROR);
    int (*xwrite)(void*,void*,int,int) = Yo_Find_Method_Of(&dst,Oj_Write_OjMID,YO_RAISE_ERROR);
    for ( ;; )
      {
        int i = xread(src,bf,YOYO_FILE_COPY_BUFFER_SIZE,0);
        if ( !i ) break;
        xwrite(dst,bf,i,i);
        count += i;
      }
    return count;
  }
#endif
  ;

#define Write_Out(Fd,Data,Count) Fd_Write_Out(Fd,Data,Count,0)
#define Write_Out_Raise(Fd,Data,Count) Fd_Write_Out(Fd,Data,Count,1)
int Fd_Write_Out(int fd, void *data, int count, int do_raise) 
#ifdef _YOYO_FILE_BUILTIN
  {
    int i;
    
    for ( i = 0; i < count;  )
      {
        int r = write(fd,(char*)data+i,count-i);
        if ( r >= 0 )
          i += r;
        else if ( errno != EAGAIN )
          {
            int err = errno;
            if ( do_raise )
              __Raise_Format(YOYO_ERROR_IO,(__yoTa("failed to write file: %s",0),strerror(err)));
            return err;
          }
      }
      
    return 0;
  }
#endif
  ;

#define Read_Into(Fd,Data,Count) Fd_Read_Into(Fd,Data,Count,0)
#define Read_Into_Raise(Fd,Data,Count) Fd_Read_Into(Fd,Data,Count,1)
int Fd_Read_Into(int fd, void *data, int count, int do_raise) 
#ifdef _YOYO_FILE_BUILTIN
  {
    int i;
    
    for ( i = 0; i < count;  )
      {
        int r = read(fd,(char*)data+i,count-i);
        if ( r > 0 )
          i += r;
        else if ( !r )
          {
            if ( do_raise )
              __Raise_Format(YOYO_ERROR_IO,(__yoTa("failed to read file: %s",0),"eof"));
            return -1;
          }
        else if ( errno != EAGAIN )
          {
            int err = errno;
            if ( do_raise )
              __Raise_Format(YOYO_ERROR_IO,(__yoTa("failed to read file: %s",0),strerror(err)));
            return err;
          }
      }
      
    return 0;
  }
#endif
  ;

#define Lseek(Fd,Pos) Fd_Lseek(Fd,Pos,0)
#define Lseek_Raise(Fd,Pos) Fd_Lseek(Fd,Pos,1)
int Fd_Lseek(int fd, quad_t pos, int do_raise)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( 0 >  
  #ifdef _FILEi32
    lseek(fd,(long)pos,(pos<0?SEEK_END:SEEK_SET))
  #else
    _WINPOSIX(_lseeki64,lseek64)(fd,pos,(pos<0?SEEK_END:SEEK_SET))
  #endif
    )
      {
        int err = errno;
        if ( do_raise )
          __Raise_Format(YOYO_ERROR_IO,(__yoTa("failed to seek file: %s",0),strerror(err)));
        return err;
      }
    return 0;
  }
#endif
  ;

#define Open_File(Name,Opt) Fd_Open_File(Name,Opt,0600,0)
#define Open_File_Raise(Name,Opt) Fd_Open_File(Name,Opt,0600,1)
int Fd_Open_File(char *name, int opt, int secu, int do_raise)
#ifdef _YOYO_FILE_BUILTIN
  {
    int fd;
    #ifdef __windoze
      if ( !(opt & _O_TEXT) ) opt |= _O_BINARY;
      fd = _wopen(Str_Utf8_To_Unicode(name),opt,secu);
    #else
      fd = open(name,opt,secu);
    #endif
    if ( fd < 0 )
      {
        int err = errno;
        if ( do_raise )
          __Raise_Format(YOYO_ERROR_IO,(__yoTa("failed to open file '%s': %s",0),name,strerror(err)));
        return -err;
      }
    return fd;
  }
#endif
  ;
  
void File_Move(char *old_name, char *new_name)
#ifdef _YOYO_FILE_BUILTIN
  {
    int err = 0;
  #ifdef __windoze
    wchar_t *So = Str_Utf8_To_Unicode(old_name);
    wchar_t *Sn = Str_Utf8_To_Unicode(new_name);
    err = _wrename(So,Sn);
    Yo_Release(Sn);







|


















|










|



|

|

|

|


|

















|









|




|





|












|













|

|





|












|












|












|











|






|












|











|










|












|








|







1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
        f = Pfile_Object(f,command,0);
    return f;
  }
#endif
  ;

void *Cfile_Open(char *name, char *access)
#ifdef _YO_FILE_BUILTIN
  {
    void *f = 0;
    __Auto_Ptr(f)
      {
        File_Check_Access_Is_Satisfied(name,File_Access_From_Str(access));
        f = Cfile_Open_Raw(name,access);
        if ( !f )
          File_Check_Error("open file",0,name,1);
      }
    return f;
  }
#endif
  ;

#define Cfile_Acquire(Name,Fd) Cfile_Object(Fd,Name,0)
#define Cfile_Share(Name,Fd)   Cfile_Object(Fd,Name,1)

void *Cfile_Temp()
#ifdef _YO_FILE_BUILTIN
  {
    FILE *f = tmpfile();
    if ( !f )
      File_Check_Error("open file",0,"tmpfile",1);
    return Cfile_Object(f,"tmpfile",0);
  }
#endif
  ;

int Oj_Write_BOM(void *f,int bom)
#ifdef _YO_FILE_BUILTIN
  {
    switch( bom )
      {
        case YO_BOM_DOESNT_PRESENT:
          return 0; // none
        case YO_BOM_UTF16_LE:
          return Oj_Write(f,"\xff\xfe",2,2);
        case YO_BOM_UTF16_BE:
          return Oj_Write(f,"\xfe\xff",2,2);
        case YO_BOM_UTF8:
          return Oj_Write(f,"\xef\xbb\xbf",3,3);
        default:
          __Raise(YO_ERROR_INVALID_PARAM,__yoTa("bad BOM identifier",0));
      }
      
    return 0; /*fake*/
  }
#endif
  ;

#define __Pfd_Lock(Pfd) __Interlock_Opt( (void)0, Pfd, __Pfd_Lock_In, __Pfd_Lock_Out, __Pfd_Lock_Out )

#ifdef __windoze

#define   LOCK_SH   1    /* shared lock */
#define   LOCK_EX   2    /* exclusive lock */
#define   LOCK_NB   4    /* don't block when locking */
#define   LOCK_UN   8    /* unlock */

int flock(int fd, int opt)
#ifdef _YO_FILE_BUILTIN
  {
    return 0;
  }
#endif
  ;

#endif /* __windoze */

void __Pfd_Lock_In(int *pfd) 
#ifdef _YO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( flock(*pfd,LOCK_EX) )
      __Raise_Format(YO_ERROR_IO,("failed to lock fd %d: %s",*pfd,strerror(errno)));
  }
#endif
  ;

void __Pfd_Lock_Out(int *pfd) 
#ifdef _YO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( flock(*pfd,LOCK_UN) )
      if ( errno != EBADF )
        __Fatal("failed to unlock file");
  }
#endif
  ;

#define __Pfd_Guard(Pfd) __Interlock_Opt( (void)0, Pfd, (void), __Pfd_Guard_Out, __Pfd_Guard_Out )
void __Pfd_Guard_Out(int *pfd) 
#ifdef _YO_FILE_BUILTIN
  {
    STRICT_REQUIRE(pfd);
    
    if ( *pfd >= 0 )
      {
        close(*pfd);
        *pfd = -1;
      }
  }
#endif
  ;

int Oj_Copy_File(void *src, void *dst)
#ifdef _YO_FILE_BUILTIN
  {
    char bf[YO_FILE_COPY_BUFFER_SIZE];
    int count = 0;
    int (*xread)(void*,void*,int,int) = Yo_Find_Method_Of(&src,Oj_Read_OjMID,YO_RAISE_ERROR);
    int (*xwrite)(void*,void*,int,int) = Yo_Find_Method_Of(&dst,Oj_Write_OjMID,YO_RAISE_ERROR);
    for ( ;; )
      {
        int i = xread(src,bf,YO_FILE_COPY_BUFFER_SIZE,0);
        if ( !i ) break;
        xwrite(dst,bf,i,i);
        count += i;
      }
    return count;
  }
#endif
  ;

#define Write_Out(Fd,Data,Count) Fd_Write_Out(Fd,Data,Count,0)
#define Write_Out_Raise(Fd,Data,Count) Fd_Write_Out(Fd,Data,Count,1)
int Fd_Write_Out(int fd, void *data, int count, int do_raise) 
#ifdef _YO_FILE_BUILTIN
  {
    int i;
    
    for ( i = 0; i < count;  )
      {
        int r = write(fd,(char*)data+i,count-i);
        if ( r >= 0 )
          i += r;
        else if ( errno != EAGAIN )
          {
            int err = errno;
            if ( do_raise )
              __Raise_Format(YO_ERROR_IO,(__yoTa("failed to write file: %s",0),strerror(err)));
            return err;
          }
      }
      
    return 0;
  }
#endif
  ;

#define Read_Into(Fd,Data,Count) Fd_Read_Into(Fd,Data,Count,0)
#define Read_Into_Raise(Fd,Data,Count) Fd_Read_Into(Fd,Data,Count,1)
int Fd_Read_Into(int fd, void *data, int count, int do_raise) 
#ifdef _YO_FILE_BUILTIN
  {
    int i;
    
    for ( i = 0; i < count;  )
      {
        int r = read(fd,(char*)data+i,count-i);
        if ( r > 0 )
          i += r;
        else if ( !r )
          {
            if ( do_raise )
              __Raise_Format(YO_ERROR_IO,(__yoTa("failed to read file: %s",0),"eof"));
            return -1;
          }
        else if ( errno != EAGAIN )
          {
            int err = errno;
            if ( do_raise )
              __Raise_Format(YO_ERROR_IO,(__yoTa("failed to read file: %s",0),strerror(err)));
            return err;
          }
      }
      
    return 0;
  }
#endif
  ;

#define Lseek(Fd,Pos) Fd_Lseek(Fd,Pos,0)
#define Lseek_Raise(Fd,Pos) Fd_Lseek(Fd,Pos,1)
int Fd_Lseek(int fd, quad_t pos, int do_raise)
#ifdef _YO_FILE_BUILTIN
  {
    if ( 0 >  
  #ifdef _FILEi32
    lseek(fd,(long)pos,(pos<0?SEEK_END:SEEK_SET))
  #else
    _WINPOSIX(_lseeki64,lseek64)(fd,pos,(pos<0?SEEK_END:SEEK_SET))
  #endif
    )
      {
        int err = errno;
        if ( do_raise )
          __Raise_Format(YO_ERROR_IO,(__yoTa("failed to seek file: %s",0),strerror(err)));
        return err;
      }
    return 0;
  }
#endif
  ;

#define Open_File(Name,Opt) Fd_Open_File(Name,Opt,0600,0)
#define Open_File_Raise(Name,Opt) Fd_Open_File(Name,Opt,0600,1)
int Fd_Open_File(char *name, int opt, int secu, int do_raise)
#ifdef _YO_FILE_BUILTIN
  {
    int fd;
    #ifdef __windoze
      if ( !(opt & _O_TEXT) ) opt |= _O_BINARY;
      fd = _wopen(Str_Utf8_To_Unicode(name),opt,secu);
    #else
      fd = open(name,opt,secu);
    #endif
    if ( fd < 0 )
      {
        int err = errno;
        if ( do_raise )
          __Raise_Format(YO_ERROR_IO,(__yoTa("failed to open file '%s': %s",0),name,strerror(err)));
        return -err;
      }
    return fd;
  }
#endif
  ;
  
void File_Move(char *old_name, char *new_name)
#ifdef _YO_FILE_BUILTIN
  {
    int err = 0;
  #ifdef __windoze
    wchar_t *So = Str_Utf8_To_Unicode(old_name);
    wchar_t *Sn = Str_Utf8_To_Unicode(new_name);
    err = _wrename(So,Sn);
    Yo_Release(Sn);
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
      {
        File_Check_Error("rename",0,old_name,1); 
      }
  }
#endif
  ;

typedef struct _YOYO_BUFFER_FILE
  {
    YOYO_BUFFER *bf;
    int offs;
  } YOYO_BUFFER_FILE;

void YOYO_BUFFER_FILE_Destruct(YOYO_BUFFER_FILE *file)
#ifdef _YOYO_FILE_BUILTIN
  {
    __Unrefe(file->bf);
    __Destruct(file);
  }
#endif
  ;

int Buffer_File_Close(YOYO_BUFFER_FILE *file)
#ifdef _YOYO_FILE_BUILTIN
  {
    return 0;
  }
#endif
  ;

int Buffer_File_Read(YOYO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( min_count < 0 ) min_count = count;
    if ( f->offs + min_count > f->bf->count )
      __Raise(YOYO_ERROR_IO_EOF,"end of file");
    count = Yo_MIN(f->bf->count-f->offs,count);
    memcpy(buf,f->bf->at+f->offs,count);
    f->offs += count;
    return count;
  }
#endif
  ;

int Buffer_File_Write(YOYO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YOYO_FILE_BUILTIN
  {
    if (f->bf->count < f->offs + count )
      Buffer_Resize(f->bf,f->offs + count);
    memcpy(f->bf->at+f->offs,buf,count);
    f->offs += count;
    return count;
  }
#endif
  ;

quad_t Buffer_File_Length(YOYO_BUFFER_FILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    return f->bf->count;
  }
#endif
  ;

quad_t Buffer_File_Available(YOYO_BUFFER_FILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( f->offs >= f->bf->count )
      return 0;
    return f->bf->count - f->offs;
  }
#endif
  ;

int Buffer_File_Eof(YOYO_BUFFER_FILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    if ( f->offs >= f->bf->count )
      return 1;
    return 0;
  }
#endif
  ;

quad_t Buffer_File_Seek(YOYO_BUFFER_FILE *f, quad_t pos, int whence)
#ifdef _YOYO_FILE_BUILTIN
  {
    quad_t old = f->offs;
    if ( whence == SEEK_SET )
      f->offs = (int)pos;
    else if ( whence == SEEK_CUR )
      f->offs += (int)pos;
    else if ( whence == SEEK_END )
      f->offs = f->bf->count + (int)pos;
    if ( f->offs < 0 ) 
      {
        f->offs = 0;
        __Raise(YOYO_ERROR_IO,"negative file offset");
      }
    return old;
  }
#endif
  ;
  
quad_t Buffer_File_Tell(YOYO_BUFFER_FILE *f)
#ifdef _YOYO_FILE_BUILTIN
  {
    return f->offs;
  }
#endif
  ;

void Buffer_File_Flush()
#ifdef _YOYO_FILE_BUILTIN
  {
  }
#endif
  ;

void *Buffer_As_File(YOYO_BUFFER *bf)
#ifdef _YOYO_FILE_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YOYO_BUFFER_FILE_Destruct},
        {Oj_Close_OjMID,       Buffer_File_Close},
        {Oj_Read_OjMID,        Buffer_File_Read},
        {Oj_Write_OjMID,       Buffer_File_Write},
        {Oj_Available_OjMID,   Buffer_File_Available},
        {Oj_Eof_OjMID,         Buffer_File_Eof},
        {Oj_Length_OjMID,      Buffer_File_Length},
        {Oj_Seek_OjMID,        Buffer_File_Seek},
        {Oj_Tell_OjMID,        Buffer_File_Tell},
        {Oj_Flush_OjMID,       Buffer_File_Flush},
        {0}
      };
    YOYO_BUFFER_FILE *file = __Object(sizeof(YOYO_BUFFER_FILE),funcs);
    file->bf = __Refe(bf);
    return file;
  }
#endif
  ;

void YOYO_MEMORY_FILE_Destruct(YOYO_BUFFER_FILE *file)
#ifdef _YOYO_FILE_BUILTIN
  {
    free(file->bf);
    __Destruct(file);
  }
#endif
  ;

int Memory_File_Write(YOYO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YOYO_FILE_BUILTIN
  {
    if (f->bf->count < f->offs + count )
      __Raise(YOYO_ERROR_OUT_OF_RANGE,"out of memory range");
    memcpy(f->bf->at+f->offs,buf,count);
    f->offs += count;
    return count;
  }
#endif
  ;

void *Memory_As_File(void *mem, int mem_len)
#ifdef _YOYO_FILE_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YOYO_MEMORY_FILE_Destruct},
        {Oj_Close_OjMID,       Buffer_File_Close},
        {Oj_Read_OjMID,        Buffer_File_Read},
        {Oj_Write_OjMID,       Memory_File_Write},
        {Oj_Available_OjMID,   Buffer_File_Available},
        {Oj_Eof_OjMID,         Buffer_File_Eof},
        {Oj_Length_OjMID,      Buffer_File_Length},
        {Oj_Seek_OjMID,        Buffer_File_Seek},
        {Oj_Tell_OjMID,        Buffer_File_Tell},
        {Oj_Flush_OjMID,       Buffer_File_Flush},
        {0}
      };
      
    YOYO_BUFFER_FILE *file = __Object(sizeof(YOYO_BUFFER_FILE),funcs);
    file->bf = __Zero_Malloc_Npl(sizeof(YOYO_BUFFER));
    file->bf->at = mem;
    file->bf->count = mem_len;
    return file;
  }
#endif
  ;

void Oj_Print(void *foj, char *S)
#ifdef _YOYO_FILE_BUILTIN
  {
    int S_len = S?strlen(S):0;
    if ( S_len )
      Oj_Write_Full(foj,S,S_len);
  }
#endif
  ;

void Oj_Printf(void *foj, char *fmt, ...)
#ifdef _YOYO_FILE_BUILTIN
  {
    __Auto_Release
      {
        va_list va;
        char *text;
        va_start(va,fmt);
        text = __Pool(Yo_Format_(fmt,va));
        va_end(va);
        Oj_Print(foj,text);
      }
  }
#endif
  ;

void Oj_Fill(void *fobj, byte_t val, int count)
#ifdef _YOYO_FILE_BUILTIN
  {
    byte_t bf[512];
    
    REQUIRE(count >= 0);
    memset(bf,val,sizeof(bf));
    while ( count > 0 )
      {
        int L = Yo_MIN(count,sizeof(bf));
        Oj_Write_Full(fobj,bf,L);
        count -= L;
      }
  }
#endif
  ;

int Oj_Apply_File(void *foj, void *accu, void (*algo)(void *accu,void *buf, int L))
#ifdef _YOYO_FILE_BUILTIN
  {
    char bf[YOYO_FILE_COPY_BUFFER_SIZE];
    int count = 0;
    int (*xread)(void*,void*,int,int) = Yo_Find_Method_Of(&foj,Oj_Read_OjMID,YO_RAISE_ERROR);
    for ( ;; )
      {
        int i = xread(foj,bf,YOYO_FILE_COPY_BUFFER_SIZE,0);
        if ( !i ) break;
        algo(accu,bf,i);
        count += i;
      }
    return count;
  }
#endif
  ;

_YOYO_FILE_EXTERN char Oj_Digest_File_Update_OjMID[] _YOYO_FILE_BUILTIN_CODE( = "digest-file-update/@*"); 
void Oj_Digest_File_Update(void *dgst,void *foj) _YOYO_FILE_BUILTIN_CODE(
  { void(*update)(void*,void*,int) = Yo_Find_Method_Of(&dgst,Oj_Digest_Update_OjMID,YO_RAISE_ERROR);
    Oj_Apply_File(foj,dgst,update); });

void File_Update_Digest(void *dgst, char *filename)
#ifdef _YOYO_FILE_BUILTIN
  {
    __Auto_Release Oj_Digest_File_Update(dgst,Cfile_Open(filename,"r"));
  }
#endif
  ;

#endif /* C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B */








|

|

|

|
|







|
|






|
|



|








|
|










|
|






|
|








|
|








|
|











|






|
|







|





|
|

|

|











|






|
|







|
|


|








|

|

|












|
|








|









|















|
















|

|




|









|
|




|








1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
      {
        File_Check_Error("rename",0,old_name,1); 
      }
  }
#endif
  ;

typedef struct _YO_BUFFER_FILE
  {
    YO_BUFFER *bf;
    int offs;
  } YO_BUFFER_FILE;

void YO_BUFFER_FILE_Destruct(YO_BUFFER_FILE *file)
#ifdef _YO_FILE_BUILTIN
  {
    __Unrefe(file->bf);
    __Destruct(file);
  }
#endif
  ;

int Buffer_File_Close(YO_BUFFER_FILE *file)
#ifdef _YO_FILE_BUILTIN
  {
    return 0;
  }
#endif
  ;

int Buffer_File_Read(YO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YO_FILE_BUILTIN
  {
    if ( min_count < 0 ) min_count = count;
    if ( f->offs + min_count > f->bf->count )
      __Raise(YO_ERROR_IO_EOF,"end of file");
    count = Yo_MIN(f->bf->count-f->offs,count);
    memcpy(buf,f->bf->at+f->offs,count);
    f->offs += count;
    return count;
  }
#endif
  ;

int Buffer_File_Write(YO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YO_FILE_BUILTIN
  {
    if (f->bf->count < f->offs + count )
      Buffer_Resize(f->bf,f->offs + count);
    memcpy(f->bf->at+f->offs,buf,count);
    f->offs += count;
    return count;
  }
#endif
  ;

quad_t Buffer_File_Length(YO_BUFFER_FILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    return f->bf->count;
  }
#endif
  ;

quad_t Buffer_File_Available(YO_BUFFER_FILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( f->offs >= f->bf->count )
      return 0;
    return f->bf->count - f->offs;
  }
#endif
  ;

int Buffer_File_Eof(YO_BUFFER_FILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    if ( f->offs >= f->bf->count )
      return 1;
    return 0;
  }
#endif
  ;

quad_t Buffer_File_Seek(YO_BUFFER_FILE *f, quad_t pos, int whence)
#ifdef _YO_FILE_BUILTIN
  {
    quad_t old = f->offs;
    if ( whence == SEEK_SET )
      f->offs = (int)pos;
    else if ( whence == SEEK_CUR )
      f->offs += (int)pos;
    else if ( whence == SEEK_END )
      f->offs = f->bf->count + (int)pos;
    if ( f->offs < 0 ) 
      {
        f->offs = 0;
        __Raise(YO_ERROR_IO,"negative file offset");
      }
    return old;
  }
#endif
  ;
  
quad_t Buffer_File_Tell(YO_BUFFER_FILE *f)
#ifdef _YO_FILE_BUILTIN
  {
    return f->offs;
  }
#endif
  ;

void Buffer_File_Flush()
#ifdef _YO_FILE_BUILTIN
  {
  }
#endif
  ;

void *Buffer_As_File(YO_BUFFER *bf)
#ifdef _YO_FILE_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YO_BUFFER_FILE_Destruct},
        {Oj_Close_OjMID,       Buffer_File_Close},
        {Oj_Read_OjMID,        Buffer_File_Read},
        {Oj_Write_OjMID,       Buffer_File_Write},
        {Oj_Available_OjMID,   Buffer_File_Available},
        {Oj_Eof_OjMID,         Buffer_File_Eof},
        {Oj_Length_OjMID,      Buffer_File_Length},
        {Oj_Seek_OjMID,        Buffer_File_Seek},
        {Oj_Tell_OjMID,        Buffer_File_Tell},
        {Oj_Flush_OjMID,       Buffer_File_Flush},
        {0}
      };
    YO_BUFFER_FILE *file = __Object(sizeof(YO_BUFFER_FILE),funcs);
    file->bf = __Refe(bf);
    return file;
  }
#endif
  ;

void YO_MEMORY_FILE_Destruct(YO_BUFFER_FILE *file)
#ifdef _YO_FILE_BUILTIN
  {
    free(file->bf);
    __Destruct(file);
  }
#endif
  ;

int Memory_File_Write(YO_BUFFER_FILE *f, void *buf, int count, int min_count)
#ifdef _YO_FILE_BUILTIN
  {
    if (f->bf->count < f->offs + count )
      __Raise(YO_ERROR_OUT_OF_RANGE,"out of memory range");
    memcpy(f->bf->at+f->offs,buf,count);
    f->offs += count;
    return count;
  }
#endif
  ;

void *Memory_As_File(void *mem, int mem_len)
#ifdef _YO_FILE_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YO_MEMORY_FILE_Destruct},
        {Oj_Close_OjMID,       Buffer_File_Close},
        {Oj_Read_OjMID,        Buffer_File_Read},
        {Oj_Write_OjMID,       Memory_File_Write},
        {Oj_Available_OjMID,   Buffer_File_Available},
        {Oj_Eof_OjMID,         Buffer_File_Eof},
        {Oj_Length_OjMID,      Buffer_File_Length},
        {Oj_Seek_OjMID,        Buffer_File_Seek},
        {Oj_Tell_OjMID,        Buffer_File_Tell},
        {Oj_Flush_OjMID,       Buffer_File_Flush},
        {0}
      };
      
    YO_BUFFER_FILE *file = __Object(sizeof(YO_BUFFER_FILE),funcs);
    file->bf = __Zero_Malloc_Npl(sizeof(YO_BUFFER));
    file->bf->at = mem;
    file->bf->count = mem_len;
    return file;
  }
#endif
  ;

void Oj_Print(void *foj, char *S)
#ifdef _YO_FILE_BUILTIN
  {
    int S_len = S?strlen(S):0;
    if ( S_len )
      Oj_Write_Full(foj,S,S_len);
  }
#endif
  ;

void Oj_Printf(void *foj, char *fmt, ...)
#ifdef _YO_FILE_BUILTIN
  {
    __Auto_Release
      {
        va_list va;
        char *text;
        va_start(va,fmt);
        text = __Pool(Yo_Format_(fmt,va));
        va_end(va);
        Oj_Print(foj,text);
      }
  }
#endif
  ;

void Oj_Fill(void *fobj, byte_t val, int count)
#ifdef _YO_FILE_BUILTIN
  {
    byte_t bf[512];
    
    REQUIRE(count >= 0);
    memset(bf,val,sizeof(bf));
    while ( count > 0 )
      {
        int L = Yo_MIN(count,sizeof(bf));
        Oj_Write_Full(fobj,bf,L);
        count -= L;
      }
  }
#endif
  ;

int Oj_Apply_File(void *foj, void *accu, void (*algo)(void *accu,void *buf, int L))
#ifdef _YO_FILE_BUILTIN
  {
    char bf[YO_FILE_COPY_BUFFER_SIZE];
    int count = 0;
    int (*xread)(void*,void*,int,int) = Yo_Find_Method_Of(&foj,Oj_Read_OjMID,YO_RAISE_ERROR);
    for ( ;; )
      {
        int i = xread(foj,bf,YO_FILE_COPY_BUFFER_SIZE,0);
        if ( !i ) break;
        algo(accu,bf,i);
        count += i;
      }
    return count;
  }
#endif
  ;

_YO_FILE_EXTERN char Oj_Digest_File_Update_OjMID[] _YO_FILE_BUILTIN_CODE( = "digest-file-update/@*"); 
void Oj_Digest_File_Update(void *dgst,void *foj) _YO_FILE_BUILTIN_CODE(
  { void(*update)(void*,void*,int) = Yo_Find_Method_Of(&dgst,Oj_Digest_Update_OjMID,YO_RAISE_ERROR);
    Oj_Apply_File(foj,dgst,update); });

void File_Update_Digest(void *dgst, char *filename)
#ifdef _YO_FILE_BUILTIN
  {
    __Auto_Release Oj_Digest_File_Update(dgst,Cfile_Open(filename,"r"));
  }
#endif
  ;

#endif /* C_once_E9479D04_5D69_4A1A_944F_0C99A852DC0B */

Changes to httpd.hc.
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
#include "buffer.hc"
#include "dicto.hc"
#include "file.hc"
#include "tcpip.hc"
#include "url.hc"

#ifdef _LIBYOYO
#define _YOYO_HTTPD_BUILTIN
#endif

struct _YOYO_HTTPD_REQUEST;
typedef int (*httpd_callback_t)(void *obj, struct _YOYO_HTTPD_REQUEST *rqst, int status);
typedef struct _YOYO_HTTPD
  {
    YOYO_TCPSOK *sok;
    char *host;
    int port;

    struct _YOYO_HTTPD_REQUEST *rqst;
    httpd_callback_t callback;
    void *obj;
  } YOYO_HTTPD;

typedef struct _YOYO_HTTPD_REQUEST
  {
    YOYO_BUFFER *bf; /* associated with instrm when post data is small */
    
    /* request */    
    void *instrm;
    char *instrm_type; /*handle by qhdr*/
    int   instrm_length;
    YOYO_DICTO  *qhdr;
    
    char *uri;
    char *referer;
    char *remote_addr;
    int   remote_port;
    int   method;
    int   httpver;
        
    /* response */
    void *outstrm;
    char *outstrm_type;
    char *outstrm_charset;
    int   outstrm_length;
    
    YOYO_ARRAY *hlns;
    YOYO_ARRAY *cookie;
    char *location;
    char *cache_control;
  
    /* internal */    
    YOYO_TCPSOK *sok;
    YOYO_HTTPD  *httpd;
    int nline;
    int left;
    struct _YOYO_HTTPD_REQUEST *next;
    
    void (*on_detach)(struct _YOYO_HTTPD_REQUEST *);
  } YOYO_HTTPD_REQUEST;

void Httpd_Detach_Request(YOYO_HTTPD_REQUEST *rqst)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_HTTPD *httpd = rqst->httpd;
    YOYO_HTTPD_REQUEST **q = &httpd->rqst;
    
    if ( rqst->on_detach )
      rqst->on_detach(rqst);
    
    while ( *q )
      {
        if ( *q == rqst )
          {
            *q = rqst->next;
            rqst->next = 0;
            break;
          }
        q = &(*q)->next;
      }
  }
#endif
  ;
  
void YOYO_HTTPD_REQUEST_Destruct(YOYO_HTTPD_REQUEST *rqst)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    Httpd_Detach_Request(rqst);
    __Unrefe(rqst->httpd);
    __Unrefe(rqst->sok);
    free(rqst->remote_addr);
    free(rqst->uri);
    free(rqst->referer);







|


|
|
|

|



|


|

|

|





|














|
|




|
|


|

|
|

|
|

|
|


















|
|







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
#include "buffer.hc"
#include "dicto.hc"
#include "file.hc"
#include "tcpip.hc"
#include "url.hc"

#ifdef _LIBYOYO
#define _YO_HTTPD_BUILTIN
#endif

struct _YO_HTTPD_REQUEST;
typedef int (*httpd_callback_t)(void *obj, struct _YO_HTTPD_REQUEST *rqst, int status);
typedef struct _YO_HTTPD
  {
    YO_TCPSOK *sok;
    char *host;
    int port;

    struct _YO_HTTPD_REQUEST *rqst;
    httpd_callback_t callback;
    void *obj;
  } YO_HTTPD;

typedef struct _YO_HTTPD_REQUEST
  {
    YO_BUFFER *bf; /* associated with instrm when post data is small */
    
    /* request */    
    void *instrm;
    char *instrm_type; /*handle by qhdr*/
    int   instrm_length;
    YO_DICTO  *qhdr;
    
    char *uri;
    char *referer;
    char *remote_addr;
    int   remote_port;
    int   method;
    int   httpver;
        
    /* response */
    void *outstrm;
    char *outstrm_type;
    char *outstrm_charset;
    int   outstrm_length;
    
    YO_ARRAY *hlns;
    YO_ARRAY *cookie;
    char *location;
    char *cache_control;
  
    /* internal */    
    YO_TCPSOK *sok;
    YO_HTTPD  *httpd;
    int nline;
    int left;
    struct _YO_HTTPD_REQUEST *next;
    
    void (*on_detach)(struct _YO_HTTPD_REQUEST *);
  } YO_HTTPD_REQUEST;

void Httpd_Detach_Request(YO_HTTPD_REQUEST *rqst)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_HTTPD *httpd = rqst->httpd;
    YO_HTTPD_REQUEST **q = &httpd->rqst;
    
    if ( rqst->on_detach )
      rqst->on_detach(rqst);
    
    while ( *q )
      {
        if ( *q == rqst )
          {
            *q = rqst->next;
            rqst->next = 0;
            break;
          }
        q = &(*q)->next;
      }
  }
#endif
  ;
  
void YO_HTTPD_REQUEST_Destruct(YO_HTTPD_REQUEST *rqst)
#ifdef _YO_HTTPD_BUILTIN
  {
    Httpd_Detach_Request(rqst);
    __Unrefe(rqst->httpd);
    __Unrefe(rqst->sok);
    free(rqst->remote_addr);
    free(rqst->uri);
    free(rqst->referer);
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
    HTTPD_PUT_METHOD       = 1003,
    HTTPD_HEAD_METHOD      = 1004,
    HTTPD_DELETE_METHOD    = 1005,

  };

char *Httpd_Method_String(int method)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    switch(method)
      {
        case HTTPD_GET_METHOD:    return "GET";
        case HTTPD_POST_METHOD:   return "POST";
        case HTTPD_PUT_METHOD:    return "PUT";
        case HTTPD_HEAD_METHOD:   return "HEAD";
        case HTTPD_DELETE_METHOD: return "DELETE";
      }
      
    return "NONE";
  }
#endif
  ;

YOYO_HTTPD_REQUEST *Httpd_Request(YOYO_HTTPD *httpd, YOYO_TCPSOK *sok)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_HTTPD_REQUEST *rqst = __Object_Dtor(sizeof(YOYO_HTTPD_REQUEST),YOYO_HTTPD_REQUEST_Destruct);
    rqst->httpd = __Refe(httpd);
    rqst->sok = __Refe(sok);
    rqst->remote_addr = Ipv4_Format_Npl(sok->ip);
    rqst->remote_port = sok->port;
    rqst->next = httpd->rqst;
    httpd->rqst = rqst;
    rqst->bf = __Refe(Buffer_Init(0));
    rqst->qhdr = __Refe(Dicto_Ptrs());
    rqst->cookie = __Refe(Array_Pchars());
    rqst->hlns = __Refe(Array_Pchars());
    Buffer_Reserve(rqst->bf,HTTPD_MAXBUF_LENGTH);
    return rqst;
  }
#endif
  ;
  
int Httpd_Rqst_Range(YOYO_HTTPD_REQUEST *rqst, int *rng_pos, int *rng_len)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    char *foo = Dicto_Get(rqst->qhdr,"RANGE",0);
    
    if ( foo )
      {
        int start = 0, end = 0;
        if ( sscanf(foo,"bytes=%u-%u",&start,&end) == 2 )
          if ( start >= 0 && end >= start )
            {
              *rng_pos = start;
              *rng_len = end-start+1;
              return 1;
            }
      }
      
    return 0;
  }
#endif
  ;
  
void Httpd_Set_Content_Range(YOYO_HTTPD_REQUEST *rqst, int rng_pos, int rng_len, int total)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    Array_Push(rqst->hlns,
              __Format_Npl("Content-Range: bytes %d-%d/%d",rng_pos,rng_len+rng_pos-1,total));
  }
#endif
  ;
  
char *Httpd_Status_Text(int st)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    switch ( st )
      {
        case 200: return "OK";
        case 201: return "Created";
        case 202: return "Accepted";
        case 203: return "Non-Authoritative Information";







|















|
|

|
















|
|




















|
|








|







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
    HTTPD_PUT_METHOD       = 1003,
    HTTPD_HEAD_METHOD      = 1004,
    HTTPD_DELETE_METHOD    = 1005,

  };

char *Httpd_Method_String(int method)
#ifdef _YO_HTTPD_BUILTIN
  {
    switch(method)
      {
        case HTTPD_GET_METHOD:    return "GET";
        case HTTPD_POST_METHOD:   return "POST";
        case HTTPD_PUT_METHOD:    return "PUT";
        case HTTPD_HEAD_METHOD:   return "HEAD";
        case HTTPD_DELETE_METHOD: return "DELETE";
      }
      
    return "NONE";
  }
#endif
  ;

YO_HTTPD_REQUEST *Httpd_Request(YO_HTTPD *httpd, YO_TCPSOK *sok)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_HTTPD_REQUEST *rqst = __Object_Dtor(sizeof(YO_HTTPD_REQUEST),YO_HTTPD_REQUEST_Destruct);
    rqst->httpd = __Refe(httpd);
    rqst->sok = __Refe(sok);
    rqst->remote_addr = Ipv4_Format_Npl(sok->ip);
    rqst->remote_port = sok->port;
    rqst->next = httpd->rqst;
    httpd->rqst = rqst;
    rqst->bf = __Refe(Buffer_Init(0));
    rqst->qhdr = __Refe(Dicto_Ptrs());
    rqst->cookie = __Refe(Array_Pchars());
    rqst->hlns = __Refe(Array_Pchars());
    Buffer_Reserve(rqst->bf,HTTPD_MAXBUF_LENGTH);
    return rqst;
  }
#endif
  ;
  
int Httpd_Rqst_Range(YO_HTTPD_REQUEST *rqst, int *rng_pos, int *rng_len)
#ifdef _YO_HTTPD_BUILTIN
  {
    char *foo = Dicto_Get(rqst->qhdr,"RANGE",0);
    
    if ( foo )
      {
        int start = 0, end = 0;
        if ( sscanf(foo,"bytes=%u-%u",&start,&end) == 2 )
          if ( start >= 0 && end >= start )
            {
              *rng_pos = start;
              *rng_len = end-start+1;
              return 1;
            }
      }
      
    return 0;
  }
#endif
  ;
  
void Httpd_Set_Content_Range(YO_HTTPD_REQUEST *rqst, int rng_pos, int rng_len, int total)
#ifdef _YO_HTTPD_BUILTIN
  {
    Array_Push(rqst->hlns,
              __Format_Npl("Content-Range: bytes %d-%d/%d",rng_pos,rng_len+rng_pos-1,total));
  }
#endif
  ;
  
char *Httpd_Status_Text(int st)
#ifdef _YO_HTTPD_BUILTIN
  {
    switch ( st )
      {
        case 200: return "OK";
        case 201: return "Created";
        case 202: return "Accepted";
        case 203: return "Non-Authoritative Information";
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
        default:  
          return "Unknown Status"; 
      }
  }
#endif
  ;
  
void Httpd_Gen_Response(YOYO_HTTPD_REQUEST *rqst, int st)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    int i;
    YOYO_BUFFER *bf = rqst->bf;
    bf->count = 0;
    Buffer_Printf(bf,"HTTP/1.1 %d %s\r\n",st,Httpd_Status_Text(st));
    Buffer_Append(bf,"Connection: close\r\n",-1);
    if ( rqst->location )
      {
        Buffer_Printf(bf,"Location: %s\r\n",rqst->location);
      }







|
|


|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
        default:  
          return "Unknown Status"; 
      }
  }
#endif
  ;
  
void Httpd_Gen_Response(YO_HTTPD_REQUEST *rqst, int st)
#ifdef _YO_HTTPD_BUILTIN
  {
    int i;
    YO_BUFFER *bf = rqst->bf;
    bf->count = 0;
    Buffer_Printf(bf,"HTTP/1.1 %d %s\r\n",st,Httpd_Status_Text(st));
    Buffer_Append(bf,"Connection: close\r\n",-1);
    if ( rqst->location )
      {
        Buffer_Printf(bf,"Location: %s\r\n",rqst->location);
      }
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
            bf->count += L;
          }
      }
  }  
#endif
  ;
  
void Cbk_Httpd_Sending_Result(YOYO_HTTPD_REQUEST *rqst, int error)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    int L;
    YOYO_BUFFER *bf = rqst->bf;

    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }







|
|


|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
            bf->count += L;
          }
      }
  }  
#endif
  ;
  
void Cbk_Httpd_Sending_Result(YO_HTTPD_REQUEST *rqst, int error)
#ifdef _YO_HTTPD_BUILTIN
  {
    int L;
    YO_BUFFER *bf = rqst->bf;

    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }
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
  finished:
    rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_FINISHED);
    Tcp_Graceful_Close(rqst->sok);
  }
#endif
  ;
  
void Httpd_Continue_Request(YOYO_HTTPD_REQUEST *rqst, int st)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_BUFFER *bf = rqst->bf;
    Httpd_Gen_Response(rqst,st);
    Tcp_Aio_Send(rqst->sok,bf->at,bf->count,Cbk_Httpd_Sending_Result,rqst);
  }
#endif
  ;
  
void Httpd_Perform_Request(YOYO_HTTPD_REQUEST *rqst)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_BUFFER *bf = rqst->bf;
    int st;
    
    if ( rqst->method == HTTPD_POST_METHOD || rqst->method == HTTPD_PUT_METHOD )
      {
        if ( !rqst->instrm ) 
          {
            rqst->instrm_length = bf->count;
            rqst->instrm = __Refe(Buffer_As_File(bf));
          }
        Oj_Seek(rqst->instrm,0,0);
      }
      
    st = rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_RQST_PERFORM);
    if ( st )
      Httpd_Continue_Request(rqst,st);
  }
#endif
  ;
    
void Cbk_Httpd_Getting_Postdta(YOYO_HTTPD_REQUEST *rqst, int error, int count)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_BUFFER *bf = rqst->bf;
    
    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }







|
|

|






|
|

|



















|
|

|







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
  finished:
    rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_FINISHED);
    Tcp_Graceful_Close(rqst->sok);
  }
#endif
  ;
  
void Httpd_Continue_Request(YO_HTTPD_REQUEST *rqst, int st)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_BUFFER *bf = rqst->bf;
    Httpd_Gen_Response(rqst,st);
    Tcp_Aio_Send(rqst->sok,bf->at,bf->count,Cbk_Httpd_Sending_Result,rqst);
  }
#endif
  ;
  
void Httpd_Perform_Request(YO_HTTPD_REQUEST *rqst)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_BUFFER *bf = rqst->bf;
    int st;
    
    if ( rqst->method == HTTPD_POST_METHOD || rqst->method == HTTPD_PUT_METHOD )
      {
        if ( !rqst->instrm ) 
          {
            rqst->instrm_length = bf->count;
            rqst->instrm = __Refe(Buffer_As_File(bf));
          }
        Oj_Seek(rqst->instrm,0,0);
      }
      
    st = rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_RQST_PERFORM);
    if ( st )
      Httpd_Continue_Request(rqst,st);
  }
#endif
  ;
    
void Cbk_Httpd_Getting_Postdta(YO_HTTPD_REQUEST *rqst, int error, int count)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_BUFFER *bf = rqst->bf;
    
    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
      {
        Httpd_Perform_Request(rqst);
      }  
  }
#endif
  ;
  
void Httpd_Analyze_Qline(char *text,YOYO_HTTPD_REQUEST *rqst)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    char *S, *q;
    
    S = text;
    while ( *S && *S != '\n' && Isspace(*S) ) ++S;
    q = S;
    while ( *q && !Isspace(*q) ) ++q;







|
|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
      {
        Httpd_Perform_Request(rqst);
      }  
  }
#endif
  ;
  
void Httpd_Analyze_Qline(char *text,YO_HTTPD_REQUEST *rqst)
#ifdef _YO_HTTPD_BUILTIN
  {
    char *S, *q;
    
    S = text;
    while ( *S && *S != '\n' && Isspace(*S) ) ++S;
    q = S;
    while ( *q && !Isspace(*q) ) ++q;
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    
    if ( !strncmp_I(S,"HTTP/1.",7) )
      rqst->httpver = strtol(S+7,0,10);
  }
#endif
  ;
  
void Httpd_Analyze_Headers(char *text,YOYO_DICTO *dct)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    int i;
    char *q, *Q, *S = text;
    while (*S!='\n') ++S; /* skip HTTP/1.x query line */
    q = ++S;
    for (;;)
      {







|
|







555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    
    if ( !strncmp_I(S,"HTTP/1.",7) )
      rqst->httpver = strtol(S+7,0,10);
  }
#endif
  ;
  
void Httpd_Analyze_Headers(char *text,YO_DICTO *dct)
#ifdef _YO_HTTPD_BUILTIN
  {
    int i;
    char *q, *Q, *S = text;
    while (*S!='\n') ++S; /* skip HTTP/1.x query line */
    q = ++S;
    for (;;)
      {
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
          }
        S = ++q;
      }
  }
#endif
  ;

void Cbk_Httpd_Getting_Request(YOYO_HTTPD_REQUEST *rqst, int error, int count)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    int i;
    YOYO_BUFFER *bf = rqst->bf;

    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }







|
|


|







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
          }
        S = ++q;
      }
  }
#endif
  ;

void Cbk_Httpd_Getting_Request(YO_HTTPD_REQUEST *rqst, int error, int count)
#ifdef _YO_HTTPD_BUILTIN
  {
    int i;
    YO_BUFFER *bf = rqst->bf;

    if ( error )
      {
        rqst->httpd->callback(rqst->httpd->obj,rqst,HTTPD_STAT_IOFAIL);
        Tcp_Close(rqst->sok);
        return;
      }
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
              }
          }
      }
  }
#endif
  ;
  
void Cbk_Httpd_Accept(YOYO_HTTPD *httpd,int error,YOYO_TCPSOK *sok)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    if ( error )
      {
        httpd->callback(httpd->obj,0,HTTPD_STAT_ACCEPTFAIL);
        return;
      }
    else
      {
        YOYO_HTTPD_REQUEST *rqst;
        Tcp_Aio_Accept(httpd->sok,Cbk_Httpd_Accept,httpd);
        rqst = Httpd_Request(httpd,sok);
        if ( HTTPD_ACCEPT == httpd->callback(httpd->obj,rqst,HTTPD_RQST_CONNECT) )
          Tcp_Aio_Recv(rqst->sok,rqst->bf->at,rqst->bf->capacity,1,Cbk_Httpd_Getting_Request,rqst);
        else
          httpd->callback(httpd->obj,rqst,HTTPD_STAT_REJECTED);
      }
  }
#endif
  ;
  
void Httpd_Listen(YOYO_HTTPD *httpd, char *host, int port)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    httpd->sok = __Refe(Tcp_Listen(host,port,0));
    free(httpd->host);
    httpd->host = Str_Copy_Npl(host,-1);
    httpd->port = port;
    Tcp_Aio_Accept(httpd->sok,Cbk_Httpd_Accept,httpd);
  }
#endif
  ;
  
void Httpd_Shutdown(YOYO_HTTPD *httpd)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    Tcp_Shutdown(httpd->sok);
  }
#endif
  ;
  
void YOYO_HTTPD_Destruct(YOYO_HTTPD *httpd)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    STRICT_REQUIRE(httpd->rqst == 0);
    free(httpd->host);
    __Unrefe(httpd->obj);
    __Unrefe(httpd->sok);
    __Destruct(httpd);
  }
#endif
  ;
  
YOYO_HTTPD *Httpd_Server(httpd_callback_t callback,void *obj)
#ifdef _YOYO_HTTPD_BUILTIN
  {
    YOYO_HTTPD *httpd = __Object_Dtor(sizeof(YOYO_HTTPD),YOYO_HTTPD_Destruct);
    httpd->obj  = __Refe(obj);
    httpd->callback = callback;
    return httpd;
  }
#endif
  ;
  
#endif /* C_once_BE85262D_CDA8_4AF5_B684_8A30EB6D7370 */








|
|








|











|
|










|
|






|
|










|
|

|









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
              }
          }
      }
  }
#endif
  ;
  
void Cbk_Httpd_Accept(YO_HTTPD *httpd,int error,YO_TCPSOK *sok)
#ifdef _YO_HTTPD_BUILTIN
  {
    if ( error )
      {
        httpd->callback(httpd->obj,0,HTTPD_STAT_ACCEPTFAIL);
        return;
      }
    else
      {
        YO_HTTPD_REQUEST *rqst;
        Tcp_Aio_Accept(httpd->sok,Cbk_Httpd_Accept,httpd);
        rqst = Httpd_Request(httpd,sok);
        if ( HTTPD_ACCEPT == httpd->callback(httpd->obj,rqst,HTTPD_RQST_CONNECT) )
          Tcp_Aio_Recv(rqst->sok,rqst->bf->at,rqst->bf->capacity,1,Cbk_Httpd_Getting_Request,rqst);
        else
          httpd->callback(httpd->obj,rqst,HTTPD_STAT_REJECTED);
      }
  }
#endif
  ;
  
void Httpd_Listen(YO_HTTPD *httpd, char *host, int port)
#ifdef _YO_HTTPD_BUILTIN
  {
    httpd->sok = __Refe(Tcp_Listen(host,port,0));
    free(httpd->host);
    httpd->host = Str_Copy_Npl(host,-1);
    httpd->port = port;
    Tcp_Aio_Accept(httpd->sok,Cbk_Httpd_Accept,httpd);
  }
#endif
  ;
  
void Httpd_Shutdown(YO_HTTPD *httpd)
#ifdef _YO_HTTPD_BUILTIN
  {
    Tcp_Shutdown(httpd->sok);
  }
#endif
  ;
  
void YO_HTTPD_Destruct(YO_HTTPD *httpd)
#ifdef _YO_HTTPD_BUILTIN
  {
    STRICT_REQUIRE(httpd->rqst == 0);
    free(httpd->host);
    __Unrefe(httpd->obj);
    __Unrefe(httpd->sok);
    __Destruct(httpd);
  }
#endif
  ;
  
YO_HTTPD *Httpd_Server(httpd_callback_t callback,void *obj)
#ifdef _YO_HTTPD_BUILTIN
  {
    YO_HTTPD *httpd = __Object_Dtor(sizeof(YO_HTTPD),YO_HTTPD_Destruct);
    httpd->obj  = __Refe(obj);
    httpd->callback = callback;
    return httpd;
  }
#endif
  ;
  
#endif /* C_once_BE85262D_CDA8_4AF5_B684_8A30EB6D7370 */

Changes to httpx.hc.
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
#include "url.hc"
#include "tasque.hc"

#ifdef _LIBYOYO
#define _HTTPX_BUILTIN
#endif

typedef void (*httpx_collback_t)(void *obj, struct _YOYO_HTTPX *httpx, int status);

typedef struct _YOYO_HTTPX
  {
    void *netchnl;
    YOYO_URL *url;
    YOYO_URL *proxy_url;
    
    int  method;
    int  maxcount;
    int  left;
    
    void *outstrm;
    void *poststrm;
    void *mon_obj;
    httpx_collback_t mon_callback;

    int nline;
    YOYO_BUFFER *bf;
    
    YOYO_DICTO  *hdrs;
    YOYO_BUFFER *content;
    int   state;
    int   streamed;
    int   status;
    char *status_text;
    
    int async:      1;
    int keepalive:  1;
    int legacy10:   1;
    int ssl:        1;
    int proxy:      1;
    int interrupted:1;
    int chunked:    1;
        
  } YOYO_HTTPX;

void YOYO_HTTPX_Destruct(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    __Unrefe(httpx->netchnl);
    __Unrefe(httpx->url);
    __Unrefe(httpx->proxy_url);
    __Unrefe(httpx->outstrm);
    __Unrefe(httpx->poststrm);







|

|


|
|











|

|
|













|

|







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
#include "url.hc"
#include "tasque.hc"

#ifdef _LIBYOYO
#define _HTTPX_BUILTIN
#endif

typedef void (*httpx_collback_t)(void *obj, struct _YO_HTTPX *httpx, int status);

typedef struct _YO_HTTPX
  {
    void *netchnl;
    YO_URL *url;
    YO_URL *proxy_url;
    
    int  method;
    int  maxcount;
    int  left;
    
    void *outstrm;
    void *poststrm;
    void *mon_obj;
    httpx_collback_t mon_callback;

    int nline;
    YO_BUFFER *bf;
    
    YO_DICTO  *hdrs;
    YO_BUFFER *content;
    int   state;
    int   streamed;
    int   status;
    char *status_text;
    
    int async:      1;
    int keepalive:  1;
    int legacy10:   1;
    int ssl:        1;
    int proxy:      1;
    int interrupted:1;
    int chunked:    1;
        
  } YO_HTTPX;

void YO_HTTPX_Destruct(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    __Unrefe(httpx->netchnl);
    __Unrefe(httpx->url);
    __Unrefe(httpx->proxy_url);
    __Unrefe(httpx->outstrm);
    __Unrefe(httpx->poststrm);
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
    HTTPX_INVALID_RESPONSE        = 0x00000d01,
    HTTPX_INVALID_RESPONSE_CODE   = 0x00000d02,
  };

#define HTTPX_SUCCEEDED(Status) (((Status)&0x8f000000) == 0)
#define HTTPX_STATUS(Status)    ((Status)&0x0fff)

void Httpx_Aio_Recv(YOYO_HTTPX *httpx, void *dta, int count, int mincount, tcp_recv_callback_t callback)
#ifdef _HTTPX_BUILTIN
  {
    if ( !httpx->ssl )
      Tcp_Aio_Recv(httpx->netchnl,dta,count,mincount,callback,httpx);
  }
#endif
  ;
  
void Httpx_Aio_Send(YOYO_HTTPX *httpx, void *dta, int count, tcp_send_callback_t callback)
#ifdef _HTTPX_BUILTIN
  {
    if ( !httpx->ssl )
      Tcp_Aio_Send(httpx->netchnl,dta,count,callback,httpx);
  }
#endif
  ;
  
void Httpx_Append_Header_Line(YOYO_BUFFER *bf, char *name, char *value)
#ifdef _HTTPX_BUILTIN
  {
    Buffer_Append(bf,name,-1);
    Buffer_Append(bf,": ",2);
    Buffer_Append(bf,value,-1);
    Buffer_Append(bf,"\r\n",2);
  }







|








|








|







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
    HTTPX_INVALID_RESPONSE        = 0x00000d01,
    HTTPX_INVALID_RESPONSE_CODE   = 0x00000d02,
  };

#define HTTPX_SUCCEEDED(Status) (((Status)&0x8f000000) == 0)
#define HTTPX_STATUS(Status)    ((Status)&0x0fff)

void Httpx_Aio_Recv(YO_HTTPX *httpx, void *dta, int count, int mincount, tcp_recv_callback_t callback)
#ifdef _HTTPX_BUILTIN
  {
    if ( !httpx->ssl )
      Tcp_Aio_Recv(httpx->netchnl,dta,count,mincount,callback,httpx);
  }
#endif
  ;
  
void Httpx_Aio_Send(YO_HTTPX *httpx, void *dta, int count, tcp_send_callback_t callback)
#ifdef _HTTPX_BUILTIN
  {
    if ( !httpx->ssl )
      Tcp_Aio_Send(httpx->netchnl,dta,count,callback,httpx);
  }
#endif
  ;
  
void Httpx_Append_Header_Line(YO_BUFFER *bf, char *name, char *value)
#ifdef _HTTPX_BUILTIN
  {
    Buffer_Append(bf,name,-1);
    Buffer_Append(bf,": ",2);
    Buffer_Append(bf,value,-1);
    Buffer_Append(bf,"\r\n",2);
  }
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
      return;
      
    Httpx_Append_Header_Line(bf,name,value); 
  }
#endif  
  ;
  
void Httpx_Append_Common_Header_Line(YOYO_BUFFER *bf, YOYO_DICTO *hdrs,char *name, char *dflt)
#ifdef _HTTPX_BUILTIN
  {
    char *val = hdrs?Dicto_Get(hdrs,name,dflt):dflt;
    Httpx_Append_Header_Line(bf,name,val); 
  }
#endif
  ;
    
void Httpx_Append_Request_Line(YOYO_BUFFER *bf, int method, char *uri, int http10)
#ifdef _HTTPX_BUILTIN
  {
    static char s_GET[3]  = "GET";
    static char s_PUT[3]  = "PUT";
    static char s_POST[4] = "POST";
    static char s_HEAD[4] = "HEAD";
    
    switch ( method )
      {
        case HTTPX_GET:  Buffer_Append(bf,s_GET,sizeof(s_GET)); break;
        case HTTPX_PUT:  Buffer_Append(bf,s_PUT,sizeof(s_PUT)); break;
        case HTTPX_POST: Buffer_Append(bf,s_POST,sizeof(s_POST)); break;
        case HTTPX_HEAD: Buffer_Append(bf,s_HEAD,sizeof(s_HEAD)); break;
        default:
          __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("invalid HTTPX request method: %d",0),method));
      }
      
    Buffer_Append(bf," ",1);
    Buffer_Append(bf,uri,-1);
    
    if ( http10 )
      Buffer_Append(bf," HTTP/1.0\r\n",11);
    else
      Buffer_Append(bf," HTTP/1.1\r\n",11);
  }
#endif
  ;
  
void Build_Http_Request(YOYO_HTTPX *httpx, int method, char *uri, YOYO_DICTO *hdrs)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_BUFFER *bf = httpx->bf;
    bf->count = 0;
    Httpx_Append_Request_Line(bf,method,uri,httpx->legacy10);
    Httpx_Append_Common_Header_Line(bf,hdrs,"Host",httpx->url->host);
    Httpx_Append_Common_Header_Line(bf,hdrs,"User-Agent","httpx");
    Httpx_Append_Common_Header_Line(bf,hdrs,"Accept","*/*");
    Httpx_Append_Common_Header_Line(bf,hdrs,"Accept-Charset","utf-8");
    if ( httpx->keepalive )







|








|














|













|


|







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
      return;
      
    Httpx_Append_Header_Line(bf,name,value); 
  }
#endif  
  ;
  
void Httpx_Append_Common_Header_Line(YO_BUFFER *bf, YO_DICTO *hdrs,char *name, char *dflt)
#ifdef _HTTPX_BUILTIN
  {
    char *val = hdrs?Dicto_Get(hdrs,name,dflt):dflt;
    Httpx_Append_Header_Line(bf,name,val); 
  }
#endif
  ;
    
void Httpx_Append_Request_Line(YO_BUFFER *bf, int method, char *uri, int http10)
#ifdef _HTTPX_BUILTIN
  {
    static char s_GET[3]  = "GET";
    static char s_PUT[3]  = "PUT";
    static char s_POST[4] = "POST";
    static char s_HEAD[4] = "HEAD";
    
    switch ( method )
      {
        case HTTPX_GET:  Buffer_Append(bf,s_GET,sizeof(s_GET)); break;
        case HTTPX_PUT:  Buffer_Append(bf,s_PUT,sizeof(s_PUT)); break;
        case HTTPX_POST: Buffer_Append(bf,s_POST,sizeof(s_POST)); break;
        case HTTPX_HEAD: Buffer_Append(bf,s_HEAD,sizeof(s_HEAD)); break;
        default:
          __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("invalid HTTPX request method: %d",0),method));
      }
      
    Buffer_Append(bf," ",1);
    Buffer_Append(bf,uri,-1);
    
    if ( http10 )
      Buffer_Append(bf," HTTP/1.0\r\n",11);
    else
      Buffer_Append(bf," HTTP/1.1\r\n",11);
  }
#endif
  ;
  
void Build_Http_Request(YO_HTTPX *httpx, int method, char *uri, YO_DICTO *hdrs)
#ifdef _HTTPX_BUILTIN
  {
    YO_BUFFER *bf = httpx->bf;
    bf->count = 0;
    Httpx_Append_Request_Line(bf,method,uri,httpx->legacy10);
    Httpx_Append_Common_Header_Line(bf,hdrs,"Host",httpx->url->host);
    Httpx_Append_Common_Header_Line(bf,hdrs,"User-Agent","httpx");
    Httpx_Append_Common_Header_Line(bf,hdrs,"Accept","*/*");
    Httpx_Append_Common_Header_Line(bf,hdrs,"Accept-Charset","utf-8");
    if ( httpx->keepalive )
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
        Httpx_Append_Header_Line(bf,"Content-Length",len);
      }
    Buffer_Append(bf,"\r\n",2);      
  }
#endif
  ;

void Httpx_Interrupt(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    httpx->interrupted = 1;
    if ( !httpx->ssl )
      Tcp_Close(httpx->netchnl);
  }
#endif
  ;
    
void Httpx_Do_Callback(YOYO_HTTPX *httpx, int status)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->mon_callback )
      httpx->mon_callback(httpx->mon_obj,httpx,httpx->state|status);

    if ( ( httpx->interrupted || !HTTPX_SUCCEEDED(status) )
      || ( httpx->state == HTTPX_FINISHED && !httpx->keepalive ) )







|









|







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
        Httpx_Append_Header_Line(bf,"Content-Length",len);
      }
    Buffer_Append(bf,"\r\n",2);      
  }
#endif
  ;

void Httpx_Interrupt(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    httpx->interrupted = 1;
    if ( !httpx->ssl )
      Tcp_Close(httpx->netchnl);
  }
#endif
  ;
    
void Httpx_Do_Callback(YO_HTTPX *httpx, int status)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->mon_callback )
      httpx->mon_callback(httpx->mon_obj,httpx,httpx->state|status);

    if ( ( httpx->interrupted || !HTTPX_SUCCEEDED(status) )
      || ( httpx->state == HTTPX_FINISHED && !httpx->keepalive ) )
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
        if ( httpx->interrupted )
          httpx->state |= HTTPX_INTERRUPTED;
      }
  }
#endif
  ;

int Httpx_Update_Until_EOH(YOYO_HTTPX *httpx, int count)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_BUFFER *bf = httpx->bf;
    int i = bf->count;
    bf->count += count;

    for ( ; i < bf->count; ++i )
      {
        if ( bf->at[i] == '\r' && bf->at[i+1] == '\n' )
          { if ( httpx->nline ) return i+2; httpx->nline = 1; ++i; } 
        else if ( bf->at[i] == '\n' )
          { if ( httpx->nline ) return i+1;  httpx->nline = 1; } 
        else
          httpx->nline = 0; 
        ++i;
      }
      
    return 0;
  }      
#endif
  ;
  
void Httpx_Analyze_Headers(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    int i;
    char *q, *Q, *S = httpx->bf->at;
    while (*S!='\n') ++S; /* skip HTTP/1.x line */
    q = ++S;
    for (;;)







|


|



















|







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
        if ( httpx->interrupted )
          httpx->state |= HTTPX_INTERRUPTED;
      }
  }
#endif
  ;

int Httpx_Update_Until_EOH(YO_HTTPX *httpx, int count)
#ifdef _HTTPX_BUILTIN
  {
    YO_BUFFER *bf = httpx->bf;
    int i = bf->count;
    bf->count += count;

    for ( ; i < bf->count; ++i )
      {
        if ( bf->at[i] == '\r' && bf->at[i+1] == '\n' )
          { if ( httpx->nline ) return i+2; httpx->nline = 1; ++i; } 
        else if ( bf->at[i] == '\n' )
          { if ( httpx->nline ) return i+1;  httpx->nline = 1; } 
        else
          httpx->nline = 0; 
        ++i;
      }
      
    return 0;
  }      
#endif
  ;
  
void Httpx_Analyze_Headers(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    int i;
    char *q, *Q, *S = httpx->bf->at;
    while (*S!='\n') ++S; /* skip HTTP/1.x line */
    q = ++S;
    for (;;)
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
          }
        S = ++q;
      }
  }
#endif
  ;
  
void Cbk_Httpx_Getting_Content(YOYO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    int L;
    YOYO_BUFFER *bf = httpx->bf;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
        return;
      }
      







|



|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
          }
        S = ++q;
      }
  }
#endif
  ;
  
void Cbk_Httpx_Getting_Content(YO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    int L;
    YO_BUFFER *bf = httpx->bf;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
        return;
      }
      
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

    Httpx_Aio_Recv(httpx, bf->at, bf->capacity, Yo_MIN(httpx->left,bf->capacity)
                          ,Cbk_Httpx_Getting_Content);
  }
#endif
  ;

void Cbk_Http_Getting_Chunked(YOYO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_BUFFER *bf = httpx->bf;
    int iterate = 0;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
        return;
      }







|


|







383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

    Httpx_Aio_Recv(httpx, bf->at, bf->capacity, Yo_MIN(httpx->left,bf->capacity)
                          ,Cbk_Httpx_Getting_Content);
  }
#endif
  ;

void Cbk_Http_Getting_Chunked(YO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    YO_BUFFER *bf = httpx->bf;
    int iterate = 0;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
        return;
      }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

    httpx->state = HTTPX_FINISHED;
    Httpx_Do_Callback(httpx,0);  
  }
#endif
  ;
    
void Cbk_Httpx_Getting_Headers(YOYO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_BUFFER *bf = httpx->bf;
    int eoh;
    
    httpx->state = HTTPX_GETTING_HEADERS;
    
    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);







|


|







462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479

    httpx->state = HTTPX_FINISHED;
    Httpx_Do_Callback(httpx,0);  
  }
#endif
  ;
    
void Cbk_Httpx_Getting_Headers(YO_HTTPX *httpx, int error, int count)
#ifdef _HTTPX_BUILTIN
  {
    YO_BUFFER *bf = httpx->bf;
    int eoh;
    
    httpx->state = HTTPX_GETTING_HEADERS;
    
    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
    
    Buffer_Grow_Reserve(bf,bf->count + 512);
    Httpx_Aio_Recv(httpx, bf->at+bf->count, 512, 1, Cbk_Httpx_Getting_Headers);    
  }
#endif
  ;
  
void Cbk_Httpx_Requested(YOYO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_REQUESTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);







|







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
    
    Buffer_Grow_Reserve(bf,bf->count + 512);
    Httpx_Aio_Recv(httpx, bf->at+bf->count, 512, 1, Cbk_Httpx_Getting_Headers);    
  }
#endif
  ;
  
void Cbk_Httpx_Requested(YO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_REQUESTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN);
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    
    Httpx_Aio_Recv(httpx, httpx->bf->at, 1023, 12 /* lengthof HTTP/1.1 200 */
                          ,Cbk_Httpx_Getting_Headers);    
  }
#endif
  ;
  
void Cbk_Httpx_Post(YOYO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_BUFFER *bf = httpx->bf;
    int i;

    if ( httpx->state != HTTPX_SENDING_POSTDATA )
      {
        bf->count = 0;
        httpx->left = httpx->poststrm?Oj_Available(httpx->poststrm):0;
      }







|


|







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
    
    Httpx_Aio_Recv(httpx, httpx->bf->at, 1023, 12 /* lengthof HTTP/1.1 200 */
                          ,Cbk_Httpx_Getting_Headers);    
  }
#endif
  ;
  
void Cbk_Httpx_Post(YO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    YO_BUFFER *bf = httpx->bf;
    int i;

    if ( httpx->state != HTTPX_SENDING_POSTDATA )
      {
        bf->count = 0;
        httpx->left = httpx->poststrm?Oj_Available(httpx->poststrm):0;
      }
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
    httpx->left -= i;
    Httpx_Aio_Send(httpx, bf->at, i,
                          httpx->left ? Cbk_Httpx_Post : Cbk_Httpx_Requested);
  }
#endif
  ;
    
void Cbk_Httpx_Connected(YOYO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_CONNECTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN







|







619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
    httpx->left -= i;
    Httpx_Aio_Send(httpx, bf->at, i,
                          httpx->left ? Cbk_Httpx_Post : Cbk_Httpx_Requested);
  }
#endif
  ;
    
void Cbk_Httpx_Connected(YO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_CONNECTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN
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
                           (httpx->method == HTTPX_POST || httpx->method == HTTPX_PUT ) 
                                ?Cbk_Httpx_Post
                                :Cbk_Httpx_Requested);    
  }
#endif
  ;
  
void Cbk_Httpx_Proxy_Connected(YOYO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_PROXY_CONNECTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN
                               |((error&TCP_PERMANENT_ERROR)?HTTPX_PERMANENT_ERROR:0));
        return;
      }
      
    Httpx_Do_Callback(httpx,HTTPX_PROXY_CONNECTED);
    
    /// auth / ssl connect
    Cbk_Httpx_Connected(httpx,error);
  }
#endif
  ;
  
void Httpx_Connect(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->keepalive && httpx->netchnl )
      {
        Httpx_Aio_Send(httpx, httpx->bf->at, httpx->bf->count,
                     (httpx->method == HTTPX_POST || httpx->method == HTTPX_PUT) 
                          ?Cbk_Httpx_Post







|



















|







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
                           (httpx->method == HTTPX_POST || httpx->method == HTTPX_PUT ) 
                                ?Cbk_Httpx_Post
                                :Cbk_Httpx_Requested);    
  }
#endif
  ;
  
void Cbk_Httpx_Proxy_Connected(YO_HTTPX *httpx, int error)
#ifdef _HTTPX_BUILTIN
  {
    httpx->state = HTTPX_PROXY_CONNECTED;

    if ( error )
      {
        Httpx_Do_Callback(httpx,HTTPX_BROKEN
                               |((error&TCP_PERMANENT_ERROR)?HTTPX_PERMANENT_ERROR:0));
        return;
      }
      
    Httpx_Do_Callback(httpx,HTTPX_PROXY_CONNECTED);
    
    /// auth / ssl connect
    Cbk_Httpx_Connected(httpx,error);
  }
#endif
  ;
  
void Httpx_Connect(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->keepalive && httpx->netchnl )
      {
        Httpx_Aio_Send(httpx, httpx->bf->at, httpx->bf->count,
                     (httpx->method == HTTPX_POST || httpx->method == HTTPX_PUT) 
                          ?Cbk_Httpx_Post
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
          Tcp_Aio_Connect(httpx->netchnl,httpx->url->host,httpx->url->port
                              ,Cbk_Httpx_Connected,httpx);
      }
  }
#endif
  ;
  
void Httpx_Query(YOYO_HTTPX *httpx, int method, char *uri, YOYO_DICTO *hdrs, void *poststrm, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->status_text ) { free(httpx->status_text); httpx->status_text = 0; }
    httpx->interrupted = 0;
    httpx->status = 0;
    httpx->method = method;
    httpx->maxcount = maxcount?maxcount:INT_MAX;







|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
          Tcp_Aio_Connect(httpx->netchnl,httpx->url->host,httpx->url->port
                              ,Cbk_Httpx_Connected,httpx);
      }
  }
#endif
  ;
  
void Httpx_Query(YO_HTTPX *httpx, int method, char *uri, YO_DICTO *hdrs, void *poststrm, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->status_text ) { free(httpx->status_text); httpx->status_text = 0; }
    httpx->interrupted = 0;
    httpx->status = 0;
    httpx->method = method;
    httpx->maxcount = maxcount?maxcount:INT_MAX;
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
    Build_Http_Request(httpx,method,uri,hdrs);
    Httpx_Connect(httpx);
  }
#endif
  ;
  
#define Httpx_Client(Url,Flags) Httpx_Client_Callback(Url,Flags,0,0)
YOYO_HTTPX *Httpx_Client_Callback(char *url,int flags, httpx_collback_t callback, void *cbkobj)
#ifdef _HTTPX_BUILTIN
  {
    YOYO_HTTPX *httpx = __Object_Dtor(sizeof(YOYO_HTTPX),YOYO_HTTPX_Destruct);
    httpx->url = __Retain(Url_Parse(url));
    
    if ( flags & HTTPX_ASYNC )
      httpx->async = 1;
    if ( flags & HTTPX_KEEPALIVE )
      httpx->keepalive = 1;
    if ( flags & HTTPX_LEGACY_10 )
      httpx->legacy10 = 1;
    
    if ( httpx->url->proto && httpx->url->proto != URLX_HTTP  )  
      __Raise(YOYO_ERROR_ILLFORMED,__yoTa("unknown HTTPX protocol requested",0));

    if ( !httpx->url->port ) 
      if ( !httpx->url->proto || httpx->url->proto == URLX_HTTP ) 
        httpx->url->port = 80;
        
    if ( callback )
      {
        httpx->mon_callback = callback;
        httpx->mon_obj = __Refe(cbkobj);
      }

    return httpx;
  }
#endif
  ;

int Httpx_Perform_Query(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->async ) return 0;
    while ( httpx->state != HTTPX_FINISHED && !(httpx->state&HTTPX_BROKEN) )
      {
        Tasque_Perform_Update(10,0);
      }
    return httpx->status;
  }
#endif
  ;
  
int Httpx_Head(YOYO_HTTPX *httpx, char *uri)
#ifdef _HTTPX_BUILTIN
  {
    int ret;
    __Auto_Release
      {
        if ( !httpx ) 
          {
            httpx = Httpx_Client(uri,0);
            uri = 0;
          }
        Httpx_Query(httpx,HTTPX_GET,uri,0,0,0,0);
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Get(YOYO_HTTPX *httpx, char *uri, YOYO_DICTO *params, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  { 
    int ret;
    __Auto_Release
      {
        if ( !httpx ) 
          {







|


|










|
















|












|


















|







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
    Build_Http_Request(httpx,method,uri,hdrs);
    Httpx_Connect(httpx);
  }
#endif
  ;
  
#define Httpx_Client(Url,Flags) Httpx_Client_Callback(Url,Flags,0,0)
YO_HTTPX *Httpx_Client_Callback(char *url,int flags, httpx_collback_t callback, void *cbkobj)
#ifdef _HTTPX_BUILTIN
  {
    YO_HTTPX *httpx = __Object_Dtor(sizeof(YO_HTTPX),YO_HTTPX_Destruct);
    httpx->url = __Retain(Url_Parse(url));
    
    if ( flags & HTTPX_ASYNC )
      httpx->async = 1;
    if ( flags & HTTPX_KEEPALIVE )
      httpx->keepalive = 1;
    if ( flags & HTTPX_LEGACY_10 )
      httpx->legacy10 = 1;
    
    if ( httpx->url->proto && httpx->url->proto != URLX_HTTP  )  
      __Raise(YO_ERROR_ILLFORMED,__yoTa("unknown HTTPX protocol requested",0));

    if ( !httpx->url->port ) 
      if ( !httpx->url->proto || httpx->url->proto == URLX_HTTP ) 
        httpx->url->port = 80;
        
    if ( callback )
      {
        httpx->mon_callback = callback;
        httpx->mon_obj = __Refe(cbkobj);
      }

    return httpx;
  }
#endif
  ;

int Httpx_Perform_Query(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    if ( httpx->async ) return 0;
    while ( httpx->state != HTTPX_FINISHED && !(httpx->state&HTTPX_BROKEN) )
      {
        Tasque_Perform_Update(10,0);
      }
    return httpx->status;
  }
#endif
  ;
  
int Httpx_Head(YO_HTTPX *httpx, char *uri)
#ifdef _HTTPX_BUILTIN
  {
    int ret;
    __Auto_Release
      {
        if ( !httpx ) 
          {
            httpx = Httpx_Client(uri,0);
            uri = 0;
          }
        Httpx_Query(httpx,HTTPX_GET,uri,0,0,0,0);
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Get(YO_HTTPX *httpx, char *uri, YO_DICTO *params, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  { 
    int ret;
    __Auto_Release
      {
        if ( !httpx ) 
          {
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Post(YOYO_HTTPX *httpx, char *uri, YOYO_DICTO *params, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  {
    int ret;
    __Auto_Release
      {
        void *poststrm = 0;
        if ( !httpx ) 







|







808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Post(YO_HTTPX *httpx, char *uri, YO_DICTO *params, void *contstrm, int maxcount)
#ifdef _HTTPX_BUILTIN
  {
    int ret;
    __Auto_Release
      {
        void *poststrm = 0;
        if ( !httpx ) 
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
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Content_Length(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    char *foo;
    if ( httpx->hdrs )
      if ( foo = Dicto_Get(httpx->hdrs,"Content-Length",0) )
        {
          return Str_To_Int(foo);
        }
    __Raise(YOYO_ERROR_ILLFORMED,"httpx client doesn´t have required headers");
  }
#endif
  ;
  
void *Httpx_Content_Md5(YOYO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    char *foo;
    if ( httpx->hdrs )
      if ( foo = Dicto_Get(httpx->hdrs,"Content-MD5",0) )
        {
          return Str_Base64_Decode(foo,0);
        }
    return 0;
  }
#endif
  ;

YOYO_DICTO *Httpx_Hdrs_Set_Range(YOYO_DICTO *dicto, int offs, int len)
#ifdef _HTTPX_BUILTIN
  {
    if ( !dicto ) dicto = Dicto_Ptrs();
    Dicto_Put(dicto,"Range",__Format_Npl("bytes=%d-%d",offs,offs+len-1));
    return dicto;
  }
#endif
  ;
  
#endif /* C_once_DAA1D391_392F_467C_B5A8_6C8D0D3A9DCC */








|








|




|













|











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
        ret = Httpx_Perform_Query(httpx);
      }
    return ret;
  }
#endif
  ;
  
int Httpx_Content_Length(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    char *foo;
    if ( httpx->hdrs )
      if ( foo = Dicto_Get(httpx->hdrs,"Content-Length",0) )
        {
          return Str_To_Int(foo);
        }
    __Raise(YO_ERROR_ILLFORMED,"httpx client doesn´t have required headers");
  }
#endif
  ;
  
void *Httpx_Content_Md5(YO_HTTPX *httpx)
#ifdef _HTTPX_BUILTIN
  {
    char *foo;
    if ( httpx->hdrs )
      if ( foo = Dicto_Get(httpx->hdrs,"Content-MD5",0) )
        {
          return Str_Base64_Decode(foo,0);
        }
    return 0;
  }
#endif
  ;

YO_DICTO *Httpx_Hdrs_Set_Range(YO_DICTO *dicto, int offs, int len)
#ifdef _HTTPX_BUILTIN
  {
    if ( !dicto ) dicto = Dicto_Ptrs();
    Dicto_Put(dicto,"Range",__Format_Npl("bytes=%d-%d",offs,offs+len-1));
    return dicto;
  }
#endif
  ;
  
#endif /* C_once_DAA1D391_392F_467C_B5A8_6C8D0D3A9DCC */

Changes to logout.hc.
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

*/

#ifndef C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC
#define C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC

#ifdef _LIBYOYO
#define _YOYO_LOGOUT_BUILTIN
#endif

#include "yoyo.hc"
#include "file.hc"

enum 
  {
    YOYO_LOG_ERROR   = 0,
    YOYO_LOG_WARN    = 10,
    YOYO_LOG_INFO    = 20,
    YOYO_LOG_DEBUG   = 50,
    YOYO_LOG_ALL     = 100,
  };

#ifdef _YOYO_LOGOUT_BUILTIN
static clock_t YOYO_Log_Clock = 0;
static int YOYO_Log_Line_No = 0;
static int YOYO_Log_Fd = -1;
static int YOYO_Log_Opt = 0;
int YOYO_Log_Level = YOYO_LOG_INFO;
/* static int YOYO_Log_Pid = 0; */
#else
int YOYO_Log_Level;
#endif

enum
  {
    YOYO_LOG_DATESTAMP = 1 << 16,
    YOYO_LOG_PID       = 1 << 17,
    YOYO_LOG_DATEMARK  = 1 << 18,
    YOYO_LOG_LINENO    = 1 << 19,
    YOYO_LOG_LEVEL     = 1 << 20,
  };
  
void Close_Log()
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    if ( YOYO_Log_Fd >= 0 )
      {
        close(YOYO_Log_Fd);
        YOYO_Log_Fd = -1;
      }
  }
#endif
  ;
  
void Append_Log(char *logname, int opt)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    Close_Log();
    Create_Required_Dirs(logname);
    YOYO_Log_Fd = Open_File_Raise(logname,O_CREAT|O_APPEND|O_WRONLY);
    YOYO_Log_Opt = opt;
    YOYO_Log_Level = opt & 0x0ff;
  }
#endif
  ;
  
void Rewrite_Log(char *logname, int opt)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    Close_Log();
    Create_Required_Dirs(logname);
    YOYO_Log_Fd = Open_File_Raise(logname,O_CREAT|O_APPEND|O_WRONLY|O_TRUNC);
    YOYO_Log_Opt = opt;
    YOYO_Log_Level = opt & 0x0ff;
  }
#endif
  ;
  
void Set_Logout_Opt(int opt)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    YOYO_Log_Opt = opt;
    YOYO_Log_Level = opt & 0x0ff;
  }
#endif
  ;

#define Log_Level(L) (YOYO_Log_Level<L)

void Logout(int level, char *text)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    if ( level <= YOYO_Log_Level )
      __Xchg_Interlock
        {        
          int log_fd = YOYO_Log_Fd >= 0 ? YOYO_Log_Fd : fileno(stderr);
          char mark[80] = {0};
          int len = strlen(text);
          if ( YOYO_Log_Opt & YOYO_LOG_DATESTAMP )
            {
              clock_t t = clock();
              if ( t - YOYO_Log_Clock > CLOCKS_PER_SEC )
                {
                  YOYO_Log_Clock = t;
                  sprintf(mark, "%%clocks%% %.3f\n",(double)YOYO_Log_Clock/CLOCKS_PER_SEC);
                  Write_Out(log_fd,mark,strlen(mark));
                }
            }
          if ( YOYO_Log_Opt & (YOYO_LOG_LEVEL) )
            {
              if ( level == YOYO_LOG_ERROR )
                Write_Out(log_fd,"{error} ",8);
              else if ( level == YOYO_LOG_WARN )
                Write_Out(log_fd,"{warn!} ",8);
              else if ( level == YOYO_LOG_INFO )
                Write_Out(log_fd,"{info!} ",8);
              else
                Write_Out(log_fd,"{debug} ",8);
            }
          if ( YOYO_Log_Opt & (YOYO_LOG_DATEMARK|YOYO_LOG_PID|YOYO_LOG_LINENO) )
            {
              int i = 1;
              mark[0] = '[';
              if ( YOYO_Log_Opt & YOYO_LOG_LINENO )
                i += sprintf(mark+i,"%4d",YOYO_Log_Line_No);
              if ( YOYO_Log_Opt & YOYO_LOG_PID ) 
                {
                  int YOYO_Log_Pid = getpid();
                  if ( i > 1 ) mark[i++] = ':';
                  i += sprintf(mark+i,"%5d",YOYO_Log_Pid);
                }
              if ( YOYO_Log_Opt & YOYO_LOG_DATEMARK ) 
                {
                  time_t t = time(0);
                  struct tm *tm = localtime(&t);
                  if ( i > 1 ) mark[i++] = ':';
                  i += sprintf(mark+i,"%02d%02d%02d/%02d:%02d",
                          tm->tm_mday,tm->tm_mon+1,(tm->tm_year+1900)%100,
                          tm->tm_hour,tm->tm_min);
                }
              mark[i++] = ']';
              mark[i++] = ' ';
              mark[i] = 0;  
              Write_Out(log_fd,mark,i);
            }
          ++YOYO_Log_Line_No;
          Write_Out(log_fd,text,len);
          if ( !len || text[len-1] != '\n' )
            Write_Out(log_fd,"\n",1);
        }
  }
#endif
  ;
  
void Logoutf(int level, char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    if ( level <= YOYO_Log_Level )
      {
        va_list va;
        char *text;
        va_start(va,fmt);
        text = Yo_Format_(fmt,va);
        Logout(level,text);
        free(text);
        va_end(va);
      }
  }
#endif
  ;

#define Logout_Debug(S) if (YOYO_Log_Level<YOYO_LOG_DEBUG); else Logout(YOYO_LOG_DEBUG,S)
#define Log_Debug if (YOYO_Log_Level<YOYO_LOG_DEBUG); else Log_Debug_
void Log_Debug_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  

















  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YOYO_LOG_DEBUG,text);
    free(text);
    va_end(va);
  }
#endif
  ;


#define Logout_Info(S) if (YOYO_Log_Level<YOYO_LOG_INFO); else Logout(YOYO_LOG_INFO,S)
#define Log_Info if (YOYO_Log_Level<YOYO_LOG_INFO); else Log_Info_
void Log_Info_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YOYO_LOG_INFO,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Warning(S) if (YOYO_Log_Level<YOYO_LOG_WARN); else Logout(YOYO_LOG_WARN,S)
#define Log_Warning if (YOYO_Log_Level<YOYO_LOG_WARN); else Log_Warning_
void Log_Warning_(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YOYO_LOG_WARN,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Error(S) if (YOYO_Log_Level<YOYO_LOG_ERROR); else Logout(YOYO_LOG_ERROR,S)
/*#define Log_Error if (YOYO_Log_Level<YOYO_LOG_ERROR); else Log_Error_*/
void Log_Error(char *fmt, ...)
#ifdef _YOYO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YOYO_LOG_ERROR,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#endif /* C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC */







|







|
|
|
|
|


|
|
|
|
|
|
|

|




|
|
|
|
|



|

|

|
|






|



|
|
|





|



|
|
|





|

|
|




|


|

|


|


|


|

|
|



|

|

|

|




|



|
|
|

|

|

|













|









|

|













|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|






|
<
|
|
|





|






|
|
|
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







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

*/

#ifndef C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC
#define C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC

#ifdef _LIBYOYO
#define _YO_LOGOUT_BUILTIN
#endif

#include "yoyo.hc"
#include "file.hc"

enum 
  {
    YO_LOG_ERROR   = 0,
    YO_LOG_WARN    = 10,
    YO_LOG_INFO    = 20,
    YO_LOG_DEBUG   = 50,
    YO_LOG_ALL     = 100,
  };

#ifdef _YO_LOGOUT_BUILTIN
static clock_t YO_Log_Clock = 0;
static int YO_Log_Line_No = 0;
static int YO_Log_Fd = -1;
static int YO_Log_Opt = 0;
int YO_Log_Level = YO_LOG_INFO;
/* static int YO_Log_Pid = 0; */
#else
int YO_Log_Level;
#endif

enum
  {
    YO_LOG_DATESTAMP = 1 << 16,
    YO_LOG_PID       = 1 << 17,
    YO_LOG_DATEMARK  = 1 << 18,
    YO_LOG_LINENO    = 1 << 19,
    YO_LOG_LEVEL     = 1 << 20,
  };
  
void Close_Log()
#ifdef _YO_LOGOUT_BUILTIN  
  {
    if ( YO_Log_Fd >= 0 )
      {
        close(YO_Log_Fd);
        YO_Log_Fd = -1;
      }
  }
#endif
  ;
  
void Append_Log(char *logname, int opt)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    Close_Log();
    Create_Required_Dirs(logname);
    YO_Log_Fd = Open_File_Raise(logname,O_CREAT|O_APPEND|O_WRONLY);
    YO_Log_Opt = opt;
    YO_Log_Level = opt & 0x0ff;
  }
#endif
  ;
  
void Rewrite_Log(char *logname, int opt)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    Close_Log();
    Create_Required_Dirs(logname);
    YO_Log_Fd = Open_File_Raise(logname,O_CREAT|O_APPEND|O_WRONLY|O_TRUNC);
    YO_Log_Opt = opt;
    YO_Log_Level = opt & 0x0ff;
  }
#endif
  ;
  
void Set_Logout_Opt(int opt)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    YO_Log_Opt = opt;
    YO_Log_Level = opt & 0x0ff;
  }
#endif
  ;

#define Log_Level(L) (YO_Log_Level<L)

void Logout(int level, char *text)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    if ( level <= YO_Log_Level )
      __Xchg_Interlock
        {        
          int log_fd = YO_Log_Fd >= 0 ? YO_Log_Fd : fileno(stderr);
          char mark[80] = {0};
          int len = strlen(text);
          if ( YO_Log_Opt & YO_LOG_DATESTAMP )
            {
              clock_t t = clock();
              if ( t - YO_Log_Clock > CLOCKS_PER_SEC )
                {
                  YO_Log_Clock = t;
                  sprintf(mark, "%%clocks%% %.3f\n",(double)YO_Log_Clock/CLOCKS_PER_SEC);
                  Write_Out(log_fd,mark,strlen(mark));
                }
            }
          if ( YO_Log_Opt & (YO_LOG_LEVEL) )
            {
              if ( level == YO_LOG_ERROR )
                Write_Out(log_fd,"{error} ",8);
              else if ( level == YO_LOG_WARN )
                Write_Out(log_fd,"{warn!} ",8);
              else if ( level == YO_LOG_INFO )
                Write_Out(log_fd,"{info!} ",8);
              else
                Write_Out(log_fd,"{debug} ",8);
            }
          if ( YO_Log_Opt & (YO_LOG_DATEMARK|YO_LOG_PID|YO_LOG_LINENO) )
            {
              int i = 1;
              mark[0] = '[';
              if ( YO_Log_Opt & YO_LOG_LINENO )
                i += sprintf(mark+i,"%4d",YO_Log_Line_No);
              if ( YO_Log_Opt & YO_LOG_PID ) 
                {
                  int YO_Log_Pid = getpid();
                  if ( i > 1 ) mark[i++] = ':';
                  i += sprintf(mark+i,"%5d",YO_Log_Pid);
                }
              if ( YO_Log_Opt & YO_LOG_DATEMARK ) 
                {
                  time_t t = time(0);
                  struct tm *tm = localtime(&t);
                  if ( i > 1 ) mark[i++] = ':';
                  i += sprintf(mark+i,"%02d%02d%02d/%02d:%02d",
                          tm->tm_mday,tm->tm_mon+1,(tm->tm_year+1900)%100,
                          tm->tm_hour,tm->tm_min);
                }
              mark[i++] = ']';
              mark[i++] = ' ';
              mark[i] = 0;  
              Write_Out(log_fd,mark,i);
            }
          ++YO_Log_Line_No;
          Write_Out(log_fd,text,len);
          if ( !len || text[len-1] != '\n' )
            Write_Out(log_fd,"\n",1);
        }
  }
#endif
  ;
  
void Logoutf(int level, char *fmt, ...)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    if ( level <= YO_Log_Level )
      {
        va_list va;
        char *text;
        va_start(va,fmt);
        text = Yo_Format_(fmt,va);
        Logout(level,text);
        free(text);
        va_end(va);
      }
  }
#endif
  ;

#define Logout_Debug(S) if (YO_Log_Level<YO_LOG_DEBUG); else Logout(YO_LOG_DEBUG,S)
#define Log_Debug if (YO_Log_Level<YO_LOG_DEBUG); else Log_Debug_
void Log_Debug_(char *fmt, ...)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YO_LOG_DEBUG,text);
    free(text);
    va_end(va);
  }
#endif
  ;


#define Logout_Info(S) if (YO_Log_Level<YO_LOG_INFO); else Logout(YO_LOG_INFO,S)
#define Log_Info if (YO_Log_Level<YO_LOG_INFO); else Log_Info_
void Log_Info_(char *fmt, ...)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YO_LOG_INFO,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Warning(S) if (YO_Log_Level<YO_LOG_WARN); else Logout(YO_LOG_WARN,S)

#define Log_Warning if (YO_Log_Level<YO_LOG_WARN); else Log_Warning_
void Log_Warning_(char *fmt, ...)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
    Logout(YO_LOG_WARN,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#define Logout_Error(S) if (YO_Log_Level<YO_LOG_ERROR); else Logout(YO_LOG_ERROR,S)
/*#define Log_Error if (YO_Log_Level<YO_LOG_ERROR); else Log_Error_*/
void Log_Error(char *fmt, ...)
#ifdef _YO_LOGOUT_BUILTIN  
  {
    va_list va;
    char *text;
    va_start(va,fmt);
    text = Yo_Format_(fmt,va);
















    Logout(YO_LOG_ERROR,text);
    free(text);
    va_end(va);
  }
#endif
  ;

#endif /* C_once_9629B105_86D6_4BF5_BAA2_62AB1ACE54EC */
Changes to lzss.hc.
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

*/

#ifndef C_once_9570D5A2_F57C_4879_851D_6EC6959C9420
#define C_once_9570D5A2_F57C_4879_851D_6EC6959C9420

#ifdef _LIBYOYO
#define _YOYO_LZSS_BUILTIN
#endif

#include "yoyo.hc"
#include "buffer.hc"

#ifdef _YOYO_LZSS_BUILTIN
enum 
  {
    LZSS_MIN_LEN = 4,
    LZSS_MAX_LEN = 15,
    LZSS_TABLE_MOD = 4095, /*4095, */
    LZSS_TABLE_LEN = LZSS_TABLE_MOD+1,
  };
#endif

int LZSS_Search_Index(char **table_S, char**iE, char* val, int strong, int *p_l, int maxl)
#ifdef _YOYO_LZSS_BUILTIN
  {
    char **iS = table_S;
    int len = iE - iS;
    int half;
    char ** middle;
    int  l = 0, ll = 0;
    if (p_l) *p_l = 0;







|





|










|







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

*/

#ifndef C_once_9570D5A2_F57C_4879_851D_6EC6959C9420
#define C_once_9570D5A2_F57C_4879_851D_6EC6959C9420

#ifdef _LIBYOYO
#define _YO_LZSS_BUILTIN
#endif

#include "yoyo.hc"
#include "buffer.hc"

#ifdef _YO_LZSS_BUILTIN
enum 
  {
    LZSS_MIN_LEN = 4,
    LZSS_MAX_LEN = 15,
    LZSS_TABLE_MOD = 4095, /*4095, */
    LZSS_TABLE_LEN = LZSS_TABLE_MOD+1,
  };
#endif

int LZSS_Search_Index(char **table_S, char**iE, char* val, int strong, int *p_l, int maxl)
#ifdef _YO_LZSS_BUILTIN
  {
    char **iS = table_S;
    int len = iE - iS;
    int half;
    char ** middle;
    int  l = 0, ll = 0;
    if (p_l) *p_l = 0;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    if ( p_l ) *p_l = l;
    return iS-table_S;
  }
#endif
  ;

void LZSS_Replace_String(char **table, char *in_b, int r_i)
#ifdef _YOYO_LZSS_BUILTIN
  {
    int l, o_idx, idx;
    if (r_i >= LZSS_TABLE_MOD) // replace
      {
        char *p = in_b+(r_i-LZSS_TABLE_MOD);
        o_idx = LZSS_Search_Index(table,table+LZSS_TABLE_MOD,p,1,0,LZSS_MAX_LEN);








|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    if ( p_l ) *p_l = l;
    return iS-table_S;
  }
#endif
  ;

void LZSS_Replace_String(char **table, char *in_b, int r_i)
#ifdef _YO_LZSS_BUILTIN
  {
    int l, o_idx, idx;
    if (r_i >= LZSS_TABLE_MOD) // replace
      {
        char *p = in_b+(r_i-LZSS_TABLE_MOD);
        o_idx = LZSS_Search_Index(table,table+LZSS_TABLE_MOD,p,1,0,LZSS_MAX_LEN);

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
        table[idx] = in_b+r_i;
      }
  }
#endif
  ;

short LZSS_Update_Table(char **table, char *in_b, int _in_i, int out_l)
#ifdef _YOYO_LZSS_BUILTIN
  {
    int code = 0, idx = 0, s_i, l=0;
    char **table_R;
    int r_i = _in_i-(LZSS_MAX_LEN-1);  // old (will replaced) string
    int t_i = _in_i;                   // encoded string
    int maxl = (out_l >= LZSS_MAX_LEN ? LZSS_MAX_LEN : out_l);








|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
        table[idx] = in_b+r_i;
      }
  }
#endif
  ;

short LZSS_Update_Table(char **table, char *in_b, int _in_i, int out_l)
#ifdef _YO_LZSS_BUILTIN
  {
    int code = 0, idx = 0, s_i, l=0;
    char **table_R;
    int r_i = _in_i-(LZSS_MAX_LEN-1);  // old (will replaced) string
    int t_i = _in_i;                   // encoded string
    int maxl = (out_l >= LZSS_MAX_LEN ? LZSS_MAX_LEN : out_l);

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

    return code;
  }
#endif
  ;

int LZSS_Compress(void *_in_b, int in_b_len, void *_out_b, int out_b_len)
#ifdef _YOYO_LZSS_BUILTIN
  {
    
    char *in_b = _in_b;
    unsigned char *out_b = _out_b;
    char **table = 0;
    int  out_i = 4, in_i = 0;
    unsigned char *cnt_p = 0;







|







206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

    return code;
  }
#endif
  ;

int LZSS_Compress(void *_in_b, int in_b_len, void *_out_b, int out_b_len)
#ifdef _YO_LZSS_BUILTIN
  {
    
    char *in_b = _in_b;
    unsigned char *out_b = _out_b;
    char **table = 0;
    int  out_i = 4, in_i = 0;
    unsigned char *cnt_p = 0;
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
    free(table);
    return out_i;
  }
#endif
  ;

int LZSS_Compress_Inplace(void *buf, int in_len)
#ifdef _YOYO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(in_len);
    int q = LZSS_Compress(buf,in_len,b,in_len);
    if ( q > 0 )
      memcpy(buf,b,q);
    free(b);
    return q;
  }
#endif
  ;
  
int LZSS_Decompress(void *_in_b, int in_b_len, void *_out_b, int out_b_len)
#ifdef _YOYO_LZSS_BUILTIN
  {
    unsigned char *in_b = _in_b;
    char *out_b = _out_b;
    int in_i = 0;
    int out_i = 0;
    
    int original_len = Four_To_Unsigned(in_b);







|












|







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
    free(table);
    return out_i;
  }
#endif
  ;

int LZSS_Compress_Inplace(void *buf, int in_len)
#ifdef _YO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(in_len);
    int q = LZSS_Compress(buf,in_len,b,in_len);
    if ( q > 0 )
      memcpy(buf,b,q);
    free(b);
    return q;
  }
#endif
  ;
  
int LZSS_Decompress(void *_in_b, int in_b_len, void *_out_b, int out_b_len)
#ifdef _YO_LZSS_BUILTIN
  {
    unsigned char *in_b = _in_b;
    char *out_b = _out_b;
    int in_i = 0;
    int out_i = 0;
    
    int original_len = Four_To_Unsigned(in_b);
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
    if ( out_i != original_len ) out_i = -out_i;
    return out_i;
  }
#endif
  ;

int LZSS_Decompress_Inplace(void *buf, int in_len, int max_len)
#ifdef _YOYO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(max_len);
    int q = LZSS_Decompress(buf,in_len,b,max_len);
    if ( q > 0 )
      memcpy(buf,b,q);
    free(b);
    return q;
  }
#endif
  ;

void Buffer_LZSS_Compress(YOYO_BUFFER *bf)
#ifdef _YOYO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(bf->count);
    int q = LZSS_Compress(bf->at,bf->count,b,bf->count);
    
    if ( q > 0 )
      {
        memcpy(bf->at,b,q);
        Buffer_Resize(bf,q);
      }
    free(b);
    
    if ( q < 0 )
      __Raise(YOYO_ERROR_COMPRESS_DATA,"uncompressable data");
  }
#endif
  ;

void Buffer_LZSS_Decompress(YOYO_BUFFER *bf)
#ifdef _YOYO_LZSS_BUILTIN
  {
    int sz = Four_To_Unsigned(bf->at);
    if ( sz > bf->count*30 ) 
      __Raise(YOYO_ERROR_CORRUPTED,"is not LZSS compressed buffer"); 
    else
      {
        void *b = Yo_Malloc_Npl(sz);
        int q = LZSS_Decompress(bf->at,bf->count,b,sz);
    
        if ( q > 0 )
          {
            Buffer_Resize(bf,q);
            memcpy(bf->at,b,q);
          }
        free(b);
    
        if ( q < 0 )
          __Raise(YOYO_ERROR_DECOMPRESS_DATA,"failed to decompress buffer");
      }
  }
#endif
  ;

#endif /* C_once_9570D5A2_F57C_4879_851D_6EC6959C9420 */








|











|
|












|




|
|



|













|







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
    if ( out_i != original_len ) out_i = -out_i;
    return out_i;
  }
#endif
  ;

int LZSS_Decompress_Inplace(void *buf, int in_len, int max_len)
#ifdef _YO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(max_len);
    int q = LZSS_Decompress(buf,in_len,b,max_len);
    if ( q > 0 )
      memcpy(buf,b,q);
    free(b);
    return q;
  }
#endif
  ;

void Buffer_LZSS_Compress(YO_BUFFER *bf)
#ifdef _YO_LZSS_BUILTIN
  {
    void *b = Yo_Malloc_Npl(bf->count);
    int q = LZSS_Compress(bf->at,bf->count,b,bf->count);
    
    if ( q > 0 )
      {
        memcpy(bf->at,b,q);
        Buffer_Resize(bf,q);
      }
    free(b);
    
    if ( q < 0 )
      __Raise(YO_ERROR_COMPRESS_DATA,"uncompressable data");
  }
#endif
  ;

void Buffer_LZSS_Decompress(YO_BUFFER *bf)
#ifdef _YO_LZSS_BUILTIN
  {
    int sz = Four_To_Unsigned(bf->at);
    if ( sz > bf->count*30 ) 
      __Raise(YO_ERROR_CORRUPTED,"is not LZSS compressed buffer"); 
    else
      {
        void *b = Yo_Malloc_Npl(sz);
        int q = LZSS_Decompress(bf->at,bf->count,b,sz);
    
        if ( q > 0 )
          {
            Buffer_Resize(bf,q);
            memcpy(bf->at,b,q);
          }
        free(b);
    
        if ( q < 0 )
          __Raise(YO_ERROR_DECOMPRESS_DATA,"failed to decompress buffer");
      }
  }
#endif
  ;

#endif /* C_once_9570D5A2_F57C_4879_851D_6EC6959C9420 */

Changes to md5.hc.
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

*/

#ifndef C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3
#define C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3

#ifdef _LIBYOYO
#define _YOYO_MD5_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YOYO_MD5
  {
    uint_t state[4];   /* state (ABCD) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64];
  } YOYO_MD5;

typedef YOYO_MD5 YOYO_MD5_SIGNER;

void *Md5_Clone(YOYO_MD5 *md5)
#ifdef _YOYO_MD5_BUILTIN
  {
    return __Clone(sizeof(YOYO_MD5),md5);
  }
#endif
  ;

void * Md5_Start(YOYO_MD5 *md5)
#ifdef _YOYO_MD5_BUILTIN
  {
    memset(md5,0,sizeof(*md5));
    md5->state[0] = 0x67452301; 
    md5->state[1] = 0xefcdab89; 
    md5->state[2] = 0x98badcfe; 
    md5->state[3] = 0x10325476;
    return md5;
  }
#endif
  ;

void Md5_Update(YOYO_MD5 *md5, void *data, int len);
void *Md5_Finish(YOYO_MD5 *md5, void *digest);

void *Md5_Init()
#ifdef _YOYO_MD5_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Md5_Clone },
        {Oj_Digest_Update_OjMID, Md5_Update },
        {0}};
    
    YOYO_MD5 *md5 = __Object(sizeof(YOYO_MD5),funcs);
    return Md5_Start(md5);
  }
#endif
  ;

#define YOYO_MD5_INITIALIZER {{0x67452301,0xefcdab89,0x98badcfe,0x10325476},{0},0,{0}}

void *Md5_Digest(void *data, int len, void *digest)
#ifdef _YOYO_MD5_BUILTIN
  {
    YOYO_MD5 md5 = YOYO_MD5_INITIALIZER;
    Md5_Update(&md5,data,len);
    return Md5_Finish(&md5,digest);
  }
#endif
  ;

void *Md5_Digest_Digest(void *data, int len, void *digest)
#ifdef _YOYO_MD5_BUILTIN
  {
    byte_t tmp[16];
    YOYO_MD5 md5 = YOYO_MD5_INITIALIZER;
    Md5_Digest(data,len,tmp);
    Md5_Update(&md5,tmp,16);
    Md5_Update(&md5,data,len);
    return Md5_Finish(&md5,digest);
  }
#endif
  ;

#define Md5_Digest_Of(Data,Len) Md5_Digest(Data,Len,0)

#ifdef _YOYO_MD5_BUILTIN

  #if defined _X86 || defined __i386 || defined __x86_64
    #define Md5_Internal_Encode memcpy
    #define Md5_Internal_Decode memcpy
  #else
    void Md5_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
      {







|





|





|

|

|
|

|




|
|











|
|


|

|





|





|


|

|







|


|










|







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

*/

#ifndef C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3
#define C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3

#ifdef _LIBYOYO
#define _YO_MD5_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YO_MD5
  {
    uint_t state[4];   /* state (ABCD) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64];
  } YO_MD5;

typedef YO_MD5 YO_MD5_SIGNER;

void *Md5_Clone(YO_MD5 *md5)
#ifdef _YO_MD5_BUILTIN
  {
    return __Clone(sizeof(YO_MD5),md5);
  }
#endif
  ;

void * Md5_Start(YO_MD5 *md5)
#ifdef _YO_MD5_BUILTIN
  {
    memset(md5,0,sizeof(*md5));
    md5->state[0] = 0x67452301; 
    md5->state[1] = 0xefcdab89; 
    md5->state[2] = 0x98badcfe; 
    md5->state[3] = 0x10325476;
    return md5;
  }
#endif
  ;

void Md5_Update(YO_MD5 *md5, void *data, int len);
void *Md5_Finish(YO_MD5 *md5, void *digest);

void *Md5_Init()
#ifdef _YO_MD5_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Md5_Clone },
        {Oj_Digest_Update_OjMID, Md5_Update },
        {0}};
    
    YO_MD5 *md5 = __Object(sizeof(YO_MD5),funcs);
    return Md5_Start(md5);
  }
#endif
  ;

#define YO_MD5_INITIALIZER {{0x67452301,0xefcdab89,0x98badcfe,0x10325476},{0},0,{0}}

void *Md5_Digest(void *data, int len, void *digest)
#ifdef _YO_MD5_BUILTIN
  {
    YO_MD5 md5 = YO_MD5_INITIALIZER;
    Md5_Update(&md5,data,len);
    return Md5_Finish(&md5,digest);
  }
#endif
  ;

void *Md5_Digest_Digest(void *data, int len, void *digest)
#ifdef _YO_MD5_BUILTIN
  {
    byte_t tmp[16];
    YO_MD5 md5 = YO_MD5_INITIALIZER;
    Md5_Digest(data,len,tmp);
    Md5_Update(&md5,tmp,16);
    Md5_Update(&md5,data,len);
    return Md5_Finish(&md5,digest);
  }
#endif
  ;

#define Md5_Digest_Of(Data,Len) Md5_Digest(Data,Len,0)

#ifdef _YO_MD5_BUILTIN

  #if defined _X86 || defined __i386 || defined __x86_64
    #define Md5_Internal_Encode memcpy
    #define Md5_Internal_Decode memcpy
  #else
    void Md5_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
      {
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | ~(z)))
  #define FF(a, b, c, d, x, s, ac) (a) += F((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define GG(a, b, c, d, x, s, ac) (a) += G((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define HH(a, b, c, d, x, s, ac) (a) += H((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define II(a, b, c, d, x, s, ac) (a) += I((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)

  void Md5_Internal_Transform(YOYO_MD5 *md5, void *block)
    {
      enum _S_constants
        {
          S11 = 7,
          S12 = 12,
          S13 = 17,
          S14 = 22,







|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | ~(z)))
  #define FF(a, b, c, d, x, s, ac) (a) += F((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define GG(a, b, c, d, x, s, ac) (a) += G((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define HH(a, b, c, d, x, s, ac) (a) += H((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)
  #define II(a, b, c, d, x, s, ac) (a) += I((b), (c), (d)) + (x) + (ac); (a) = ROTATE_LEFT((a), (s)) + (b)

  void Md5_Internal_Transform(YO_MD5 *md5, void *block)
    {
      enum _S_constants
        {
          S11 = 7,
          S12 = 12,
          S13 = 17,
          S14 = 22,
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  #undef I
  #undef ROTATE_LEFT
  #undef FF
  #undef GG
  #undef HH
  #undef II

  void Md5_Update(YOYO_MD5 *md5, void *input, int input_length)
    {
      int i, index, partLen;
      uint_t *count = md5->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);







|







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  #undef I
  #undef ROTATE_LEFT
  #undef FF
  #undef GG
  #undef HH
  #undef II

  void Md5_Update(YO_MD5 *md5, void *input, int input_length)
    {
      int i, index, partLen;
      uint_t *count = md5->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
          index = 0;
        }
      else
        i = 0;
      memcpy(&md5->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Md5_Finish(YOYO_MD5 *md5, void *digest)
    {
      if ( !md5->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0







|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
          index = 0;
        }
      else
        i = 0;
      memcpy(&md5->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Md5_Finish(YO_MD5 *md5, void *digest)
    {
      if ( !md5->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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
          md5->finished = 1;
        }
      if ( !digest ) digest = __Malloc(16);
      Md5_Internal_Encode(digest, md5->state, 16);
      return digest;
    }

#endif /* _YOYO_MD5_BUILTIN */

typedef struct _YOYO_HMAC_MD5
  {
    YOYO_MD5 md5;
    byte_t ipad[64];
    byte_t opad[64];
  } YOYO_HMAC_MD5;

void *Hmac_Md5_Clone(YOYO_HMAC_MD5 *hmac)
#ifdef _YOYO_MD5_BUILTIN
  {
    return __Clone(sizeof(YOYO_HMAC_MD5),hmac);
  }
#endif
  ;

void *Hmac_Md5_Start(YOYO_HMAC_MD5 *hmac, void *key, int key_len)
#ifdef _YOYO_MD5_BUILTIN
  {
    int i;
    byte_t sum[16];
    
    if ( key_len > 64 )
      {
        Md5_Start(&hmac->md5);







|

|

|


|

|
|

|




|
|







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
          md5->finished = 1;
        }
      if ( !digest ) digest = __Malloc(16);
      Md5_Internal_Encode(digest, md5->state, 16);
      return digest;
    }

#endif /* _YO_MD5_BUILTIN */

typedef struct _YO_HMAC_MD5
  {
    YO_MD5 md5;
    byte_t ipad[64];
    byte_t opad[64];
  } YO_HMAC_MD5;

void *Hmac_Md5_Clone(YO_HMAC_MD5 *hmac)
#ifdef _YO_MD5_BUILTIN
  {
    return __Clone(sizeof(YO_HMAC_MD5),hmac);
  }
#endif
  ;

void *Hmac_Md5_Start(YO_HMAC_MD5 *hmac, void *key, int key_len)
#ifdef _YO_MD5_BUILTIN
  {
    int i;
    byte_t sum[16];
    
    if ( key_len > 64 )
      {
        Md5_Start(&hmac->md5);
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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Md5_Update(YOYO_HMAC_MD5 *hmac, void *input, int input_length)
#ifdef _YOYO_MD5_BUILTIN
  {
    Md5_Update(&hmac->md5,input,input_length);
  }
#endif
  ;

void Hmac_Md5_Reset(YOYO_HMAC_MD5 *hmac)
#ifdef _YOYO_MD5_BUILTIN
  {
    Md5_Start(&hmac->md5);
    Md5_Update(&hmac->md5,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Md5_Finish(YOYO_HMAC_MD5 *hmac, void *digest)
#ifdef _YOYO_MD5_BUILTIN
  {
    byte_t tmpb[16];
    Md5_Finish(&hmac->md5,tmpb);
    Md5_Start(&hmac->md5);
    Md5_Update(&hmac->md5,&hmac->opad,64);
    Md5_Update(&hmac->md5,tmpb,16);
    memset(tmpb,0,16);
    return Md5_Finish(&hmac->md5,digest);
  }
#endif
  ;

void *Hmac_Md5_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YOYO_MD5_BUILTIN
  {
    YOYO_HMAC_MD5 hmac5;
    Hmac_Md5_Start(&hmac5,key,key_len);
    Md5_Update(&hmac5.md5,data,len);
    return Hmac_Md5_Finish(&hmac5,digest);
  }
#endif
  ;

void *Hmac_Md5_Init(void *key, int key_len)
#ifdef _YOYO_MD5_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Md5_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Md5_Update },
        {0}};
    
    YOYO_HMAC_MD5 *md5 = __Object(sizeof(YOYO_HMAC_MD5),funcs);
    return Hmac_Md5_Start(md5,key,key_len);
  }
#endif
  ;

#endif /* C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3 */








|
|






|
|







|
|













|

|








|

|





|







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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Md5_Update(YO_HMAC_MD5 *hmac, void *input, int input_length)
#ifdef _YO_MD5_BUILTIN
  {
    Md5_Update(&hmac->md5,input,input_length);
  }
#endif
  ;

void Hmac_Md5_Reset(YO_HMAC_MD5 *hmac)
#ifdef _YO_MD5_BUILTIN
  {
    Md5_Start(&hmac->md5);
    Md5_Update(&hmac->md5,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Md5_Finish(YO_HMAC_MD5 *hmac, void *digest)
#ifdef _YO_MD5_BUILTIN
  {
    byte_t tmpb[16];
    Md5_Finish(&hmac->md5,tmpb);
    Md5_Start(&hmac->md5);
    Md5_Update(&hmac->md5,&hmac->opad,64);
    Md5_Update(&hmac->md5,tmpb,16);
    memset(tmpb,0,16);
    return Md5_Finish(&hmac->md5,digest);
  }
#endif
  ;

void *Hmac_Md5_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YO_MD5_BUILTIN
  {
    YO_HMAC_MD5 hmac5;
    Hmac_Md5_Start(&hmac5,key,key_len);
    Md5_Update(&hmac5.md5,data,len);
    return Hmac_Md5_Finish(&hmac5,digest);
  }
#endif
  ;

void *Hmac_Md5_Init(void *key, int key_len)
#ifdef _YO_MD5_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Md5_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Md5_Update },
        {0}};
    
    YO_HMAC_MD5 *md5 = __Object(sizeof(YO_HMAC_MD5),funcs);
    return Hmac_Md5_Start(md5,key,key_len);
  }
#endif
  ;

#endif /* C_once_C5021104_5DB9_4FCC_BAFC_AFB22BD458D3 */

Changes to mime.hc.
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
#ifndef C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011
#define C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011

#include "yoyo.hc"
#include "string.hc"

#ifdef _LIBYOYO
#define _YOYO_MIME_BUILTIN
#endif

#ifdef _YOYO_MIME_BUILTIN
  #define _YOYO_MIME_BUILTIN_CODE(Code) Code
  #define _YOYO_MIME_EXTERN 
#else
  #define _YOYO_MIME_BUILTIN_CODE(Code)
  #define _YOYO_MIME_EXTERN extern
#endif

enum
  {
    YOYO_MIME_NONE  = __FOUR_CHARS('`','`','`','`'),
    YOYO_MIME_OCTS  = __FOUR_CHARS('O','C','T','S'),
    YOYO_MIME_JPEG  = __FOUR_CHARS('J','P','E','G'),
    YOYO_MIME_PNG   = __FOUR_CHARS('x','P','N','G'),
    YOYO_MIME_GIF   = __FOUR_CHARS('x','G','I','F'),
    YOYO_MIME_PICT  = __FOUR_CHARS('P','I','C','T'),
    YOYO_MIME_HTML  = __FOUR_CHARS('H','T','M','L'),
    YOYO_MIME_TEXT  = __FOUR_CHARS('T','E','X','T'),
    YOYO_MIME_GZIP  = __FOUR_CHARS('G','Z','I','P'),
    YOYO_MIME_PKZIP = __FOUR_CHARS('x','Z','I','P'),
    YOYO_MIME_7ZIP  = __FOUR_CHARS('7','Z','I','P'),
    YOYO_MIME_APP   = __FOUR_CHARS('x','A','P','P'),
    YOYO_MIME_JS    = __FOUR_CHARS('x','x','J','S'),
    YOYO_MIME_CSS   = __FOUR_CHARS('x','C','S','S'),
    YOYO_MIME_EXE   = __FOUR_CHARS('x','E','X','E'),
    YOYO_MIME_JSON  = __FOUR_CHARS('J','S','O','N'),
    YOYO_MIME_UNKNOWN = -1,
  };

typedef struct _YOYO_EXT_MAP_RECORD
  {
    char *ext;
    int   extlen;
    int   code;
  } YOYO_EXT_MAP_RECORD; 

_YOYO_MIME_EXTERN YOYO_EXT_MAP_RECORD Mime_Ext_Map[] 
#ifdef _YOYO_MIME_BUILTIN
  = { 
    {".html", 5, YOYO_MIME_HTML},
    {".htm",  4, YOYO_MIME_HTML},
    {".txt",  4, YOYO_MIME_TEXT},
    {".jpeg", 5, YOYO_MIME_JPEG},
    {".jpg",  4, YOYO_MIME_JPEG},
    {".png",  4, YOYO_MIME_PNG},
    {".gif",  4, YOYO_MIME_GIF},
    {".zip",  4, YOYO_MIME_PKZIP},
    {".7z",   3, YOYO_MIME_7ZIP},
    {".gz",   3, YOYO_MIME_GZIP},
    {".exe",  4, YOYO_MIME_APP},
    {".js",   3, YOYO_MIME_JS},
    {".css",  4, YOYO_MIME_CSS},
    {".json", 5, YOYO_MIME_JSON},
    {0,0}
  }
#endif
  ;

int Mime_Code_Of_Path(char *path, int dflt)
#ifdef _YOYO_MIME_BUILTIN
  {
    YOYO_EXT_MAP_RECORD *R = Mime_Ext_Map;
    int L = strlen(path);
    for ( ; R->ext; ++R )
      {
        if ( L >= R->extlen && !strncmp_I(path+L-R->extlen,R->ext,R->extlen) )
          return R->code;
      }
    return dflt;
  }
#endif
  ;
  
int Mime_Code_Of(char *mime_type)
#ifdef _YOYO_MIME_BUILTIN
  {
    int i;
    char _S[80] = {0};
    char *S = _S;
    for ( i = 0; mime_type[i] && i < sizeof(_S)-1; ++i ) _S[i] = Tolower(mime_type[i]);
    if ( !strncmp(S,"application/",12) )
      {
        S += 12;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"octet-stream") ) return YOYO_MIME_OCTS;
        if ( !strcmp(S,"javascript") )   return YOYO_MIME_JS;
        if ( !strcmp(S,"msdownload") )   return YOYO_MIME_EXE;
        if ( !strcmp(S,"json") )         return YOYO_MIME_JSON;
        if ( !strcmp(S,"gzip") )         return YOYO_MIME_GZIP;
        if ( !strcmp(S,"zip") )          return YOYO_MIME_PKZIP;
        if ( !strcmp(S,"7zip") )         return YOYO_MIME_7ZIP;
        return YOYO_MIME_APP;
      }
    else if ( !strncmp(S,"text/",5) )
      {
        S += 5;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"html") ) return YOYO_MIME_HTML;
        if ( !strcmp(S,"css") )   return YOYO_MIME_CSS;
        if ( !strcmp(S,"javascript") ) return YOYO_MIME_JS;
        if ( !strcmp(S,"json") ) return YOYO_MIME_JSON;
        else return YOYO_MIME_TEXT;
      }
    else if ( !strncmp(S,"image/",6) )
      {
        S += 6;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"jpeg") ) return YOYO_MIME_JPEG;
        if ( !strcmp(S,"png") )  return YOYO_MIME_PNG;
        if ( !strcmp(S,"gif") )  return YOYO_MIME_GIF;
        return YOYO_MIME_PICT;
      }
    return YOYO_MIME_NONE;
  }
#endif
  ;

int Mime_Is_Image(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_JPEG:  
        case YOYO_MIME_PNG:   
        case YOYO_MIME_GIF: 
        case YOYO_MIME_PICT: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Compressed(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_JPEG:  
        case YOYO_MIME_PNG:   
        case YOYO_MIME_GIF: 
        case YOYO_MIME_GZIP: 
        case YOYO_MIME_PKZIP: 
        case YOYO_MIME_7ZIP: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Text(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_HTML:
        case YOYO_MIME_TEXT:
        case YOYO_MIME_JS:
        case YOYO_MIME_CSS:
        case YOYO_MIME_JSON:
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Binary(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    return !Mime_Is_Text(mime);
  }
#endif
  ;
  
#define Mime_String_Of_Npl(Mime) Str_Copy_Npl(Mime_String_Of(Mime),-1)
char *Mime_String_Of(int mime)
#ifdef _YOYO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YOYO_MIME_OCTS: return "application/octet-stream";
        case YOYO_MIME_JPEG: return "image/jpeg";
        case YOYO_MIME_PNG:  return "image/png";
        case YOYO_MIME_GIF:  return "image/gif";
        case YOYO_MIME_PICT: return "image/octet-stream";
        case YOYO_MIME_HTML: return "text/html";
        case YOYO_MIME_TEXT: return "text/plain";
        case YOYO_MIME_GZIP: return "application/x-gzip";
        case YOYO_MIME_PKZIP:return "application/zip";
        case YOYO_MIME_7ZIP: return "application/x-7zip";
        case YOYO_MIME_APP:  return "application/octet-stream";
        case YOYO_MIME_CSS:  return "text/css";
        case YOYO_MIME_JS:   return "text/javascript";
        case YOYO_MIME_EXE:  return "application/x-msdownload";
        case YOYO_MIME_JSON: return "application/json";
      }
    return "application/octet-stream";
  }
#endif
  ;

_YOYO_MIME_EXTERN char Oj_Mimetype_Of_OjMID[] _YOYO_MIME_BUILTIN_CODE( = "mimetype_of/@"); 
int Oj_Mimetype_Of(void *o) _YOYO_MIME_BUILTIN_CODE(
  { return ((int(*)(void*,void*))Yo_Find_Method_Of(&o,Oj_Mimetype_Of_OjMID,YO_RAISE_ERROR))
        (o); });
  
#endif /* C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011 */








|


|
|
|

|
|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|




|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|






|

|












|









|
|
|
|
|
|
|
|





|
|
|
|
|





|
|
|
|

|





|



|
|
|
|








|



|
|
|
|
|
|








|



|
|
|
|
|








|








|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|






|
|
|




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
#ifndef C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011
#define C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011

#include "yoyo.hc"
#include "string.hc"

#ifdef _LIBYOYO
#define _YO_MIME_BUILTIN
#endif

#ifdef _YO_MIME_BUILTIN
  #define _YO_MIME_BUILTIN_CODE(Code) Code
  #define _YO_MIME_EXTERN 
#else
  #define _YO_MIME_BUILTIN_CODE(Code)
  #define _YO_MIME_EXTERN extern
#endif

enum
  {
    YO_MIME_NONE  = __FOUR_CHARS('`','`','`','`'),
    YO_MIME_OCTS  = __FOUR_CHARS('O','C','T','S'),
    YO_MIME_JPEG  = __FOUR_CHARS('J','P','E','G'),
    YO_MIME_PNG   = __FOUR_CHARS('x','P','N','G'),
    YO_MIME_GIF   = __FOUR_CHARS('x','G','I','F'),
    YO_MIME_PICT  = __FOUR_CHARS('P','I','C','T'),
    YO_MIME_HTML  = __FOUR_CHARS('H','T','M','L'),
    YO_MIME_TEXT  = __FOUR_CHARS('T','E','X','T'),
    YO_MIME_GZIP  = __FOUR_CHARS('G','Z','I','P'),
    YO_MIME_PKZIP = __FOUR_CHARS('x','Z','I','P'),
    YO_MIME_7ZIP  = __FOUR_CHARS('7','Z','I','P'),
    YO_MIME_APP   = __FOUR_CHARS('x','A','P','P'),
    YO_MIME_JS    = __FOUR_CHARS('x','x','J','S'),
    YO_MIME_CSS   = __FOUR_CHARS('x','C','S','S'),
    YO_MIME_EXE   = __FOUR_CHARS('x','E','X','E'),
    YO_MIME_JSON  = __FOUR_CHARS('J','S','O','N'),
    YO_MIME_UNKNOWN = -1,
  };

typedef struct _YO_EXT_MAP_RECORD
  {
    char *ext;
    int   extlen;
    int   code;
  } YO_EXT_MAP_RECORD; 

_YO_MIME_EXTERN YO_EXT_MAP_RECORD Mime_Ext_Map[] 
#ifdef _YO_MIME_BUILTIN
  = { 
    {".html", 5, YO_MIME_HTML},
    {".htm",  4, YO_MIME_HTML},
    {".txt",  4, YO_MIME_TEXT},
    {".jpeg", 5, YO_MIME_JPEG},
    {".jpg",  4, YO_MIME_JPEG},
    {".png",  4, YO_MIME_PNG},
    {".gif",  4, YO_MIME_GIF},
    {".zip",  4, YO_MIME_PKZIP},
    {".7z",   3, YO_MIME_7ZIP},
    {".gz",   3, YO_MIME_GZIP},
    {".exe",  4, YO_MIME_APP},
    {".js",   3, YO_MIME_JS},
    {".css",  4, YO_MIME_CSS},
    {".json", 5, YO_MIME_JSON},
    {0,0}
  }
#endif
  ;

int Mime_Code_Of_Path(char *path, int dflt)
#ifdef _YO_MIME_BUILTIN
  {
    YO_EXT_MAP_RECORD *R = Mime_Ext_Map;
    int L = strlen(path);
    for ( ; R->ext; ++R )
      {
        if ( L >= R->extlen && !strncmp_I(path+L-R->extlen,R->ext,R->extlen) )
          return R->code;
      }
    return dflt;
  }
#endif
  ;
  
int Mime_Code_Of(char *mime_type)
#ifdef _YO_MIME_BUILTIN
  {
    int i;
    char _S[80] = {0};
    char *S = _S;
    for ( i = 0; mime_type[i] && i < sizeof(_S)-1; ++i ) _S[i] = Tolower(mime_type[i]);
    if ( !strncmp(S,"application/",12) )
      {
        S += 12;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"octet-stream") ) return YO_MIME_OCTS;
        if ( !strcmp(S,"javascript") )   return YO_MIME_JS;
        if ( !strcmp(S,"msdownload") )   return YO_MIME_EXE;
        if ( !strcmp(S,"json") )         return YO_MIME_JSON;
        if ( !strcmp(S,"gzip") )         return YO_MIME_GZIP;
        if ( !strcmp(S,"zip") )          return YO_MIME_PKZIP;
        if ( !strcmp(S,"7zip") )         return YO_MIME_7ZIP;
        return YO_MIME_APP;
      }
    else if ( !strncmp(S,"text/",5) )
      {
        S += 5;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"html") ) return YO_MIME_HTML;
        if ( !strcmp(S,"css") )   return YO_MIME_CSS;
        if ( !strcmp(S,"javascript") ) return YO_MIME_JS;
        if ( !strcmp(S,"json") ) return YO_MIME_JSON;
        else return YO_MIME_TEXT;
      }
    else if ( !strncmp(S,"image/",6) )
      {
        S += 6;
        if ( !strncmp(S,"x-",2) ) S +=2;
        if ( !strcmp(S,"jpeg") ) return YO_MIME_JPEG;
        if ( !strcmp(S,"png") )  return YO_MIME_PNG;
        if ( !strcmp(S,"gif") )  return YO_MIME_GIF;
        return YO_MIME_PICT;
      }
    return YO_MIME_NONE;
  }
#endif
  ;

int Mime_Is_Image(int mime)
#ifdef _YO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YO_MIME_JPEG:  
        case YO_MIME_PNG:   
        case YO_MIME_GIF: 
        case YO_MIME_PICT: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Compressed(int mime)
#ifdef _YO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YO_MIME_JPEG:  
        case YO_MIME_PNG:   
        case YO_MIME_GIF: 
        case YO_MIME_GZIP: 
        case YO_MIME_PKZIP: 
        case YO_MIME_7ZIP: 
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Text(int mime)
#ifdef _YO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YO_MIME_HTML:
        case YO_MIME_TEXT:
        case YO_MIME_JS:
        case YO_MIME_CSS:
        case YO_MIME_JSON:
          return 1;
      }
    return 0;
  }
#endif
  ;
  
int Mime_Is_Binary(int mime)
#ifdef _YO_MIME_BUILTIN
  {
    return !Mime_Is_Text(mime);
  }
#endif
  ;
  
#define Mime_String_Of_Npl(Mime) Str_Copy_Npl(Mime_String_Of(Mime),-1)
char *Mime_String_Of(int mime)
#ifdef _YO_MIME_BUILTIN
  {
    switch(mime)
      {
        case YO_MIME_OCTS: return "application/octet-stream";
        case YO_MIME_JPEG: return "image/jpeg";
        case YO_MIME_PNG:  return "image/png";
        case YO_MIME_GIF:  return "image/gif";
        case YO_MIME_PICT: return "image/octet-stream";
        case YO_MIME_HTML: return "text/html";
        case YO_MIME_TEXT: return "text/plain";
        case YO_MIME_GZIP: return "application/x-gzip";
        case YO_MIME_PKZIP:return "application/zip";
        case YO_MIME_7ZIP: return "application/x-7zip";
        case YO_MIME_APP:  return "application/octet-stream";
        case YO_MIME_CSS:  return "text/css";
        case YO_MIME_JS:   return "text/javascript";
        case YO_MIME_EXE:  return "application/x-msdownload";
        case YO_MIME_JSON: return "application/json";
      }
    return "application/octet-stream";
  }
#endif
  ;

_YO_MIME_EXTERN char Oj_Mimetype_Of_OjMID[] _YO_MIME_BUILTIN_CODE( = "mimetype_of/@"); 
int Oj_Mimetype_Of(void *o) _YO_MIME_BUILTIN_CODE(
  { return ((int(*)(void*))Yo_Find_Method_Of(&o,Oj_Mimetype_Of_OjMID,YO_RAISE_ERROR))
        (o); });
  
#endif /* C_once_E5DC0CBD_6EF6_4E8C_A4F5_CF78FA971011 */

Changes to newdes96.hc.
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

*/

#ifndef C_once_144D66DB_5194_4393_9B79_FCE53D00D162
#define C_once_144D66DB_5194_4393_9B79_FCE53D00D162

#ifdef _LIBYOYO
#define _YOYO_NEWDES96_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"

#ifdef _YOYO_NEWDES96_BUILTIN
static byte_t NEWDES96_SBOX[256] = {
    32, 137, 239, 188, 102, 125, 221, 72, 212, 68, 81, 37, 86, 237, 147, 149,
    70, 229, 17, 124, 115, 207, 33, 20, 122, 143, 25, 215, 51, 183, 138, 142,
    146, 211, 110, 173, 1, 228, 189, 14, 103, 78, 162, 36, 253, 167, 116, 255,
    158, 45, 185, 50, 98, 168, 250, 235, 54, 141, 195, 247, 240, 63, 148, 2,
    224, 169, 214, 180, 62, 22, 117, 108, 19, 172, 161, 159, 160, 47, 43, 171,
    194, 175, 178, 56, 196, 112, 23, 220, 89, 21, 164, 130, 157, 8, 85, 251,
    216, 44, 94, 179, 226, 38, 90, 119, 40, 202, 34, 206, 35, 69, 231, 246,
    29, 109, 74, 71, 176, 6, 60, 145, 65, 13, 77, 151, 12, 127, 95, 199,
    57, 101, 5, 232, 150, 210, 129, 24, 181, 10, 121, 187, 48, 193, 139, 252,
    219, 64, 88, 233, 96, 128, 80, 53, 191, 144, 218, 11, 106, 132, 155, 104,
    91, 136, 31, 42, 243, 66, 126, 135, 30, 26, 87, 186, 182, 154, 242, 123,
    82, 166, 208, 39, 152, 190, 113, 205, 114, 105, 225, 84, 73, 163, 99, 111,
    204, 61, 200, 217, 170, 15, 198, 28, 192, 254, 134, 234, 222, 7, 236, 248,
    201, 41, 177, 156, 92, 131, 67, 249, 245, 184, 203, 9, 241, 0, 27, 46,
    133, 174, 75, 18, 93, 209, 100, 120, 76, 213, 16, 83, 4, 107, 140, 52,
    58, 55, 3, 244, 97, 197, 238, 227, 118, 49, 79, 230, 223, 165, 153, 59
  };
#endif

typedef struct _YOYO_NEWDES96
  {
    byte_t key[15];
  } YOYO_NEWDES96;

void NEWDES96_Destruct(YOYO_NEWDES96 *self)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    Yo_Object_Destruct(self);
  }
#endif
  ;

void NEWDES96_Encrypt8(YOYO_NEWDES96 *self, void *d)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    byte_t *data = d;
    byte_t *key = self->key;
    byte_t *f = NEWDES96_SBOX;
 
    byte_t B0 = data[0], B1 = data[1], B2 = data[2], B3 = data[3], 
           B4 = data[4], B5 = data[5], B6 = data[6], B7 = data[7];







|






|




















|


|

|
|






|
|







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

*/

#ifndef C_once_144D66DB_5194_4393_9B79_FCE53D00D162
#define C_once_144D66DB_5194_4393_9B79_FCE53D00D162

#ifdef _LIBYOYO
#define _YO_NEWDES96_BUILTIN
#endif

#include "yoyo.hc"
#include "cipher.hc"
#include "md5.hc"

#ifdef _YO_NEWDES96_BUILTIN
static byte_t NEWDES96_SBOX[256] = {
    32, 137, 239, 188, 102, 125, 221, 72, 212, 68, 81, 37, 86, 237, 147, 149,
    70, 229, 17, 124, 115, 207, 33, 20, 122, 143, 25, 215, 51, 183, 138, 142,
    146, 211, 110, 173, 1, 228, 189, 14, 103, 78, 162, 36, 253, 167, 116, 255,
    158, 45, 185, 50, 98, 168, 250, 235, 54, 141, 195, 247, 240, 63, 148, 2,
    224, 169, 214, 180, 62, 22, 117, 108, 19, 172, 161, 159, 160, 47, 43, 171,
    194, 175, 178, 56, 196, 112, 23, 220, 89, 21, 164, 130, 157, 8, 85, 251,
    216, 44, 94, 179, 226, 38, 90, 119, 40, 202, 34, 206, 35, 69, 231, 246,
    29, 109, 74, 71, 176, 6, 60, 145, 65, 13, 77, 151, 12, 127, 95, 199,
    57, 101, 5, 232, 150, 210, 129, 24, 181, 10, 121, 187, 48, 193, 139, 252,
    219, 64, 88, 233, 96, 128, 80, 53, 191, 144, 218, 11, 106, 132, 155, 104,
    91, 136, 31, 42, 243, 66, 126, 135, 30, 26, 87, 186, 182, 154, 242, 123,
    82, 166, 208, 39, 152, 190, 113, 205, 114, 105, 225, 84, 73, 163, 99, 111,
    204, 61, 200, 217, 170, 15, 198, 28, 192, 254, 134, 234, 222, 7, 236, 248,
    201, 41, 177, 156, 92, 131, 67, 249, 245, 184, 203, 9, 241, 0, 27, 46,
    133, 174, 75, 18, 93, 209, 100, 120, 76, 213, 16, 83, 4, 107, 140, 52,
    58, 55, 3, 244, 97, 197, 238, 227, 118, 49, 79, 230, 223, 165, 153, 59
  };
#endif

typedef struct _YO_NEWDES96
  {
    byte_t key[15];
  } YO_NEWDES96;

void NEWDES96_Destruct(YO_NEWDES96 *self)
#ifdef _YO_NEWDES96_BUILTIN
  {
    Yo_Object_Destruct(self);
  }
#endif
  ;

void NEWDES96_Encrypt8(YO_NEWDES96 *self, void *d)
#ifdef _YO_NEWDES96_BUILTIN
  {
    byte_t *data = d;
    byte_t *key = self->key;
    byte_t *f = NEWDES96_SBOX;
 
    byte_t B0 = data[0], B1 = data[1], B2 = data[2], B3 = data[3], 
           B4 = data[4], B5 = data[5], B6 = data[6], B7 = data[7];
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    data[5] = B5;
    data[6] = B6;
    data[7] = B7;
  }
#endif
  ;
  
void NEWDES96_Decrypt8(YOYO_NEWDES96 *self, void *d)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    byte_t *data = d;
    byte_t *key = self->key;
    byte_t *f = NEWDES96_SBOX;

    byte_t B0 = data[0], B1 = data[1], B2 = data[2], B3 = data[3], 
           B4 = data[4], B5 = data[5], B6 = data[6], B7 = data[7];







|
|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    data[5] = B5;
    data[6] = B6;
    data[7] = B7;
  }
#endif
  ;
  
void NEWDES96_Decrypt8(YO_NEWDES96 *self, void *d)
#ifdef _YO_NEWDES96_BUILTIN
  {
    byte_t *data = d;
    byte_t *key = self->key;
    byte_t *f = NEWDES96_SBOX;

    byte_t B0 = data[0], B1 = data[1], B2 = data[2], B3 = data[3], 
           B4 = data[4], B5 = data[5], B6 = data[6], B7 = data[7];
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
    data[5] = B5;
    data[6] = B6;
    data[7] = B7;
  }
#endif
  ;

YOYO_NEWDES96 *NEWDES96_Init_Static(YOYO_NEWDES96 *self, void *key, int key_len)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    memcpy(self->key,key,Yo_MIN(key_len,sizeof(self->key)));
    return self;
  }
#endif
  ;

void *NEWDES96_Init(void *key, int key_len)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, NEWDES96_Destruct},
        {Oj_Encrypt8_OjMID, NEWDES96_Encrypt8},
        {Oj_Decrypt8_OjMID, NEWDES96_Decrypt8},
        {0}};
    YOYO_NEWDES96 *self = Yo_Object(sizeof(YOYO_NEWDES96),funcs);
    return NEWDES96_Init_Static(self, key, key_len);
  }
#endif
  ;
void *NEWDES96_Object_Init_With_Text_Key(char *Skey)
#ifdef _YOYO_NEWDES96_BUILTIN
  {
    byte_t key[16] = {0};
    Md5_Digest(Skey,strlen(Skey),key);
    return NEWDES96_Init(key+1,15);
  }
#endif
  ;

#define NEWDES96_Decipher(Skey) NEWDES96_Object_Init_With_Text_Key(Skey)
#define NEWDES96_Encipher(Skey) NEWDES96_Object_Init_With_Text_Key(Skey)

#endif /* C_once_144D66DB_5194_4393_9B79_FCE53D00D162 */








|
|








|

|





|





|













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
    data[5] = B5;
    data[6] = B6;
    data[7] = B7;
  }
#endif
  ;

YO_NEWDES96 *NEWDES96_Init_Static(YO_NEWDES96 *self, void *key, int key_len)
#ifdef _YO_NEWDES96_BUILTIN
  {
    memcpy(self->key,key,Yo_MIN(key_len,sizeof(self->key)));
    return self;
  }
#endif
  ;

void *NEWDES96_Init(void *key, int key_len)
#ifdef _YO_NEWDES96_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID, NEWDES96_Destruct},
        {Oj_Encrypt8_OjMID, NEWDES96_Encrypt8},
        {Oj_Decrypt8_OjMID, NEWDES96_Decrypt8},
        {0}};
    YO_NEWDES96 *self = Yo_Object(sizeof(YO_NEWDES96),funcs);
    return NEWDES96_Init_Static(self, key, key_len);
  }
#endif
  ;
void *NEWDES96_Object_Init_With_Text_Key(char *Skey)
#ifdef _YO_NEWDES96_BUILTIN
  {
    byte_t key[16] = {0};
    Md5_Digest(Skey,strlen(Skey),key);
    return NEWDES96_Init(key+1,15);
  }
#endif
  ;

#define NEWDES96_Decipher(Skey) NEWDES96_Object_Init_With_Text_Key(Skey)
#define NEWDES96_Encipher(Skey) NEWDES96_Object_Init_With_Text_Key(Skey)

#endif /* C_once_144D66DB_5194_4393_9B79_FCE53D00D162 */

Changes to pefile.hc.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

*/

#ifndef C_once_EA617668_2E48_4AC6_9079_699B387A0662
#define C_once_EA617668_2E48_4AC6_9079_699B387A0662

#ifdef _LIBYOYO
#define _YOYO_PEFILE_BUILTIN
#endif

#include "yoyo.hc"
#include "file.hc"

// The Machine field has one of the following values that specifies its CPU type. 
// An image file can be run only on the specified machine or on a system that emulates the specified machine.







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

*/

#ifndef C_once_EA617668_2E48_4AC6_9079_699B387A0662
#define C_once_EA617668_2E48_4AC6_9079_699B387A0662

#ifdef _LIBYOYO
#define _YO_PEFILE_BUILTIN
#endif

#include "yoyo.hc"
#include "file.hc"

// The Machine field has one of the following values that specifies its CPU type. 
// An image file can be run only on the specified machine or on a system that emulates the specified machine.
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
#define Pe_GET_SEC_64(Pe) \
  ((PE_SECTION_HEADER*)((char*)(Pe) + ((PE_DOS_HEADER*)(Pe))->e_lfanew + 4 + sizeof(PE_FILE_HEADER) + Pe_GET_NTH_64(Pe)->FileHeader.SizeOfOptionalHeader ))

#define Is_PE_32(Pe) (Pe_GET_NTH_32(Pe)->OptionalHeader.Magic == PE_OPT32_MAGIC)
#define Is_PE_64(Pe) (Pe_GET_NTH_64(Pe)->OptionalHeader.Magic == PE_OPT64_MAGIC)

int Pe_Headers_Is_Valid(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return 1;
  }
#endif
  ;

void Pe_Validate_Headers(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( !Pe_Headers_Is_Valid(pe) )
      __Raise(YOYO_ERROR_CORRUPTED,"there is not PE headers");
  }
#endif
  ;

PE_HEADERS_32 *Pe_Get_Nth_32(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return ((PE_HEADERS_32*)((char*)pe + ((PE_DOS_HEADER*)pe)->e_lfanew));
  }
#endif
  ;

PE_HEADERS_64 *Pe_Get_Nth_64(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return ((PE_HEADERS_64*)((char*)pe + ((PE_DOS_HEADER*)pe)->e_lfanew));
  }
#endif
  ;

PE_FILE_HEADER *Pe_Get_File_Header(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return &Pe_GET_NTH_32(pe)->FileHeader;
    else
      return &Pe_GET_NTH_64(pe)->FileHeader;
  }
#endif
  ;

#define Pe_Section_Number(Pe) (Pe_File_Header(Pe)->NumberOfSections)

PE_SECTION_HEADER *Pe_Get_First_Section(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_SEC_32(pe);
    else
      return Pe_GET_SEC_64(pe);
  }
#endif
  ;

PE_SECTION_HEADER *Pe_Find_Section(void *pe,char *name)
#ifdef _YOYO_PEFILE_BUILTIN
 {
    PE_SECTION_HEADER *sec = Pe_Get_First_Section(pe);
    PE_SECTION_HEADER *seE = sec + Pe_Get_File_Header(pe)->NumberOfSections;
    for ( ; sec != seE; ++sec )
      {
        if ( !strncmp(sec->Name,name,8) )
          return sec;
      }
    return 0;
  }
#endif
  ;

quad_t Pe_Get_ImageBase(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.ImageBase;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.ImageBase;
  }
#endif
  ;

quad_t Pe_Get_SizeOfImage(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.SizeOfImage;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.SizeOfImage;
  }
#endif
  ;
  
PE_DATA_DIRECTORY *Pe_Get_Dir(void *pe, int idx)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    REQUIRE(idx < 16 && idx >= 0 );
    if ( Is_PE_32(pe) )
      return &Pe_GET_NTH_32(pe)->OptionalHeader.DataDirectory[idx];
    else
      return &Pe_GET_NTH_64(pe)->OptionalHeader.DataDirectory[idx];
  }
#endif
  ;

longptr_t Pe_Get_File_Alignment(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.FileAlignment;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.FileAlignment;
  }
#endif
  ;

longptr_t Pe_Get_Section_Alignment(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.SectionAlignment;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.SectionAlignment;
  }
#endif
  ;

#define Pe_ALIGN_TO_q(Val,Mod)  ((Val)+(Mod)-1)&~((Mod)-1)
#define Pe_ALIGN_TO_FILE(Val,Nth)  Pe_ALIGN_TO_q((Val),(Nth)->OptionalHeader.FileAlignment)
#define Pe_ALIGN_TO_SECTION(Val,Nth) Pe_ALIGN_TO_q((Val),(Nth)->OptionalHeader.SectionAlignment)
#define Pe_SECION_SIZE(Sec,Nth) Yo_Max( Pe_ALIGN_TO_FILE(Sec->SizeOfRawData,Nth), Pe_ALIGN_TO_SECTION(Sec->Misc.VirtualSize,Nth))

longptr_t Pe_Align_To_File(void *pe,longptr_t val)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return Pe_ALIGN_TO_q(val,Pe_Get_File_Alignment(pe));
  }
#endif
  ;

longptr_t Pe_Align_To_Section(void *pe,longptr_t val)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return Pe_ALIGN_TO_q(val,Pe_Get_Section_Alignment(pe));
  }
#endif
  ;

longptr_t Pe_Section_Size(void *pe, PE_SECTION_HEADER *sec)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    longptr_t FileAlignment = Pe_Get_File_Alignment(pe);
    longptr_t SectionAlignment = Pe_Get_Section_Alignment(pe);
    return Yo_MAX( Pe_ALIGN_TO_q(sec->SizeOfRawData,FileAlignment), 
                   Pe_ALIGN_TO_q(sec->Misc.VirtualSize,SectionAlignment));
  }
#endif
  ;

PE_SECTION_HEADER *Pe_RVA_To_Section(void *pe, longptr_t rva)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( rva )
      {
        PE_SECTION_HEADER *sec = Pe_Get_First_Section(pe);
        PE_SECTION_HEADER *seE = sec + Pe_Get_File_Header(pe)->NumberOfSections;
    
        for ( ; sec != seE; ++sec )
          {
            if ( rva >= sec->VirtualAddress 
              && rva < sec->VirtualAddress+Pe_Section_Size(pe,sec) )
              return sec;
          }
      }
      
    return 0;
  }
#endif
  ;

longptr_t Pe_RVA_To_Offs(void *pe, longptr_t rva)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    if ( rva )
      {
        PE_SECTION_HEADER *sec = Pe_RVA_To_Section(pe,rva);
        if ( sec )
          {
            longptr_t offs = rva - sec->VirtualAddress;
            longptr_t datasize = Pe_Align_To_File(pe,sec->SizeOfRawData);
            if ( offs <= datasize )
              return sec->PointerToRawData + offs;
          }
      }
      
    return 0;
  }
#endif
  ;

void *Pe_RVA_To_Ptr(void *pe, longptr_t rva)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    longptr_t offs = Pe_RVA_To_Offs(pe,rva);
    return offs ? (byte_t*)pe+offs : 0;
  }
#endif
  ;

void *Pe_Get_Dir_Ptr(void *pe, int idx)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return Pe_RVA_To_Ptr(pe,Pe_Get_Dir(pe,idx)->VirtualAddress);
  }
#endif
  ;

longptr_t Pe_Export_Bsearch(void *pe,PE_EXPORT_DIRECTORY *dir,char *name)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    uint_t   *AddressOfNames        = Pe_RVA_To_Ptr(pe,dir->AddressOfNames);
    ushort_t *AddressOfNameOrdinals = Pe_RVA_To_Ptr(pe,dir->AddressOfNameOrdinals);
    uint_t   *AddressOfFunctions    = Pe_RVA_To_Ptr(pe,dir->AddressOfFunctions);
  
    int L = 0;
    int R = dir->NumberOfNames-1;







|







|


|





|







|







|












|










|














|










|










|











|










|















|







|







|










|




















|



















|








|







|







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
#define Pe_GET_SEC_64(Pe) \
  ((PE_SECTION_HEADER*)((char*)(Pe) + ((PE_DOS_HEADER*)(Pe))->e_lfanew + 4 + sizeof(PE_FILE_HEADER) + Pe_GET_NTH_64(Pe)->FileHeader.SizeOfOptionalHeader ))

#define Is_PE_32(Pe) (Pe_GET_NTH_32(Pe)->OptionalHeader.Magic == PE_OPT32_MAGIC)
#define Is_PE_64(Pe) (Pe_GET_NTH_64(Pe)->OptionalHeader.Magic == PE_OPT64_MAGIC)

int Pe_Headers_Is_Valid(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    return 1;
  }
#endif
  ;

void Pe_Validate_Headers(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( !Pe_Headers_Is_Valid(pe) )
      __Raise(YO_ERROR_CORRUPTED,"there is not PE headers");
  }
#endif
  ;

PE_HEADERS_32 *Pe_Get_Nth_32(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    return ((PE_HEADERS_32*)((char*)pe + ((PE_DOS_HEADER*)pe)->e_lfanew));
  }
#endif
  ;

PE_HEADERS_64 *Pe_Get_Nth_64(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    return ((PE_HEADERS_64*)((char*)pe + ((PE_DOS_HEADER*)pe)->e_lfanew));
  }
#endif
  ;

PE_FILE_HEADER *Pe_Get_File_Header(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return &Pe_GET_NTH_32(pe)->FileHeader;
    else
      return &Pe_GET_NTH_64(pe)->FileHeader;
  }
#endif
  ;

#define Pe_Section_Number(Pe) (Pe_File_Header(Pe)->NumberOfSections)

PE_SECTION_HEADER *Pe_Get_First_Section(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_SEC_32(pe);
    else
      return Pe_GET_SEC_64(pe);
  }
#endif
  ;

PE_SECTION_HEADER *Pe_Find_Section(void *pe,char *name)
#ifdef _YO_PEFILE_BUILTIN
 {
    PE_SECTION_HEADER *sec = Pe_Get_First_Section(pe);
    PE_SECTION_HEADER *seE = sec + Pe_Get_File_Header(pe)->NumberOfSections;
    for ( ; sec != seE; ++sec )
      {
        if ( !strncmp(sec->Name,name,8) )
          return sec;
      }
    return 0;
  }
#endif
  ;

quad_t Pe_Get_ImageBase(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.ImageBase;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.ImageBase;
  }
#endif
  ;

quad_t Pe_Get_SizeOfImage(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.SizeOfImage;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.SizeOfImage;
  }
#endif
  ;
  
PE_DATA_DIRECTORY *Pe_Get_Dir(void *pe, int idx)
#ifdef _YO_PEFILE_BUILTIN
  {
    REQUIRE(idx < 16 && idx >= 0 );
    if ( Is_PE_32(pe) )
      return &Pe_GET_NTH_32(pe)->OptionalHeader.DataDirectory[idx];
    else
      return &Pe_GET_NTH_64(pe)->OptionalHeader.DataDirectory[idx];
  }
#endif
  ;

longptr_t Pe_Get_File_Alignment(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.FileAlignment;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.FileAlignment;
  }
#endif
  ;

longptr_t Pe_Get_Section_Alignment(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( Is_PE_32(pe) )
      return Pe_GET_NTH_32(pe)->OptionalHeader.SectionAlignment;
    else
      return Pe_GET_NTH_64(pe)->OptionalHeader.SectionAlignment;
  }
#endif
  ;

#define Pe_ALIGN_TO_q(Val,Mod)  ((Val)+(Mod)-1)&~((Mod)-1)
#define Pe_ALIGN_TO_FILE(Val,Nth)  Pe_ALIGN_TO_q((Val),(Nth)->OptionalHeader.FileAlignment)
#define Pe_ALIGN_TO_SECTION(Val,Nth) Pe_ALIGN_TO_q((Val),(Nth)->OptionalHeader.SectionAlignment)
#define Pe_SECION_SIZE(Sec,Nth) Yo_Max( Pe_ALIGN_TO_FILE(Sec->SizeOfRawData,Nth), Pe_ALIGN_TO_SECTION(Sec->Misc.VirtualSize,Nth))

longptr_t Pe_Align_To_File(void *pe,longptr_t val)
#ifdef _YO_PEFILE_BUILTIN
  {
    return Pe_ALIGN_TO_q(val,Pe_Get_File_Alignment(pe));
  }
#endif
  ;

longptr_t Pe_Align_To_Section(void *pe,longptr_t val)
#ifdef _YO_PEFILE_BUILTIN
  {
    return Pe_ALIGN_TO_q(val,Pe_Get_Section_Alignment(pe));
  }
#endif
  ;

longptr_t Pe_Section_Size(void *pe, PE_SECTION_HEADER *sec)
#ifdef _YO_PEFILE_BUILTIN
  {
    longptr_t FileAlignment = Pe_Get_File_Alignment(pe);
    longptr_t SectionAlignment = Pe_Get_Section_Alignment(pe);
    return Yo_MAX( Pe_ALIGN_TO_q(sec->SizeOfRawData,FileAlignment), 
                   Pe_ALIGN_TO_q(sec->Misc.VirtualSize,SectionAlignment));
  }
#endif
  ;

PE_SECTION_HEADER *Pe_RVA_To_Section(void *pe, longptr_t rva)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( rva )
      {
        PE_SECTION_HEADER *sec = Pe_Get_First_Section(pe);
        PE_SECTION_HEADER *seE = sec + Pe_Get_File_Header(pe)->NumberOfSections;
    
        for ( ; sec != seE; ++sec )
          {
            if ( rva >= sec->VirtualAddress 
              && rva < sec->VirtualAddress+Pe_Section_Size(pe,sec) )
              return sec;
          }
      }
      
    return 0;
  }
#endif
  ;

longptr_t Pe_RVA_To_Offs(void *pe, longptr_t rva)
#ifdef _YO_PEFILE_BUILTIN
  {
    if ( rva )
      {
        PE_SECTION_HEADER *sec = Pe_RVA_To_Section(pe,rva);
        if ( sec )
          {
            longptr_t offs = rva - sec->VirtualAddress;
            longptr_t datasize = Pe_Align_To_File(pe,sec->SizeOfRawData);
            if ( offs <= datasize )
              return sec->PointerToRawData + offs;
          }
      }
      
    return 0;
  }
#endif
  ;

void *Pe_RVA_To_Ptr(void *pe, longptr_t rva)
#ifdef _YO_PEFILE_BUILTIN
  {
    longptr_t offs = Pe_RVA_To_Offs(pe,rva);
    return offs ? (byte_t*)pe+offs : 0;
  }
#endif
  ;

void *Pe_Get_Dir_Ptr(void *pe, int idx)
#ifdef _YO_PEFILE_BUILTIN
  {
    return Pe_RVA_To_Ptr(pe,Pe_Get_Dir(pe,idx)->VirtualAddress);
  }
#endif
  ;

longptr_t Pe_Export_Bsearch(void *pe,PE_EXPORT_DIRECTORY *dir,char *name)
#ifdef _YO_PEFILE_BUILTIN
  {
    uint_t   *AddressOfNames        = Pe_RVA_To_Ptr(pe,dir->AddressOfNames);
    ushort_t *AddressOfNameOrdinals = Pe_RVA_To_Ptr(pe,dir->AddressOfNameOrdinals);
    uint_t   *AddressOfFunctions    = Pe_RVA_To_Ptr(pe,dir->AddressOfFunctions);
  
    int L = 0;
    int R = dir->NumberOfNames-1;
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
    return 0;
  }
#endif
  ;

#define Pe_Get_Proc_Ptr(Pe,Name) Pe_RVA_To_Ptr(Pe_Get_Proc_RVA(Pe,Name))
longptr_t Pe_Get_Proc_RVA(void *pe, char *procname)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_DATA_DIRECTORY expo = *Pe_Get_Dir(pe,PE_DIRECTORY_ENTRY_EXPORT);
    if ( expo.Size )
      {
        PE_EXPORT_DIRECTORY *edir = Pe_RVA_To_Ptr(pe,expo.VirtualAddress);
        if ( (longptr_t)procname >> 16 )
          return Pe_Export_Bsearch(pe,edir,procname);
        else
          return ((uint_t*)Pe_RVA_To_Ptr(pe,edir->AddressOfFunctions))
                  [(longptr_t)procname - edir->Base];
      }
    
    return 0;
  }
#endif
  ;

void Pe_Fixup_Rsrc_Req(byte_t *rsrc, longptr_t rva, PE_RESOURCE_DIRECTORY *dir)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_RESOURCE_DIRECTORY_ENTRY *r = (PE_RESOURCE_DIRECTORY_ENTRY *)((byte_t*)dir + sizeof(*dir));
    PE_RESOURCE_DIRECTORY_ENTRY *rE = r+dir->NumberOfIdEntries+dir->NumberOfNamedEntries;
    for ( ; r != rE; ++r )
      if ( r->DataIsDirectory )
        Pe_Fixup_Rsrc_Req(rsrc,rva,(PE_RESOURCE_DIRECTORY *)(rsrc+r->OffsetToDirectory));
      else
        {
          PE_RESOURCE_DATA_ENTRY *e = (PE_RESOURCE_DATA_ENTRY *)(rsrc+r->OffsetToData);
          e->OffsetToData += rva;
        }
  }
#endif
  ;

void Pe_Fixup_Rsrc(void *rsrc, longptr_t rva)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    Pe_Fixup_Rsrc_Req(rsrc,rva,(PE_RESOURCE_DIRECTORY *)rsrc);
  }
#endif
  ;
  
YOYO_BUFFER *Pe_Copy_Rsrc(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_SECTION_HEADER *S = Pe_RVA_To_Section(pe,Pe_Get_Dir(pe,PE_DIRECTORY_ENTRY_RESOURCE)->VirtualAddress);
    YOYO_BUFFER *bf = 0;
    
    if ( S )
      {
        int q = S->SizeOfRawData;
        if ( q > S->Misc.VirtualSize && S->Misc.VirtualSize && q-S->Misc.VirtualSize < 0x1000)
         {
           q = S->Misc.VirtualSize;
         }
        bf = Buffer_Copy((byte_t*)pe+S->PointerToRawData,q);
        Pe_Fixup_Rsrc(bf->at,-S->VirtualAddress);
      }
    
    return bf;
  }
#endif
  ;

longptr_t Pe_Get_Executable_Size(void *pe)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_SECTION_HEADER *S = Pe_Get_First_Section(pe);
    PE_SECTION_HEADER *E = S + Pe_Get_File_Header(pe)->NumberOfSections;
    
    --E;
    for ( ; E >= S; --E )
      {
        if ( E->SizeOfRawData && E->PointerToRawData )
          return Pe_Align_To_File(pe,E->PointerToRawData + E->SizeOfRawData);
      }
      
    return 0;
  }
#endif
  ;

void *Pe_Read_NT_Headers(char *filename,int magic)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    PE_DOS_HEADER dos;
    void *hdr = __Zero_Malloc(sizeof(PE_HEADERS_64));
    YOYO_CFILE *f = Cfile_Open(filename,"r");
    Cfile_Read(f,&dos,sizeof(dos),sizeof(dos));
    if ( dos.e_magic != PE_DOS_SIGNATURE )
      __Raise(YOYO_ERROR_INCONSISTENT,"MZ signature doesn´t match");
    Cfile_Seek(f,dos.e_lfanew,0);
    Cfile_Read(f,hdr,sizeof(PE_HEADERS_64),sizeof(PE_HEADERS_64));
    if ( ((PE_HEADERS_64*)hdr)->Signature != PE_NT_SIGNATURE )
      __Raise(YOYO_ERROR_INCONSISTENT,"PE signature doesn´t match");
    if ( ((PE_HEADERS_64*)hdr)->OptionalHeader.Magic != magic )
      __Raise(YOYO_ERROR_INCONSISTENT,"magic doesn´t match");
    return hdr;
  }
#endif
  ;

PE_HEADERS_32 *Pe_Read_NT_Headers_32(char *filename)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_32*)Pe_Read_NT_Headers(filename,PE_OPT32_MAGIC);
  }
#endif
  ;
  
PE_HEADERS_64 *Pe_Read_NT_Headers_64(char *filename)
#ifdef _YOYO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_64*)Pe_Read_NT_Headers(filename,PE_OPT64_MAGIC);
  }
#endif
  ;

#endif /* C_once_EA617668_2E48_4AC6_9079_699B387A0662 */









|


















|
















|






|
|


|


















|

















|



|


|



|

|






|







|









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
    return 0;
  }
#endif
  ;

#define Pe_Get_Proc_Ptr(Pe,Name) Pe_RVA_To_Ptr(Pe_Get_Proc_RVA(Pe,Name))
longptr_t Pe_Get_Proc_RVA(void *pe, char *procname)
#ifdef _YO_PEFILE_BUILTIN
  {
    PE_DATA_DIRECTORY expo = *Pe_Get_Dir(pe,PE_DIRECTORY_ENTRY_EXPORT);
    if ( expo.Size )
      {
        PE_EXPORT_DIRECTORY *edir = Pe_RVA_To_Ptr(pe,expo.VirtualAddress);
        if ( (longptr_t)procname >> 16 )
          return Pe_Export_Bsearch(pe,edir,procname);
        else
          return ((uint_t*)Pe_RVA_To_Ptr(pe,edir->AddressOfFunctions))
                  [(longptr_t)procname - edir->Base];
      }
    
    return 0;
  }
#endif
  ;

void Pe_Fixup_Rsrc_Req(byte_t *rsrc, longptr_t rva, PE_RESOURCE_DIRECTORY *dir)
#ifdef _YO_PEFILE_BUILTIN
  {
    PE_RESOURCE_DIRECTORY_ENTRY *r = (PE_RESOURCE_DIRECTORY_ENTRY *)((byte_t*)dir + sizeof(*dir));
    PE_RESOURCE_DIRECTORY_ENTRY *rE = r+dir->NumberOfIdEntries+dir->NumberOfNamedEntries;
    for ( ; r != rE; ++r )
      if ( r->DataIsDirectory )
        Pe_Fixup_Rsrc_Req(rsrc,rva,(PE_RESOURCE_DIRECTORY *)(rsrc+r->OffsetToDirectory));
      else
        {
          PE_RESOURCE_DATA_ENTRY *e = (PE_RESOURCE_DATA_ENTRY *)(rsrc+r->OffsetToData);
          e->OffsetToData += rva;
        }
  }
#endif
  ;

void Pe_Fixup_Rsrc(void *rsrc, longptr_t rva)
#ifdef _YO_PEFILE_BUILTIN
  {
    Pe_Fixup_Rsrc_Req(rsrc,rva,(PE_RESOURCE_DIRECTORY *)rsrc);
  }
#endif
  ;
  
YO_BUFFER *Pe_Copy_Rsrc(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    PE_SECTION_HEADER *S = Pe_RVA_To_Section(pe,Pe_Get_Dir(pe,PE_DIRECTORY_ENTRY_RESOURCE)->VirtualAddress);
    YO_BUFFER *bf = 0;
    
    if ( S )
      {
        int q = S->SizeOfRawData;
        if ( q > S->Misc.VirtualSize && S->Misc.VirtualSize && q-S->Misc.VirtualSize < 0x1000)
         {
           q = S->Misc.VirtualSize;
         }
        bf = Buffer_Copy((byte_t*)pe+S->PointerToRawData,q);
        Pe_Fixup_Rsrc(bf->at,-S->VirtualAddress);
      }
    
    return bf;
  }
#endif
  ;

longptr_t Pe_Get_Executable_Size(void *pe)
#ifdef _YO_PEFILE_BUILTIN
  {
    PE_SECTION_HEADER *S = Pe_Get_First_Section(pe);
    PE_SECTION_HEADER *E = S + Pe_Get_File_Header(pe)->NumberOfSections;
    
    --E;
    for ( ; E >= S; --E )
      {
        if ( E->SizeOfRawData && E->PointerToRawData )
          return Pe_Align_To_File(pe,E->PointerToRawData + E->SizeOfRawData);
      }
      
    return 0;
  }
#endif
  ;

void *Pe_Read_NT_Headers(char *filename,int magic)
#ifdef _YO_PEFILE_BUILTIN
  {
    PE_DOS_HEADER dos;
    void *hdr = __Zero_Malloc(sizeof(PE_HEADERS_64));
    YO_CFILE *f = Cfile_Open(filename,"r");
    Cfile_Read(f,&dos,sizeof(dos),sizeof(dos));
    if ( dos.e_magic != PE_DOS_SIGNATURE )
      __Raise(YO_ERROR_INCONSISTENT,"MZ signature doesn´t match");
    Cfile_Seek(f,dos.e_lfanew,0);
    Cfile_Read(f,hdr,sizeof(PE_HEADERS_64),sizeof(PE_HEADERS_64));
    if ( ((PE_HEADERS_64*)hdr)->Signature != PE_NT_SIGNATURE )
      __Raise(YO_ERROR_INCONSISTENT,"PE signature doesn´t match");
    if ( ((PE_HEADERS_64*)hdr)->OptionalHeader.Magic != magic )
      __Raise(YO_ERROR_INCONSISTENT,"magic doesn´t match");
    return hdr;
  }
#endif
  ;

PE_HEADERS_32 *Pe_Read_NT_Headers_32(char *filename)
#ifdef _YO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_32*)Pe_Read_NT_Headers(filename,PE_OPT32_MAGIC);
  }
#endif
  ;
  
PE_HEADERS_64 *Pe_Read_NT_Headers_64(char *filename)
#ifdef _YO_PEFILE_BUILTIN
  {
    return (PE_HEADERS_64*)Pe_Read_NT_Headers(filename,PE_OPT64_MAGIC);
  }
#endif
  ;

#endif /* C_once_EA617668_2E48_4AC6_9079_699B387A0662 */


Changes to pictbmp.hc.
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

*/

#ifndef C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE
#define C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE

#ifdef _LIBYOYO
#define _YOYO_PICTBMP_BUILTIN
#endif

#include "picture.hc"  
#include "buffer.hc"
#include "file.hc"

#ifdef _YOYO_PICTBMP_BUILTIN

enum { YOYO_BI_BITFIELDS = 3, YOYO_BI_RGB = 0, };

#pragma pack(push,2)
typedef struct _YOYO_BITMAPFILEHEADER 
  {
    u16_t  bfType;
    u32_t  bfSize;
    u16_t  bfReserved1;
    u16_t  bfReserved2;
    u32_t  bfOffBits;
  } YOYO_BITMAPFILEHEADER;
typedef struct _YOYO_BITMAPINFOHEADER
  {
    u32_t  biSize;
    i32_t  biWidth;
    i32_t  biHeight;
    u16_t  biPlanes;
    u16_t  biBitCount;
    u32_t  biCompression;
    u32_t  biSizeImage;
    i32_t  biXPelsPerMeter;
    i32_t  biYPelsPerMeter;
    u32_t  biClrUsed;
    u32_t  biClrImportant;
  } YOYO_BITMAPINFOHEADER;
#pragma pack(pop)

#endif

#define Pict_From_BMP(Bytes,Count) Pict_From_BMP_Specific(Bytes,Count,YOYO_RGBA8_PICTURE)
YOYO_PICTURE *Pict_From_BMP_Specific(void *bytes, int count, int format)
#ifdef _YOYO_PICTBMP_BUILTIN
  {
    YOYO_PICTURE *pict = __Object_Dtor(sizeof(YOYO_PICTURE),YOYO_PICTURE_Destruct);
    pict->format = format;

    if ( !pict->format ) pict->format = YOYO_RGBA8_PICTURE;
    
    __Auto_Release
      {
        YOYO_BITMAPFILEHEADER *bmFH = bytes;
        YOYO_BITMAPINFOHEADER *bmIH = (YOYO_BITMAPINFOHEADER *)((char*)bytes + sizeof(YOYO_BITMAPFILEHEADER));
        u32_t  *palette = (u32_t*)((char*)bmIH+bmIH->biSize);
        byte_t *image  = (byte_t*)bmFH+bmFH->bfOffBits;
        
        if ( (bmFH->bfType == 0x4D42) && (bmFH->bfSize <= count) )
          {
            int bpp = (bmIH->biBitCount/8);
            int stride, jformat, i;
            byte_t *row = 0;
            if ( bmIH->biCompression != YOYO_BI_RGB )
              __Raise(YOYO_ERROR_CORRUPTED,"supporting BI_RGB comression bitmaps only");
            
            switch ( bmIH->biBitCount )
              {
                case 32: jformat = YOYO_BGRA8_PICTURE; break;
                case 24: jformat = YOYO_BGR8_PICTURE; break;
                case 8:  jformat = YOYO_PAL8_PICTURE; break;
                case 16:
                  if ( bmIH->biCompression == YOYO_BI_BITFIELDS && palette[1] != 0x03e0 )
                    jformat = YOYO_BGR6_PICTURE;
                  else
                    jformat = YOYO_BGR5A1_PICTURE; 
                  break;
                default:
                  __Raise_Format(YOYO_ERROR_CORRUPTED,("bitCount %d is not supported",bmIH->biBitCount));
              }
            
            stride = (bmIH->biWidth*Pict_Format_Bytes_PP(jformat) + 3) & ~3;
            pict->width  = bmIH->biWidth;
            pict->height = Yo_Absi(bmIH->biHeight); /* sign selects direction of rendering rows down-to-up or up-to-down*/
            Pict_Allocate_Buffer(pict);

            for ( i = 0; i < pict->height; ++i )
              {
                int l = (bmIH->biHeight < 0) ? i : pict->height - i - 1; 
                if ( jformat != pict->format )
                  {
                    if ( jformat == YOYO_PAL8_PICTURE )
                      Pict_Convert_Pixels_Row_Pal(
                        image + l*stride, YOYO_BGRX8_PICTURE,
                        pict->pixels+i*pict->pitch, pict->format,
                        pict->width,
                        palette, bmIH->biClrUsed);
                    else
                      Pict_Convert_Pixels_Row(
                        image + l*stride, jformat,
                        pict->pixels+i*pict->pitch, pict->format,
                        pict->width);
                  }
                else
                  memcpy(pict->pixels+i*pict->pitch, image + l*stride, pict->width*Pict_Format_Bytes_PP(jformat));
              }
          }
      }
      
    return pict;
  }
#endif
  ;
  
#define Pict_From_BMP_File(Filename) Pict_From_BMP_File_Specific(Filename,YOYO_RGBA8_PICTURE)
YOYO_PICTURE *Pict_From_BMP_File_Specific(char *filename, int format)
#ifdef _YOYO_PICTBMP_BUILTIN
  {
    YOYO_PICTURE *pict = 0;
    __Auto_Ptr(pict)
      {
        YOYO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"r"));
        pict = Pict_From_BMP_Specific(bf->at,bf->count,format);
      }
    return pict;
  }
#endif
  ;

#endif /* C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE */







|






|

|


|






|
|












|




|
|
|

|


|



|
|








|
|



|
|
|

|
|

|


|












|

|




















|
|
|

|


|








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

*/

#ifndef C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE
#define C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE

#ifdef _LIBYOYO
#define _YO_PICTBMP_BUILTIN
#endif

#include "picture.hc"  
#include "buffer.hc"
#include "file.hc"

#ifdef _YO_PICTBMP_BUILTIN

enum { YO_BI_BITFIELDS = 3, YO_BI_RGB = 0, };

#pragma pack(push,2)
typedef struct _YO_BITMAPFILEHEADER 
  {
    u16_t  bfType;
    u32_t  bfSize;
    u16_t  bfReserved1;
    u16_t  bfReserved2;
    u32_t  bfOffBits;
  } YO_BITMAPFILEHEADER;
typedef struct _YO_BITMAPINFOHEADER
  {
    u32_t  biSize;
    i32_t  biWidth;
    i32_t  biHeight;
    u16_t  biPlanes;
    u16_t  biBitCount;
    u32_t  biCompression;
    u32_t  biSizeImage;
    i32_t  biXPelsPerMeter;
    i32_t  biYPelsPerMeter;
    u32_t  biClrUsed;
    u32_t  biClrImportant;
  } YO_BITMAPINFOHEADER;
#pragma pack(pop)

#endif

#define Pict_From_BMP(Bytes,Count) Pict_From_BMP_Specific(Bytes,Count,YO_RGBA8_PICTURE)
YO_PICTURE *Pict_From_BMP_Specific(void *bytes, int count, int format)
#ifdef _YO_PICTBMP_BUILTIN
  {
    YO_PICTURE *pict = __Object_Dtor(sizeof(YO_PICTURE),YO_PICTURE_Destruct);
    pict->format = format;

    if ( !pict->format ) pict->format = YO_RGBA8_PICTURE;
    
    __Auto_Release
      {
        YO_BITMAPFILEHEADER *bmFH = bytes;
        YO_BITMAPINFOHEADER *bmIH = (YO_BITMAPINFOHEADER *)((char*)bytes + sizeof(YO_BITMAPFILEHEADER));
        u32_t  *palette = (u32_t*)((char*)bmIH+bmIH->biSize);
        byte_t *image  = (byte_t*)bmFH+bmFH->bfOffBits;
        
        if ( (bmFH->bfType == 0x4D42) && (bmFH->bfSize <= count) )
          {
            int bpp = (bmIH->biBitCount/8);
            int stride, jformat, i;
            byte_t *row = 0;
            if ( bmIH->biCompression != YO_BI_RGB )
              __Raise(YO_ERROR_CORRUPTED,"supporting BI_RGB comression bitmaps only");
            
            switch ( bmIH->biBitCount )
              {
                case 32: jformat = YO_BGRA8_PICTURE; break;
                case 24: jformat = YO_BGR8_PICTURE; break;
                case 8:  jformat = YO_PAL8_PICTURE; break;
                case 16:
                  if ( bmIH->biCompression == YO_BI_BITFIELDS && palette[1] != 0x03e0 )
                    jformat = YO_BGR6_PICTURE;
                  else
                    jformat = YO_BGR5A1_PICTURE; 
                  break;
                default:
                  __Raise_Format(YO_ERROR_CORRUPTED,("bitCount %d is not supported",bmIH->biBitCount));
              }
            
            stride = (bmIH->biWidth*Pict_Format_Bytes_PP(jformat) + 3) & ~3;
            pict->width  = bmIH->biWidth;
            pict->height = Yo_Absi(bmIH->biHeight); /* sign selects direction of rendering rows down-to-up or up-to-down*/
            Pict_Allocate_Buffer(pict);

            for ( i = 0; i < pict->height; ++i )
              {
                int l = (bmIH->biHeight < 0) ? i : pict->height - i - 1; 
                if ( jformat != pict->format )
                  {
                    if ( jformat == YO_PAL8_PICTURE )
                      Pict_Convert_Pixels_Row_Pal(
                        image + l*stride, YO_BGRX8_PICTURE,
                        pict->pixels+i*pict->pitch, pict->format,
                        pict->width,
                        palette, bmIH->biClrUsed);
                    else
                      Pict_Convert_Pixels_Row(
                        image + l*stride, jformat,
                        pict->pixels+i*pict->pitch, pict->format,
                        pict->width);
                  }
                else
                  memcpy(pict->pixels+i*pict->pitch, image + l*stride, pict->width*Pict_Format_Bytes_PP(jformat));
              }
          }
      }
      
    return pict;
  }
#endif
  ;
  
#define Pict_From_BMP_File(Filename) Pict_From_BMP_File_Specific(Filename,YO_RGBA8_PICTURE)
YO_PICTURE *Pict_From_BMP_File_Specific(char *filename, int format)
#ifdef _YO_PICTBMP_BUILTIN
  {
    YO_PICTURE *pict = 0;
    __Auto_Ptr(pict)
      {
        YO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"r"));
        pict = Pict_From_BMP_Specific(bf->at,bf->count,format);
      }
    return pict;
  }
#endif
  ;

#endif /* C_once_F02ABD1D_F661_464B_8226_CBED6A3DA7CE */
Changes to pictpng.hc.
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

*/

#ifndef C_once_324CA35F_3399_4699_91FD_FC523999882D
#define C_once_324CA35F_3399_4699_91FD_FC523999882D

#ifdef _LIBYOYO
#define _YOYO_PICTPNG_BUILTIN
#endif

#include "picture.hc"

#ifdef _YOYO_PICTPNG_BUILTIN
#include <png.h>
#include <pngstruct.h>

static void Pict_From_PNG_Read_Data(png_structp png_ptr, void *dest, png_size_t count)
  {
    byte_t **p = png_ptr->io_ptr;
    if ( *p + count > p[1] ) 
      png_error(png_ptr, "png read error in Pict_From_PNG_Read_Data"); 
    memcpy(dest,*p,count);
    *p += count;
  }

#endif

#define Pict_From_PNG(Bytes,Count) Pict_From_PNG_Specific(Bytes,Count,YOYO_RGBA8_PICTURE)
YOYO_PICTURE *Pict_From_PNG_Specific(void *bytes, int count, int format)
#ifdef _YOYO_PICTPNG_BUILTIN
  {
    YOYO_PICTURE *pict = __Object_Dtor(sizeof(YOYO_PICTURE),YOYO_PICTURE_Destruct);
    pict->format = format;
    
    __Auto_Release
      {
        png_struct* png_ptr;
        png_info*   info_ptr;
        byte_t*     read_ptr[2];
        int         stride;
        byte_t     *row;
        int         jformat;
        int         i;
        
        if ( !png_check_sig(bytes,8) )
          __Raise(YOYO_ERROR_UNSUPPORTED,"is not PNG image");

        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
        info_ptr = png_create_info_struct(png_ptr);
        
        if ( !setjmp(png_jmpbuf(png_ptr)) ) 
          {
            int bpp;







|




|














|
|
|

|













|







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

*/

#ifndef C_once_324CA35F_3399_4699_91FD_FC523999882D
#define C_once_324CA35F_3399_4699_91FD_FC523999882D

#ifdef _LIBYOYO
#define _YO_PICTPNG_BUILTIN
#endif

#include "picture.hc"

#ifdef _YO_PICTPNG_BUILTIN
#include <png.h>
#include <pngstruct.h>

static void Pict_From_PNG_Read_Data(png_structp png_ptr, void *dest, png_size_t count)
  {
    byte_t **p = png_ptr->io_ptr;
    if ( *p + count > p[1] ) 
      png_error(png_ptr, "png read error in Pict_From_PNG_Read_Data"); 
    memcpy(dest,*p,count);
    *p += count;
  }

#endif

#define Pict_From_PNG(Bytes,Count) Pict_From_PNG_Specific(Bytes,Count,YO_RGBA8_PICTURE)
YO_PICTURE *Pict_From_PNG_Specific(void *bytes, int count, int format)
#ifdef _YO_PICTPNG_BUILTIN
  {
    YO_PICTURE *pict = __Object_Dtor(sizeof(YO_PICTURE),YO_PICTURE_Destruct);
    pict->format = format;
    
    __Auto_Release
      {
        png_struct* png_ptr;
        png_info*   info_ptr;
        byte_t*     read_ptr[2];
        int         stride;
        byte_t     *row;
        int         jformat;
        int         i;
        
        if ( !png_check_sig(bytes,8) )
          __Raise(YO_ERROR_UNSUPPORTED,"is not PNG image");

        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
        info_ptr = png_create_info_struct(png_ptr);
        
        if ( !setjmp(png_jmpbuf(png_ptr)) ) 
          {
            int bpp;
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

            if (  png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA )
              bpp = 4;
            else 
              bpp = 3;

            stride = (bpp*pict->width + 3) & ~3;
            jformat = (bpp==4?YOYO_RGBA8_PICTURE:YOYO_RGB8_PICTURE);
            if ( jformat != pict->format )
              row = __Malloc(stride);
          }
        else
          {
            if ( !setjmp(png_jmpbuf(png_ptr)) )
              png_destroy_read_struct(&png_ptr,&info_ptr,0);
            __Raise(YOYO_ERROR_CORRUPTED,"failed to decode PNG info");
          }
          
        Pict_Allocate_Buffer(pict);
        
        if ( !setjmp(png_jmpbuf(png_ptr)) ) 
          {
            for ( i = 0; i < pict->height; ++i )







|







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

            if (  png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA )
              bpp = 4;
            else 
              bpp = 3;

            stride = (bpp*pict->width + 3) & ~3;
            jformat = (bpp==4?YO_RGBA8_PICTURE:YO_RGB8_PICTURE);
            if ( jformat != pict->format )
              row = __Malloc(stride);
          }
        else
          {
            if ( !setjmp(png_jmpbuf(png_ptr)) )
              png_destroy_read_struct(&png_ptr,&info_ptr,0);
            __Raise(YO_ERROR_CORRUPTED,"failed to decode PNG info");
          }
          
        Pict_Allocate_Buffer(pict);
        
        if ( !setjmp(png_jmpbuf(png_ptr)) ) 
          {
            for ( i = 0; i < pict->height; ++i )
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
              }
            //png_read_end(png_ptr,info_ptr);
          }
        else
          {
            if ( !setjmp(png_jmpbuf(png_ptr)) )
              png_destroy_read_struct(&png_ptr,&info_ptr,0);
            __Raise(YOYO_ERROR_CORRUPTED,"failed to decode PNG bits");
          }
      }
      
    return pict;
  }
#endif
  ;

#define Pict_From_PNG_File(Filename) Pict_From_PNG_File_Specific(Filename,YOYO_RGBA8_PICTURE)
YOYO_PICTURE *Pict_From_PNG_File_Specific(char *filename, int format)
#ifdef _YOYO_PICTPNG_BUILTIN
  {
    YOYO_PICTURE *pict = 0;
    __Auto_Ptr(pict)
      {
        YOYO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"r"));
        pict = Pict_From_PNG_Specific(bf->at,bf->count,format);
      }
    return pict;
  }
#endif
  ;

#endif /* C_once_324CA35F_3399_4699_91FD_FC523999882D */








|








|
|
|

|


|









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
              }
            //png_read_end(png_ptr,info_ptr);
          }
        else
          {
            if ( !setjmp(png_jmpbuf(png_ptr)) )
              png_destroy_read_struct(&png_ptr,&info_ptr,0);
            __Raise(YO_ERROR_CORRUPTED,"failed to decode PNG bits");
          }
      }
      
    return pict;
  }
#endif
  ;

#define Pict_From_PNG_File(Filename) Pict_From_PNG_File_Specific(Filename,YO_RGBA8_PICTURE)
YO_PICTURE *Pict_From_PNG_File_Specific(char *filename, int format)
#ifdef _YO_PICTPNG_BUILTIN
  {
    YO_PICTURE *pict = 0;
    __Auto_Ptr(pict)
      {
        YO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"r"));
        pict = Pict_From_PNG_Specific(bf->at,bf->count,format);
      }
    return pict;
  }
#endif
  ;

#endif /* C_once_324CA35F_3399_4699_91FD_FC523999882D */

Changes to picture.hc.
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

*/

#ifndef C_once_E194EBE7_E43F_4305_A75C_3872532B12DB
#define C_once_E194EBE7_E43F_4305_A75C_3872532B12DB

#ifdef _LIBYOYO
#define _YOYO_PICTURE_BUILTIN
#endif

#include "yoyo.hc"

enum
  {
    YOYO_PAL8_PICTURE  = __FOUR_CHARS('P',1,'8',0),
    YOYO_RGBAf_PICTURE = __FOUR_CHARS('R',16,'f','A'),
    YOYO_RGB8_PICTURE  = __FOUR_CHARS('R',3,'8',0),
    YOYO_RGB5_PICTURE  = __FOUR_CHARS('R',2,'5',0),
    YOYO_RGB6_PICTURE  = __FOUR_CHARS('R',2,'6',0),
    YOYO_RGBA8_PICTURE = __FOUR_CHARS('R',4,'8','A'),
    YOYO_RGBX8_PICTURE = __FOUR_CHARS('R',4,'8',0),
    YOYO_RGB5A1_PICTURE= __FOUR_CHARS('R',2,'5','A'),
    YOYO_BGR8_PICTURE  = __FOUR_CHARS('B',3,'8',0),
    YOYO_BGR5_PICTURE  = __FOUR_CHARS('B',2,'5',0),
    YOYO_BGR6_PICTURE  = __FOUR_CHARS('B',2,'6',0),
    YOYO_BGRA8_PICTURE = __FOUR_CHARS('B',4,'8','A'),
    YOYO_BGRX8_PICTURE = __FOUR_CHARS('B',4,'8',0),
    YOYO_BGR5A1_PICTURE= __FOUR_CHARS('B',2,'5','A'),
  };

#define Pict_Format_Bytes_PP(Fmt) ((Fmt>>8)&0x0ff)

typedef struct _YOYO_PICTURE
  {
    int width;
    int height;
    int pitch;
    int weight;
    int format;
    byte_t *pixels;
  } YOYO_PICTURE;

void YOYO_PICTURE_Destruct(YOYO_PICTURE *pict)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    free(pict->pixels);
    __Destruct(pict);
  }
#endif
  ;

typedef struct _YOYO_RGBA8
  {
    byte_t r;
    byte_t g;
    byte_t b;
    byte_t a;
  } YOYO_RGBA8;

typedef struct _YOYO_BGRA8
  {
    byte_t b;
    byte_t g;
    byte_t r;
    byte_t a;
  } YOYO_BGRA8;

typedef struct _YOYO_RGBAf
  {
    float r;
    float g;
    float b;
    float a;
  } YOYO_RGBAf;

typedef struct _YOYO_RGB8
  {
    byte_t r;
    byte_t g;
    byte_t b;
  } YOYO_RGB8;

typedef struct _YOYO_BGR8
  {
    byte_t b;
    byte_t g;
    byte_t r;
  } YOYO_BGR8;

YOYO_RGBA8 Pict_Get_RGBA8_Pixel(byte_t *ptr, int format)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    switch ( format )
      {
        case YOYO_RGBA8_PICTURE:
          return *(YOYO_RGBA8*)ptr;
        case YOYO_RGB8_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = ((YOYO_RGB8*)ptr)->r;
            rgba.g = ((YOYO_RGB8*)ptr)->g;
            rgba.b = ((YOYO_RGB8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YOYO_RGBX8_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = ((YOYO_RGB8*)ptr)->r;
            rgba.g = ((YOYO_RGB8*)ptr)->g;
            rgba.b = ((YOYO_RGB8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YOYO_BGR8_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = ((YOYO_BGR8*)ptr)->r;
            rgba.g = ((YOYO_BGR8*)ptr)->g;
            rgba.b = ((YOYO_BGR8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YOYO_BGRX8_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = ((YOYO_BGRA8*)ptr)->r;
            rgba.g = ((YOYO_BGRA8*)ptr)->g;
            rgba.b = ((YOYO_BGRA8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YOYO_BGRA8_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = ((YOYO_BGRA8*)ptr)->r;
            rgba.g = ((YOYO_BGRA8*)ptr)->g;
            rgba.b = ((YOYO_BGRA8*)ptr)->b;
            rgba.a = ((YOYO_BGRA8*)ptr)->a;
            return rgba;
          }
        case YOYO_RGBAf_PICTURE:
          {
            YOYO_RGBA8 rgba;
            rgba.r = (byte_t)(Yo_MAX(((YOYO_RGBAf*)ptr)->r + .5f ,1.f) * 255.f);
            rgba.g = (byte_t)(Yo_MAX(((YOYO_RGBAf*)ptr)->g + .5f ,1.f) * 255.f);
            rgba.b = (byte_t)(Yo_MAX(((YOYO_RGBAf*)ptr)->b + .5f ,1.f) * 255.f);
            rgba.a = (byte_t)(Yo_MAX(((YOYO_RGBAf*)ptr)->a + .5f ,1.f) * 255.f);
            return rgba;
          }
        default:
          {
            YOYO_RGBA8 rgba = {0};
            __Raise(YOYO_ERROR_UNSUPPORTED,"bad pixel format");
            return rgba;
          }
      }
  }
#endif
  ;

YOYO_RGBA8 Pict_Get_RGBA8(YOYO_PICTURE *pict, int x, int y)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    byte_t *ptr = pict->pixels + (pict->pitch * y + x * pict->weight);
    
    if ( pict->format == YOYO_RGBA8_PICTURE )
      return *(YOYO_RGBA8*)ptr;
    
    return Pict_Get_RGBA8_Pixel(ptr, pict->format);
  }
#endif
  ;

YOYO_RGBAf Pict_Get_RGBAf_Pixel(byte_t *ptr, int format)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    if ( format == YOYO_RGBAf_PICTURE )
      return *(YOYO_RGBAf*)ptr;
    else if ( format == YOYO_RGBA8_PICTURE )
      {
        YOYO_RGBAf rgba;
        rgba.r = (((YOYO_RGBA8*)ptr)->r + .5f) / 255.f;
        rgba.g = (((YOYO_RGBA8*)ptr)->g + .5f) / 255.f;
        rgba.b = (((YOYO_RGBA8*)ptr)->b + .5f) / 255.f;
        rgba.a = (((YOYO_RGBA8*)ptr)->a + .5f) / 255.f;
        return rgba;
      }
    else
      {
        YOYO_RGBA8 tmp = Pict_Get_RGBA8_Pixel(ptr,format);
        YOYO_RGBAf rgba;
        rgba.r = (tmp.r + .5f) / 255.f;
        rgba.g = (tmp.g + .5f) / 255.f;
        rgba.b = (tmp.b + .5f) / 255.f;
        rgba.a = (tmp.a + .5f) / 255.f;
        return rgba;
      }
  }
#endif
  ;

void Pict_Set_RGBA8_Pixel(byte_t *ptr, YOYO_RGBA8 pix, int format)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    switch ( format )
      {
        case YOYO_RGBA8_PICTURE:
          *(YOYO_RGBA8*)ptr = pix;
          break;
        case YOYO_RGB8_PICTURE:
          ((YOYO_RGB8*)ptr)->r = pix.r;
          ((YOYO_RGB8*)ptr)->g = pix.g;
          ((YOYO_RGB8*)ptr)->b = pix.b;
          break;
        case YOYO_RGBX8_PICTURE:
          ((YOYO_RGBA8*)ptr)->r = pix.r;
          ((YOYO_RGBA8*)ptr)->g = pix.g;
          ((YOYO_RGBA8*)ptr)->b = pix.b;
          ((YOYO_RGBA8*)ptr)->a = 0;
          break;
        case YOYO_BGR8_PICTURE:
          ((YOYO_BGRA8*)ptr)->r = pix.r;
          ((YOYO_BGRA8*)ptr)->g = pix.g;
          ((YOYO_BGRA8*)ptr)->b = pix.b;
          break;
        case YOYO_BGRX8_PICTURE:
          ((YOYO_BGRA8*)ptr)->r = pix.r;
          ((YOYO_BGRA8*)ptr)->g = pix.g;
          ((YOYO_BGRA8*)ptr)->b = pix.b;
          ((YOYO_BGRA8*)ptr)->a = 0;
          break;
        case YOYO_BGRA8_PICTURE:
          ((YOYO_BGRA8*)ptr)->r = pix.r;
          ((YOYO_BGRA8*)ptr)->g = pix.g;
          ((YOYO_BGRA8*)ptr)->b = pix.b;
          ((YOYO_BGRA8*)ptr)->a = pix.a;
          break;
        case YOYO_RGBAf_PICTURE:
          ((YOYO_RGBAf*)ptr)->r = (pix.r + .5f) / 255.f;
          ((YOYO_RGBAf*)ptr)->g = (pix.g + .5f) / 255.f;
          ((YOYO_RGBAf*)ptr)->b = (pix.b + .5f) / 255.f;
          ((YOYO_RGBAf*)ptr)->a = (pix.a + .5f) / 255.f;
          break;
        default:
          __Raise(YOYO_ERROR_UNSUPPORTED,"bad pixel format");
      }
  }
#endif
  ;

void Pict_Set_RGBA8(YOYO_PICTURE *pict, int x, int y, YOYO_RGBA8 pix)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    byte_t *ptr = pict->pixels + (pict->pitch * y + x * pict->weight);
    
    if ( pict->format == YOYO_RGBA8_PICTURE )
      *(YOYO_RGBA8*)ptr = pix;
    
    Pict_Set_RGBA8_Pixel(pict->pixels + (pict->pitch * y + x * pict->weight), pix, pict->format);
  }
#endif
  ;

void Pict_Allocate_Buffer(YOYO_PICTURE *pict)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    if ( pict->pixels ) 
      __Raise(YOYO_ERROR_ALREADY_EXISTS,"pixel buffer already exists");
    
    switch( pict->format )
      {
        case YOYO_RGBA8_PICTURE:
        case YOYO_RGBX8_PICTURE:
          pict->pitch  = sizeof(YOYO_RGBA8)*pict->width;
          pict->weight = sizeof(YOYO_RGBA8);
          break;
        case YOYO_RGB8_PICTURE:
          pict->pitch  = sizeof(YOYO_RGB8)*pict->width;
          pict->weight = sizeof(YOYO_RGB8);
          break;
        case YOYO_BGRA8_PICTURE:
        case YOYO_BGRX8_PICTURE:
          pict->pitch  = sizeof(YOYO_BGRA8)*pict->width;
          pict->weight = sizeof(YOYO_BGRA8);
          break;
        case YOYO_BGR8_PICTURE:
          pict->pitch  = sizeof(YOYO_BGR8)*pict->width;
          pict->weight = sizeof(YOYO_BGR8);
          break;
        case YOYO_RGBAf_PICTURE:
          pict->pitch  = sizeof(YOYO_RGBAf)*pict->width;
          pict->weight = sizeof(YOYO_RGBAf);
          break;
        default:
          __Raise(YOYO_ERROR_UNSUPPORTED,"bad pixel format");
      }
      
    pict->pixels = __Malloc_Npl(pict->pitch*pict->height);
  }
#endif
  ;
  
void Pict_Nullify_Transparent_Pixels(YOYO_PICTURE *pict, byte_t threshold)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    if ( pict->format == YOYO_RGBA8_PICTURE || pict->format == YOYO_BGRA8_PICTURE )
      {
        int i;
        for ( i = 0; i < pict->height; ++i )
          {
            YOYO_RGBA8 *pixel = (YOYO_RGBA8 *)(pict->pixels+i*pict->pitch);
            YOYO_RGBA8 *pixelE = pixel+pict->width;
            for ( ; pixel < pixelE; ++pixel  )
              if ( pixel->a < threshold ) 
                memset(pixel,0,sizeof(*pixel));
          }
      }
  }
#endif
  ;
  
void Pict_Convert_Pixels_Row(byte_t *src, int src_format, byte_t *dst, int dst_format, int count )
#ifdef _YOYO_PICTURE_BUILTIN
  {
    int i;
    int src_weight = ((src_format >> 8) & 0x0ff);
    int dst_weight = ((dst_format >> 8) & 0x0ff);
    byte_t *src_pixel = src;
    byte_t *dst_pixel = dst;
    if ( src_format == dst_format )
      {
        memcpy(dst,src,count*dst_weight);
      }
    else if ( dst_format  == YOYO_RGBAf_PICTURE )
      for ( i = 0; i < count; ++i )
        {
          *(YOYO_RGBAf*)dst_pixel = Pict_Get_RGBAf_Pixel(src_pixel,src_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
    else if ( dst_format  == YOYO_RGBA8_PICTURE )
      for ( i = 0; i < count; ++i )
        {
          *(YOYO_RGBA8*)dst_pixel = Pict_Get_RGBA8_Pixel(src_pixel,src_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
    else
      for ( i = 0; i < count; ++i )
        {
          YOYO_RGBA8 tmp = Pict_Get_RGBA8_Pixel(src_pixel,src_format);
          Pict_Set_RGBA8_Pixel(dst_pixel,tmp,dst_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
  }
#endif
  ;
  
void Pict_Convert_Pixels_Row_Pal(byte_t *src, int src_format, byte_t *dst, int dst_format, int count, void *pal, int pal_count )
#ifdef _YOYO_PICTURE_BUILTIN
  {
    int i, bpp = Pict_Format_Bytes_PP(dst_format);
    byte_t palx[256*16]; /* sizeof(rgbaf) == 16 */
    Pict_Convert_Pixels_Row(pal,src_format,palx,dst_format,pal_count);
    if ( bpp == 4 )
      for ( i = 0; i < count; ++i )
        ((u32_t*)dst)[i] = ((u32_t*)palx)[src[i]];
    else if ( bpp == 2 )
      for ( i = 0; i < count; ++i )
        ((u32_t*)dst)[i] = ((u32_t*)palx)[src[i]];
    else
      for ( i = 0; i < count; ++i )
        memcpy((dst + i * bpp),palx + src[i]*bpp,bpp);
  }
#endif
  ;

#ifdef __windoze
HBITMAP Pict_Create_HBITMAP(YOYO_PICTURE *pict)
#ifdef _YOYO_PICTURE_BUILTIN
  {
    BITMAPINFOHEADER bi;
    HDC dc;
    HBITMAP bmp;
    byte_t *bits = 0;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth  = pict->width;
    bi.biHeight = -pict->height;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = pict->width * pict->height * 4;
    dc  = GetDC(0);
    //bmp = CreateCompatibleBitmap(dc,pict->width,pict->height);
    //SetDIBits(dc,bmp,0,pict->height,pict->pixels,(BITMAPINFO*)&bi,DIB_RGB_COLORS);
    bmp = CreateDIBSection(dc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, &bits, 0, 0);
    if ( pict->format == YOYO_BGRA8_PICTURE )
      memcpy(bits,pict->pixels,bi.biSizeImage);
    else
      {
        int i;
        for ( i = 0; i < pict->height; ++i )
          Pict_Convert_Pixels_Row(
              pict->pixels+i*pict->pitch,pict->format,
              bits+pict->width*4*i,YOYO_BGRA8_PICTURE,
              pict->width);          
      }
    ReleaseDC(0,dc);
    return bmp;
  }
#endif
  ;
#endif

#endif /* C_once_E194EBE7_E43F_4305_A75C_3872532B12DB */








|






|
|
|
|
|
|
|
|
|
|
|
|
|
|




|







|

|
|







|





|

|





|

|





|

|




|

|




|

|
|



|
|
|

|
|
|
|



|

|
|
|
|



|

|
|
|
|



|

|
|
|
|



|

|
|
|
|
|


|

|
|
|
|
|




|
|







|
|



|
|






|
|

|
|
|

|
|
|
|
|




|
|










|
|



|
|

|
|
|
|

|
|
|
|
|

|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|


|





|
|



|
|






|
|


|



|
|
|
|

|
|
|

|
|
|
|

|
|
|

|
|
|


|







|
|

|




|
|










|










|


|



|


|






|









|


















|
|
















|







|











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

*/

#ifndef C_once_E194EBE7_E43F_4305_A75C_3872532B12DB
#define C_once_E194EBE7_E43F_4305_A75C_3872532B12DB

#ifdef _LIBYOYO
#define _YO_PICTURE_BUILTIN
#endif

#include "yoyo.hc"

enum
  {
    YO_PAL8_PICTURE  = __FOUR_CHARS('P',1,'8',0),
    YO_RGBAf_PICTURE = __FOUR_CHARS('R',16,'f','A'),
    YO_RGB8_PICTURE  = __FOUR_CHARS('R',3,'8',0),
    YO_RGB5_PICTURE  = __FOUR_CHARS('R',2,'5',0),
    YO_RGB6_PICTURE  = __FOUR_CHARS('R',2,'6',0),
    YO_RGBA8_PICTURE = __FOUR_CHARS('R',4,'8','A'),
    YO_RGBX8_PICTURE = __FOUR_CHARS('R',4,'8',0),
    YO_RGB5A1_PICTURE= __FOUR_CHARS('R',2,'5','A'),
    YO_BGR8_PICTURE  = __FOUR_CHARS('B',3,'8',0),
    YO_BGR5_PICTURE  = __FOUR_CHARS('B',2,'5',0),
    YO_BGR6_PICTURE  = __FOUR_CHARS('B',2,'6',0),
    YO_BGRA8_PICTURE = __FOUR_CHARS('B',4,'8','A'),
    YO_BGRX8_PICTURE = __FOUR_CHARS('B',4,'8',0),
    YO_BGR5A1_PICTURE= __FOUR_CHARS('B',2,'5','A'),
  };

#define Pict_Format_Bytes_PP(Fmt) ((Fmt>>8)&0x0ff)

typedef struct _YO_PICTURE
  {
    int width;
    int height;
    int pitch;
    int weight;
    int format;
    byte_t *pixels;
  } YO_PICTURE;

void YO_PICTURE_Destruct(YO_PICTURE *pict)
#ifdef _YO_PICTURE_BUILTIN
  {
    free(pict->pixels);
    __Destruct(pict);
  }
#endif
  ;

typedef struct _YO_RGBA8
  {
    byte_t r;
    byte_t g;
    byte_t b;
    byte_t a;
  } YO_RGBA8;

typedef struct _YO_BGRA8
  {
    byte_t b;
    byte_t g;
    byte_t r;
    byte_t a;
  } YO_BGRA8;

typedef struct _YO_RGBAf
  {
    float r;
    float g;
    float b;
    float a;
  } YO_RGBAf;

typedef struct _YO_RGB8
  {
    byte_t r;
    byte_t g;
    byte_t b;
  } YO_RGB8;

typedef struct _YO_BGR8
  {
    byte_t b;
    byte_t g;
    byte_t r;
  } YO_BGR8;

YO_RGBA8 Pict_Get_RGBA8_Pixel(byte_t *ptr, int format)
#ifdef _YO_PICTURE_BUILTIN
  {
    switch ( format )
      {
        case YO_RGBA8_PICTURE:
          return *(YO_RGBA8*)ptr;
        case YO_RGB8_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = ((YO_RGB8*)ptr)->r;
            rgba.g = ((YO_RGB8*)ptr)->g;
            rgba.b = ((YO_RGB8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YO_RGBX8_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = ((YO_RGB8*)ptr)->r;
            rgba.g = ((YO_RGB8*)ptr)->g;
            rgba.b = ((YO_RGB8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YO_BGR8_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = ((YO_BGR8*)ptr)->r;
            rgba.g = ((YO_BGR8*)ptr)->g;
            rgba.b = ((YO_BGR8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YO_BGRX8_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = ((YO_BGRA8*)ptr)->r;
            rgba.g = ((YO_BGRA8*)ptr)->g;
            rgba.b = ((YO_BGRA8*)ptr)->b;
            rgba.a = 0xff;
            return rgba;
          }
        case YO_BGRA8_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = ((YO_BGRA8*)ptr)->r;
            rgba.g = ((YO_BGRA8*)ptr)->g;
            rgba.b = ((YO_BGRA8*)ptr)->b;
            rgba.a = ((YO_BGRA8*)ptr)->a;
            return rgba;
          }
        case YO_RGBAf_PICTURE:
          {
            YO_RGBA8 rgba;
            rgba.r = (byte_t)(Yo_MAX(((YO_RGBAf*)ptr)->r + .5f ,1.f) * 255.f);
            rgba.g = (byte_t)(Yo_MAX(((YO_RGBAf*)ptr)->g + .5f ,1.f) * 255.f);
            rgba.b = (byte_t)(Yo_MAX(((YO_RGBAf*)ptr)->b + .5f ,1.f) * 255.f);
            rgba.a = (byte_t)(Yo_MAX(((YO_RGBAf*)ptr)->a + .5f ,1.f) * 255.f);
            return rgba;
          }
        default:
          {
            YO_RGBA8 rgba = {0};
            __Raise(YO_ERROR_UNSUPPORTED,"bad pixel format");
            return rgba;
          }
      }
  }
#endif
  ;

YO_RGBA8 Pict_Get_RGBA8(YO_PICTURE *pict, int x, int y)
#ifdef _YO_PICTURE_BUILTIN
  {
    byte_t *ptr = pict->pixels + (pict->pitch * y + x * pict->weight);
    
    if ( pict->format == YO_RGBA8_PICTURE )
      return *(YO_RGBA8*)ptr;
    
    return Pict_Get_RGBA8_Pixel(ptr, pict->format);
  }
#endif
  ;

YO_RGBAf Pict_Get_RGBAf_Pixel(byte_t *ptr, int format)
#ifdef _YO_PICTURE_BUILTIN
  {
    if ( format == YO_RGBAf_PICTURE )
      return *(YO_RGBAf*)ptr;
    else if ( format == YO_RGBA8_PICTURE )
      {
        YO_RGBAf rgba;
        rgba.r = (((YO_RGBA8*)ptr)->r + .5f) / 255.f;
        rgba.g = (((YO_RGBA8*)ptr)->g + .5f) / 255.f;
        rgba.b = (((YO_RGBA8*)ptr)->b + .5f) / 255.f;
        rgba.a = (((YO_RGBA8*)ptr)->a + .5f) / 255.f;
        return rgba;
      }
    else
      {
        YO_RGBA8 tmp = Pict_Get_RGBA8_Pixel(ptr,format);
        YO_RGBAf rgba;
        rgba.r = (tmp.r + .5f) / 255.f;
        rgba.g = (tmp.g + .5f) / 255.f;
        rgba.b = (tmp.b + .5f) / 255.f;
        rgba.a = (tmp.a + .5f) / 255.f;
        return rgba;
      }
  }
#endif
  ;

void Pict_Set_RGBA8_Pixel(byte_t *ptr, YO_RGBA8 pix, int format)
#ifdef _YO_PICTURE_BUILTIN
  {
    switch ( format )
      {
        case YO_RGBA8_PICTURE:
          *(YO_RGBA8*)ptr = pix;
          break;
        case YO_RGB8_PICTURE:
          ((YO_RGB8*)ptr)->r = pix.r;
          ((YO_RGB8*)ptr)->g = pix.g;
          ((YO_RGB8*)ptr)->b = pix.b;
          break;
        case YO_RGBX8_PICTURE:
          ((YO_RGBA8*)ptr)->r = pix.r;
          ((YO_RGBA8*)ptr)->g = pix.g;
          ((YO_RGBA8*)ptr)->b = pix.b;
          ((YO_RGBA8*)ptr)->a = 0;
          break;
        case YO_BGR8_PICTURE:
          ((YO_BGRA8*)ptr)->r = pix.r;
          ((YO_BGRA8*)ptr)->g = pix.g;
          ((YO_BGRA8*)ptr)->b = pix.b;
          break;
        case YO_BGRX8_PICTURE:
          ((YO_BGRA8*)ptr)->r = pix.r;
          ((YO_BGRA8*)ptr)->g = pix.g;
          ((YO_BGRA8*)ptr)->b = pix.b;
          ((YO_BGRA8*)ptr)->a = 0;
          break;
        case YO_BGRA8_PICTURE:
          ((YO_BGRA8*)ptr)->r = pix.r;
          ((YO_BGRA8*)ptr)->g = pix.g;
          ((YO_BGRA8*)ptr)->b = pix.b;
          ((YO_BGRA8*)ptr)->a = pix.a;
          break;
        case YO_RGBAf_PICTURE:
          ((YO_RGBAf*)ptr)->r = (pix.r + .5f) / 255.f;
          ((YO_RGBAf*)ptr)->g = (pix.g + .5f) / 255.f;
          ((YO_RGBAf*)ptr)->b = (pix.b + .5f) / 255.f;
          ((YO_RGBAf*)ptr)->a = (pix.a + .5f) / 255.f;
          break;
        default:
          __Raise(YO_ERROR_UNSUPPORTED,"bad pixel format");
      }
  }
#endif
  ;

void Pict_Set_RGBA8(YO_PICTURE *pict, int x, int y, YO_RGBA8 pix)
#ifdef _YO_PICTURE_BUILTIN
  {
    byte_t *ptr = pict->pixels + (pict->pitch * y + x * pict->weight);
    
    if ( pict->format == YO_RGBA8_PICTURE )
      *(YO_RGBA8*)ptr = pix;
    
    Pict_Set_RGBA8_Pixel(pict->pixels + (pict->pitch * y + x * pict->weight), pix, pict->format);
  }
#endif
  ;

void Pict_Allocate_Buffer(YO_PICTURE *pict)
#ifdef _YO_PICTURE_BUILTIN
  {
    if ( pict->pixels ) 
      __Raise(YO_ERROR_ALREADY_EXISTS,"pixel buffer already exists");
    
    switch( pict->format )
      {
        case YO_RGBA8_PICTURE:
        case YO_RGBX8_PICTURE:
          pict->pitch  = sizeof(YO_RGBA8)*pict->width;
          pict->weight = sizeof(YO_RGBA8);
          break;
        case YO_RGB8_PICTURE:
          pict->pitch  = sizeof(YO_RGB8)*pict->width;
          pict->weight = sizeof(YO_RGB8);
          break;
        case YO_BGRA8_PICTURE:
        case YO_BGRX8_PICTURE:
          pict->pitch  = sizeof(YO_BGRA8)*pict->width;
          pict->weight = sizeof(YO_BGRA8);
          break;
        case YO_BGR8_PICTURE:
          pict->pitch  = sizeof(YO_BGR8)*pict->width;
          pict->weight = sizeof(YO_BGR8);
          break;
        case YO_RGBAf_PICTURE:
          pict->pitch  = sizeof(YO_RGBAf)*pict->width;
          pict->weight = sizeof(YO_RGBAf);
          break;
        default:
          __Raise(YO_ERROR_UNSUPPORTED,"bad pixel format");
      }
      
    pict->pixels = __Malloc_Npl(pict->pitch*pict->height);
  }
#endif
  ;
  
void Pict_Nullify_Transparent_Pixels(YO_PICTURE *pict, byte_t threshold)
#ifdef _YO_PICTURE_BUILTIN
  {
    if ( pict->format == YO_RGBA8_PICTURE || pict->format == YO_BGRA8_PICTURE )
      {
        int i;
        for ( i = 0; i < pict->height; ++i )
          {
            YO_RGBA8 *pixel = (YO_RGBA8 *)(pict->pixels+i*pict->pitch);
            YO_RGBA8 *pixelE = pixel+pict->width;
            for ( ; pixel < pixelE; ++pixel  )
              if ( pixel->a < threshold ) 
                memset(pixel,0,sizeof(*pixel));
          }
      }
  }
#endif
  ;
  
void Pict_Convert_Pixels_Row(byte_t *src, int src_format, byte_t *dst, int dst_format, int count )
#ifdef _YO_PICTURE_BUILTIN
  {
    int i;
    int src_weight = ((src_format >> 8) & 0x0ff);
    int dst_weight = ((dst_format >> 8) & 0x0ff);
    byte_t *src_pixel = src;
    byte_t *dst_pixel = dst;
    if ( src_format == dst_format )
      {
        memcpy(dst,src,count*dst_weight);
      }
    else if ( dst_format  == YO_RGBAf_PICTURE )
      for ( i = 0; i < count; ++i )
        {
          *(YO_RGBAf*)dst_pixel = Pict_Get_RGBAf_Pixel(src_pixel,src_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
    else if ( dst_format  == YO_RGBA8_PICTURE )
      for ( i = 0; i < count; ++i )
        {
          *(YO_RGBA8*)dst_pixel = Pict_Get_RGBA8_Pixel(src_pixel,src_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
    else
      for ( i = 0; i < count; ++i )
        {
          YO_RGBA8 tmp = Pict_Get_RGBA8_Pixel(src_pixel,src_format);
          Pict_Set_RGBA8_Pixel(dst_pixel,tmp,dst_format);
          src_pixel += src_weight;
          dst_pixel += dst_weight;
        }
  }
#endif
  ;
  
void Pict_Convert_Pixels_Row_Pal(byte_t *src, int src_format, byte_t *dst, int dst_format, int count, void *pal, int pal_count )
#ifdef _YO_PICTURE_BUILTIN
  {
    int i, bpp = Pict_Format_Bytes_PP(dst_format);
    byte_t palx[256*16]; /* sizeof(rgbaf) == 16 */
    Pict_Convert_Pixels_Row(pal,src_format,palx,dst_format,pal_count);
    if ( bpp == 4 )
      for ( i = 0; i < count; ++i )
        ((u32_t*)dst)[i] = ((u32_t*)palx)[src[i]];
    else if ( bpp == 2 )
      for ( i = 0; i < count; ++i )
        ((u32_t*)dst)[i] = ((u32_t*)palx)[src[i]];
    else
      for ( i = 0; i < count; ++i )
        memcpy((dst + i * bpp),palx + src[i]*bpp,bpp);
  }
#endif
  ;

#ifdef __windoze
HBITMAP Pict_Create_HBITMAP(YO_PICTURE *pict)
#ifdef _YO_PICTURE_BUILTIN
  {
    BITMAPINFOHEADER bi;
    HDC dc;
    HBITMAP bmp;
    byte_t *bits = 0;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth  = pict->width;
    bi.biHeight = -pict->height;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = pict->width * pict->height * 4;
    dc  = GetDC(0);
    //bmp = CreateCompatibleBitmap(dc,pict->width,pict->height);
    //SetDIBits(dc,bmp,0,pict->height,pict->pixels,(BITMAPINFO*)&bi,DIB_RGB_COLORS);
    bmp = CreateDIBSection(dc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, &bits, 0, 0);
    if ( pict->format == YO_BGRA8_PICTURE )
      memcpy(bits,pict->pixels,bi.biSizeImage);
    else
      {
        int i;
        for ( i = 0; i < pict->height; ++i )
          Pict_Convert_Pixels_Row(
              pict->pixels+i*pict->pitch,pict->format,
              bits+pict->width*4*i,YO_BGRA8_PICTURE,
              pict->width);          
      }
    ReleaseDC(0,dc);
    return bmp;
  }
#endif
  ;
#endif

#endif /* C_once_E194EBE7_E43F_4305_A75C_3872532B12DB */

Changes to pipex.hc.
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
#ifdef __windoze
typedef HANDLE process_t;
#else
typedef int process_t;
#endif

#ifdef _LIBYOYO
#define _YOYO_PIPEX_BUILTIN
#endif

#ifdef _YOYO_PIPEX_BUILTIN
  #define YOYO_PIPEX_EXTERN
#else
  #define YOYO_PIPEX_EXTERN extern
#endif

#define INVALID_PROCESS_ID ((process_t)0)
enum { PIPEX_STILL_ACTIVE = -1, PIPEX_WAS_TERMINATED = -2 };

typedef struct _YOYO_PIPEX
  {
    char *command;
    YOYO_CFILE *fin;
    YOYO_CFILE *fout;
    YOYO_CFILE *ferr;
    process_t pid;
    int exitcode;
  } YOYO_PIPEX;

#ifdef __windoze

typedef struct _YOYO_PIPEX_WINPIPE
  {
    HANDLE pin;
    HANDLE pout;
    HANDLE xhndl;
  }YOYO_PIPEX_WINPIPE;

void YOYO_PIPEX_WINPIPE_Destruct(YOYO_PIPEX_WINPIPE *wp)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( wp->pin && wp->pin != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pin);
    if ( wp->pout && wp->pout != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pout);
    if ( wp->xhndl && wp->xhndl != INVALID_HANDLE_VALUE )
      CloseHandle(wp->xhndl);
    __Destruct(wp);
  }
#endif
  ;
  
#endif

YOYO_PIPEX_EXTERN char *PIPEX_NONE
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)-1
#endif
  ;

YOYO_PIPEX_EXTERN char *PIPEX_WRAP
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)0
#endif
  ;

YOYO_PIPEX_EXTERN char *PIPEX_TMPFILE
#ifdef _YOYO_PIPEX_BUILTIN
  = (char*)-2
#endif
  ;

#define PIPEX_TMPFILE(X) PIPEX_TMPFILE_GEN(X)
char *PIPEX_TMPFILE_GEN(char *fname)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    return Str_Concat("~*",fname);
  }
#endif
  ;
  
void Pipex_Kill(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( pipex->pid != INVALID_PROCESS_ID )
      {
        pipex->exitcode = PIPEX_WAS_TERMINATED;
        TerminateProcess(pipex->pid,255);
        CloseHandle(pipex->pid);
        pipex->pid = INVALID_PROCESS_ID;
      }
    __Unrefe(pipex->fin);
    __Unrefe(pipex->fout);
    __Unrefe(pipex->ferr);
  }
#endif
  ;
  
void YOYO_PIPEX_Destruct(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    Pipex_Kill(pipex);
    __Destruct(pipex);
  }
#endif
  ;
  
void Pipex_Init_Pipe(YOYO_PIPEX_WINPIPE **x, char *xstd, HANDLE *ystd, int wr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    SECURITY_ATTRIBUTES saa = {0};
    saa.nLength = sizeof(SECURITY_ATTRIBUTES);
    *x = __Object_Dtor(sizeof(YOYO_PIPEX_WINPIPE),YOYO_PIPEX_WINPIPE_Destruct);
    if ( xstd == PIPEX_WRAP )
      {
        if ( !CreatePipe(&(*x)->pin, &(*x)->pout, &saa, 0))
          __Raise_System_Error();
        *ystd = !wr ? (*x)->pin : (*x)->pout;
      }
    else if ( xstd == PIPEX_NONE )







|


|
|

|





|


|
|
|


|



|




|

|
|














|
|




|
|




|
|






|






|
|















|
|







|
|



|







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
#ifdef __windoze
typedef HANDLE process_t;
#else
typedef int process_t;
#endif

#ifdef _LIBYOYO
#define _YO_PIPEX_BUILTIN
#endif

#ifdef _YO_PIPEX_BUILTIN
  #define YO_PIPEX_EXTERN
#else
  #define YO_PIPEX_EXTERN extern
#endif

#define INVALID_PROCESS_ID ((process_t)0)
enum { PIPEX_STILL_ACTIVE = -1, PIPEX_WAS_TERMINATED = -2 };

typedef struct _YO_PIPEX
  {
    char *command;
    YO_CFILE *fin;
    YO_CFILE *fout;
    YO_CFILE *ferr;
    process_t pid;
    int exitcode;
  } YO_PIPEX;

#ifdef __windoze

typedef struct _YO_PIPEX_WINPIPE
  {
    HANDLE pin;
    HANDLE pout;
    HANDLE xhndl;
  }YO_PIPEX_WINPIPE;

void YO_PIPEX_WINPIPE_Destruct(YO_PIPEX_WINPIPE *wp)
#ifdef _YO_PIPEX_BUILTIN
  {
    if ( wp->pin && wp->pin != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pin);
    if ( wp->pout && wp->pout != INVALID_HANDLE_VALUE )
      CloseHandle(wp->pout);
    if ( wp->xhndl && wp->xhndl != INVALID_HANDLE_VALUE )
      CloseHandle(wp->xhndl);
    __Destruct(wp);
  }
#endif
  ;
  
#endif

YO_PIPEX_EXTERN char *PIPEX_NONE
#ifdef _YO_PIPEX_BUILTIN
  = (char*)-1
#endif
  ;

YO_PIPEX_EXTERN char *PIPEX_WRAP
#ifdef _YO_PIPEX_BUILTIN
  = (char*)0
#endif
  ;

YO_PIPEX_EXTERN char *PIPEX_TMPFILE
#ifdef _YO_PIPEX_BUILTIN
  = (char*)-2
#endif
  ;

#define PIPEX_TMPFILE(X) PIPEX_TMPFILE_GEN(X)
char *PIPEX_TMPFILE_GEN(char *fname)
#ifdef _YO_PIPEX_BUILTIN
  {
    return Str_Concat("~*",fname);
  }
#endif
  ;
  
void Pipex_Kill(YO_PIPEX *pipex)
#ifdef _YO_PIPEX_BUILTIN
  {
    if ( pipex->pid != INVALID_PROCESS_ID )
      {
        pipex->exitcode = PIPEX_WAS_TERMINATED;
        TerminateProcess(pipex->pid,255);
        CloseHandle(pipex->pid);
        pipex->pid = INVALID_PROCESS_ID;
      }
    __Unrefe(pipex->fin);
    __Unrefe(pipex->fout);
    __Unrefe(pipex->ferr);
  }
#endif
  ;
  
void YO_PIPEX_Destruct(YO_PIPEX *pipex)
#ifdef _YO_PIPEX_BUILTIN
  {
    Pipex_Kill(pipex);
    __Destruct(pipex);
  }
#endif
  ;
  
void Pipex_Init_Pipe(YO_PIPEX_WINPIPE **x, char *xstd, HANDLE *ystd, int wr)
#ifdef _YO_PIPEX_BUILTIN
  {
    SECURITY_ATTRIBUTES saa = {0};
    saa.nLength = sizeof(SECURITY_ATTRIBUTES);
    *x = __Object_Dtor(sizeof(YO_PIPEX_WINPIPE),YO_PIPEX_WINPIPE_Destruct);
    if ( xstd == PIPEX_WRAP )
      {
        if ( !CreatePipe(&(*x)->pin, &(*x)->pout, &saa, 0))
          __Raise_System_Error();
        *ystd = !wr ? (*x)->pin : (*x)->pout;
      }
    else if ( xstd == PIPEX_NONE )
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
        if ( *ystd == INVALID_HANDLE_VALUE )
          __Raise_System_Error();
      }
   }
#endif
  ;

YOYO_CFILE *Pipex_Cfile(YOYO_PIPEX_WINPIPE *wp, int wr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    if ( !(!wr?wp->pin:wp->pout) )
      return 0;
    else
      {
        void *ret;
        int foo = _open_osfhandle((longptr_t)(!wr?wp->pin:wp->pout), (!wr?(_O_RDONLY|_O_BINARY):(_O_WRONLY|_O_BINARY)) );
        FILE *f = _fdopen(foo,!wr?"rb":"wb");
        ret = Cfile_Object(f,"pipex",0);
        if ( !wr )  wp->pin = 0; else wp->pout = 0;
        return ret;
      }
  }
#endif
  ;
  
YOYO_PIPEX *Pipex_Exec(char *command, char *xstdin, char *xstdout, char *xstderr)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    YOYO_PIPEX *pipex = 0;
    __Auto_Ptr(pipex)
      {
        int foo;
        PROCESS_INFORMATION piProcInfo = {0};
        STARTUPINFOW siStartInfo = {0};
        STARTUPINFOW siStartInfo1 = {0};
        
        YOYO_PIPEX_WINPIPE *xin = 0, *xout = 0, *xerr = 0;
        wchar_t *comspec = __Zero_Malloc(257*sizeof(wchar_t));
        
        pipex = __Object_Dtor(sizeof(YOYO_PIPEX),YOYO_PIPEX_Destruct);

        siStartInfo1.cb = sizeof(STARTUPINFOW);
        siStartInfo1.dwFlags    = STARTF_USESTDHANDLES;
        GetStartupInfoW(&siStartInfo1);
        siStartInfo.hStdInput  = siStartInfo1.hStdInput;
        siStartInfo.hStdOutput = siStartInfo1.hStdOutput;
        siStartInfo.hStdError  = siStartInfo1.hStdError;







|
|
















|
|

|







|


|







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
        if ( *ystd == INVALID_HANDLE_VALUE )
          __Raise_System_Error();
      }
   }
#endif
  ;

YO_CFILE *Pipex_Cfile(YO_PIPEX_WINPIPE *wp, int wr)
#ifdef _YO_PIPEX_BUILTIN
  {
    if ( !(!wr?wp->pin:wp->pout) )
      return 0;
    else
      {
        void *ret;
        int foo = _open_osfhandle((longptr_t)(!wr?wp->pin:wp->pout), (!wr?(_O_RDONLY|_O_BINARY):(_O_WRONLY|_O_BINARY)) );
        FILE *f = _fdopen(foo,!wr?"rb":"wb");
        ret = Cfile_Object(f,"pipex",0);
        if ( !wr )  wp->pin = 0; else wp->pout = 0;
        return ret;
      }
  }
#endif
  ;
  
YO_PIPEX *Pipex_Exec(char *command, char *xstdin, char *xstdout, char *xstderr)
#ifdef _YO_PIPEX_BUILTIN
  {
    YO_PIPEX *pipex = 0;
    __Auto_Ptr(pipex)
      {
        int foo;
        PROCESS_INFORMATION piProcInfo = {0};
        STARTUPINFOW siStartInfo = {0};
        STARTUPINFOW siStartInfo1 = {0};
        
        YO_PIPEX_WINPIPE *xin = 0, *xout = 0, *xerr = 0;
        wchar_t *comspec = __Zero_Malloc(257*sizeof(wchar_t));
        
        pipex = __Object_Dtor(sizeof(YO_PIPEX),YO_PIPEX_Destruct);

        siStartInfo1.cb = sizeof(STARTUPINFOW);
        siStartInfo1.dwFlags    = STARTF_USESTDHANDLES;
        GetStartupInfoW(&siStartInfo1);
        siStartInfo.hStdInput  = siStartInfo1.hStdInput;
        siStartInfo.hStdOutput = siStartInfo1.hStdOutput;
        siStartInfo.hStdError  = siStartInfo1.hStdError;
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
      }      
    
    return pipex;
  }
#endif
  ;
  
int Pipex_Exit_Code(YOYO_PIPEX *pipex)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    unsigned long ecode;
    if ( pipex->pid != INVALID_PROCESS_ID )
      if ( GetExitCodeProcess(pipex->pid,&ecode) )
        if ( ecode == STILL_ACTIVE )
          return PIPEX_STILL_ACTIVE;
        else
          pipex->exitcode = ecode;
    return pipex->exitcode;
  }
#endif
  ;
  
int Pipex_Wait(YOYO_PIPEX *pipex, int ms)
#ifdef _YOYO_PIPEX_BUILTIN
  {
    while ( Pipex_Exit_Code(pipex) == PIPEX_STILL_ACTIVE )
      {  
        if ( WaitForSingleObject(pipex->pid,ms) == WAIT_TIMEOUT ) 
          return PIPEX_STILL_ACTIVE;
      }
    return pipex->exitcode;
  }
#endif
  ;
  







|
|













|
|











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
      }      
    
    return pipex;
  }
#endif
  ;
  
int Pipex_Exit_Code(YO_PIPEX *pipex)
#ifdef _YO_PIPEX_BUILTIN
  {
    unsigned long ecode;
    if ( pipex->pid != INVALID_PROCESS_ID )
      if ( GetExitCodeProcess(pipex->pid,&ecode) )
        if ( ecode == STILL_ACTIVE )
          return PIPEX_STILL_ACTIVE;
        else
          pipex->exitcode = ecode;
    return pipex->exitcode;
  }
#endif
  ;
  
int Pipex_Wait(YO_PIPEX *pipex, int ms)
#ifdef _YO_PIPEX_BUILTIN
  {
    while ( Pipex_Exit_Code(pipex) == PIPEX_STILL_ACTIVE )
      {  
        if ( WaitForSingleObject(pipex->pid,ms) == WAIT_TIMEOUT ) 
          return PIPEX_STILL_ACTIVE;
      }
    return pipex->exitcode;
  }
#endif
  ;
  
Changes to prog.hc.
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

*/

#ifndef C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F
#define C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F

#ifdef _LIBYOYO
#define _YOYO_PROG_BUILTIN
#endif

#include "yoyo.hc"
#include "dicto.hc"
#include "array.hc"
#include "string.hc"
#include "logout.hc"

#ifdef _YOYO_PROG_BUILTIN
static void *Prog_Data_Opts = 0;
static void *Prog_Data_Args = 0;
static char *Prog_Dir_S = 0;
static char *Prog_Nam_S = 0;
#endif

enum _YOYO_ROG_FLAGS
  {
    PROG_CMDLINE_OPTS_FIRST = 1,
    PROG_EXIT_ON_ERROR = 2,
  };

typedef enum _YOYO_PROG_PARAM_FEATURES
  {
    PROG_PARAM_HAS_NO_ARGUMENT,
    PROG_PARAM_HAS_ARGUMENT,
    PROG_PARAM_CAN_HAVE_ARGUMENT
  } YOYO_PROG_PARAM_FEATURES;

typedef struct _YOYO_PROG_PARAM_INFO
  {
    void *vals;
    int  *present;
    YOYO_PROG_PARAM_FEATURES features;
  } YOYO_PROG_PARAM_INFO;

void Prog_Param_Info_Destruct(YOYO_PROG_PARAM_INFO *o)
#ifdef _YOYO_PROG_BUILTIN
  {
    Yo_Unrefe(o->vals);
    Yo_Unrefe(o->present);
    Yo_Object_Destruct(o);
  }
#endif
  ;

void *Prog_Param_Info(void)
#ifdef _YOYO_PROG_BUILTIN
  {
    return Yo_Object_Dtor(sizeof(YOYO_PROG_PARAM_INFO),Prog_Param_Info_Destruct);
  }
#endif
  ;

void *Prog_Parse_Command_Line_Pattern(char *patt)
#ifdef _YOYO_PROG_BUILTIN
  {
    int i,j;
    void *dt = Dicto_Refs();
    YOYO_ARRAY *L = Str_Split(patt,",; \t\n\r");
    
    for ( i = 0; i < L->count; ++i )
      {
        YOYO_ARRAY *Q = Str_Split(L->at[i],"|");
        if ( Q->count )
          {
            int *present = Yo_Object(sizeof(int),0);
            void *vals = 0;
            
            for ( j = 0; j < Q->count; ++j )
              {
                YOYO_PROG_PARAM_INFO *nfo = Prog_Param_Info();
                char *S = Q->at[j];
                int S_Ln = strlen(S)-1;
                
                if ( S[S_Ln] == ':' )
                  { 
                    nfo->features = PROG_PARAM_HAS_ARGUMENT; 
                    S[S_Ln] = 0;







|








|






|





|




|

|



|
|

|
|









|

|





|



|



|







|







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

*/

#ifndef C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F
#define C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F

#ifdef _LIBYOYO
#define _YO_PROG_BUILTIN
#endif

#include "yoyo.hc"
#include "dicto.hc"
#include "array.hc"
#include "string.hc"
#include "logout.hc"

#ifdef _YO_PROG_BUILTIN
static void *Prog_Data_Opts = 0;
static void *Prog_Data_Args = 0;
static char *Prog_Dir_S = 0;
static char *Prog_Nam_S = 0;
#endif

enum _YO_ROG_FLAGS
  {
    PROG_CMDLINE_OPTS_FIRST = 1,
    PROG_EXIT_ON_ERROR = 2,
  };

typedef enum _YO_PROG_PARAM_FEATURES
  {
    PROG_PARAM_HAS_NO_ARGUMENT,
    PROG_PARAM_HAS_ARGUMENT,
    PROG_PARAM_CAN_HAVE_ARGUMENT
  } YO_PROG_PARAM_FEATURES;

typedef struct _YO_PROG_PARAM_INFO
  {
    void *vals;
    int  *present;
    YO_PROG_PARAM_FEATURES features;
  } YO_PROG_PARAM_INFO;

void Prog_Param_Info_Destruct(YO_PROG_PARAM_INFO *o)
#ifdef _YO_PROG_BUILTIN
  {
    Yo_Unrefe(o->vals);
    Yo_Unrefe(o->present);
    Yo_Object_Destruct(o);
  }
#endif
  ;

void *Prog_Param_Info(void)
#ifdef _YO_PROG_BUILTIN
  {
    return Yo_Object_Dtor(sizeof(YO_PROG_PARAM_INFO),Prog_Param_Info_Destruct);
  }
#endif
  ;

void *Prog_Parse_Command_Line_Pattern(char *patt)
#ifdef _YO_PROG_BUILTIN
  {
    int i,j;
    void *dt = Dicto_Refs();
    YO_ARRAY *L = Str_Split(patt,",; \t\n\r");
    
    for ( i = 0; i < L->count; ++i )
      {
        YO_ARRAY *Q = Str_Split(L->at[i],"|");
        if ( Q->count )
          {
            int *present = Yo_Object(sizeof(int),0);
            void *vals = 0;
            
            for ( j = 0; j < Q->count; ++j )
              {
                YO_PROG_PARAM_INFO *nfo = Prog_Param_Info();
                char *S = Q->at[j];
                int S_Ln = strlen(S)-1;
                
                if ( S[S_Ln] == ':' )
                  { 
                    nfo->features = PROG_PARAM_HAS_ARGUMENT; 
                    S[S_Ln] = 0;
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
      
    return dt;
  }
#endif
  ;

void Prog_Parse_Command_Line(int argc, char **argv, char *patt, unsigned flags)
#ifdef _YOYO_PROG_BUILTIN
  {
    int i;
    void *args = Array_Void();
    void *opts = Prog_Parse_Command_Line_Pattern(patt);
    
    int argument_passed = 0;
    for ( i = 1; i < argc; ++i )
      {
        if ( (*argv[i] == '-' && argv[i][1] && (argv[i][1] != '-' || argv[i][2]))
          && (!(flags&PROG_CMDLINE_OPTS_FIRST)||!argument_passed) )
          {
            YOYO_ARRAY *L;
            YOYO_PROG_PARAM_INFO *a;
            char *Q = argv[i]+1;
            
            if ( *Q == '-' ) ++Q;
            if ( !*Q ) continue;

            L = Str_Split_Once(Q,"=");
            if ( 0 != (a = Dicto_Get(opts,L->at[0],0)) )
              {
                if ( a->features == PROG_PARAM_HAS_ARGUMENT && L->count == 1 )
                  {
                    if ( argc > i+1 )
                      {
                      #ifdef __windoze
                        Array_Push(L,Str_Locale_To_Utf8_Npl(argv[i+1])); 
                      #else
                        Array_Push(L,Str_Copy_Npl(argv[i+1],-1)); 
                      #endif
                        ++i;
                      }
                    else
                        Yo_Raise(YOYO_ERROR_ILLFORMED,
                                  Yo_Format("comandline option -%s requires parameter",(L->at)[0]),
                                  __FILE__,__LINE__);
                  }
                                
                if ( a->features == PROG_PARAM_HAS_NO_ARGUMENT && L->count > 1 )
                      Yo_Raise(YOYO_ERROR_ILLFORMED,
                                Yo_Format("comandline option -%s does not have parameter",(L->at)[0]),
                                __FILE__,__LINE__);
                *a->present = 1;
                if ( L->count > 1 )
                  Array_Push(a->vals,Array_Take_Npl(L,1));
              }
            else
                Yo_Raise(YOYO_ERROR_ILLFORMED,
                          Yo_Format("unknown comandline option -%s",(L->at)[0]),
                          __FILE__,__LINE__);
          }
        else
          {
            argument_passed = 1;
            Array_Push(args,argv[i]);
          }
      }

    Prog_Data_Opts = Yo_Refe(opts);
    Prog_Data_Args = Yo_Refe(args);
  }
#endif
  ;

void Prog_Clear_At_Exit(void)
#ifdef _YOYO_PROG_BUILTIN
  {
    Close_Log();
    Yo_Unrefe(Prog_Data_Opts);
    Yo_Unrefe(Prog_Data_Args);
    Yo_Thread_Cleanup();
    Yo_Global_Cleanup();
    free(Prog_Dir_S);
    free(Prog_Nam_S);
  }
#endif
  ;
  
int Prog_Init(int argc, char **argv, char *patt, unsigned flags)
#ifdef _YOYO_PROG_BUILTIN
  {
    int rt = 0;
    __Auto_Release __Try_Except
      {
        setlocale(LC_NUMERIC,"C");
        setlocale(LC_TIME,"C");
        Prog_Parse_Command_Line(argc,argv,patt,flags);







|











|
|




















|





|







|

















|













|







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
      
    return dt;
  }
#endif
  ;

void Prog_Parse_Command_Line(int argc, char **argv, char *patt, unsigned flags)
#ifdef _YO_PROG_BUILTIN
  {
    int i;
    void *args = Array_Void();
    void *opts = Prog_Parse_Command_Line_Pattern(patt);
    
    int argument_passed = 0;
    for ( i = 1; i < argc; ++i )
      {
        if ( (*argv[i] == '-' && argv[i][1] && (argv[i][1] != '-' || argv[i][2]))
          && (!(flags&PROG_CMDLINE_OPTS_FIRST)||!argument_passed) )
          {
            YO_ARRAY *L;
            YO_PROG_PARAM_INFO *a;
            char *Q = argv[i]+1;
            
            if ( *Q == '-' ) ++Q;
            if ( !*Q ) continue;

            L = Str_Split_Once(Q,"=");
            if ( 0 != (a = Dicto_Get(opts,L->at[0],0)) )
              {
                if ( a->features == PROG_PARAM_HAS_ARGUMENT && L->count == 1 )
                  {
                    if ( argc > i+1 )
                      {
                      #ifdef __windoze
                        Array_Push(L,Str_Locale_To_Utf8_Npl(argv[i+1])); 
                      #else
                        Array_Push(L,Str_Copy_Npl(argv[i+1],-1)); 
                      #endif
                        ++i;
                      }
                    else
                        Yo_Raise(YO_ERROR_ILLFORMED,
                                  Yo_Format("comandline option -%s requires parameter",(L->at)[0]),
                                  __FILE__,__LINE__);
                  }
                                
                if ( a->features == PROG_PARAM_HAS_NO_ARGUMENT && L->count > 1 )
                      Yo_Raise(YO_ERROR_ILLFORMED,
                                Yo_Format("comandline option -%s does not have parameter",(L->at)[0]),
                                __FILE__,__LINE__);
                *a->present = 1;
                if ( L->count > 1 )
                  Array_Push(a->vals,Array_Take_Npl(L,1));
              }
            else
                Yo_Raise(YO_ERROR_ILLFORMED,
                          Yo_Format("unknown comandline option -%s",(L->at)[0]),
                          __FILE__,__LINE__);
          }
        else
          {
            argument_passed = 1;
            Array_Push(args,argv[i]);
          }
      }

    Prog_Data_Opts = Yo_Refe(opts);
    Prog_Data_Args = Yo_Refe(args);
  }
#endif
  ;

void Prog_Clear_At_Exit(void)
#ifdef _YO_PROG_BUILTIN
  {
    Close_Log();
    Yo_Unrefe(Prog_Data_Opts);
    Yo_Unrefe(Prog_Data_Args);
    Yo_Thread_Cleanup();
    Yo_Global_Cleanup();
    free(Prog_Dir_S);
    free(Prog_Nam_S);
  }
#endif
  ;
  
int Prog_Init(int argc, char **argv, char *patt, unsigned flags)
#ifdef _YO_PROG_BUILTIN
  {
    int rt = 0;
    __Auto_Release __Try_Except
      {
        setlocale(LC_NUMERIC,"C");
        setlocale(LC_TIME,"C");
        Prog_Parse_Command_Line(argc,argv,patt,flags);
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
          Error_Print_N_Exit(Yo__basename(argv[0]),-1);
      }
    return rt;
  }
#endif
  ;

YOYO_ARRAY *Prog_Argc_Argv(char *input)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_ARRAY *argv = Array_Pchars();
    
    __Auto_Release
      {
        int   argc;
        char *arg;
        char *copybuf;
        int   dquote = 0;







|
|

|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
          Error_Print_N_Exit(Yo__basename(argv[0]),-1);
      }
    return rt;
  }
#endif
  ;

YO_ARRAY *Prog_Argc_Argv(char *input)
#ifdef _YO_PROG_BUILTIN
  {
    YO_ARRAY *argv = Array_Pchars();
    
    __Auto_Release
      {
        int   argc;
        char *arg;
        char *copybuf;
        int   dquote = 0;
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
    return argv;
  }
#endif
  ;
  
#ifdef __windoze
int Prog_Init_Windoze(char *patt, unsigned flags)
#ifdef _YOYO_PROG_BUILTIN
  {
    int rt;
    
    __Auto_Release
      {
        YOYO_ARRAY *argv = Prog_Argc_Argv(Str_Unicode_To_Utf8(GetCommandLineW()));
        rt = Prog_Init(argv->count,(char**)argv->at,patt,flags);
      }
      
    return rt;
  }
#endif
  ;
#endif

int Prog_Arguments_Count()
#ifdef _YOYO_PROG_BUILTIN
  {
    return Array_Count(Prog_Data_Args);
  }
#endif
  ;

char *Prog_Argument(int no)
#ifdef _YOYO_PROG_BUILTIN
  {
    return Array_At(Prog_Data_Args,no);
  }
#endif
  ;

char *Prog_Argument_Dflt(int no,char *dflt)
#ifdef _YOYO_PROG_BUILTIN
  {
    if ( no < 0 || no >= Array_Count(Prog_Data_Args) )
      return dflt;
    return Array_At(Prog_Data_Args,no);
  }
#endif
  ;

int Prog_Argument_Int(int no)
#ifdef _YOYO_PROG_BUILTIN
  {
    char *S = Array_At(Prog_Data_Args,no);
    return strtol(S,0,10);
  }
#endif
  ;

int Prog_Has_Opt(char *name)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    return i && *i->present;    
  }
#endif
  ;

int Prog_Opt_Count(char *name)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( i && *i->present && i->vals )
      return Array_Count(i->vals);
    return 0;
  }
#endif
  ;

char *Prog_Opt(char *name,int no)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals )
      return 0;
    return Array_At(i->vals,no);
  }
#endif
  ;
  
char *Prog_First_Opt(char *name,char *dflt)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals || !Array_Count(i->vals) )
      return dflt;
    return Array_At(i->vals,0);
  }
#endif
  ;

int Prog_First_Opt_Int(char *name,int dflt)
#ifdef _YOYO_PROG_BUILTIN
  {
    char *Q = Prog_First_Opt(name,0);
    if ( !Q ) return dflt;
    return strtol(Q,0,10);
  }
#endif
  ;

char *Prog_Last_Opt(char *name,char *dflt)
#ifdef _YOYO_PROG_BUILTIN
  {
    YOYO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals || !Array_Count(i->vals) )
      return dflt;
    return Array_At(i->vals,-1);
  }
#endif
  ;

int Prog_Last_Opt_Int(char *name,int dflt)
#ifdef _YOYO_PROG_BUILTIN
  {
    char *Q = Prog_Last_Opt(name,0);
    if ( !Q ) return dflt;
    return strtol(Q,0,10);
  }
#endif
  ;

char *Prog_Directory()
#ifdef _YOYO_PROG_BUILTIN
  {
    return Prog_Dir_S;
  }
#endif
  ;

char *Prog_Fullname()
#ifdef _YOYO_PROG_BUILTIN
  {
    return Prog_Nam_S;
  }
#endif
  ;

#endif /* C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F */








|





|










|







|







|









|








|

|






|

|








|

|








|

|








|









|

|








|









|







|








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
    return argv;
  }
#endif
  ;
  
#ifdef __windoze
int Prog_Init_Windoze(char *patt, unsigned flags)
#ifdef _YO_PROG_BUILTIN
  {
    int rt;
    
    __Auto_Release
      {
        YO_ARRAY *argv = Prog_Argc_Argv(Str_Unicode_To_Utf8(GetCommandLineW()));
        rt = Prog_Init(argv->count,(char**)argv->at,patt,flags);
      }
      
    return rt;
  }
#endif
  ;
#endif

int Prog_Arguments_Count()
#ifdef _YO_PROG_BUILTIN
  {
    return Array_Count(Prog_Data_Args);
  }
#endif
  ;

char *Prog_Argument(int no)
#ifdef _YO_PROG_BUILTIN
  {
    return Array_At(Prog_Data_Args,no);
  }
#endif
  ;

char *Prog_Argument_Dflt(int no,char *dflt)
#ifdef _YO_PROG_BUILTIN
  {
    if ( no < 0 || no >= Array_Count(Prog_Data_Args) )
      return dflt;
    return Array_At(Prog_Data_Args,no);
  }
#endif
  ;

int Prog_Argument_Int(int no)
#ifdef _YO_PROG_BUILTIN
  {
    char *S = Array_At(Prog_Data_Args,no);
    return strtol(S,0,10);
  }
#endif
  ;

int Prog_Has_Opt(char *name)
#ifdef _YO_PROG_BUILTIN
  {
    YO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    return i && *i->present;    
  }
#endif
  ;

int Prog_Opt_Count(char *name)
#ifdef _YO_PROG_BUILTIN
  {
    YO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( i && *i->present && i->vals )
      return Array_Count(i->vals);
    return 0;
  }
#endif
  ;

char *Prog_Opt(char *name,int no)
#ifdef _YO_PROG_BUILTIN
  {
    YO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals )
      return 0;
    return Array_At(i->vals,no);
  }
#endif
  ;
  
char *Prog_First_Opt(char *name,char *dflt)
#ifdef _YO_PROG_BUILTIN
  {
    YO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals || !Array_Count(i->vals) )
      return dflt;
    return Array_At(i->vals,0);
  }
#endif
  ;

int Prog_First_Opt_Int(char *name,int dflt)
#ifdef _YO_PROG_BUILTIN
  {
    char *Q = Prog_First_Opt(name,0);
    if ( !Q ) return dflt;
    return strtol(Q,0,10);
  }
#endif
  ;

char *Prog_Last_Opt(char *name,char *dflt)
#ifdef _YO_PROG_BUILTIN
  {
    YO_PROG_PARAM_INFO *i = Dicto_Get(Prog_Data_Opts,name,0);
    if ( !i || !*i->present || !i->vals || !Array_Count(i->vals) )
      return dflt;
    return Array_At(i->vals,-1);
  }
#endif
  ;

int Prog_Last_Opt_Int(char *name,int dflt)
#ifdef _YO_PROG_BUILTIN
  {
    char *Q = Prog_Last_Opt(name,0);
    if ( !Q ) return dflt;
    return strtol(Q,0,10);
  }
#endif
  ;

char *Prog_Directory()
#ifdef _YO_PROG_BUILTIN
  {
    return Prog_Dir_S;
  }
#endif
  ;

char *Prog_Fullname()
#ifdef _YO_PROG_BUILTIN
  {
    return Prog_Nam_S;
  }
#endif
  ;

#endif /* C_once_AF69CAD4_02C8_492E_9C13_B69483693E5F */

Changes to random.hc.
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

*/

#ifndef C_once_FF657866_8205_4CAE_9D01_65B8583E9D19
#define C_once_FF657866_8205_4CAE_9D01_65B8583E9D19

#ifdef _LIBYOYO
#define _YOYO_RANDOM_BUILTIN
#endif

#include "yoyo.hc"
#include "sha1.hc"

#ifdef __windoze
# include <wincrypt.h>
# ifdef _MSC_VER
#  pragma comment(lib,"advapi32.lib")
# endif
#else
#endif

#define _YOYO_DEV_RANDOM "/dev/urandom"

#ifdef _YOYO_RANDOM_BUILTIN
# define _YOYO_RANDOM_EXTERN
# define _YOYO_RANDOM_BUILTIN_CODE(Code) Code
#else
# define _YOYO_RANDOM_EXTERN extern
# define _YOYO_RANDOM_BUILTIN_CODE(Code)
#endif

void Soft_Random(byte_t *bits, int count)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    static uquad_t rnd_ct[4] = {0};
    static byte_t  rnd_bits[20] = {0}; 
    static int rnd_bcont = 0;
    static int initialized = 0;
    __Xchg_Interlock
      {







|













|

|
|
|

|
|



|







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

*/

#ifndef C_once_FF657866_8205_4CAE_9D01_65B8583E9D19
#define C_once_FF657866_8205_4CAE_9D01_65B8583E9D19

#ifdef _LIBYOYO
#define _YO_RANDOM_BUILTIN
#endif

#include "yoyo.hc"
#include "sha1.hc"

#ifdef __windoze
# include <wincrypt.h>
# ifdef _MSC_VER
#  pragma comment(lib,"advapi32.lib")
# endif
#else
#endif

#define _YO_DEV_RANDOM "/dev/urandom"

#ifdef _YO_RANDOM_BUILTIN
# define _YO_RANDOM_EXTERN
# define _YO_RANDOM_BUILTIN_CODE(Code) Code
#else
# define _YO_RANDOM_EXTERN extern
# define _YO_RANDOM_BUILTIN_CODE(Code)
#endif

void Soft_Random(byte_t *bits, int count)
#ifdef _YO_RANDOM_BUILTIN
  {
    static uquad_t rnd_ct[4] = {0};
    static byte_t  rnd_bits[20] = {0}; 
    static int rnd_bcont = 0;
    static int initialized = 0;
    __Xchg_Interlock
      {
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
          }
      }
  }
#endif
  ;
  
void System_Random(void *bits,int count /* of bytes*/ )
#ifdef _YOYO_RANDOM_BUILTIN
  {
  #ifdef _SOFTRND
    goto simulate;
  #elif !defined __windoze
    int i, fd = open(_YOYO_DEV_RANDOM,O_RDONLY|O_NONBLOCK);
    if ( fd >= 0 )
      {
        for ( i = 0; i < count; )
          {
            int rd = read(fd,bits+i,count-i);
            if ( rd < 0 )
              {
                if ( rd == EAGAIN )
                  {
                    Soft_Random(bits+i,count-i);
                    break;
                  }
                else
                  {
                    char *err = strerror(errno);
                    close(fd);
                    __Raise_Format(YOYO_ERROR_IO,
                      (_YOYO_DEV_RANDOM " does not have required data: %s",err));
                  }
              }
            i += rd;
          }
        close(fd);
        return;
      }







|




|
















|
|







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
          }
      }
  }
#endif
  ;
  
void System_Random(void *bits,int count /* of bytes*/ )
#ifdef _YO_RANDOM_BUILTIN
  {
  #ifdef _SOFTRND
    goto simulate;
  #elif !defined __windoze
    int i, fd = open(_YO_DEV_RANDOM,O_RDONLY|O_NONBLOCK);
    if ( fd >= 0 )
      {
        for ( i = 0; i < count; )
          {
            int rd = read(fd,bits+i,count-i);
            if ( rd < 0 )
              {
                if ( rd == EAGAIN )
                  {
                    Soft_Random(bits+i,count-i);
                    break;
                  }
                else
                  {
                    char *err = strerror(errno);
                    close(fd);
                    __Raise_Format(YO_ERROR_IO,
                      (_YO_DEV_RANDOM " does not have required data: %s",err));
                  }
              }
            i += rd;
          }
        close(fd);
        return;
      }
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  simulate:
    Soft_Random(bits,count);
  }
#endif
  ;

ulong_t Random_Bits(int no)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    static byte_t bits[128] = {0};
    static int bits_count = 0;
    ulong_t r = 0;
    
    STRICT_REQUIRE( no > 0 && no <= sizeof(ulong_t)*8 );
    







|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  simulate:
    Soft_Random(bits,count);
  }
#endif
  ;

ulong_t Random_Bits(int no)
#ifdef _YO_RANDOM_BUILTIN
  {
    static byte_t bits[128] = {0};
    static int bits_count = 0;
    ulong_t r = 0;
    
    STRICT_REQUIRE( no > 0 && no <= sizeof(ulong_t)*8 );
    
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
    return r;
  }
#endif
  ;

#if 0
ulong_t Get_Random(unsigned min, unsigned max)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    ulong_t r;
    int k = sizeof(r)*8/2;
    STRICT_REQUIRE(max > min);
    r = ((Random_Bits(k)*(max-min))>>k) + min;
    STRICT_REQUIRE(r >= min && r < max);
    return r;
  }
#endif
  ;
#endif

uint_t Get_Random(uint_t min, uint_t max)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    uint_t r;
    uint_t dif = max - min;
    STRICT_REQUIRE(max > min);
    r = (uint_t)(((uquad_t)Random_Bits(32)*dif) >> 32) + min;
    STRICT_REQUIRE(r >= min && r < max);
    return r;







|













|







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
    return r;
  }
#endif
  ;

#if 0
ulong_t Get_Random(unsigned min, unsigned max)
#ifdef _YO_RANDOM_BUILTIN
  {
    ulong_t r;
    int k = sizeof(r)*8/2;
    STRICT_REQUIRE(max > min);
    r = ((Random_Bits(k)*(max-min))>>k) + min;
    STRICT_REQUIRE(r >= min && r < max);
    return r;
  }
#endif
  ;
#endif

uint_t Get_Random(uint_t min, uint_t max)
#ifdef _YO_RANDOM_BUILTIN
  {
    uint_t r;
    uint_t dif = max - min;
    STRICT_REQUIRE(max > min);
    r = (uint_t)(((uquad_t)Random_Bits(32)*dif) >> 32) + min;
    STRICT_REQUIRE(r >= min && r < max);
    return r;
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
Hiroshima University and The University of Tokyo.
All rights reserved.
The 3-clause BSD License is applied to this software
*/

enum
  {
    YOYO_FASTRND_TINYMT32_MEXP = 127,
    YOYO_FASTRND_TINYMT32_SH0  = 1,
    YOYO_FASTRND_TINYMT32_SH1  = 10,
    YOYO_FASTRND_TINYMT32_SH8  = 8,
    YOYO_FASTRND_TINYMT32_MASK = 0x7fffffff,
  };
  
typedef struct _YOYO_FASTRND
  {
    uint_t status[4];
    uint_t mat1;
    uint_t mat2;
    uint_t tmat;
  } YOYO_FASTRND;

void Fast_Random_Next_State(YOYO_FASTRND *random)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    uint_t x;
    uint_t y;
    
    y = random->status[3];
    x = (random->status[0] & YOYO_FASTRND_TINYMT32_MASK)
        ^ random->status[1]
        ^ random->status[2];
    x ^= (x << YOYO_FASTRND_TINYMT32_SH0);
    y ^= (y >> YOYO_FASTRND_TINYMT32_SH0) ^ x;
    random->status[0] = random->status[1];
    random->status[1] = random->status[2];
    random->status[2] = x ^ (y << YOYO_FASTRND_TINYMT32_SH1);
    random->status[3] = y;
    random->status[1] ^= -((int)(y & 1)) & random->mat1;
    random->status[2] ^= -((int)(y & 1)) & random->mat2;
  }
#endif
  ;

uint_t Fast_Random_Temper(YOYO_FASTRND *random)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    uint_t t0, t1;
    t0 = random->status[3];
    t1 = random->status[0] + (random->status[2] >> YOYO_FASTRND_TINYMT32_SH8);
    t0 ^= t1;
    t0 ^= -((int)(t1 & 1)) & random->tmat;
    return t0;
  }
#endif
  ;

_YOYO_RANDOM_EXTERN char Oj_Random_32_OjMID[] _YOYO_RANDOM_BUILTIN_CODE( = "random_32/@"); 
uint_t Oj_Random_32(void *random) _YOYO_RANDOM_BUILTIN_CODE(
  { return 
      ((uint_t(*)(void*))Yo_Find_Method_Of(&random,Oj_Random_32_OjMID,YO_RAISE_ERROR))
        (random); });

_YOYO_RANDOM_EXTERN char Oj_Random_Flt_OjMID[] _YOYO_RANDOM_BUILTIN_CODE( = "random_flt/@"); 
float Oj_Random_Flt(void *random) _YOYO_RANDOM_BUILTIN_CODE(
  { return 
      ((float(*)(void*))Yo_Find_Method_Of(&random,Oj_Random_Flt_OjMID,YO_RAISE_ERROR))
        (random); });

_YOYO_RANDOM_EXTERN char Oj_Random_OjMID[] _YOYO_RANDOM_BUILTIN_CODE( = "random/@ii"); 
int Oj_Random(void *random,int min_val,int max_val) _YOYO_RANDOM_BUILTIN_CODE(
  { return 
      ((int(*)(void*,int,int))Yo_Find_Method_Of(&random,Oj_Random_OjMID,YO_RAISE_ERROR))
        (random,min_val,max_val); });

uint_t Fast_Random_Next_32(YOYO_FASTRND *random)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    Fast_Random_Next_State(random);
    return Fast_Random_Temper(random);
  }
#endif
  ;

float Fast_Random_Next_Flt(YOYO_FASTRND *random)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    Fast_Random_Next_State(random);
    return Fast_Random_Temper(random) * (1.0f / 4294967296.0f);
  }
#endif
  ;

int Fast_Random(YOYO_FASTRND *random,int min_val, int max_val)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    quad_t q;
    Fast_Random_Next_State(random);
    q = Fast_Random_Temper(random);
    return (int)((q * max_val)>>32) + min_val;
  }
#endif
  ;

void Fast_Random_Period_Certification(YOYO_FASTRND *random) 
#ifdef _YOYO_RANDOM_BUILTIN
  {
    if ( !(random->status[0] & YOYO_FASTRND_TINYMT32_MASK)
      && !random->status[1] 
      && !random->status[2]
      && !random->status[3]) 
      {
        random->status[0] = 'T';
        random->status[1] = 'I';
        random->status[2] = 'N';
        random->status[3] = 'Y';
      }
  }
#endif
  ;
  
YOYO_FASTRND *Fast_Random_Init_Static(YOYO_FASTRND *random,uint_t seed)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    int i;
    random->status[0] = seed;
    random->status[1] = random->mat1;
    random->status[2] = random->mat2;
    random->status[3] = random->tmat;
    for (i = 1; i < 8; i++) 
      {
        random->status[i & 3] ^= i + 1812433253U
          * (random->status[(i - 1) & 3]
          ^ (random->status[(i - 1) & 3] >> 30));
      }
    Fast_Random_Period_Certification(random);
    for (i = 0; i < 8; i++)
      Fast_Random_Next_State(random);
    return random;
  }
#endif
  ;

YOYO_FASTRND *Fast_Random_Init(uint_t seed)
#ifdef _YOYO_RANDOM_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Random_32_OjMID,  Fast_Random_Next_32},
        {Oj_Random_Flt_OjMID, Fast_Random_Next_Flt},
        {Oj_Random_OjMID,     Fast_Random},
        {0}};
    YOYO_FASTRND *random = __Object(sizeof(YOYO_FASTRND),funcs);
    return Fast_Random_Init_Static(random,seed);
  }
#endif
  ;

#endif /* C_once_FF657866_8205_4CAE_9D01_65B8583E9D19 */








|
|
|
|
|


|





|

|
|





|


|
|


|







|
|



|







|
|




|
|




|
|




|
|







|
|







|
|









|
|

|













|
|




















|
|

|





|







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
Hiroshima University and The University of Tokyo.
All rights reserved.
The 3-clause BSD License is applied to this software
*/

enum
  {
    YO_FASTRND_TINYMT32_MEXP = 127,
    YO_FASTRND_TINYMT32_SH0  = 1,
    YO_FASTRND_TINYMT32_SH1  = 10,
    YO_FASTRND_TINYMT32_SH8  = 8,
    YO_FASTRND_TINYMT32_MASK = 0x7fffffff,
  };
  
typedef struct _YO_FASTRND
  {
    uint_t status[4];
    uint_t mat1;
    uint_t mat2;
    uint_t tmat;
  } YO_FASTRND;

void Fast_Random_Next_State(YO_FASTRND *random)
#ifdef _YO_RANDOM_BUILTIN
  {
    uint_t x;
    uint_t y;
    
    y = random->status[3];
    x = (random->status[0] & YO_FASTRND_TINYMT32_MASK)
        ^ random->status[1]
        ^ random->status[2];
    x ^= (x << YO_FASTRND_TINYMT32_SH0);
    y ^= (y >> YO_FASTRND_TINYMT32_SH0) ^ x;
    random->status[0] = random->status[1];
    random->status[1] = random->status[2];
    random->status[2] = x ^ (y << YO_FASTRND_TINYMT32_SH1);
    random->status[3] = y;
    random->status[1] ^= -((int)(y & 1)) & random->mat1;
    random->status[2] ^= -((int)(y & 1)) & random->mat2;
  }
#endif
  ;

uint_t Fast_Random_Temper(YO_FASTRND *random)
#ifdef _YO_RANDOM_BUILTIN
  {
    uint_t t0, t1;
    t0 = random->status[3];
    t1 = random->status[0] + (random->status[2] >> YO_FASTRND_TINYMT32_SH8);
    t0 ^= t1;
    t0 ^= -((int)(t1 & 1)) & random->tmat;
    return t0;
  }
#endif
  ;

_YO_RANDOM_EXTERN char Oj_Random_32_OjMID[] _YO_RANDOM_BUILTIN_CODE( = "random_32/@"); 
uint_t Oj_Random_32(void *random) _YO_RANDOM_BUILTIN_CODE(
  { return 
      ((uint_t(*)(void*))Yo_Find_Method_Of(&random,Oj_Random_32_OjMID,YO_RAISE_ERROR))
        (random); });

_YO_RANDOM_EXTERN char Oj_Random_Flt_OjMID[] _YO_RANDOM_BUILTIN_CODE( = "random_flt/@"); 
float Oj_Random_Flt(void *random) _YO_RANDOM_BUILTIN_CODE(
  { return 
      ((float(*)(void*))Yo_Find_Method_Of(&random,Oj_Random_Flt_OjMID,YO_RAISE_ERROR))
        (random); });

_YO_RANDOM_EXTERN char Oj_Random_OjMID[] _YO_RANDOM_BUILTIN_CODE( = "random/@ii"); 
int Oj_Random(void *random,int min_val,int max_val) _YO_RANDOM_BUILTIN_CODE(
  { return 
      ((int(*)(void*,int,int))Yo_Find_Method_Of(&random,Oj_Random_OjMID,YO_RAISE_ERROR))
        (random,min_val,max_val); });

uint_t Fast_Random_Next_32(YO_FASTRND *random)
#ifdef _YO_RANDOM_BUILTIN
  {
    Fast_Random_Next_State(random);
    return Fast_Random_Temper(random);
  }
#endif
  ;

float Fast_Random_Next_Flt(YO_FASTRND *random)
#ifdef _YO_RANDOM_BUILTIN
  {
    Fast_Random_Next_State(random);
    return Fast_Random_Temper(random) * (1.0f / 4294967296.0f);
  }
#endif
  ;

int Fast_Random(YO_FASTRND *random,int min_val, int max_val)
#ifdef _YO_RANDOM_BUILTIN
  {
    quad_t q;
    Fast_Random_Next_State(random);
    q = Fast_Random_Temper(random);
    return (int)((q * max_val)>>32) + min_val;
  }
#endif
  ;

void Fast_Random_Period_Certification(YO_FASTRND *random) 
#ifdef _YO_RANDOM_BUILTIN
  {
    if ( !(random->status[0] & YO_FASTRND_TINYMT32_MASK)
      && !random->status[1] 
      && !random->status[2]
      && !random->status[3]) 
      {
        random->status[0] = 'T';
        random->status[1] = 'I';
        random->status[2] = 'N';
        random->status[3] = 'Y';
      }
  }
#endif
  ;
  
YO_FASTRND *Fast_Random_Init_Static(YO_FASTRND *random,uint_t seed)
#ifdef _YO_RANDOM_BUILTIN
  {
    int i;
    random->status[0] = seed;
    random->status[1] = random->mat1;
    random->status[2] = random->mat2;
    random->status[3] = random->tmat;
    for (i = 1; i < 8; i++) 
      {
        random->status[i & 3] ^= i + 1812433253U
          * (random->status[(i - 1) & 3]
          ^ (random->status[(i - 1) & 3] >> 30));
      }
    Fast_Random_Period_Certification(random);
    for (i = 0; i < 8; i++)
      Fast_Random_Next_State(random);
    return random;
  }
#endif
  ;

YO_FASTRND *Fast_Random_Init(uint_t seed)
#ifdef _YO_RANDOM_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Random_32_OjMID,  Fast_Random_Next_32},
        {Oj_Random_Flt_OjMID, Fast_Random_Next_Flt},
        {Oj_Random_OjMID,     Fast_Random},
        {0}};
    YO_FASTRND *random = __Object(sizeof(YO_FASTRND),funcs);
    return Fast_Random_Init_Static(random,seed);
  }
#endif
  ;

#endif /* C_once_FF657866_8205_4CAE_9D01_65B8583E9D19 */

Changes to sar.hc.
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

#ifndef C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88
#define C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88

#include "yoyo.hc"

#ifdef _LIBYOYO
#define _YOYO_SAR_BUITIN
#endif

typedef struct _YOYO_STRUCTED_ARRAY
  {
    byte_t *at;
    int  count;
    int  allocated;
  } YOYO_STRUCTED_ARRAY;

void *Structed_Array_Insert(YOYO_STRUCTED_ARRAY *arr,void *el,int width,int at, int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count+at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    
    arr->count = Yo_Elm_Insert_Npl(&arr->at,at,arr->count,el,count,width,&arr->allocated);
    return arr->at+(at*width);
  }
#endif
  ;
  
int Structed_Array_Remove(YOYO_STRUCTED_ARRAY *arr,int width,int at,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count+at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    STRICT_REQUIRE( count <= arr->count );
    
    if ( arr->count < count && at < arr->count - count )
      memmove(arr->at+at*width,arr->at+(at+count)*width,arr->count-(at+count)*width);
    arr->count -= count;
    return count;
  }
#endif
  ;
  
int Structed_Array_Resize(YOYO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);
    if ( arr->count < count ) memset(arr->at+(arr->count*width),0,(count-arr->count)*width);
    arr->count = count;
    return arr->allocated/width;
  }
#endif
  ;

int Structed_Array_Reserve(YOYO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YOYO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);







|


|




|

|
|














|
|

















|
|














|
|







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

#ifndef C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88
#define C_once_B280024F_42F5_4D98_9F57_2A5BEABC1C88

#include "yoyo.hc"

#ifdef _LIBYOYO
#define _YO_SAR_BUITIN
#endif

typedef struct _YO_STRUCTED_ARRAY
  {
    byte_t *at;
    int  count;
    int  allocated;
  } YO_STRUCTED_ARRAY;

void *Structed_Array_Insert(YO_STRUCTED_ARRAY *arr,void *el,int width,int at, int count)
#ifdef _YO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count+at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    
    arr->count = Yo_Elm_Insert_Npl(&arr->at,at,arr->count,el,count,width,&arr->allocated);
    return arr->at+(at*width);
  }
#endif
  ;
  
int Structed_Array_Remove(YO_STRUCTED_ARRAY *arr,int width,int at,int count)
#ifdef _YO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    if ( at < 0 ) at = arr->count+at+1;
    STRICT_REQUIRE( at >= 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( el != 0 );
    STRICT_REQUIRE( width >= 0 );
    STRICT_REQUIRE( count <= arr->count );
    
    if ( arr->count < count && at < arr->count - count )
      memmove(arr->at+at*width,arr->at+(at+count)*width,arr->count-(at+count)*width);
    arr->count -= count;
    return count;
  }
#endif
  ;
  
int Structed_Array_Resize(YO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);
    if ( arr->count < count ) memset(arr->at+(arr->count*width),0,(count-arr->count)*width);
    arr->count = count;
    return arr->allocated/width;
  }
#endif
  ;

int Structed_Array_Reserve(YO_STRUCTED_ARRAY *arr,int width,int count)
#ifdef _YO_SAR_BUITIN
  {
    STRICT_REQUIRE( arr != 0 );
    STRICT_REQUIRE( count >= 0 );
    STRICT_REQUIRE( width >= 0 );

    if ( count*width > arr->allocated )
      Yo_Elm_Resize_Npl(&arr->at,count,width,&arr->allocated);
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
    {\
      Elm_Tp *at;\
      int count;\
      int _;\
    } Arr_Tp;\
  Elm_Tp *Fpfx##_Insert(Arr_Tp *arr,Elm_Tp el,int at)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),at,1);\
    }\
  Elm_Tp *Fpfx##_Insert_Ptr(Arr_Tp *arr,Elm_Tp *el,int at,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),at,count);\
    }\
  Elm_Tp *Fpfx##_Push(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),-1,1);\
    }\
  Elm_Tp *Fpfx##_Push_Zero(Arr_Tp *arr)\
    {\
      byte_t el[sizeof(Elm_Tp)] = {0};\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),-1,1);\
    }\
  Elm_Tp *Fpfx##_Push_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),-1,count);\
    }\
  Elm_Tp *Fpfx##_Push_Front(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),0,1);\
    }\
  Elm_Tp *Fpfx##_Push_Front_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YOYO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),0,count);\
    }\
  int Fpfx##_Remove(Arr_Tp *arr,int at,int count)\
    {\
      return Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),at,count);\
    }\
  int Fpfx##_Empty(Arr_Tp *arr)\
    {\
      return !arr->count;\
    }\
  int Fpfx##_Pop(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[arr->count-1]; result = 1; }\
      Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),-1,1);\
      return result;\
    }\
  int Fpfx##_Pop_Front(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[0]; result = 1; }\
      Structed_Array_Remove((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),0,1);\
      return result;\
    }\
  int Fpfx##_Resize(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Resize((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  int Fpfx##_Reserve(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Reserve((YOYO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  void Arr_Tp##_Destruct(Arr_Tp *arr)\
    {\
      free(arr->at);\
      __Destruct(arr);\
    }\
  Arr_Tp *Fpfx##_Init()\







|



|



|




|



|



|



|



|









|






|




|



|







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
    {\
      Elm_Tp *at;\
      int count;\
      int _;\
    } Arr_Tp;\
  Elm_Tp *Fpfx##_Insert(Arr_Tp *arr,Elm_Tp el,int at)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),at,1);\
    }\
  Elm_Tp *Fpfx##_Insert_Ptr(Arr_Tp *arr,Elm_Tp *el,int at,int count)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),at,count);\
    }\
  Elm_Tp *Fpfx##_Push(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),-1,1);\
    }\
  Elm_Tp *Fpfx##_Push_Zero(Arr_Tp *arr)\
    {\
      byte_t el[sizeof(Elm_Tp)] = {0};\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),-1,1);\
    }\
  Elm_Tp *Fpfx##_Push_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),-1,count);\
    }\
  Elm_Tp *Fpfx##_Push_Front(Arr_Tp *arr,Elm_Tp el)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,&el,sizeof(Elm_Tp),0,1);\
    }\
  Elm_Tp *Fpfx##_Push_Front_Ptr(Arr_Tp *arr,Elm_Tp *el,int count)\
    {\
      return Structed_Array_Insert((YO_STRUCTED_ARRAY*)arr,el,sizeof(Elm_Tp),0,count);\
    }\
  int Fpfx##_Remove(Arr_Tp *arr,int at,int count)\
    {\
      return Structed_Array_Remove((YO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),at,count);\
    }\
  int Fpfx##_Empty(Arr_Tp *arr)\
    {\
      return !arr->count;\
    }\
  int Fpfx##_Pop(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[arr->count-1]; result = 1; }\
      Structed_Array_Remove((YO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),-1,1);\
      return result;\
    }\
  int Fpfx##_Pop_Front(Arr_Tp *arr,Elm_Tp *top)\
    {\
      int result = 0;\
      if ( top && arr->count ) { *top = arr->at[0]; result = 1; }\
      Structed_Array_Remove((YO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),0,1);\
      return result;\
    }\
  int Fpfx##_Resize(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Resize((YO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  int Fpfx##_Reserve(Arr_Tp *arr,int count)\
    {\
      return Structed_Array_Reserve((YO_STRUCTED_ARRAY*)arr,sizeof(Elm_Tp),count);\
    }\
  void Arr_Tp##_Destruct(Arr_Tp *arr)\
    {\
      free(arr->at);\
      __Destruct(arr);\
    }\
  Arr_Tp *Fpfx##_Init()\
Changes to sha1.hc.
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

*/

#ifndef C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF
#define C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF

#ifdef _LIBYOYO
#define _YOYO_SHA1_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YOYO_SHA1
  {
    uint_t state[5];   /* state (ABCDE) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64]; /* input buffer */
  } YOYO_SHA1;

#define YOYO_SHA1_INITIALIZER {{0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0},{0},0,{0}}

void *Sha1_Clone(YOYO_SHA1 *sha1)
#ifdef _YOYO_SHA1_BUILTIN
  {
    return __Clone(sizeof(YOYO_SHA1),sha1);
  }
#endif
  ;

void *Sha1_Start(YOYO_SHA1 *sha1)
#ifdef _YOYO_SHA1_BUILTIN
  {
    memset(sha1,0,sizeof(*sha1));
    sha1->state[0] = 0x67452301; 
    sha1->state[1] = 0xefcdab89; 
    sha1->state[2] = 0x98badcfe; 
    sha1->state[3] = 0x10325476;
    sha1->state[4] = 0xc3d2e1f0;
    return sha1;
  }
#endif
  ;

void Sha1_Update(YOYO_SHA1 *sha1, void *data, int len);
void *Sha1_Finish(YOYO_SHA1 *sha1, void *digest);

void *Sha1_Init()
#ifdef _YOYO_SHA1_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Sha1_Clone },
        {Oj_Digest_Update_OjMID, Sha1_Update },
        {0}};
    
    YOYO_SHA1 *sha1 = __Object(sizeof(YOYO_SHA1),funcs);
    return Sha1_Start(sha1);
  }
#endif
  ;

void *Sha1_Digest(void *data, int len, void *digest)
#ifdef _YOYO_SHA1_BUILTIN
  {
    YOYO_SHA1 sha1 = YOYO_SHA1_INITIALIZER;
    Sha1_Update(&sha1,data,len);
    return Sha1_Finish(&sha1,digest);
  }
#endif
  ;

void *Sha1_Digest_Digest(void *data, int len, void *digest)
#ifdef _YOYO_SHA1_BUILTIN
  {
    byte_t tmp[20];
    YOYO_SHA1 sha1 = YOYO_SHA1_INITIALIZER;
    Sha1_Digest(data,len,tmp);
    Sha1_Update(&sha1,tmp,20);
    Sha1_Update(&sha1,data,len);
    return Sha1_Finish(&sha1,digest);
  }
#endif
  ;

#define Sha1_Digest_Of(Data,Len) Sha1_Digest(Data,Len,0)

#ifdef _YOYO_SHA1_BUILTIN

  void Sha1_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4) 
        {







|





|





|

|

|
|

|




|
|












|
|


|

|





|






|

|







|


|










|







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

*/

#ifndef C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF
#define C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF

#ifdef _LIBYOYO
#define _YO_SHA1_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YO_SHA1
  {
    uint_t state[5];   /* state (ABCDE) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64]; /* input buffer */
  } YO_SHA1;

#define YO_SHA1_INITIALIZER {{0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0},{0},0,{0}}

void *Sha1_Clone(YO_SHA1 *sha1)
#ifdef _YO_SHA1_BUILTIN
  {
    return __Clone(sizeof(YO_SHA1),sha1);
  }
#endif
  ;

void *Sha1_Start(YO_SHA1 *sha1)
#ifdef _YO_SHA1_BUILTIN
  {
    memset(sha1,0,sizeof(*sha1));
    sha1->state[0] = 0x67452301; 
    sha1->state[1] = 0xefcdab89; 
    sha1->state[2] = 0x98badcfe; 
    sha1->state[3] = 0x10325476;
    sha1->state[4] = 0xc3d2e1f0;
    return sha1;
  }
#endif
  ;

void Sha1_Update(YO_SHA1 *sha1, void *data, int len);
void *Sha1_Finish(YO_SHA1 *sha1, void *digest);

void *Sha1_Init()
#ifdef _YO_SHA1_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Sha1_Clone },
        {Oj_Digest_Update_OjMID, Sha1_Update },
        {0}};
    
    YO_SHA1 *sha1 = __Object(sizeof(YO_SHA1),funcs);
    return Sha1_Start(sha1);
  }
#endif
  ;

void *Sha1_Digest(void *data, int len, void *digest)
#ifdef _YO_SHA1_BUILTIN
  {
    YO_SHA1 sha1 = YO_SHA1_INITIALIZER;
    Sha1_Update(&sha1,data,len);
    return Sha1_Finish(&sha1,digest);
  }
#endif
  ;

void *Sha1_Digest_Digest(void *data, int len, void *digest)
#ifdef _YO_SHA1_BUILTIN
  {
    byte_t tmp[20];
    YO_SHA1 sha1 = YO_SHA1_INITIALIZER;
    Sha1_Digest(data,len,tmp);
    Sha1_Update(&sha1,tmp,20);
    Sha1_Update(&sha1,data,len);
    return Sha1_Finish(&sha1,digest);
  }
#endif
  ;

#define Sha1_Digest_Of(Data,Len) Sha1_Digest(Data,Len,0)

#ifdef _YO_SHA1_BUILTIN

  void Sha1_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4) 
        {
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  #define G(x,y,z) (x ^ y ^ z)
  #define GG(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + G(b,c,d) + 0x6ed9eba1u + q; b = ROTATE_LEFT(b,30)
  #define H(x,y,z) ((x & y) | (z & (x | y)))
  #define HH(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + H(b,c,d) + 0x8f1bbcdcu + q; b = ROTATE_LEFT(b,30)
  #define I(x,y,z) (x ^ y ^ z)
  #define II(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + I(b,c,d) + 0xca62c1d6u + q; b = ROTATE_LEFT(b,30)

  void Sha1_Internal_Transform(YOYO_SHA1 *sha1, void *block)
    {
      uint_t *state = sha1->state;
      uint_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4], x[16];

      Sha1_Internal_Decode(x, block, 64);

      FF( a, b, c, d, e, x[0]  );







|







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  #define G(x,y,z) (x ^ y ^ z)
  #define GG(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + G(b,c,d) + 0x6ed9eba1u + q; b = ROTATE_LEFT(b,30)
  #define H(x,y,z) ((x & y) | (z & (x | y)))
  #define HH(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + H(b,c,d) + 0x8f1bbcdcu + q; b = ROTATE_LEFT(b,30)
  #define I(x,y,z) (x ^ y ^ z)
  #define II(a,b,c,d,e,q) e += ROTATE_LEFT(a,5) + I(b,c,d) + 0xca62c1d6u + q; b = ROTATE_LEFT(b,30)

  void Sha1_Internal_Transform(YO_SHA1 *sha1, void *block)
    {
      uint_t *state = sha1->state;
      uint_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4], x[16];

      Sha1_Internal_Decode(x, block, 64);

      FF( a, b, c, d, e, x[0]  );
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  #undef I
  #undef ROTATE_LEFT
  #undef FF
  #undef GG
  #undef HH
  #undef II

  void Sha1_Update(YOYO_SHA1 *sha1, void *input, int input_length)
    {      
      int i, index, partLen;
      uint_t *count = sha1->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);







|







276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
  #undef I
  #undef ROTATE_LEFT
  #undef FF
  #undef GG
  #undef HH
  #undef II

  void Sha1_Update(YO_SHA1 *sha1, void *input, int input_length)
    {      
      int i, index, partLen;
      uint_t *count = sha1->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
          index = 0;
        }
      else
        i = 0;
      memcpy(&sha1->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Sha1_Finish(YOYO_SHA1 *sha1, void *digest)
    {
      if ( !sha1->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0







|







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
          index = 0;
        }
      else
        i = 0;
      memcpy(&sha1->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Sha1_Finish(YO_SHA1 *sha1, void *digest)
    {
      if ( !sha1->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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
          sha1->finished = 1;
        }
      if ( !digest ) digest = __Malloc(20);
      Sha1_Internal_Encode(digest, sha1->state, 20);
      return digest;
    }

#endif /* _YOYO_SHA1_BUILTIN */

typedef struct _YOYO_HMAC_SHA1
  {
    YOYO_SHA1 sha1;
    byte_t ipad[64];
    byte_t opad[64];
  } YOYO_HMAC_SHA1;

void *Hmac_Sha1_Clone(YOYO_HMAC_SHA1 *hmac)
#ifdef _YOYO_SHA1_BUILTIN
  {
    return __Clone(sizeof(YOYO_HMAC_SHA1),hmac);
  }
#endif
  ;

void *Hmac_Sha1_Start(YOYO_HMAC_SHA1 *hmac, void *key, int key_len)
#ifdef _YOYO_SHA1_BUILTIN
  {
    int i;
    byte_t sum[20];
    
    if ( key_len > 64 )
      {
        Sha1_Start(&hmac->sha1);







|

|

|


|

|
|

|




|
|







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
          sha1->finished = 1;
        }
      if ( !digest ) digest = __Malloc(20);
      Sha1_Internal_Encode(digest, sha1->state, 20);
      return digest;
    }

#endif /* _YO_SHA1_BUILTIN */

typedef struct _YO_HMAC_SHA1
  {
    YO_SHA1 sha1;
    byte_t ipad[64];
    byte_t opad[64];
  } YO_HMAC_SHA1;

void *Hmac_Sha1_Clone(YO_HMAC_SHA1 *hmac)
#ifdef _YO_SHA1_BUILTIN
  {
    return __Clone(sizeof(YO_HMAC_SHA1),hmac);
  }
#endif
  ;

void *Hmac_Sha1_Start(YO_HMAC_SHA1 *hmac, void *key, int key_len)
#ifdef _YO_SHA1_BUILTIN
  {
    int i;
    byte_t sum[20];
    
    if ( key_len > 64 )
      {
        Sha1_Start(&hmac->sha1);
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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Sha1_Update(YOYO_HMAC_SHA1 *hmac, void *input, int input_length)
#ifdef _YOYO_SHA1_BUILTIN
  {
    Sha1_Update(&hmac->sha1,input,input_length);
  }
#endif
  ;

void *Hmac_Sha1_Finish(YOYO_HMAC_SHA1 *hmac, void *digest)
#ifdef _YOYO_SHA1_BUILTIN
  {
    byte_t tmpb[20];
    Sha1_Finish(&hmac->sha1,tmpb);
    Sha1_Start(&hmac->sha1);
    Sha1_Update(&hmac->sha1,&hmac->opad,64);
    Sha1_Update(&hmac->sha1,tmpb,20);
    memset(tmpb,0,20);
    return Sha1_Finish(&hmac->sha1,digest);
  }
#endif
  ;

void Hmac_Sha1_Reset(YOYO_HMAC_SHA1 *hmac)
#ifdef _YOYO_SHA1_BUILTIN
  {
    Sha1_Start(&hmac->sha1);
    Sha1_Update(&hmac->sha1,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Sha1_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YOYO_SHA1_BUILTIN
  {
    YOYO_HMAC_SHA1 hmac1;
    Hmac_Sha1_Start(&hmac1,key,key_len);
    Sha1_Update(&hmac1.sha1,data,len);
    return Hmac_Sha1_Finish(&hmac1,digest);
  }
#endif
  ;

void *Hmac_Sha1_Init(void *key, int key_len)
#ifdef _YOYO_SHA1_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Sha1_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Sha1_Update },
        {0}};
    
    YOYO_HMAC_SHA1 *sha1 = __Object(sizeof(YOYO_HMAC_SHA1),funcs);
    return Hmac_Sha1_Start(sha1,key,key_len);
  }
#endif
  ;

#endif /* C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF */








|
|






|
|












|
|








|

|








|

|





|







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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Sha1_Update(YO_HMAC_SHA1 *hmac, void *input, int input_length)
#ifdef _YO_SHA1_BUILTIN
  {
    Sha1_Update(&hmac->sha1,input,input_length);
  }
#endif
  ;

void *Hmac_Sha1_Finish(YO_HMAC_SHA1 *hmac, void *digest)
#ifdef _YO_SHA1_BUILTIN
  {
    byte_t tmpb[20];
    Sha1_Finish(&hmac->sha1,tmpb);
    Sha1_Start(&hmac->sha1);
    Sha1_Update(&hmac->sha1,&hmac->opad,64);
    Sha1_Update(&hmac->sha1,tmpb,20);
    memset(tmpb,0,20);
    return Sha1_Finish(&hmac->sha1,digest);
  }
#endif
  ;

void Hmac_Sha1_Reset(YO_HMAC_SHA1 *hmac)
#ifdef _YO_SHA1_BUILTIN
  {
    Sha1_Start(&hmac->sha1);
    Sha1_Update(&hmac->sha1,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Sha1_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YO_SHA1_BUILTIN
  {
    YO_HMAC_SHA1 hmac1;
    Hmac_Sha1_Start(&hmac1,key,key_len);
    Sha1_Update(&hmac1.sha1,data,len);
    return Hmac_Sha1_Finish(&hmac1,digest);
  }
#endif
  ;

void *Hmac_Sha1_Init(void *key, int key_len)
#ifdef _YO_SHA1_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Sha1_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Sha1_Update },
        {0}};
    
    YO_HMAC_SHA1 *sha1 = __Object(sizeof(YO_HMAC_SHA1),funcs);
    return Hmac_Sha1_Start(sha1,key,key_len);
  }
#endif
  ;

#endif /* C_once_1B3E01E2_7457_494E_A17C_3A12388FC4AF */

Changes to sha2.hc.
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

*/

#ifndef C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E
#define C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E

#ifdef _LIBYOYO
#define _YOYO_SHA2_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YOYO_SHA2
  {
    uint_t state[8];   /* state (ABCDEFGH) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64]; /* input buffer */
  } YOYO_SHA2;

void *Sha2_Clone(YOYO_SHA2 *sha2)
#ifdef _YOYO_SHA2_BUILTIN
  {
    return __Clone(sizeof(YOYO_SHA2),sha2);
  }
#endif
  ;

void *Sha2_Start(YOYO_SHA2 *sha2)
#ifdef _YOYO_SHA2_BUILTIN
  {
    memset(sha2,0,sizeof(*sha2));
    sha2->state[0] = 0x6a09e667;
    sha2->state[1] = 0xbb67ae85;
    sha2->state[2] = 0x3c6ef372;
    sha2->state[3] = 0xa54ff53a;
    sha2->state[4] = 0x510e527f;
    sha2->state[5] = 0x9b05688c;
    sha2->state[6] = 0x1f83d9ab;
    sha2->state[7] = 0x5be0cd19;
    return sha2;
  }
#endif
  ;

void Sha2_Update(YOYO_SHA2 *sha2, void *data, int len);
void *Sha2_Finish(YOYO_SHA2 *sha2, void *digest);

void *Sha2_Init()
#ifdef _YOYO_SHA2_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Sha2_Clone },
        {Oj_Digest_Update_OjMID, Sha2_Update },
        {0}};
    
    YOYO_SHA2 *sha2 = __Object(sizeof(YOYO_SHA2),funcs);
    return Sha2_Start(sha2);
  }
#endif
  ;

#define YOYO_SHA2_INITIALIZER {\
  {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, \
   0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19} \
   ,{0},0,{0}}

void *Sha2_Digest(void *data, int len, void *digest)
#ifdef _YOYO_SHA2_BUILTIN
  {
    YOYO_SHA2 sha2 = YOYO_SHA2_INITIALIZER;
    Sha2_Update(&sha2,data,len);
    return Sha2_Finish(&sha2,digest);
  }
#endif
  ;

void *Sha2_Digest_Digest(void *data, int len, void *digest)
#ifdef _YOYO_SHA2_BUILTIN
  {
    byte_t tmp[32];
    YOYO_SHA2 sha2 = YOYO_SHA2_INITIALIZER;
    Sha2_Digest(data,len,tmp);
    Sha2_Update(&sha2,tmp,32);
    Sha2_Update(&sha2,data,len);
    return Sha2_Finish(&sha2,digest);
  }
#endif
  ;

#define Sha2_Digest_Of(Data,Len) Sha2_Digest(Data,Len,0)

#ifdef _YOYO_SHA2_BUILTIN

  void Sha2_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4) 
        {







|





|





|

|
|

|




|
|















|
|


|

|





|





|





|

|







|


|










|







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

*/

#ifndef C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E
#define C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E

#ifdef _LIBYOYO
#define _YO_SHA2_BUILTIN
#endif

#include "yoyo.hc"
#include "crc.hc"

typedef struct _YO_SHA2
  {
    uint_t state[8];   /* state (ABCDEFGH) */
    uint_t count[2];   /* number of bits, modulo 2^64 (lsb first) */
    int    finished;
    byte_t buffer[64]; /* input buffer */
  } YO_SHA2;

void *Sha2_Clone(YO_SHA2 *sha2)
#ifdef _YO_SHA2_BUILTIN
  {
    return __Clone(sizeof(YO_SHA2),sha2);
  }
#endif
  ;

void *Sha2_Start(YO_SHA2 *sha2)
#ifdef _YO_SHA2_BUILTIN
  {
    memset(sha2,0,sizeof(*sha2));
    sha2->state[0] = 0x6a09e667;
    sha2->state[1] = 0xbb67ae85;
    sha2->state[2] = 0x3c6ef372;
    sha2->state[3] = 0xa54ff53a;
    sha2->state[4] = 0x510e527f;
    sha2->state[5] = 0x9b05688c;
    sha2->state[6] = 0x1f83d9ab;
    sha2->state[7] = 0x5be0cd19;
    return sha2;
  }
#endif
  ;

void Sha2_Update(YO_SHA2 *sha2, void *data, int len);
void *Sha2_Finish(YO_SHA2 *sha2, void *digest);

void *Sha2_Init()
#ifdef _YO_SHA2_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Sha2_Clone },
        {Oj_Digest_Update_OjMID, Sha2_Update },
        {0}};
    
    YO_SHA2 *sha2 = __Object(sizeof(YO_SHA2),funcs);
    return Sha2_Start(sha2);
  }
#endif
  ;

#define YO_SHA2_INITIALIZER {\
  {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, \
   0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19} \
   ,{0},0,{0}}

void *Sha2_Digest(void *data, int len, void *digest)
#ifdef _YO_SHA2_BUILTIN
  {
    YO_SHA2 sha2 = YO_SHA2_INITIALIZER;
    Sha2_Update(&sha2,data,len);
    return Sha2_Finish(&sha2,digest);
  }
#endif
  ;

void *Sha2_Digest_Digest(void *data, int len, void *digest)
#ifdef _YO_SHA2_BUILTIN
  {
    byte_t tmp[32];
    YO_SHA2 sha2 = YO_SHA2_INITIALIZER;
    Sha2_Digest(data,len,tmp);
    Sha2_Update(&sha2,tmp,32);
    Sha2_Update(&sha2,data,len);
    return Sha2_Finish(&sha2,digest);
  }
#endif
  ;

#define Sha2_Digest_Of(Data,Len) Sha2_Digest(Data,Len,0)

#ifdef _YO_SHA2_BUILTIN

  void Sha2_Internal_Encode(byte_t *output, uint_t *input, uint_t len) 
    {
      uint_t i, j;

      for (i = 0, j = 0; j < len; i++, j += 4) 
        {
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  #define F(a,b,c,d,e,f,g,h,x,K) \
  { \
      uint_t foo = h + S3(e) + F1(e,f,g) + K + x; \
      uint_t bar = S2(a) + F0(a,b,c); \
      d += foo; h = foo + bar; \
  }
  
  void Sha2_Internal_Transform(YOYO_SHA2 *sha2, void *block)
    {
      uint_t *state = sha2->state;
      uint_t 
        a = state[0], 
        b = state[1], 
        c = state[2], 
        d = state[3], 







|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  #define F(a,b,c,d,e,f,g,h,x,K) \
  { \
      uint_t foo = h + S3(e) + F1(e,f,g) + K + x; \
      uint_t bar = S2(a) + F0(a,b,c); \
      d += foo; h = foo + bar; \
  }
  
  void Sha2_Internal_Transform(YO_SHA2 *sha2, void *block)
    {
      uint_t *state = sha2->state;
      uint_t 
        a = state[0], 
        b = state[1], 
        c = state[2], 
        d = state[3], 
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  #undef S2
  #undef S3
  #undef F0
  #undef F1
  #undef SHR
  #undef ROTR

  void Sha2_Update(YOYO_SHA2 *sha2, void *input, int input_length)
    {      
      int i, index, partLen;
      uint_t *count = sha2->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);







|







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
  #undef S2
  #undef S3
  #undef F0
  #undef F1
  #undef SHR
  #undef ROTR

  void Sha2_Update(YO_SHA2 *sha2, void *input, int input_length)
    {      
      int i, index, partLen;
      uint_t *count = sha2->count;
      index = (uint_t)((count[0] >> 3) & 0x3F);
      if ((count[0] += ((uint_t)input_length << 3)) < ((uint_t)input_length << 3))
        count[1]++;
      count[1] += ((uint_t)input_length >> 29);
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
          index = 0;
        }
      else
        i = 0;
      memcpy(&sha2->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Sha2_Finish(YOYO_SHA2 *sha2, void *digest)
    {
      if ( !sha2->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
          index = 0;
        }
      else
        i = 0;
      memcpy(&sha2->buffer[index],&((byte_t*)input)[i],input_length-i);
    }

  void *Sha2_Finish(YO_SHA2 *sha2, void *digest)
    {
      if ( !sha2->finished )
        {
          static byte_t PADDING[64] = {
            0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
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
          sha2->finished = 1;
        }
      if ( !digest ) digest = __Malloc(32);
      Sha2_Internal_Encode(digest, sha2->state, 32);
      return digest;
    }

#endif /* _YOYO_SHA2_BUILTIN */

typedef struct _YOYO_HMAC_SHA2
  {
    YOYO_SHA2 sha2;
    byte_t ipad[64];
    byte_t opad[64];
  } YOYO_HMAC_SHA2;

void *Hmac_Sha2_Clone(YOYO_HMAC_SHA2 *hmac)
#ifdef _YOYO_SHA2_BUILTIN
  {
    return __Clone(sizeof(YOYO_HMAC_SHA2),hmac);
  }
#endif
  ;

void *Hmac_Sha2_Start(YOYO_HMAC_SHA2 *hmac, void *key, int key_len)
#ifdef _YOYO_SHA2_BUILTIN
  {
    int i;
    byte_t sum[32];
    
    if ( key_len > 64 )
      {
        Sha2_Start(&hmac->sha2);







|

|

|


|

|
|

|




|
|







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
          sha2->finished = 1;
        }
      if ( !digest ) digest = __Malloc(32);
      Sha2_Internal_Encode(digest, sha2->state, 32);
      return digest;
    }

#endif /* _YO_SHA2_BUILTIN */

typedef struct _YO_HMAC_SHA2
  {
    YO_SHA2 sha2;
    byte_t ipad[64];
    byte_t opad[64];
  } YO_HMAC_SHA2;

void *Hmac_Sha2_Clone(YO_HMAC_SHA2 *hmac)
#ifdef _YO_SHA2_BUILTIN
  {
    return __Clone(sizeof(YO_HMAC_SHA2),hmac);
  }
#endif
  ;

void *Hmac_Sha2_Start(YO_HMAC_SHA2 *hmac, void *key, int key_len)
#ifdef _YO_SHA2_BUILTIN
  {
    int i;
    byte_t sum[32];
    
    if ( key_len > 64 )
      {
        Sha2_Start(&hmac->sha2);
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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Sha2_Update(YOYO_HMAC_SHA2 *hmac, void *input, int input_length)
#ifdef _YOYO_SHA2_BUILTIN
  {
    Sha2_Update(&hmac->sha2,input,input_length);
  }
#endif
  ;

void *Hmac_Sha2_Finish(YOYO_HMAC_SHA2 *hmac, void *digest)
#ifdef _YOYO_SHA2_BUILTIN
  {
    byte_t tmpb[32];
    Sha2_Finish(&hmac->sha2,tmpb);
    Sha2_Start(&hmac->sha2);
    Sha2_Update(&hmac->sha2,&hmac->opad,64);
    Sha2_Update(&hmac->sha2,tmpb,32);
    memset(tmpb,0,32);
    return Sha2_Finish(&hmac->sha2,digest);
  }
#endif
  ;

void Hmac_Sha2_Reset(YOYO_HMAC_SHA2 *hmac)
#ifdef _YOYO_SHA2_BUILTIN
  {
    Sha2_Start(&hmac->sha2);
    Sha2_Update(&hmac->sha2,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Sha2_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YOYO_SHA2_BUILTIN
  {
    YOYO_HMAC_SHA2 hmac2;
    Hmac_Sha2_Start(&hmac2,key,key_len);
    Sha2_Update(&hmac2.sha2,data,len);
    return Hmac_Sha2_Finish(&hmac2,digest);
  }
#endif
  ;

void *Hmac_Sha2_Init(void *key, int key_len)
#ifdef _YOYO_SHA2_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Sha2_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Sha2_Update },
        {0}};
    
    YOYO_HMAC_SHA2 *sha2 = __Object(sizeof(YOYO_HMAC_SHA2),funcs);
    return Hmac_Sha2_Start(sha2,key,key_len);
  }
#endif
  ;

#endif /* C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E */








|
|






|
|












|
|








|

|








|

|





|







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
    
    memset(sum,0,sizeof(sum));
    return hmac;
  }
#endif
  ;

void Hmac_Sha2_Update(YO_HMAC_SHA2 *hmac, void *input, int input_length)
#ifdef _YO_SHA2_BUILTIN
  {
    Sha2_Update(&hmac->sha2,input,input_length);
  }
#endif
  ;

void *Hmac_Sha2_Finish(YO_HMAC_SHA2 *hmac, void *digest)
#ifdef _YO_SHA2_BUILTIN
  {
    byte_t tmpb[32];
    Sha2_Finish(&hmac->sha2,tmpb);
    Sha2_Start(&hmac->sha2);
    Sha2_Update(&hmac->sha2,&hmac->opad,64);
    Sha2_Update(&hmac->sha2,tmpb,32);
    memset(tmpb,0,32);
    return Sha2_Finish(&hmac->sha2,digest);
  }
#endif
  ;

void Hmac_Sha2_Reset(YO_HMAC_SHA2 *hmac)
#ifdef _YO_SHA2_BUILTIN
  {
    Sha2_Start(&hmac->sha2);
    Sha2_Update(&hmac->sha2,hmac->ipad,64);
  }
#endif
  ;

void *Hmac_Sha2_Digest(void *data, int len, void *key, int key_len, void *digest)
#ifdef _YO_SHA2_BUILTIN
  {
    YO_HMAC_SHA2 hmac2;
    Hmac_Sha2_Start(&hmac2,key,key_len);
    Sha2_Update(&hmac2.sha2,data,len);
    return Hmac_Sha2_Finish(&hmac2,digest);
  }
#endif
  ;

void *Hmac_Sha2_Init(void *key, int key_len)
#ifdef _YO_SHA2_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Clone_OjMID, Hmac_Sha2_Clone },
        {Oj_Digest_Update_OjMID, Hmac_Sha2_Update },
        {0}};
    
    YO_HMAC_SHA2 *sha2 = __Object(sizeof(YO_HMAC_SHA2),funcs);
    return Hmac_Sha2_Start(sha2,key,key_len);
  }
#endif
  ;

#endif /* C_once_18F7EAA7_0DBC_4720_BA4A_7E0B1A9A5B1E */

Changes to string.hc.
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
#ifndef C_once_0ED387CD_668B_44C3_9D91_A6336A2F5F48
#define C_once_0ED387CD_668B_44C3_9D91_A6336A2F5F48

#include "yoyo.hc"
#include "array.hc"

#ifdef _LIBYOYO
#define _YOYO_STRING_BUILTIN
#endif

#ifdef _YOYO_STRING_BUILTIN
#define _YOYO_STRING_EXTERN
#else
#define _YOYO_STRING_EXTERN extern
#endif

/* caseinsensitive strcmp, returns 0 if equal */
#define Str_Ansi_Equal_Nocase(Cs,Ct) (!strcmp_I(Cs,Ct))
int strcmp_I(char *cs, char *ct)
#ifdef _YOYO_STRING_BUILTIN
  {
    int q = 0;
    if ( cs && ct ) do 
      {
        q = Toupper(*cs) - Toupper(*ct++);
      }
    while ( *cs++ && !q );
    return q;
  }
#endif
  ;

#define Str_Unicode_Compare_Nocase(Cs,Ct) wcscmp_I(Cs,Ct)
int wcscmp_I(wchar_t *cs, wchar_t *ct)
#ifdef _YOYO_STRING_BUILTIN
  {
    int q = 0;
    if ( cs && ct ) do 
      {
        q = towupper(*cs) - towupper(*ct++);
      }
    while ( *cs++ && !q );
    return q;
  }
#endif
  ;

/* caseinsensitive strncmp, returns 0 if equal */
int strncmp_I(char *cs, char *ct, int l)
#ifdef _YOYO_STRING_BUILTIN
  {
    int q = 0;
    if ( l && cs && ct ) do 
      {
        q = Toupper(*cs) - Toupper(*ct++);
      }
    while ( *cs++ && !q && --l );
    return q;
  }    
#endif
  ;

int wcsncmp_I(wchar_t *cs, wchar_t *ct, int l)
#ifdef _YOYO_STRING_BUILTIN
  {
    int q = 0;
    if ( l && cs && ct ) do 
      {
        q = towupper(*cs) - towupper(*ct++);
      }
    while ( *cs++ && !q && --l );
    return q;
  }    
#endif
  ;

int Str_Length(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    return S ? strlen(S) : 0;
  }
#endif
  ;

int Str_Is_Empty(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( !S ) return 1;
    while ( *S && Isspace(*S) ) ++S;
    return !*S;
  }
#endif
  ;

char Str_Last(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    int L = S ? strlen(S) : 0;
    return L ? S[L-1] : 0;
  }
#endif
  ;
  
#define Str_Copy(Str) Str_Copy_L(Str,-1)
#define Str_Copy_L(Str,Len) __Pool(Str_Copy_Npl(Str,Len))
char *Str_Copy_Npl(char *S,int L)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *p;
    if ( L < 0 ) L = S?strlen(S):0;
    p = Yo_Malloc_Npl(L+1);
    if ( L )
      memcpy(p,S,L);
    p[L] = 0;
    return p;
  }
#endif
  ;

#define Str_Range(Start,End) __Pool(Str_Range_Npl(Start,End))
char *Str_Range_Npl(char *S, char *E)
#ifdef _YOYO_STRING_BUILTIN
  {
    STRICT_REQUIRE(E >= S);
    return Str_Copy_Npl(S,E-S);
  }
#endif
  ;

#define Str_Trim_Copy(Str) Str_Trim_Copy_L(Str,-1)
#define Str_Trim_Copy_L(Str,Len) __Pool(Str_Trim_Copy_Npl(Str,Len))
char *Str_Trim_Copy_Npl(char *S, int L)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( L < 0 ) L = S?strlen(S):0;
    if ( L && S )
      {
        while ( *S && Isspace(*S) ) { ++S; --L; }
        while ( L && Isspace(S[L-1]) ) --L;
      }
    return Str_Copy_Npl(S,L);
  }
#endif
  ;

#define Str_Unicode_Copy(Str) Str_Unicode_Copy_L(Str,-1)
#define Str_Unicode_Copy_L(Str,Len) Yo_Pool(Str_Unicode_Copy_Npl(Str,Len))
wchar_t *Str_Unicode_Copy_Npl(wchar_t *S,int L)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t *p;
    if ( L < 0 ) L = S?wcslen(S):0;
    p = Yo_Malloc_Npl((L+1)*sizeof(wchar_t));
    if ( L )
      memcpy(p,S,L*sizeof(wchar_t));
    p[L] = 0;
    return p;
  }
#endif
  ;

char *Str_Split_Once_Into(char *S,char *delims,void *arr)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( !S || !*S ) return 0;
    
    if ( delims )
      {
        char *d;
        int j = 0;







|


|
|

|





|














|














|













|













|







|









|










|














|










|















|













|







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
#ifndef C_once_0ED387CD_668B_44C3_9D91_A6336A2F5F48
#define C_once_0ED387CD_668B_44C3_9D91_A6336A2F5F48

#include "yoyo.hc"
#include "array.hc"

#ifdef _LIBYOYO
#define _YO_STRING_BUILTIN
#endif

#ifdef _YO_STRING_BUILTIN
#define _YO_STRING_EXTERN
#else
#define _YO_STRING_EXTERN extern
#endif

/* caseinsensitive strcmp, returns 0 if equal */
#define Str_Ansi_Equal_Nocase(Cs,Ct) (!strcmp_I(Cs,Ct))
int strcmp_I(char *cs, char *ct)
#ifdef _YO_STRING_BUILTIN
  {
    int q = 0;
    if ( cs && ct ) do 
      {
        q = Toupper(*cs) - Toupper(*ct++);
      }
    while ( *cs++ && !q );
    return q;
  }
#endif
  ;

#define Str_Unicode_Compare_Nocase(Cs,Ct) wcscmp_I(Cs,Ct)
int wcscmp_I(wchar_t *cs, wchar_t *ct)
#ifdef _YO_STRING_BUILTIN
  {
    int q = 0;
    if ( cs && ct ) do 
      {
        q = towupper(*cs) - towupper(*ct++);
      }
    while ( *cs++ && !q );
    return q;
  }
#endif
  ;

/* caseinsensitive strncmp, returns 0 if equal */
int strncmp_I(char *cs, char *ct, int l)
#ifdef _YO_STRING_BUILTIN
  {
    int q = 0;
    if ( l && cs && ct ) do 
      {
        q = Toupper(*cs) - Toupper(*ct++);
      }
    while ( *cs++ && !q && --l );
    return q;
  }    
#endif
  ;

int wcsncmp_I(wchar_t *cs, wchar_t *ct, int l)
#ifdef _YO_STRING_BUILTIN
  {
    int q = 0;
    if ( l && cs && ct ) do 
      {
        q = towupper(*cs) - towupper(*ct++);
      }
    while ( *cs++ && !q && --l );
    return q;
  }    
#endif
  ;

int Str_Length(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    return S ? strlen(S) : 0;
  }
#endif
  ;

int Str_Is_Empty(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    if ( !S ) return 1;
    while ( *S && Isspace(*S) ) ++S;
    return !*S;
  }
#endif
  ;

char Str_Last(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    int L = S ? strlen(S) : 0;
    return L ? S[L-1] : 0;
  }
#endif
  ;
  
#define Str_Copy(Str) Str_Copy_L(Str,-1)
#define Str_Copy_L(Str,Len) __Pool(Str_Copy_Npl(Str,Len))
char *Str_Copy_Npl(char *S,int L)
#ifdef _YO_STRING_BUILTIN
  {
    char *p;
    if ( L < 0 ) L = S?strlen(S):0;
    p = Yo_Malloc_Npl(L+1);
    if ( L )
      memcpy(p,S,L);
    p[L] = 0;
    return p;
  }
#endif
  ;

#define Str_Range(Start,End) __Pool(Str_Range_Npl(Start,End))
char *Str_Range_Npl(char *S, char *E)
#ifdef _YO_STRING_BUILTIN
  {
    STRICT_REQUIRE(E >= S);
    return Str_Copy_Npl(S,E-S);
  }
#endif
  ;

#define Str_Trim_Copy(Str) Str_Trim_Copy_L(Str,-1)
#define Str_Trim_Copy_L(Str,Len) __Pool(Str_Trim_Copy_Npl(Str,Len))
char *Str_Trim_Copy_Npl(char *S, int L)
#ifdef _YO_STRING_BUILTIN
  {
    if ( L < 0 ) L = S?strlen(S):0;
    if ( L && S )
      {
        while ( *S && Isspace(*S) ) { ++S; --L; }
        while ( L && Isspace(S[L-1]) ) --L;
      }
    return Str_Copy_Npl(S,L);
  }
#endif
  ;

#define Str_Unicode_Copy(Str) Str_Unicode_Copy_L(Str,-1)
#define Str_Unicode_Copy_L(Str,Len) Yo_Pool(Str_Unicode_Copy_Npl(Str,Len))
wchar_t *Str_Unicode_Copy_Npl(wchar_t *S,int L)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t *p;
    if ( L < 0 ) L = S?wcslen(S):0;
    p = Yo_Malloc_Npl((L+1)*sizeof(wchar_t));
    if ( L )
      memcpy(p,S,L*sizeof(wchar_t));
    p[L] = 0;
    return p;
  }
#endif
  ;

char *Str_Split_Once_Into(char *S,char *delims,void *arr)
#ifdef _YO_STRING_BUILTIN
  {
    if ( !S || !*S ) return 0;
    
    if ( delims )
      {
        char *d;
        int j = 0;
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
        return *q ? q : 0;
      }
  }
#endif
  ;

void *Str_Split_Once(char *S,char *delims)
#ifdef _YOYO_STRING_BUILTIN
  {
    YOYO_ARRAY *L = Array_Ptrs();
    if ( S )
      {
        S = Str_Split_Once_Into(S,delims,L);
        if ( S )
          Array_Push(L,Str_Copy_Npl(S,-1));
      }
    return L;
  }
#endif
  ;

void *Str_Split(char *S,char *delims)
#ifdef _YOYO_STRING_BUILTIN
  {
    YOYO_ARRAY *L = Array_Ptrs();
    while ( S )
      S = Str_Split_Once_Into(S,delims,L);
    return L;
  }
#endif
  ;

int Bits_Pop(ulong_t *r, void *b, int *bits_count, int count)
#ifdef _YOYO_STRING_BUILTIN
  {
  #if 1  
    byte_t const *bits = (byte_t const*)b;
    int bC = *bits_count - 1;
    int Q = Yo_MIN(count,bC+1);
    int r_count = Q;








|

|












|

|








|







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
        return *q ? q : 0;
      }
  }
#endif
  ;

void *Str_Split_Once(char *S,char *delims)
#ifdef _YO_STRING_BUILTIN
  {
    YO_ARRAY *L = Array_Ptrs();
    if ( S )
      {
        S = Str_Split_Once_Into(S,delims,L);
        if ( S )
          Array_Push(L,Str_Copy_Npl(S,-1));
      }
    return L;
  }
#endif
  ;

void *Str_Split(char *S,char *delims)
#ifdef _YO_STRING_BUILTIN
  {
    YO_ARRAY *L = Array_Ptrs();
    while ( S )
      S = Str_Split_Once_Into(S,delims,L);
    return L;
  }
#endif
  ;

int Bits_Pop(ulong_t *r, void *b, int *bits_count, int count)
#ifdef _YO_STRING_BUILTIN
  {
  #if 1  
    byte_t const *bits = (byte_t const*)b;
    int bC = *bits_count - 1;
    int Q = Yo_MIN(count,bC+1);
    int r_count = Q;

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
    return r_count;
  #endif
  }
#endif
  ;

void Bits_Push(ulong_t bits, void *b, int *bits_count, int count)
#ifdef _YOYO_STRING_BUILTIN
  {
    while ( count-- )
      {
        int q = *bits_count;
        byte_t *d = ((byte_t *)b+q/8);
        *d = (byte_t)(((bits&1) << (q%8)) | (*d&~(1<<(q%8))));
        ++*bits_count;
        bits >>= 1;
      }
  }
#endif
  ;

char *Str_Xbit_Encode(void *data, int count /*of bits*/, int BC, char *bit_table, char *out )
#ifdef _YOYO_STRING_BUILTIN
  {
    char *Q = out;
    ulong_t q = 0;
    if ( count%BC ) 
      {
        Bits_Pop(&q,data,&count,count%BC);
        *Q++ = bit_table[q];
      }
    while ( count )
      {
        q = 0;
        Bits_Pop(&q,data,&count,BC);
        *Q++ = bit_table[q];
      }
    return out;
  }
#endif
  ;

_YOYO_STRING_EXTERN char Str_5bit_Encoding_Table[] /* 32 */ 
#ifdef _YOYO_STRING_BUILTIN
  = "0123456789abcdefgjkmnpqrstuvwxyz"
#endif
  ;
  
_YOYO_STRING_EXTERN char Str_5bit_Encoding_Table_Upper[] /* 32 */ 
#ifdef _YOYO_STRING_BUILTIN
  = "0123456789ABCDEFGJKMNPQRSTUVWXYZ"
#endif
  ;

_YOYO_STRING_EXTERN char Str_6bit_Encoding_Table[] /* 64 */ 
#ifdef _YOYO_STRING_BUILTIN
  = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"
#endif
  ;

#define Str_5bit_Encode(S,L) Str_Qbit_Encode(S,L,Str_5bit_Encoding_Table,5)
#define Str_5bit_Encode_Upper(S,L) Str_Qbit_Encode(S,L,Str_5bit_Encoding_Table_Upper,5)
#define Str_6bit_Encode(S,L) Str_Qbit_Encode(S,L,Str_6bit_Encoding_Table,6)

char *Str_Qbit_Encode(void *data,int len, char *tbl, int btl)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( data && len )
      {
        int rq_len = (len*8+btl-1)/btl;
        char *out = Yo_Malloc(rq_len+1);
        memset(out,0,rq_len+1);
        return Str_Xbit_Encode(data,len*8,btl,tbl,out);
      }
    return 0;
  }
#endif
  ;

void *Str_Xbit_Decode(char *inS, int len, int BC, byte_t *bit_table, void *out)
#ifdef _YOYO_STRING_BUILTIN
  {
    int count = 0;
    byte_t *S = ((byte_t*)inS+len)-1, *E = (byte_t*)inS-1;
    while ( S != E )
      {
        byte_t bits = bit_table[*S--];
        if ( bits == 255 )
          __Raise(YOYO_ERROR_CORRUPTED,
            __Format(__yoTa("bad symbol '%c' in encoded sequence",0),S[1]));
        Bits_Push(bits,out,&count,BC);
      }
    return out;
  }
#endif
  ;

_YOYO_STRING_EXTERN byte_t Str_5bit_Decoding_Table[] /* 32 */ 
#ifdef _YOYO_STRING_BUILTIN
= {
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,
    255, 10, 11, 12, 13, 14, 15, 16,255,255, 17, 18,255, 19, 20,255,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,255,255,255,255,255,







|














|



















|
|




|
|




|
|









|














|







|








|
|







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
    return r_count;
  #endif
  }
#endif
  ;

void Bits_Push(ulong_t bits, void *b, int *bits_count, int count)
#ifdef _YO_STRING_BUILTIN
  {
    while ( count-- )
      {
        int q = *bits_count;
        byte_t *d = ((byte_t *)b+q/8);
        *d = (byte_t)(((bits&1) << (q%8)) | (*d&~(1<<(q%8))));
        ++*bits_count;
        bits >>= 1;
      }
  }
#endif
  ;

char *Str_Xbit_Encode(void *data, int count /*of bits*/, int BC, char *bit_table, char *out )
#ifdef _YO_STRING_BUILTIN
  {
    char *Q = out;
    ulong_t q = 0;
    if ( count%BC ) 
      {
        Bits_Pop(&q,data,&count,count%BC);
        *Q++ = bit_table[q];
      }
    while ( count )
      {
        q = 0;
        Bits_Pop(&q,data,&count,BC);
        *Q++ = bit_table[q];
      }
    return out;
  }
#endif
  ;

_YO_STRING_EXTERN char Str_5bit_Encoding_Table[] /* 32 */ 
#ifdef _YO_STRING_BUILTIN
  = "0123456789abcdefgjkmnpqrstuvwxyz"
#endif
  ;
  
_YO_STRING_EXTERN char Str_5bit_Encoding_Table_Upper[] /* 32 */ 
#ifdef _YO_STRING_BUILTIN
  = "0123456789ABCDEFGJKMNPQRSTUVWXYZ"
#endif
  ;

_YO_STRING_EXTERN char Str_6bit_Encoding_Table[] /* 64 */ 
#ifdef _YO_STRING_BUILTIN
  = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"
#endif
  ;

#define Str_5bit_Encode(S,L) Str_Qbit_Encode(S,L,Str_5bit_Encoding_Table,5)
#define Str_5bit_Encode_Upper(S,L) Str_Qbit_Encode(S,L,Str_5bit_Encoding_Table_Upper,5)
#define Str_6bit_Encode(S,L) Str_Qbit_Encode(S,L,Str_6bit_Encoding_Table,6)

char *Str_Qbit_Encode(void *data,int len, char *tbl, int btl)
#ifdef _YO_STRING_BUILTIN
  {
    if ( data && len )
      {
        int rq_len = (len*8+btl-1)/btl;
        char *out = Yo_Malloc(rq_len+1);
        memset(out,0,rq_len+1);
        return Str_Xbit_Encode(data,len*8,btl,tbl,out);
      }
    return 0;
  }
#endif
  ;

void *Str_Xbit_Decode(char *inS, int len, int BC, byte_t *bit_table, void *out)
#ifdef _YO_STRING_BUILTIN
  {
    int count = 0;
    byte_t *S = ((byte_t*)inS+len)-1, *E = (byte_t*)inS-1;
    while ( S != E )
      {
        byte_t bits = bit_table[*S--];
        if ( bits == 255 )
          __Raise(YO_ERROR_CORRUPTED,
            __Format(__yoTa("bad symbol '%c' in encoded sequence",0),S[1]));
        Bits_Push(bits,out,&count,BC);
      }
    return out;
  }
#endif
  ;

_YO_STRING_EXTERN byte_t Str_5bit_Decoding_Table[] /* 32 */ 
#ifdef _YO_STRING_BUILTIN
= {
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,
    255, 10, 11, 12, 13, 14, 15, 16,255,255, 17, 18,255, 19, 20,255,
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,255,255,255,255,255,
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  }
#endif
  ;

_YOYO_STRING_EXTERN byte_t Str_6bit_Decoding_Table[] /* 64 */ 
#ifdef _YOYO_STRING_BUILTIN
= {
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,63, 255,255,
    0  ,1  ,2  ,3  ,4  ,5  ,6  ,7  ,8  ,9  ,255,255,255,255,255,255,
    255,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 ,255,255,255,255,62 ,







|
|







419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  }
#endif
  ;

_YO_STRING_EXTERN byte_t Str_6bit_Decoding_Table[] /* 64 */ 
#ifdef _YO_STRING_BUILTIN
= {
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
    255,255,255,255,255,255,255,255,255,255,255,255,255,63, 255,255,
    0  ,1  ,2  ,3  ,4  ,5  ,6  ,7  ,8  ,9  ,255,255,255,255,255,255,
    255,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 ,255,255,255,255,62 ,
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
#endif
  ;

#define Str_5bit_Decode(S,L) Str_Qbit_Decode(S,L,Str_5bit_Decoding_Table,5)
#define Str_6bit_Decode(S,L) Str_Qbit_Decode(S,L,Str_6bit_Decoding_Table,6)

void *Str_Qbit_Decode(char *S,int *len,byte_t *tbl,int btl)
#ifdef _YOYO_STRING_BUILTIN
  {
    int S_len = S ? strlen(S): 0;
    int rq_len = S_len ? (S_len*btl+7)/8 : 0;
    
    if ( rq_len )
      {
        void *out = Yo_Malloc(rq_len);
        memset(out,0,rq_len);
        Str_Xbit_Decode(S,S_len,btl,tbl,out);
        if ( len ) *len = rq_len;
        return out;
      }
    
    return 0;
  }
#endif
  ;

char *Str_Hex_Byte(byte_t val,char pfx,void *out)
#ifdef _YOYO_STRING_BUILTIN
  {
    static char symbols[] = 
      { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
    char *q = out;
    switch ( pfx )
      {
        case 'x': *q++='0'; *q++='x'; break;
        case '\\': *q++='\\'; *q++='x'; break;
        case '%': *q++='%'; break; 
        default: break;
      }
    *q++ = symbols[(val>>4)];
    *q++ = symbols[val&0x0f];
    *q = 0;
    return out;
  }
#endif
  ;

char *Str_Hex_Encode(void *data, int len)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( data && len )
      {
        int i;
        int rq_len = len*2;
        char *out = Yo_Malloc(rq_len+1);
        memset(out,0,rq_len+1);







|



















|




















|







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
#endif
  ;

#define Str_5bit_Decode(S,L) Str_Qbit_Decode(S,L,Str_5bit_Decoding_Table,5)
#define Str_6bit_Decode(S,L) Str_Qbit_Decode(S,L,Str_6bit_Decoding_Table,6)

void *Str_Qbit_Decode(char *S,int *len,byte_t *tbl,int btl)
#ifdef _YO_STRING_BUILTIN
  {
    int S_len = S ? strlen(S): 0;
    int rq_len = S_len ? (S_len*btl+7)/8 : 0;
    
    if ( rq_len )
      {
        void *out = Yo_Malloc(rq_len);
        memset(out,0,rq_len);
        Str_Xbit_Decode(S,S_len,btl,tbl,out);
        if ( len ) *len = rq_len;
        return out;
      }
    
    return 0;
  }
#endif
  ;

char *Str_Hex_Byte(byte_t val,char pfx,void *out)
#ifdef _YO_STRING_BUILTIN
  {
    static char symbols[] = 
      { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
    char *q = out;
    switch ( pfx )
      {
        case 'x': *q++='0'; *q++='x'; break;
        case '\\': *q++='\\'; *q++='x'; break;
        case '%': *q++='%'; break; 
        default: break;
      }
    *q++ = symbols[(val>>4)];
    *q++ = symbols[val&0x0f];
    *q = 0;
    return out;
  }
#endif
  ;

char *Str_Hex_Encode(void *data, int len)
#ifdef _YO_STRING_BUILTIN
  {
    if ( data && len )
      {
        int i;
        int rq_len = len*2;
        char *out = Yo_Malloc(rq_len+1);
        memset(out,0,rq_len+1);
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
            r |= (*(c)-'0') << (i); \
          else if ( *(c) >= 'a' && *(c) <= 'f' ) \
            r |= (*(c)-'a'+10) << (i); \
          else if ( *(c) >= 'A' && *(c) <= 'F' ) \
            r |= (*(c)-'A'+10) << (i); \

byte_t Str_Unhex_Byte(char *S,int pfx,int *cnt)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    byte_t r = 0;
    byte_t *c = (byte_t*)S;
    if ( pfx )
      {
        if ( *c == '0' && c[1] == 'x' ) c+=2;







|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
            r |= (*(c)-'0') << (i); \
          else if ( *(c) >= 'a' && *(c) <= 'f' ) \
            r |= (*(c)-'a'+10) << (i); \
          else if ( *(c) >= 'A' && *(c) <= 'F' ) \
            r |= (*(c)-'A'+10) << (i); \

byte_t Str_Unhex_Byte(char *S,int pfx,int *cnt)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    byte_t r = 0;
    byte_t *c = (byte_t*)S;
    if ( pfx )
      {
        if ( *c == '0' && c[1] == 'x' ) c+=2;
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
    if ( cnt ) *cnt = c-(byte_t*)S;
    return r;
  }
#endif
  ;

void *Str_Hex_Decode(char *S,int *len)
#ifdef _YOYO_STRING_BUILTIN
  {
    int S_len = S ? strlen(S): 0;
    int rq_len = S_len ? S_len/2 : 0;
    
    if ( rq_len )
      {
        int i;







|







535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
    if ( cnt ) *cnt = c-(byte_t*)S;
    return r;
  }
#endif
  ;

void *Str_Hex_Decode(char *S,int *len)
#ifdef _YO_STRING_BUILTIN
  {
    int S_len = S ? strlen(S): 0;
    int rq_len = S_len ? S_len/2 : 0;
    
    if ( rq_len )
      {
        int i;
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    
    return 0;
  }
#endif
  ;

int Str_Urldecode_Char(char **S)
#ifdef _YOYO_STRING_BUILTIN
  {
    int r = 0;
    if ( *S ) 
      {
        if ( **S == '+' ) 
          {
            r = ' ';







|







557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
    
    return 0;
  }
#endif
  ;

int Str_Urldecode_Char(char **S)
#ifdef _YO_STRING_BUILTIN
  {
    int r = 0;
    if ( *S ) 
      {
        if ( **S == '+' ) 
          {
            r = ' ';
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
      }
    return r;
  }
#endif
  ;

byte_t *Str_Base64_Decode(char *S, int *l)
#ifdef _YOYO_STRING_BUILTIN
  {
    return 0;
  }
#endif
  ;

char *Str_Base64_Encode(void *data, int l)
#ifdef _YOYO_STRING_BUILTIN
  {
    return 0;
  }
#endif
  ;

void Quad_To_Hex16(uquad_t val,char *out)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 8; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

void Unsigned_To_Hex8(uint_t val,char *out)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 4; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

void Unsigned_To_Hex4(uint_t val,char *out)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 2; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

#define Unsigned_To_Hex2(Val,Out) Str_Hex_Byte((byte_t)(Val),0,Out)

uquad_t Hex16_To_Quad(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 8; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

uint_t Hex8_To_Unsigned(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 4; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

uint_t Hex4_To_Unsigned(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 2; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

#define Hex2_To_Unsigned(S) ( (uint_t)Str_Unhex_Byte(S,0,0) )

_YOYO_STRING_EXTERN char Utf8_Char_Length[] 
#ifdef _YOYO_STRING_BUILTIN
  = {
    /* Map UTF-8 encoded prefix byte to sequence length.  zero means
       illegal prefix.  see RFC 2279 for details */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,







|







|







|









|









|











|











|











|












|
|







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
      }
    return r;
  }
#endif
  ;

byte_t *Str_Base64_Decode(char *S, int *l)
#ifdef _YO_STRING_BUILTIN
  {
    return 0;
  }
#endif
  ;

char *Str_Base64_Encode(void *data, int l)
#ifdef _YO_STRING_BUILTIN
  {
    return 0;
  }
#endif
  ;

void Quad_To_Hex16(uquad_t val,char *out)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 8; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

void Unsigned_To_Hex8(uint_t val,char *out)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 4; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

void Unsigned_To_Hex4(uint_t val,char *out)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    for ( i = 0; i < 2; ++i )
      Str_Hex_Byte((byte_t)(val>>(i*8)),0,out+i*2);
  }
#endif
  ;

#define Unsigned_To_Hex2(Val,Out) Str_Hex_Byte((byte_t)(Val),0,Out)

uquad_t Hex16_To_Quad(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 8; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

uint_t Hex8_To_Unsigned(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 4; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

uint_t Hex4_To_Unsigned(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    uint_t ret = 0;
    int i;
    for ( i = 0; i < 2; ++i )
      ret |= ( (uint_t)Str_Unhex_Byte(S+i*2,0,0) << (i*8) );
    return ret;
  }
#endif
  ;

#define Hex2_To_Unsigned(S) ( (uint_t)Str_Unhex_Byte(S,0,0) )

_YO_STRING_EXTERN char Utf8_Char_Length[] 
#ifdef _YO_STRING_BUILTIN
  = {
    /* Map UTF-8 encoded prefix byte to sequence length.  zero means
       illegal prefix.  see RFC 2279 for details */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
  }
#endif
  ;

wchar_t Utf8_Char_Decode(void *S,int *cnt)
#ifdef _YOYO_STRING_BUILTIN
  {
    byte_t *text = S;
    int c = -1;
    int c0 = *text++; if ( cnt ) ++*cnt;
    if (c0 < 0x80) 
      c = (wchar_t)c0;
    else







|







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
  }
#endif
  ;

wchar_t Utf8_Char_Decode(void *S,int *cnt)
#ifdef _YO_STRING_BUILTIN
  {
    byte_t *text = S;
    int c = -1;
    int c0 = *text++; if ( cnt ) ++*cnt;
    if (c0 < 0x80) 
      c = (wchar_t)c0;
    else
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
      }
    return c;
  }
#endif
  ;

int Utf8_Wide_Length(wchar_t c)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( c < 0x80 ) 
      return 1; 
    else if ( c < 0x0800 )
      return 2;
    else
      return 3;
    return 0;
  }
#endif
  ;

char *Utf8_Wide_Encode(void *_bf,wchar_t c,int *cnt)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *bf = _bf;
    int l = 0;
    if ( c < 0x80 ) 
      { 
        *bf++ = (char)c; 
        l = 1; 







|













|







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
      }
    return c;
  }
#endif
  ;

int Utf8_Wide_Length(wchar_t c)
#ifdef _YO_STRING_BUILTIN
  {
    if ( c < 0x80 ) 
      return 1; 
    else if ( c < 0x0800 )
      return 2;
    else
      return 3;
    return 0;
  }
#endif
  ;

char *Utf8_Wide_Encode(void *_bf,wchar_t c,int *cnt)
#ifdef _YO_STRING_BUILTIN
  {
    char *bf = _bf;
    int l = 0;
    if ( c < 0x80 ) 
      { 
        *bf++ = (char)c; 
        l = 1; 
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
    if ( cnt ) *cnt += l;
    return bf;
  }
#endif
  ;

wchar_t Utf8_Get_Wide(char **S)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t out = 0;
    if ( S && *S )
      {
        int cnt = 0;
        out = Utf8_Char_Decode(*S,&cnt);
        while( **S && cnt-- ) ++*S;
      }
    return out;
  }
#endif
  ;

char *Utf8_Skip(char *S,int l)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( S )
      while ( *S && l-- )
        {
          int q = Utf8_Char_Length[(unsigned)*S]; 
          if ( q ) while ( q-- && *S ) ++S;
          else ++S;
        }
    return S;
  }
#endif
  ;

wchar_t *Str_Utf8_To_Unicode_Convert(char *S, wchar_t *out, int maxL)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i = 0;
    if ( S )
      {
        for(; *S && i < maxL; ) { out[i++] = Utf8_Get_Wide(&S); }
      }
    if ( i < maxL ) out[i] = 0;
    return out;
  }
#endif
  ;
  
#define Str_Utf8_To_Unicode(S) Yo_Pool(Str_Utf8_To_Unicode_Npl(S))
wchar_t *Str_Utf8_To_Unicode_Npl(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t *out = 0;
    if ( S )
      {
        int n = 0;
        char *Q = S;
        while( *Q ) { Utf8_Get_Wide(&Q); ++n; }
        out = Yo_Malloc_Npl((n+1)*sizeof(wchar_t));
        for( n = 0; *S; ) { out[n++] = Utf8_Get_Wide(&S); }
        out[n] = 0;
      }
    return out;
  }
#endif
  ;

char *Str_Unicode_To_Utf8_Convert(wchar_t *S, char *out, int maxL)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i = 0;
    if ( S )
      {
        for(; *S && i + Utf8_Wide_Length(*S) < maxL; ) 
          { Utf8_Wide_Encode(out+i,*S++,&i); }
      }
    if ( i < maxL ) out[i] = 0;
    return out;
  }
#endif
  ;

#define Str_Unicode_To_Utf8(S) Yo_Pool(Str_Unicode_To_Utf8_Npl(S))  
char *Str_Unicode_To_Utf8_Npl(wchar_t *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *out = 0;
    if ( S )
      {
        int n = 0;
        wchar_t *Q = S;
        while ( *Q )







|














|














|














|

















|















|







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
    if ( cnt ) *cnt += l;
    return bf;
  }
#endif
  ;

wchar_t Utf8_Get_Wide(char **S)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t out = 0;
    if ( S && *S )
      {
        int cnt = 0;
        out = Utf8_Char_Decode(*S,&cnt);
        while( **S && cnt-- ) ++*S;
      }
    return out;
  }
#endif
  ;

char *Utf8_Skip(char *S,int l)
#ifdef _YO_STRING_BUILTIN
  {
    if ( S )
      while ( *S && l-- )
        {
          int q = Utf8_Char_Length[(unsigned)*S]; 
          if ( q ) while ( q-- && *S ) ++S;
          else ++S;
        }
    return S;
  }
#endif
  ;

wchar_t *Str_Utf8_To_Unicode_Convert(char *S, wchar_t *out, int maxL)
#ifdef _YO_STRING_BUILTIN
  {
    int i = 0;
    if ( S )
      {
        for(; *S && i < maxL; ) { out[i++] = Utf8_Get_Wide(&S); }
      }
    if ( i < maxL ) out[i] = 0;
    return out;
  }
#endif
  ;
  
#define Str_Utf8_To_Unicode(S) Yo_Pool(Str_Utf8_To_Unicode_Npl(S))
wchar_t *Str_Utf8_To_Unicode_Npl(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t *out = 0;
    if ( S )
      {
        int n = 0;
        char *Q = S;
        while( *Q ) { Utf8_Get_Wide(&Q); ++n; }
        out = Yo_Malloc_Npl((n+1)*sizeof(wchar_t));
        for( n = 0; *S; ) { out[n++] = Utf8_Get_Wide(&S); }
        out[n] = 0;
      }
    return out;
  }
#endif
  ;

char *Str_Unicode_To_Utf8_Convert(wchar_t *S, char *out, int maxL)
#ifdef _YO_STRING_BUILTIN
  {
    int i = 0;
    if ( S )
      {
        for(; *S && i + Utf8_Wide_Length(*S) < maxL; ) 
          { Utf8_Wide_Encode(out+i,*S++,&i); }
      }
    if ( i < maxL ) out[i] = 0;
    return out;
  }
#endif
  ;

#define Str_Unicode_To_Utf8(S) Yo_Pool(Str_Unicode_To_Utf8_Npl(S))  
char *Str_Unicode_To_Utf8_Npl(wchar_t *S)
#ifdef _YO_STRING_BUILTIN
  {
    char *out = 0;
    if ( S )
      {
        int n = 0;
        wchar_t *Q = S;
        while ( *Q )
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
  }
#endif
  ;

/** specially for windoze **/
#define Str_Locale_To_Unicode(S) Yo_Pool(Str_Locale_To_Unicode_Npl(S));
wchar_t *Str_Locale_To_Unicode_Npl(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
  #ifdef __windoze
    int L = strlen(S);
    wchar_t *ret = Yo_Malloc_Npl((L+1)*sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP,0,S,-1,ret,L);
    ret[L] = 0;
    return ret;
  #else
    return Str_Utf8_To_Unicode_Npl(S);
  #endif
  }
#endif
  ;

/** specially for windoze **/
#define Str_Locale_To_Utf8(S) Yo_Pool(Str_Locale_To_Utf8_Npl(S));
char *Str_Locale_To_Utf8_Npl(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
  #ifdef __windoze
    wchar_t *tmp = Str_Locale_To_Unicode_Npl(S);
    char *ret = Str_Unicode_To_Utf8_Npl(tmp);
    free(tmp);
    return ret;
  #else
    return Str_Copy_Npl(S,-1);
  #endif
  }
#endif
  ;

#define Str_Concat(A,B) Yo_Pool(Str_Concat_Npl(A,B))
char *Str_Concat_Npl(char *a, char *b)
#ifdef _YOYO_STRING_BUILTIN
  {
    int a_len = a?strlen(a):0;
    int b_len = b?strlen(b):0;
    char *out = Yo_Malloc_Npl(a_len+b_len+1);
    if ( a_len )
      memcpy(out,a,a_len);
    if ( b_len )
      memcpy(out+a_len,b,b_len);
    out[a_len+b_len] = 0;
    return out;
  }
#endif
  ;

#define Str_Join_Q(Sep,Sx) ((char*)__Pool(Str_Join_Q_Npl(Sep,Sx)))
char *Str_Join_Q_Npl(char sep, char **Sx)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    int len = 0;
    char *q = 0, *out = 0;
    for ( i = 0; !!(q = Sx[i]); ++i )
      len += strlen(q)+(sep?1:0);
    if ( len )







|

















|















|
















|







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
  }
#endif
  ;

/** specially for windoze **/
#define Str_Locale_To_Unicode(S) Yo_Pool(Str_Locale_To_Unicode_Npl(S));
wchar_t *Str_Locale_To_Unicode_Npl(char *S)
#ifdef _YO_STRING_BUILTIN
  {
  #ifdef __windoze
    int L = strlen(S);
    wchar_t *ret = Yo_Malloc_Npl((L+1)*sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP,0,S,-1,ret,L);
    ret[L] = 0;
    return ret;
  #else
    return Str_Utf8_To_Unicode_Npl(S);
  #endif
  }
#endif
  ;

/** specially for windoze **/
#define Str_Locale_To_Utf8(S) Yo_Pool(Str_Locale_To_Utf8_Npl(S));
char *Str_Locale_To_Utf8_Npl(char *S)
#ifdef _YO_STRING_BUILTIN
  {
  #ifdef __windoze
    wchar_t *tmp = Str_Locale_To_Unicode_Npl(S);
    char *ret = Str_Unicode_To_Utf8_Npl(tmp);
    free(tmp);
    return ret;
  #else
    return Str_Copy_Npl(S,-1);
  #endif
  }
#endif
  ;

#define Str_Concat(A,B) Yo_Pool(Str_Concat_Npl(A,B))
char *Str_Concat_Npl(char *a, char *b)
#ifdef _YO_STRING_BUILTIN
  {
    int a_len = a?strlen(a):0;
    int b_len = b?strlen(b):0;
    char *out = Yo_Malloc_Npl(a_len+b_len+1);
    if ( a_len )
      memcpy(out,a,a_len);
    if ( b_len )
      memcpy(out+a_len,b,b_len);
    out[a_len+b_len] = 0;
    return out;
  }
#endif
  ;

#define Str_Join_Q(Sep,Sx) ((char*)__Pool(Str_Join_Q_Npl(Sep,Sx)))
char *Str_Join_Q_Npl(char sep, char **Sx)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    int len = 0;
    char *q = 0, *out = 0;
    for ( i = 0; !!(q = Sx[i]); ++i )
      len += strlen(q)+(sep?1:0);
    if ( len )
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
      }
    return out;
  }
#endif
  ;

char *Str_Join_Va_Npl(char sep, va_list va)
#ifdef _YOYO_STRING_BUILTIN
  {
    int len = 0;
    char *q = 0, *out = 0;
    va_list va2;
#ifdef __GNUC__
    va_copy(va2,va);
#else







|







959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
      }
    return out;
  }
#endif
  ;

char *Str_Join_Va_Npl(char sep, va_list va)
#ifdef _YO_STRING_BUILTIN
  {
    int len = 0;
    char *q = 0, *out = 0;
    va_list va2;
#ifdef __GNUC__
    va_copy(va2,va);
#else
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
      }
    return out;
  }
#endif
  ;

char *Str_Join_Npl_(char sep, ...)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *out;
    va_list va;
    va_start(va,sep);
    out = Str_Join_Va_Npl(sep,va);
    va_end(va);
    return out;
  }
#endif
  ;
  
#define Str_Join_Npl_2(Sep,S1,S2) Str_Join_Npl_(Sep,S1,S2,(char*)0)
#define Str_Join_Npl_3(Sep,S1,S2,S3) Str_Join_Npl_(Sep,S1,S2,S3,(char*)0)
#define Str_Join_Npl_4(Sep,S1,S2,S3,S4) Str_Join_Npl_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Join_Npl_5(Sep,S1,S2,S3,S4,S5) Str_Join_Npl_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Join_Npl_6(Sep,S1,S2,S3,S4,S5,S6) Str_Join_Npl_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

char *Str_Join_(char sep, ...)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *out;
    va_list va;
    va_start(va,sep);
    out = Yo_Pool(Str_Join_Va_Npl(sep,va));
    va_end(va);
    return out;
  }
#endif
  ;

#define Str_Join_2(Sep,S1,S2) Str_Join_(Sep,S1,S2,(char*)0)
#define Str_Join_3(Sep,S1,S2,S3) Str_Join_(Sep,S1,S2,S3,(char*)0)
#define Str_Join_4(Sep,S1,S2,S3,S4) Str_Join_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Join_5(Sep,S1,S2,S3,S4,S5) Str_Join_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Join_6(Sep,S1,S2,S3,S4,S5,S6) Str_Join_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

#define Str_Unicode_Concat(A,B) ((wchar_t*)__Pool(Str_Unicode_Concat_Npl(A,B)))
wchar_t *Str_Unicode_Concat_Npl(wchar_t *a, wchar_t *b)
#ifdef _YOYO_STRING_BUILTIN
  {
    int a_len = a?wcslen(a):0;
    int b_len = b?wcslen(b):0;
    wchar_t *out = Yo_Malloc_Npl((a_len+b_len+1)*sizeof(wchar_t));
    if ( a_len )
      memcpy(out,a,a_len*sizeof(wchar_t));
    if ( b_len )
      memcpy(out+a_len,b,b_len*sizeof(wchar_t));
    out[a_len+b_len] = 0;
    return out;
  }
#endif
  ;

wchar_t *Str_Unicode_Join_Va_Npl(int sep, va_list va)
#ifdef _YOYO_STRING_BUILTIN
  {
    int len = 0;
    wchar_t *q, *out = 0;
    va_list va2;
#ifdef __GNUC__
    va_copy(va2,va);
#else







|


















|



















|















|







995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
      }
    return out;
  }
#endif
  ;

char *Str_Join_Npl_(char sep, ...)
#ifdef _YO_STRING_BUILTIN
  {
    char *out;
    va_list va;
    va_start(va,sep);
    out = Str_Join_Va_Npl(sep,va);
    va_end(va);
    return out;
  }
#endif
  ;
  
#define Str_Join_Npl_2(Sep,S1,S2) Str_Join_Npl_(Sep,S1,S2,(char*)0)
#define Str_Join_Npl_3(Sep,S1,S2,S3) Str_Join_Npl_(Sep,S1,S2,S3,(char*)0)
#define Str_Join_Npl_4(Sep,S1,S2,S3,S4) Str_Join_Npl_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Join_Npl_5(Sep,S1,S2,S3,S4,S5) Str_Join_Npl_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Join_Npl_6(Sep,S1,S2,S3,S4,S5,S6) Str_Join_Npl_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

char *Str_Join_(char sep, ...)
#ifdef _YO_STRING_BUILTIN
  {
    char *out;
    va_list va;
    va_start(va,sep);
    out = Yo_Pool(Str_Join_Va_Npl(sep,va));
    va_end(va);
    return out;
  }
#endif
  ;

#define Str_Join_2(Sep,S1,S2) Str_Join_(Sep,S1,S2,(char*)0)
#define Str_Join_3(Sep,S1,S2,S3) Str_Join_(Sep,S1,S2,S3,(char*)0)
#define Str_Join_4(Sep,S1,S2,S3,S4) Str_Join_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Join_5(Sep,S1,S2,S3,S4,S5) Str_Join_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Join_6(Sep,S1,S2,S3,S4,S5,S6) Str_Join_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

#define Str_Unicode_Concat(A,B) ((wchar_t*)__Pool(Str_Unicode_Concat_Npl(A,B)))
wchar_t *Str_Unicode_Concat_Npl(wchar_t *a, wchar_t *b)
#ifdef _YO_STRING_BUILTIN
  {
    int a_len = a?wcslen(a):0;
    int b_len = b?wcslen(b):0;
    wchar_t *out = Yo_Malloc_Npl((a_len+b_len+1)*sizeof(wchar_t));
    if ( a_len )
      memcpy(out,a,a_len*sizeof(wchar_t));
    if ( b_len )
      memcpy(out+a_len,b,b_len*sizeof(wchar_t));
    out[a_len+b_len] = 0;
    return out;
  }
#endif
  ;

wchar_t *Str_Unicode_Join_Va_Npl(int sep, va_list va)
#ifdef _YO_STRING_BUILTIN
  {
    int len = 0;
    wchar_t *q, *out = 0;
    va_list va2;
#ifdef __GNUC__
    va_copy(va2,va);
#else
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
      }
    return out;
  }
#endif
  ;

wchar_t *Str_Unicode_Join_Npl_(int sep, ...)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t *out;
    va_list va;
    va_start(va,sep);
    out = Str_Unicode_Join_Va_Npl(sep,va);
    va_end(va);
    return out;
  }
#endif
  ;
  
#define Str_Unicode_Join_Npl_2(Sep,S1,S2) Str_Unicode_Join_Npl_(Sep,S1,S2,(char*)0)
#define Str_Unicode_Join_Npl_3(Sep,S1,S2,S3) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,(char*)0)
#define Str_Unicode_Join_Npl_4(Sep,S1,S2,S3,S4) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Unicode_Join_Npl_5(Sep,S1,S2,S3,S4,S5) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Unicode_Join_Npl_6(Sep,S1,S2,S3,S4,S5,S6) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

wchar_t *Str_Unicode_Join_(int sep, ...)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t *out;
    va_list va;
    va_start(va,sep);
    out = __Pool(Str_Unicode_Join_Va_Npl(sep,va));
    va_end(va);
    return out;
  }
#endif
  ;

#define Str_Unicode_Join_2(Sep,S1,S2) Str_Unicode_Join_(Sep,S1,S2,(char*)0)
#define Str_Unicode_Join_3(Sep,S1,S2,S3) Str_Unicode_Join_(Sep,S1,S2,S3,(char*)0)
#define Str_Unicode_Join_4(Sep,S1,S2,S3,S4) Str_Unicode_Join_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Unicode_Join_5(Sep,S1,S2,S3,S4,S5) Str_Unicode_Join_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Unicode_Join_6(Sep,S1,S2,S3,S4,S5,S6) Str_Unicode_Join_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

#define Str_From_Int(Value) Str_From_Int_Base(Value,10)
char *Str_From_Int_Base(long value, int base)
#ifdef _YOYO_STRING_BUILTIN
  {
    char syms[70] = {0};
    int l = 0;
    switch ( base )
      {
        case 16: 
          l = sprintf(syms,"0x%lx",value); break;
        case 8:  
          l = sprintf(syms,"%0lo",value); break;
        case 10: 
        default:
          l = sprintf(syms,"%ld",value); break;      
      }
    return Str_Copy_L(syms,l);
  }
#endif
  ;

#define Str_From_Flt(Value) Str_From_Flt_Perc(Value,3);
char *Str_From_Flt_Perc(double value, int perc)
#ifdef _YOYO_STRING_BUILTIN
  {
    int l;
    char syms[70] = {0};
    char fmt[] = "%._f";
    if ( perc )
      fmt[2] = (perc%9)+'0';
    l = sprintf(syms,fmt,value);
    return Str_Copy_L(syms,l);
  }
#endif
  ;

char *Str_From_Bool(int b)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( b )
      return Str_Copy_L("#true",5);
    else
      return Str_Copy_L("#false",6);
  }
#endif
  ;

int Str_To_Bool_Dflt(char *S,int dflt)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( S && *S == '#' ) ++S;
    if ( !S || !*S || !strcmp_I(S,"no") || !strcmp_I(S,"off") || !strcmp_I(S,"false") || !strcmp_I(S,"1") )
      return 0;
    if ( !strcmp_I(S,"yes") || !strcmp_I(S,"on") || !strcmp_I(S,"true") || !strcmp_I(S,"0") )
      return 1;
    return dflt;
  }
#endif
  ;

int Str_To_Bool(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    int q = Str_To_Bool_Dflt(S,3);
    if ( q == 3 )
      __Raise(YOYO_ERROR_ILLFORMED,__Format("invalid logical value '%s'",S));
    return q;
  }
#endif
  ;

long Str_To_Int(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    long l = 0;
    
    if (!S) 
      __Raise(YOYO_ERROR_NULL_PTR,0);
    else
      {
        char *ep = 0;
        l = strtol(S,&ep,0);
        if ( !*S || *ep )
          __Raise(YOYO_ERROR_ILLFORMED,__Format("invalid integer value '%s'",S));
      }
      
    return l;
  }
#endif
  ;

long Str_To_Int_Dflt(char *S, long dflt)
#ifdef _YOYO_STRING_BUILTIN
  {
    long l;
    if (!S) 
      l = dflt;
    else
      {
        char *ep = 0;
        l = strtol(S,&ep,0);
        if ( !*S || *ep )
          l = dflt;
      }
    return l;
  }
#endif
  ;

double Str_To_Flt(char *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    double l = 0;
    
    if (!S) 
      __Raise(YOYO_ERROR_NULL_PTR,0);
    else
      {
        char *ep = 0;
        l = strtod(S,&ep);
        if ( !*S || *ep )
          __Raise(YOYO_ERROR_ILLFORMED,__Format("invalid float value '%s'",S));
      }
      
    return l;
  }
#endif
  ;

double Str_To_Flt_Dflt(char *S, double dflt)
#ifdef _YOYO_STRING_BUILTIN
  {
    double l = 0;
    
    if (!S) 
      l = dflt;
    else
      {
        char *ep = 0;
        l = strtod(S,&ep);
        if ( !*S || *ep )
          l = dflt;
      }
    
    return l;
  }
#endif
  ;

#define Str_Equal_Nocase(Cs,Ct) Str_Equal_Nocase_Len(Cs,Ct,INT_MAX)
int Str_Equal_Nocase_Len(char *S, char *T, int L)
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t c;
    char *Se = S+L;
    char *Te = T+L;
    
    if (L <= 0) return 0;
    
    do 
      {
        if ( (c = Utf8_Get_Wide(&S)) != Utf8_Get_Wide(&T) )
          return 0;
      } 
    while ( c && S < Se && T < Te );
    return 1;
  }    
#endif
  ;

enum 
  {
    YOYO_BOM_DOESNT_PRESENT = 0,
    YOYO_BOM_UTF16_LE = 1,
    YOYO_BOM_UTF16_BE = 2,
    YOYO_BOM_UTF8 = 3,
  };

int Str_Find_BOM(void *S)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( *(byte_t*)S == 0x0ff && ((byte_t*)S)[1] == 0x0fe )
      return YOYO_BOM_UTF16_LE;
    if ( *(byte_t*)S == 0x0fe && ((byte_t*)S)[1] == 0x0ff )
      return YOYO_BOM_UTF16_BE;
    if ( *(byte_t*)S == 0x0ef && ((byte_t*)S)[1] == 0x0bb && ((byte_t*)S)[1] == 0x0bf )
      return YOYO_BOM_UTF8;
    return YOYO_BOM_DOESNT_PRESENT;
  }
#endif
  ;

int Str_Starts_With(char *S, char *patt)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;

    while ( *patt )
      if ( *S++ != *patt++ )
        return 0;
    return 1;
  }
#endif
  ;

int Str_Unicode_Starts_With(wchar_t *S, wchar_t *patt)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;

    while ( *patt )
      if ( *S++ != *patt++ )
        return 0;
    return 1;
  }
#endif
  ;

int Str_Unicode_Starts_With_Nocase(wchar_t *S, wchar_t *patt)
#ifdef _YOYO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;
    
    while ( *patt )
      if ( !*S || towupper(*S++) != towupper(*patt++) )
        return 0;

    return 1;
  }
#endif
  ;

void Str_Cat(char **inout, char *S, int L)
#ifdef _YOYO_STRING_BUILTIN
  {

    int count = *inout?strlen(*inout):0;
    if ( L < 0 ) L = S?strlen(S):0;
    
    __Elm_Append(inout,count,S,L,1,0);
  }
#endif
  ;

void Str_Unicode_Cat(wchar_t **inout, wchar_t *S, int L)
#ifdef _YOYO_STRING_BUILTIN
  {
    int count = *inout?wcslen(*inout):0;
    if ( L < 0 ) L = S?wcslen(S):0;
    
    __Elm_Append(inout,count,S,L,sizeof(wchar_t),0);
  }
#endif
  ;

wchar_t *Str_Unicode_Cr_To_CfLr_Inplace(wchar_t **S_ptr)
#ifdef _YOYO_STRING_BUILTIN
  {
    int capacity = 0;
    wchar_t *S = *S_ptr;
    int i, L = wcslen(S);
    for ( i = 0; i < L; ++i )
      {
        if ( S[i] == '\n' && ( !i || S[i-1] != '\r' ) )







|


















|



















|




















|













|










|












|



|






|




|





|








|

















|




|





|








|




















|




















|
|
|
|



|


|

|

|
|





|












|












|













|











|










|







1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
      }
    return out;
  }
#endif
  ;

wchar_t *Str_Unicode_Join_Npl_(int sep, ...)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t *out;
    va_list va;
    va_start(va,sep);
    out = Str_Unicode_Join_Va_Npl(sep,va);
    va_end(va);
    return out;
  }
#endif
  ;
  
#define Str_Unicode_Join_Npl_2(Sep,S1,S2) Str_Unicode_Join_Npl_(Sep,S1,S2,(char*)0)
#define Str_Unicode_Join_Npl_3(Sep,S1,S2,S3) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,(char*)0)
#define Str_Unicode_Join_Npl_4(Sep,S1,S2,S3,S4) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Unicode_Join_Npl_5(Sep,S1,S2,S3,S4,S5) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Unicode_Join_Npl_6(Sep,S1,S2,S3,S4,S5,S6) Str_Unicode_Join_Npl_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

wchar_t *Str_Unicode_Join_(int sep, ...)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t *out;
    va_list va;
    va_start(va,sep);
    out = __Pool(Str_Unicode_Join_Va_Npl(sep,va));
    va_end(va);
    return out;
  }
#endif
  ;

#define Str_Unicode_Join_2(Sep,S1,S2) Str_Unicode_Join_(Sep,S1,S2,(char*)0)
#define Str_Unicode_Join_3(Sep,S1,S2,S3) Str_Unicode_Join_(Sep,S1,S2,S3,(char*)0)
#define Str_Unicode_Join_4(Sep,S1,S2,S3,S4) Str_Unicode_Join_(Sep,S1,S2,S3,S4,(char*)0)
#define Str_Unicode_Join_5(Sep,S1,S2,S3,S4,S5) Str_Unicode_Join_(Sep,S1,S2,S3,S4,S5,(char*)0)
#define Str_Unicode_Join_6(Sep,S1,S2,S3,S4,S5,S6) Str_Unicode_Join_(Sep,S1,S2,S3,S4,S5,S6,(char*)0)

#define Str_From_Int(Value) Str_From_Int_Base(Value,10)
char *Str_From_Int_Base(long value, int base)
#ifdef _YO_STRING_BUILTIN
  {
    char syms[70] = {0};
    int l = 0;
    switch ( base )
      {
        case 16: 
          l = sprintf(syms,"0x%lx",value); break;
        case 8:  
          l = sprintf(syms,"%0lo",value); break;
        case 10: 
        default:
          l = sprintf(syms,"%ld",value); break;      
      }
    return Str_Copy_L(syms,l);
  }
#endif
  ;

#define Str_From_Flt(Value) Str_From_Flt_Perc(Value,3);
char *Str_From_Flt_Perc(double value, int perc)
#ifdef _YO_STRING_BUILTIN
  {
    int l;
    char syms[70] = {0};
    char fmt[] = "%._f";
    if ( perc )
      fmt[2] = (perc%9)+'0';
    l = sprintf(syms,fmt,value);
    return Str_Copy_L(syms,l);
  }
#endif
  ;

char *Str_From_Bool(int b)
#ifdef _YO_STRING_BUILTIN
  {
    if ( b )
      return Str_Copy_L("#true",5);
    else
      return Str_Copy_L("#false",6);
  }
#endif
  ;

int Str_To_Bool_Dflt(char *S,int dflt)
#ifdef _YO_STRING_BUILTIN
  {
    if ( S && *S == '#' ) ++S;
    if ( !S || !*S || !strcmp_I(S,"no") || !strcmp_I(S,"off") || !strcmp_I(S,"false") || !strcmp_I(S,"1") )
      return 0;
    if ( !strcmp_I(S,"yes") || !strcmp_I(S,"on") || !strcmp_I(S,"true") || !strcmp_I(S,"0") )
      return 1;
    return dflt;
  }
#endif
  ;

int Str_To_Bool(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    int q = Str_To_Bool_Dflt(S,3);
    if ( q == 3 )
      __Raise(YO_ERROR_ILLFORMED,__Format("invalid logical value '%s'",S));
    return q;
  }
#endif
  ;

long Str_To_Int(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    long l = 0;
    
    if (!S) 
      __Raise(YO_ERROR_NULL_PTR,0);
    else
      {
        char *ep = 0;
        l = strtol(S,&ep,0);
        if ( !*S || *ep )
          __Raise(YO_ERROR_ILLFORMED,__Format("invalid integer value '%s'",S));
      }
      
    return l;
  }
#endif
  ;

long Str_To_Int_Dflt(char *S, long dflt)
#ifdef _YO_STRING_BUILTIN
  {
    long l;
    if (!S) 
      l = dflt;
    else
      {
        char *ep = 0;
        l = strtol(S,&ep,0);
        if ( !*S || *ep )
          l = dflt;
      }
    return l;
  }
#endif
  ;

double Str_To_Flt(char *S)
#ifdef _YO_STRING_BUILTIN
  {
    double l = 0;
    
    if (!S) 
      __Raise(YO_ERROR_NULL_PTR,0);
    else
      {
        char *ep = 0;
        l = strtod(S,&ep);
        if ( !*S || *ep )
          __Raise(YO_ERROR_ILLFORMED,__Format("invalid float value '%s'",S));
      }
      
    return l;
  }
#endif
  ;

double Str_To_Flt_Dflt(char *S, double dflt)
#ifdef _YO_STRING_BUILTIN
  {
    double l = 0;
    
    if (!S) 
      l = dflt;
    else
      {
        char *ep = 0;
        l = strtod(S,&ep);
        if ( !*S || *ep )
          l = dflt;
      }
    
    return l;
  }
#endif
  ;

#define Str_Equal_Nocase(Cs,Ct) Str_Equal_Nocase_Len(Cs,Ct,INT_MAX)
int Str_Equal_Nocase_Len(char *S, char *T, int L)
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t c;
    char *Se = S+L;
    char *Te = T+L;
    
    if (L <= 0) return 0;
    
    do 
      {
        if ( (c = Utf8_Get_Wide(&S)) != Utf8_Get_Wide(&T) )
          return 0;
      } 
    while ( c && S < Se && T < Te );
    return 1;
  }    
#endif
  ;

enum 
  {
    YO_BOM_DOESNT_PRESENT = 0,
    YO_BOM_UTF16_LE = 1,
    YO_BOM_UTF16_BE = 2,
    YO_BOM_UTF8 = 3,
  };

int Str_Find_BOM(void *S)
#ifdef _YO_STRING_BUILTIN
  {
    if ( *(byte_t*)S == 0x0ff && ((byte_t*)S)[1] == 0x0fe )
      return YO_BOM_UTF16_LE;
    if ( *(byte_t*)S == 0x0fe && ((byte_t*)S)[1] == 0x0ff )
      return YO_BOM_UTF16_BE;
    if ( *(byte_t*)S == 0x0ef && ((byte_t*)S)[1] == 0x0bb && ((byte_t*)S)[1] == 0x0bf )
      return YO_BOM_UTF8;
    return YO_BOM_DOESNT_PRESENT;
  }
#endif
  ;

int Str_Starts_With(char *S, char *patt)
#ifdef _YO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;

    while ( *patt )
      if ( *S++ != *patt++ )
        return 0;
    return 1;
  }
#endif
  ;

int Str_Unicode_Starts_With(wchar_t *S, wchar_t *patt)
#ifdef _YO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;

    while ( *patt )
      if ( *S++ != *patt++ )
        return 0;
    return 1;
  }
#endif
  ;

int Str_Unicode_Starts_With_Nocase(wchar_t *S, wchar_t *patt)
#ifdef _YO_STRING_BUILTIN
  {
    if ( !patt || !S ) return 0;
    
    while ( *patt )
      if ( !*S || towupper(*S++) != towupper(*patt++) )
        return 0;

    return 1;
  }
#endif
  ;

void Str_Cat(char **inout, char *S, int L)
#ifdef _YO_STRING_BUILTIN
  {

    int count = *inout?strlen(*inout):0;
    if ( L < 0 ) L = S?strlen(S):0;
    
    __Elm_Append(inout,count,S,L,1,0);
  }
#endif
  ;

void Str_Unicode_Cat(wchar_t **inout, wchar_t *S, int L)
#ifdef _YO_STRING_BUILTIN
  {
    int count = *inout?wcslen(*inout):0;
    if ( L < 0 ) L = S?wcslen(S):0;
    
    __Elm_Append(inout,count,S,L,sizeof(wchar_t),0);
  }
#endif
  ;

wchar_t *Str_Unicode_Cr_To_CfLr_Inplace(wchar_t **S_ptr)
#ifdef _YO_STRING_BUILTIN
  {
    int capacity = 0;
    wchar_t *S = *S_ptr;
    int i, L = wcslen(S);
    for ( i = 0; i < L; ++i )
      {
        if ( S[i] == '\n' && ( !i || S[i-1] != '\r' ) )
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  }
#endif
  ;

#define Str_Unicode_Search(S,Patt) Str_Unicode_Search_(S,-1,Patt,-1,0)
#define Str_Unicode_Search_Nocase(S,Patt) Str_Unicode_Search_(S,-1,Patt,-1,1)
int Str_Unicode_Search_( wchar_t *S, int L, wchar_t *patt, int pattL, int nocase )
#ifdef _YOYO_STRING_BUILTIN
  {
    wchar_t *p, *pE;
    
    if ( L < 0 ) L = S?wcslen(S):0;
    if ( pattL < 0 ) pattL = patt?wcslen(patt):0;

    if ( L < pattL ) return -1;







|







1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  }
#endif
  ;

#define Str_Unicode_Search(S,Patt) Str_Unicode_Search_(S,-1,Patt,-1,0)
#define Str_Unicode_Search_Nocase(S,Patt) Str_Unicode_Search_(S,-1,Patt,-1,1)
int Str_Unicode_Search_( wchar_t *S, int L, wchar_t *patt, int pattL, int nocase )
#ifdef _YO_STRING_BUILTIN
  {
    wchar_t *p, *pE;
    
    if ( L < 0 ) L = S?wcslen(S):0;
    if ( pattL < 0 ) pattL = patt?wcslen(patt):0;

    if ( L < pattL ) return -1;
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  }
#endif
  ;
  
/* #define Str_Search_Nocase(S,Patt) Str_Search_Nocase_(S,-1,Patt,-1,1) */
#define Str_Search(S,Patt) Str_Search_(S,-1,Patt,-1)
int Str_Search_( char *S, int L, char *patt, int pattL )
#ifdef _YOYO_STRING_BUILTIN
  {
    char *p, *pE;
    
    if ( L < 0 ) L = S?strlen(S):0;
    if ( pattL < 0 ) pattL = patt?strlen(patt):0;

    if ( L < pattL ) return -1;







|







1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  }
#endif
  ;
  
/* #define Str_Search_Nocase(S,Patt) Str_Search_Nocase_(S,-1,Patt,-1,1) */
#define Str_Search(S,Patt) Str_Search_(S,-1,Patt,-1)
int Str_Search_( char *S, int L, char *patt, int pattL )
#ifdef _YO_STRING_BUILTIN
  {
    char *p, *pE;
    
    if ( L < 0 ) L = S?strlen(S):0;
    if ( pattL < 0 ) pattL = patt?strlen(patt):0;

    if ( L < pattL ) return -1;
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  }
#endif
  ;

#define Str_Replace_Npl(S,Patt,Val) Str_Replace_Npl_(S,-1,Patt,-1,Val,-1)
#define Str_Replace(S,Patt,Val) __Pool(Str_Replace_Npl_(S,-1,Patt,-1,Val,-1))
char *Str_Replace_Npl_(char *S, int L, char *patt, int pattL, char *val, int valL)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    char *R = 0;
    int R_count = 0;
    int R_capacity = 0;
    
    if ( pattL < 0 ) pattL = patt?strlen(patt):0;







|







1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
  }
#endif
  ;

#define Str_Replace_Npl(S,Patt,Val) Str_Replace_Npl_(S,-1,Patt,-1,Val,-1)
#define Str_Replace(S,Patt,Val) __Pool(Str_Replace_Npl_(S,-1,Patt,-1,Val,-1))
char *Str_Replace_Npl_(char *S, int L, char *patt, int pattL, char *val, int valL)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    char *R = 0;
    int R_count = 0;
    int R_capacity = 0;
    
    if ( pattL < 0 ) pattL = patt?strlen(patt):0;
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  ;

#define Str_Unicode_Replace_Npl(S,Patt,Val) Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,0)
#define Str_Unicode_Replace_Nocase_Npl(S,Patt,Val) __Pool(Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,1))
#define Str_Unicode_Replace(S,Patt,Val) Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,0)
#define Str_Unicode_Replace_Nocase(S,Patt,Val) __Pool(Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,1))
wchar_t *Str_Unicode_Replace_Npl_(wchar_t *S, int L, wchar_t *patt, int pattL, wchar_t *val, int valL, int nocase)
#ifdef _YOYO_STRING_BUILTIN
  {
    int i;
    wchar_t *R = 0;
    int R_count = 0;
    int R_capacity = 0;
    
    if ( pattL < 0 ) pattL = patt?wcslen(patt):0;







|







1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
  ;

#define Str_Unicode_Replace_Npl(S,Patt,Val) Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,0)
#define Str_Unicode_Replace_Nocase_Npl(S,Patt,Val) __Pool(Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,1))
#define Str_Unicode_Replace(S,Patt,Val) Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,0)
#define Str_Unicode_Replace_Nocase(S,Patt,Val) __Pool(Str_Unicode_Replace_Npl_(S,-1,Patt,-1,Val,-1,1))
wchar_t *Str_Unicode_Replace_Npl_(wchar_t *S, int L, wchar_t *patt, int pattL, wchar_t *val, int valL, int nocase)
#ifdef _YO_STRING_BUILTIN
  {
    int i;
    wchar_t *R = 0;
    int R_count = 0;
    int R_capacity = 0;
    
    if ( pattL < 0 ) pattL = patt?wcslen(patt):0;
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
  ;

#define Str_Match(S,Patt) Str_Submatch(S,Patt,0)
#define Str_Match_Nocase(S,Patt) Str_Submatch(S,Patt,1)
int Str_Submatch(char *S, char *patt, int nocase);

int Str_Submatch_Nocase_(char *S, char *patt)
#ifdef _YOYO_STRING_BUILTIN
  {
    char *SS = S;
    
    if ( *S )
      {
        do
          {







|







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
  ;

#define Str_Match(S,Patt) Str_Submatch(S,Patt,0)
#define Str_Match_Nocase(S,Patt) Str_Submatch(S,Patt,1)
int Str_Submatch(char *S, char *patt, int nocase);

int Str_Submatch_Nocase_(char *S, char *patt)
#ifdef _YO_STRING_BUILTIN
  {
    char *SS = S;
    
    if ( *S )
      {
        do
          {
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
      }
      
    return 0;
  }
#endif
  ;

#ifdef _YOYO_STRING_BUILTIN  
int Str_Submatch(char *S, char *patt, int nocase)
  {
    if ( S && patt )
      {
        while ( *S && *patt )
          {
            char *SS = S;







|







1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
      }
      
    return 0;
  }
#endif
  ;

#ifdef _YO_STRING_BUILTIN  
int Str_Submatch(char *S, char *patt, int nocase)
  {
    if ( S && patt )
      {
        while ( *S && *patt )
          {
            char *SS = S;
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
        return !*S && *S==*patt;
      }
    return 0;
  }
#endif

char *Str_Fetch_Substr(char *S, char *prefx, char *skip, char *stopat)
#ifdef _YOYO_STRING_BUILTIN  
  {
    int j = 0;
    char *qoo;
    char *Q = strstr(S,prefx);
    if ( Q )
      {
        Q += strlen(prefx);







|







1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
        return !*S && *S==*patt;
      }
    return 0;
  }
#endif

char *Str_Fetch_Substr(char *S, char *prefx, char *skip, char *stopat)
#ifdef _YO_STRING_BUILTIN  
  {
    int j = 0;
    char *qoo;
    char *Q = strstr(S,prefx);
    if ( Q )
      {
        Q += strlen(prefx);
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
    return 0;
  }
#endif
  ;
  
#define Str_Reverse(S,L) __Pool(Str_Reverse_Npl(S,L))
char *Str_Reverse_Npl(char *S, int L)
#ifdef _YOYO_STRING_BUILTIN  
  {
    int i;
    char *ret;
    if ( L < 0 ) L = S?strlen(S):0;
    ret = __Malloc_Npl(L+1);
    for ( i = 0; i < L; ++i )
      ret[i] = S[(L-i)-1];
    ret[L] = 0;
    return ret;
  }
#endif
  ;
  
wchar_t *Str_Unicode_Transform_Npl(wchar_t *S, int L, wchar_t (*transform)(wchar_t))
#ifdef _YOYO_STRING_BUILTIN  
  {
    int i;
    wchar_t *ret;
    if ( L < 0 ) L = S?wcslen(S):0;
    ret = __Malloc_Npl((L+1)*sizeof(wchar_t));
    for ( i = 0; i < L; ++i )
      ret[i] = transform(S[i]);
    ret[i] = 0;
    return ret;
  }
#endif
  ;

#define Str_Unicode_Upper(S,L) ((wchar_t*)__Pool(Str_Unicode_Upper_Npl(S,L)))
#define Str_Unicode_Upper_Npl(S,L) Str_Unicode_Transform_Npl(S,L,(void*)towupper)
#define Str_Unicode_Lower(S,L) ((wchar_t*)__Pool(Str_Unicode_Lower_Npl(S,L)))
#define Str_Unicode_Lower_Npl(S,L) Str_Unicode_Transform_Npl(S,L,(void*)towlower)

char *Str_Ansi_Transform_Npl(char *S, int L, char (*transform)(char))
#ifdef _YOYO_STRING_BUILTIN  
  {
    int i;
    char *ret;
    if ( L < 0 ) L = S?strlen(S):0;
    ret = __Malloc_Npl(L+1);
    for ( i = 0; i < L; ++i )
      ret[i] = transform(S[i]);
    ret[i] = 0;
    return ret;
  }
#endif
  ;

#define Str_Ansi_Upper(S,L) ((char*)__Pool(Str_Ansi_Upper_Npl(S,L)))
#define Str_Ansi_Upper_Npl(S,L) Str_Ansi_Transform_Npl(S,L,(void*)toupper)
#define Str_Ansi_Lower(S,L) ((char*)__Pool(Str_Ansi_Lower_Npl(S,L)))
#define Str_Ansi_Lower_Npl(S,L) Str_Ansi_Transform_Npl(S,L,(void*)tolower)

char *Str_Utf8_Transform_Npl(char *S, int L, wchar_t (*transform)(wchar_t) )
#ifdef _YOYO_STRING_BUILTIN  
  {
    char *E, *R = 0;
    int R_capacity = 1;
    int R_count = 0;
    
    if ( S )
      {







|














|



















|



















|







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
    return 0;
  }
#endif
  ;
  
#define Str_Reverse(S,L) __Pool(Str_Reverse_Npl(S,L))
char *Str_Reverse_Npl(char *S, int L)
#ifdef _YO_STRING_BUILTIN  
  {
    int i;
    char *ret;
    if ( L < 0 ) L = S?strlen(S):0;
    ret = __Malloc_Npl(L+1);
    for ( i = 0; i < L; ++i )
      ret[i] = S[(L-i)-1];
    ret[L] = 0;
    return ret;
  }
#endif
  ;
  
wchar_t *Str_Unicode_Transform_Npl(wchar_t *S, int L, wchar_t (*transform)(wchar_t))
#ifdef _YO_STRING_BUILTIN  
  {
    int i;
    wchar_t *ret;
    if ( L < 0 ) L = S?wcslen(S):0;
    ret = __Malloc_Npl((L+1)*sizeof(wchar_t));
    for ( i = 0; i < L; ++i )
      ret[i] = transform(S[i]);
    ret[i] = 0;
    return ret;
  }
#endif
  ;

#define Str_Unicode_Upper(S,L) ((wchar_t*)__Pool(Str_Unicode_Upper_Npl(S,L)))
#define Str_Unicode_Upper_Npl(S,L) Str_Unicode_Transform_Npl(S,L,(void*)towupper)
#define Str_Unicode_Lower(S,L) ((wchar_t*)__Pool(Str_Unicode_Lower_Npl(S,L)))
#define Str_Unicode_Lower_Npl(S,L) Str_Unicode_Transform_Npl(S,L,(void*)towlower)

char *Str_Ansi_Transform_Npl(char *S, int L, char (*transform)(char))
#ifdef _YO_STRING_BUILTIN  
  {
    int i;
    char *ret;
    if ( L < 0 ) L = S?strlen(S):0;
    ret = __Malloc_Npl(L+1);
    for ( i = 0; i < L; ++i )
      ret[i] = transform(S[i]);
    ret[i] = 0;
    return ret;
  }
#endif
  ;

#define Str_Ansi_Upper(S,L) ((char*)__Pool(Str_Ansi_Upper_Npl(S,L)))
#define Str_Ansi_Upper_Npl(S,L) Str_Ansi_Transform_Npl(S,L,(void*)toupper)
#define Str_Ansi_Lower(S,L) ((char*)__Pool(Str_Ansi_Lower_Npl(S,L)))
#define Str_Ansi_Lower_Npl(S,L) Str_Ansi_Transform_Npl(S,L,(void*)tolower)

char *Str_Utf8_Transform_Npl(char *S, int L, wchar_t (*transform)(wchar_t) )
#ifdef _YO_STRING_BUILTIN  
  {
    char *E, *R = 0;
    int R_capacity = 1;
    int R_count = 0;
    
    if ( S )
      {
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
#define Str_Utf8_Upper_L(S,L) ((char*)__Pool(Str_Utf8_Upper_Npl(S,L)))
#define Str_Utf8_Upper_Npl(S,L) Str_Utf8_Transform_Npl(S,L,(void*)towupper)
#define Str_Utf8_Lower(S)     Str_Utf8_Lower_L(S,-1)
#define Str_Utf8_Lower_L(S,L) ((char*)__Pool(Str_Utf8_Lower_Npl(S,L)))
#define Str_Utf8_Lower_Npl(S,L) Str_Utf8_Transform_Npl(S,L,(void*)towlower)

char *Str_Safe_Quote(char *S)
#ifdef _YOYO_STRING_BUILTIN  
  {
    int S_len = S? strlen(S):0;
    int R_count = 0;
    int R_capacity = S_len+1;
    char *R = 0;

    if ( S )







|







1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
#define Str_Utf8_Upper_L(S,L) ((char*)__Pool(Str_Utf8_Upper_Npl(S,L)))
#define Str_Utf8_Upper_Npl(S,L) Str_Utf8_Transform_Npl(S,L,(void*)towupper)
#define Str_Utf8_Lower(S)     Str_Utf8_Lower_L(S,-1)
#define Str_Utf8_Lower_L(S,L) ((char*)__Pool(Str_Utf8_Lower_Npl(S,L)))
#define Str_Utf8_Lower_Npl(S,L) Str_Utf8_Transform_Npl(S,L,(void*)towlower)

char *Str_Safe_Quote(char *S)
#ifdef _YO_STRING_BUILTIN  
  {
    int S_len = S? strlen(S):0;
    int R_count = 0;
    int R_capacity = S_len+1;
    char *R = 0;

    if ( S )
Changes to tasque.hc.
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
#ifndef C_once_FDCDEF27_5EA4_4C1D_99AB_1CD0A992A18A
#define C_once_FDCDEF27_5EA4_4C1D_99AB_1CD0A992A18A

#include "yoyo.hc"
#include "threads.hc"

#ifdef _LIBYOYO
#define _YOYO_TASQUE_BUILTIN
#endif

typedef void (*tasque_proc_t)(void *obj);
typedef void (*tasque_update_t)(void *monitor, void *obj, int status);
typedef void (*tasque_alert_t)(void *obj, int status);

enum 
  {
    TASQUE_COMPLETE = 0,
    TASQUE_FAIL     = 0x80000000,
    TASQUE_STACK_SIZE = 64*KILOBYTE,
  };

typedef struct _YOYO_TASQUE_TASK
  {
    struct _YOYO_TASQUE_TASK *next;
    tasque_proc_t task;  
    void *obj;
    tasque_update_t update;
    void *monitor;
    thread_t processor;
  } YOYO_TASQUE_TASK;

typedef struct _YOYO_TASQUE_ALERT
  {
    struct _YOYO_TASQUE_ALERT *next;
    tasque_alert_t callback;  
    void *obj;
    quad_t deadline;
  } YOYO_TASQUE_ALERT;

#ifdef _YOYO_TASQUE_BUILTIN
int Tasque_MAX = 1000;
int Tasque_RESERVE = 5;
int Tasque_ONCARE = 0;
int Tasque_COUNT = 0;
YOYO_TASQUE_TASK * volatile Tasque_Task_In = 0;
YOYO_TASQUE_TASK * volatile Tasque_Task_Out = 0;
YOYO_TASQUE_TASK * volatile Tasque_Task_Care = 0;
YOYO_TASQUE_ALERT *Tasque_Alerts_List = 0;
YOYO_THRSYNC Tasque_Lock = YOYO_THRSYNC_INIT;
YOYO_THRSYNC Tasque_Out_Monitor = YOYO_THRSYNC_INIT;
#else
extern int Tasque_MAX;
extern int Tasque_RESERVE;
#endif

void YOYO_TASQUE_TASK_Destruct(YOYO_TASQUE_TASK *tpt)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    STRICT_REQUIRE(!tpt->next);
    __Unrefe(tpt->obj);
    __Unrefe(tpt->monitor);
    __Destruct(tpt);
  }
#endif
  ;
  
void YOYO_TASQUE_ALERT_Destruct(YOYO_TASQUE_ALERT *tpt)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    STRICT_REQUIRE(!tpt->next);
    __Unrefe(tpt->obj);
    __Destruct(tpt);
  }
#endif
  ;

void Tasque_Task_Processor(void *_)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    int alive = 1;
    thread_t th = Thread_Get_Current();
    YOYO_TASQUE_TASK *t = 0;
    
    __Thr_Lock(&Tasque_Lock) 
      {
        ++Tasque_ONCARE;
        ++Tasque_COUNT;
      }
       
    while ( alive ) 
      {
        __Thr_Lock(&Tasque_Lock)
          {            
            if ( Tasque_Task_In ) 
              {
                t = Slist_Pop((YOYO_TASQUE_TASK**)&Tasque_Task_In);

                STRICT_REQUIRE(Tasque_ONCARE > 0);
                STRICT_REQUIRE(!t->processor);

                t->processor = th;
                Slist_Push((YOYO_TASQUE_TASK**)&Tasque_Task_Care,t);
                --Tasque_ONCARE;
              }
            else
              {
                if ( Tasque_ONCARE > Tasque_RESERVE ) 
                  {
                    alive = 0;







|













|

|





|

|

|



|

|




|
|
|
|
|
|





|
|









|
|









|



|













|





|







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
#ifndef C_once_FDCDEF27_5EA4_4C1D_99AB_1CD0A992A18A
#define C_once_FDCDEF27_5EA4_4C1D_99AB_1CD0A992A18A

#include "yoyo.hc"
#include "threads.hc"

#ifdef _LIBYOYO
#define _YO_TASQUE_BUILTIN
#endif

typedef void (*tasque_proc_t)(void *obj);
typedef void (*tasque_update_t)(void *monitor, void *obj, int status);
typedef void (*tasque_alert_t)(void *obj, int status);

enum 
  {
    TASQUE_COMPLETE = 0,
    TASQUE_FAIL     = 0x80000000,
    TASQUE_STACK_SIZE = 64*KILOBYTE,
  };

typedef struct _YO_TASQUE_TASK
  {
    struct _YO_TASQUE_TASK *next;
    tasque_proc_t task;  
    void *obj;
    tasque_update_t update;
    void *monitor;
    thread_t processor;
  } YO_TASQUE_TASK;

typedef struct _YO_TASQUE_ALERT
  {
    struct _YO_TASQUE_ALERT *next;
    tasque_alert_t callback;  
    void *obj;
    quad_t deadline;
  } YO_TASQUE_ALERT;

#ifdef _YO_TASQUE_BUILTIN
int Tasque_MAX = 1000;
int Tasque_RESERVE = 5;
int Tasque_ONCARE = 0;
int Tasque_COUNT = 0;
YO_TASQUE_TASK * volatile Tasque_Task_In = 0;
YO_TASQUE_TASK * volatile Tasque_Task_Out = 0;
YO_TASQUE_TASK * volatile Tasque_Task_Care = 0;
YO_TASQUE_ALERT *Tasque_Alerts_List = 0;
YO_THRSYNC Tasque_Lock = YO_THRSYNC_INIT;
YO_THRSYNC Tasque_Out_Monitor = YO_THRSYNC_INIT;
#else
extern int Tasque_MAX;
extern int Tasque_RESERVE;
#endif

void YO_TASQUE_TASK_Destruct(YO_TASQUE_TASK *tpt)
#ifdef _YO_TASQUE_BUILTIN
  {
    STRICT_REQUIRE(!tpt->next);
    __Unrefe(tpt->obj);
    __Unrefe(tpt->monitor);
    __Destruct(tpt);
  }
#endif
  ;
  
void YO_TASQUE_ALERT_Destruct(YO_TASQUE_ALERT *tpt)
#ifdef _YO_TASQUE_BUILTIN
  {
    STRICT_REQUIRE(!tpt->next);
    __Unrefe(tpt->obj);
    __Destruct(tpt);
  }
#endif
  ;

void Tasque_Task_Processor(void *_)
#ifdef _YO_TASQUE_BUILTIN
  {
    int alive = 1;
    thread_t th = Thread_Get_Current();
    YO_TASQUE_TASK *t = 0;
    
    __Thr_Lock(&Tasque_Lock) 
      {
        ++Tasque_ONCARE;
        ++Tasque_COUNT;
      }
       
    while ( alive ) 
      {
        __Thr_Lock(&Tasque_Lock)
          {            
            if ( Tasque_Task_In ) 
              {
                t = Slist_Pop((YO_TASQUE_TASK**)&Tasque_Task_In);

                STRICT_REQUIRE(Tasque_ONCARE > 0);
                STRICT_REQUIRE(!t->processor);

                t->processor = th;
                Slist_Push((YO_TASQUE_TASK**)&Tasque_Task_Care,t);
                --Tasque_ONCARE;
              }
            else
              {
                if ( Tasque_ONCARE > Tasque_RESERVE ) 
                  {
                    alive = 0;
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
          
        if ( t )
          {
            t->task(t->obj);

            __Thr_Lock(&Tasque_Lock)
              {
                Slist_Remove((YOYO_TASQUE_TASK**)&Tasque_Task_Care,t);
                Slist_Push((YOYO_TASQUE_TASK**)&Tasque_Task_Out,t);
                t = 0;
                ++Tasque_ONCARE;
              }
              
            Nolock_Notify(&Tasque_Out_Monitor);
         }
      }
      
    Nolock_Notify(&Tasque_Lock);
  }
#endif
  ;

void Tasque_Queue(tasque_proc_t task, void *obj, tasque_update_t update, void *monitor)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    __Thr_Lock(&Tasque_Lock)
      {
        YOYO_TASQUE_TASK *t = __Object_Dtor(sizeof(YOYO_TASQUE_TASK),YOYO_TASQUE_TASK_Destruct);
        t->task = task;
        t->obj  = __Refe(obj);
        t->update = update;
        t->monitor = __Refe(monitor);
        Slist_Push((YOYO_TASQUE_TASK**)&Tasque_Task_In,__Retain(t));
        if ( !Tasque_ONCARE && Tasque_COUNT < Tasque_MAX )
          Thread_Run_Close(Tasque_Task_Processor,0,TASQUE_STACK_SIZE);
      }
    Nolock_Notify(&Tasque_Lock);
  }
#endif
  ;

void Tasque_Alert(int ms, tasque_alert_t callback, void *obj)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    YOYO_TASQUE_ALERT *t = __Object_Dtor(sizeof(YOYO_TASQUE_ALERT),YOYO_TASQUE_ALERT_Destruct);
    quad_t deadline = Get_System_Millis() + ms;
    t->deadline = deadline;
    t->callback = callback;
    t->obj = __Refe(obj);
    Slist_Push(&Tasque_Alerts_List,__Retain(t));
  }
#endif
  ;
  
int Tasque_Perform_Update(int ms, int worktime)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    int i;
    quad_t deadline = worktime ? Get_System_Millis() + worktime : 0;
    YOYO_TASQUE_TASK *t;
    YOYO_TASQUE_ALERT *k;
    YOYO_TASQUE_ALERT **a; 
    
    if ( !Tasque_Task_Out )
      Nolock_Wait(&Tasque_Out_Monitor,ms);  
    
    do for ( i=0; i < 10 && Tasque_Task_Out; ++i ) __Auto_Release
      {
        __Thr_Lock(&Tasque_Lock)
          t = __Pool_RefPtr(Slist_Pop((YOYO_TASQUE_TASK**)&Tasque_Task_Out));
        t->update(t->monitor,t->obj,TASQUE_COMPLETE);
      }
    while (Tasque_Task_Out && ( !deadline || Get_System_Millis() < deadline) ); 
    
    deadline = Get_System_Millis() + 10;
    
    if ( Tasque_Alerts_List )







|
|














|



|




|









|

|










|



|
|
|







|







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
          
        if ( t )
          {
            t->task(t->obj);

            __Thr_Lock(&Tasque_Lock)
              {
                Slist_Remove((YO_TASQUE_TASK**)&Tasque_Task_Care,t);
                Slist_Push((YO_TASQUE_TASK**)&Tasque_Task_Out,t);
                t = 0;
                ++Tasque_ONCARE;
              }
              
            Nolock_Notify(&Tasque_Out_Monitor);
         }
      }
      
    Nolock_Notify(&Tasque_Lock);
  }
#endif
  ;

void Tasque_Queue(tasque_proc_t task, void *obj, tasque_update_t update, void *monitor)
#ifdef _YO_TASQUE_BUILTIN
  {
    __Thr_Lock(&Tasque_Lock)
      {
        YO_TASQUE_TASK *t = __Object_Dtor(sizeof(YO_TASQUE_TASK),YO_TASQUE_TASK_Destruct);
        t->task = task;
        t->obj  = __Refe(obj);
        t->update = update;
        t->monitor = __Refe(monitor);
        Slist_Push((YO_TASQUE_TASK**)&Tasque_Task_In,__Retain(t));
        if ( !Tasque_ONCARE && Tasque_COUNT < Tasque_MAX )
          Thread_Run_Close(Tasque_Task_Processor,0,TASQUE_STACK_SIZE);
      }
    Nolock_Notify(&Tasque_Lock);
  }
#endif
  ;

void Tasque_Alert(int ms, tasque_alert_t callback, void *obj)
#ifdef _YO_TASQUE_BUILTIN
  {
    YO_TASQUE_ALERT *t = __Object_Dtor(sizeof(YO_TASQUE_ALERT),YO_TASQUE_ALERT_Destruct);
    quad_t deadline = Get_System_Millis() + ms;
    t->deadline = deadline;
    t->callback = callback;
    t->obj = __Refe(obj);
    Slist_Push(&Tasque_Alerts_List,__Retain(t));
  }
#endif
  ;
  
int Tasque_Perform_Update(int ms, int worktime)
#ifdef _YO_TASQUE_BUILTIN
  {
    int i;
    quad_t deadline = worktime ? Get_System_Millis() + worktime : 0;
    YO_TASQUE_TASK *t;
    YO_TASQUE_ALERT *k;
    YO_TASQUE_ALERT **a; 
    
    if ( !Tasque_Task_Out )
      Nolock_Wait(&Tasque_Out_Monitor,ms);  
    
    do for ( i=0; i < 10 && Tasque_Task_Out; ++i ) __Auto_Release
      {
        __Thr_Lock(&Tasque_Lock)
          t = __Pool_RefPtr(Slist_Pop((YO_TASQUE_TASK**)&Tasque_Task_Out));
        t->update(t->monitor,t->obj,TASQUE_COMPLETE);
      }
    while (Tasque_Task_Out && ( !deadline || Get_System_Millis() < deadline) ); 
    
    deadline = Get_System_Millis() + 10;
    
    if ( Tasque_Alerts_List )
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
      i =  !!Tasque_Task_In || !!Tasque_Task_Out || !!Tasque_Task_Care || !!Tasque_Alerts_List;
    
    return i;
  }
#endif
  ;

void Tasque_Finish_Task_List(YOYO_TASQUE_TASK * volatile *lst,int status)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    YOYO_TASQUE_TASK *t;
    while ( *lst ) __Auto_Release
      {
        t = __Pool_RefPtr(Slist_Pop((YOYO_TASQUE_TASK**)lst));
        if ( t->processor )
          Thread_Terminate(t->processor);
        t->update(t->monitor,t->obj,status);
      }
  }
#endif
  ;
  
void Tasque_Terminate()
#ifdef _YOYO_TASQUE_BUILTIN
  {
    YOYO_TASQUE_TASK *t;
    Tasque_MAX = 0;
    Tasque_RESERVE = 0;
 
    if ( Tasque_COUNT )
      {
        Nolock_Notify(&Tasque_Lock);
        Sleep(30);
      }
          
    __Thr_Lock(&Tasque_Lock)
      {
        Tasque_Finish_Task_List(&Tasque_Task_Care,TASQUE_FAIL);
        Tasque_Finish_Task_List(&Tasque_Task_In,TASQUE_FAIL);
        Tasque_Finish_Task_List(&Tasque_Task_Out,TASQUE_FAIL);
      }
  }
#endif
  ;

void Tasque_Stop(long ms)
#ifdef _YOYO_TASQUE_BUILTIN
  {
    quad_t t = System_Millis() + ms;
    Tasque_MAX = 0;
    Tasque_RESERVE = 0;
    
    do 
      {







|
|

|


|









|

|




















|







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
      i =  !!Tasque_Task_In || !!Tasque_Task_Out || !!Tasque_Task_Care || !!Tasque_Alerts_List;
    
    return i;
  }
#endif
  ;

void Tasque_Finish_Task_List(YO_TASQUE_TASK * volatile *lst,int status)
#ifdef _YO_TASQUE_BUILTIN
  {
    YO_TASQUE_TASK *t;
    while ( *lst ) __Auto_Release
      {
        t = __Pool_RefPtr(Slist_Pop((YO_TASQUE_TASK**)lst));
        if ( t->processor )
          Thread_Terminate(t->processor);
        t->update(t->monitor,t->obj,status);
      }
  }
#endif
  ;
  
void Tasque_Terminate()
#ifdef _YO_TASQUE_BUILTIN
  {
    YO_TASQUE_TASK *t;
    Tasque_MAX = 0;
    Tasque_RESERVE = 0;
 
    if ( Tasque_COUNT )
      {
        Nolock_Notify(&Tasque_Lock);
        Sleep(30);
      }
          
    __Thr_Lock(&Tasque_Lock)
      {
        Tasque_Finish_Task_List(&Tasque_Task_Care,TASQUE_FAIL);
        Tasque_Finish_Task_List(&Tasque_Task_In,TASQUE_FAIL);
        Tasque_Finish_Task_List(&Tasque_Task_Out,TASQUE_FAIL);
      }
  }
#endif
  ;

void Tasque_Stop(long ms)
#ifdef _YO_TASQUE_BUILTIN
  {
    quad_t t = System_Millis() + ms;
    Tasque_MAX = 0;
    Tasque_RESERVE = 0;
    
    do 
      {
Changes to tcpip.hc.
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
  #include <netdb.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  typedef int socket_t;
#endif

#ifdef _LIBYOYO
#define _YOYO_TCPIP_BUILTIN
#endif

typedef struct ipaddr_t 
  { 
    u32_t v4;
  #ifdef _IPV6
    u16_t e6[6];
  #endif 
  } ipaddr_t;

typedef struct 
  {
    struct sockaddr_in addr4;
  #ifdef _IPV6
    struct sockaddr_in6 addr6;
  #endif
  } IPV4V6_ADDR_MIX;

void Tcp_Expand_Ip_Addr(ipaddr_t *ip, int port, IPV4V6_ADDR_MIX *addr, int *addr_len)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    memset(addr,0,sizeof(*addr));
    #ifdef _IPV6
    if ( !memcmp( ip->e6, "\xff\xff\0\0\0\0\0\0\0\0\0\0", 12) )
      {
    #endif
        addr->addr4.sin_family = AF_INET;







|



















|







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
  #include <netdb.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  typedef int socket_t;
#endif

#ifdef _LIBYOYO
#define _YO_TCPIP_BUILTIN
#endif

typedef struct ipaddr_t 
  { 
    u32_t v4;
  #ifdef _IPV6
    u16_t e6[6];
  #endif 
  } ipaddr_t;

typedef struct 
  {
    struct sockaddr_in addr4;
  #ifdef _IPV6
    struct sockaddr_in6 addr6;
  #endif
  } IPV4V6_ADDR_MIX;

void Tcp_Expand_Ip_Addr(ipaddr_t *ip, int port, IPV4V6_ADDR_MIX *addr, int *addr_len)
#ifdef _YO_TCPIP_BUILTIN
  {
    memset(addr,0,sizeof(*addr));
    #ifdef _IPV6
    if ( !memcmp( ip->e6, "\xff\xff\0\0\0\0\0\0\0\0\0\0", 12) )
      {
    #endif
        addr->addr4.sin_family = AF_INET;
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
      }
    #endif
  } 
#endif
  ;
  
ipaddr_t Tcp_Sin_Ip(void *_a)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    ipaddr_t ip;
    struct sockaddr_in *a = _a;
    memset(&ip,sizeof(ip),0);
    if ( a->sin_family == AF_INET ) 
      {
        ip.v4 = (ulong_t)a->sin_addr.s_addr;
  #ifdef _IPV6
        ip.e6[0] = 0x0ffff;
      }
    else if ( ((struct sockaddr_in6*)a)->sin6_family == AF_INET6 )
      {
        memcpy(&ip,&((struct sockaddr_in6*)a)->sin6_addr,sizeof(ip));
  #endif  
      }
    return ip; 
  }
#endif
  ;
  
typedef struct _YOYO_TCPSOK
  {
    ipaddr_t  ip;
    int       skt;
    int       port;
  } YOYO_TCPSOK;

enum  
  {
    TCP_AIO_COMPLETE    = 0,
    TCP_AIO_FAIL        = 0x80000000,
    TCP_PERMANENT_ERROR = 0x40000000,
    TCP_IS_CLOSED       = 0x20000000,
  };

#ifdef __windoze

#define Tcp_Errno() WSAGetLastError()

void _WSA_Term(void)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    WSACleanup();
  }
#endif
  ;
  
void _WSA_Init()
#ifdef _YOYO_TCPIP_BUILTIN
  {
    static int wsa_status = -1;
    static WSADATA wsa_data = {0};
    if ( wsa_status != 0 )
      {
        if ( 0 != WSAStartup(MAKEWORD(2, 2), &wsa_data) )
          { 
            __Raise(YOYO_ERROR_SUBSYSTEM_INIT,"failed to initialize WSA subsystem");
          }
        else
          {
            wsa_status = 0;
            atexit(_WSA_Term);
          }
      }
  }
#endif
  ;

#else
#define Tcp_Errno() errno
#define _WSA_Init() 
#endif

#define Tcp_Format_Error() Tcp_Format_Error_Code(Tcp_Errno())

char *Tcp_Format_Error_Code(int err)
#ifdef _YOYO_TCPIP_BUILTIN
  {
  #ifdef __windoze
    char *msg = __Malloc(1024);
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
                  FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPSTR)msg, 1024,0);
    return msg;  
  #else
    return strerror(errno);
  #endif
  }
#endif
  ;

#define Ip_Format(Ip) Ipv4_Format(Ip)
#define Ip_Format_Npl(Ip) Ipv4_Format_Npl(Ip)
#define Ipv4_Format(Ip) __Pool(Ipv4_Format_Npl(Ip))
char *Ipv4_Format_Npl(ipaddr_t ip)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    return __Format_Npl("%d.%d.%d.%d"
              ,( ip.v4     &0x0ff)
              ,((ip.v4>>8) &0x0ff)
              ,((ip.v4>>16)&0x0ff)
              ,((ip.v4>>24)&0x0ff));
  }
#endif
  ;
  
int Dns_IPv4_Resolve(char *host, ipaddr_t *ip)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    struct hostent *hstn = 0;
   
    memset(ip,0,sizeof(*ip));
  
  #ifdef _IPV6
    ip->e6[0] = 0x0ffff;







|




















|




|














|







|







|



















|



















|











|







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
      }
    #endif
  } 
#endif
  ;
  
ipaddr_t Tcp_Sin_Ip(void *_a)
#ifdef _YO_TCPIP_BUILTIN
  {
    ipaddr_t ip;
    struct sockaddr_in *a = _a;
    memset(&ip,sizeof(ip),0);
    if ( a->sin_family == AF_INET ) 
      {
        ip.v4 = (ulong_t)a->sin_addr.s_addr;
  #ifdef _IPV6
        ip.e6[0] = 0x0ffff;
      }
    else if ( ((struct sockaddr_in6*)a)->sin6_family == AF_INET6 )
      {
        memcpy(&ip,&((struct sockaddr_in6*)a)->sin6_addr,sizeof(ip));
  #endif  
      }
    return ip; 
  }
#endif
  ;
  
typedef struct _YO_TCPSOK
  {
    ipaddr_t  ip;
    int       skt;
    int       port;
  } YO_TCPSOK;

enum  
  {
    TCP_AIO_COMPLETE    = 0,
    TCP_AIO_FAIL        = 0x80000000,
    TCP_PERMANENT_ERROR = 0x40000000,
    TCP_IS_CLOSED       = 0x20000000,
  };

#ifdef __windoze

#define Tcp_Errno() WSAGetLastError()

void _WSA_Term(void)
#ifdef _YO_TCPIP_BUILTIN
  {
    WSACleanup();
  }
#endif
  ;
  
void _WSA_Init()
#ifdef _YO_TCPIP_BUILTIN
  {
    static int wsa_status = -1;
    static WSADATA wsa_data = {0};
    if ( wsa_status != 0 )
      {
        if ( 0 != WSAStartup(MAKEWORD(2, 2), &wsa_data) )
          { 
            __Raise(YO_ERROR_SUBSYSTEM_INIT,"failed to initialize WSA subsystem");
          }
        else
          {
            wsa_status = 0;
            atexit(_WSA_Term);
          }
      }
  }
#endif
  ;

#else
#define Tcp_Errno() errno
#define _WSA_Init() 
#endif

#define Tcp_Format_Error() Tcp_Format_Error_Code(Tcp_Errno())

char *Tcp_Format_Error_Code(int err)
#ifdef _YO_TCPIP_BUILTIN
  {
  #ifdef __windoze
    char *msg = __Malloc(1024);
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
                  FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                  (LPSTR)msg, 1024,0);
    return msg;  
  #else
    return strerror(errno);
  #endif
  }
#endif
  ;

#define Ip_Format(Ip) Ipv4_Format(Ip)
#define Ip_Format_Npl(Ip) Ipv4_Format_Npl(Ip)
#define Ipv4_Format(Ip) __Pool(Ipv4_Format_Npl(Ip))
char *Ipv4_Format_Npl(ipaddr_t ip)
#ifdef _YO_TCPIP_BUILTIN
  {
    return __Format_Npl("%d.%d.%d.%d"
              ,( ip.v4     &0x0ff)
              ,((ip.v4>>8) &0x0ff)
              ,((ip.v4>>16)&0x0ff)
              ,((ip.v4>>24)&0x0ff));
  }
#endif
  ;
  
int Dns_IPv4_Resolve(char *host, ipaddr_t *ip)
#ifdef _YO_TCPIP_BUILTIN
  {
    struct hostent *hstn = 0;
   
    memset(ip,0,sizeof(*ip));
  
  #ifdef _IPV6
    ip->e6[0] = 0x0ffff;
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
      }
    return 0;
  }        
#endif
  ;

ipaddr_t Dns_Resolve(char *host)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    ipaddr_t ip;

    _WSA_Init();

    switch ( Dns_IPv4_Resolve(host,&ip) )
      {
        case 0:
          break;
        case NO_RECOVERY:
          __Raise(YOYO_ERROR_DNS,"unrecoverable DNS error");
        default: 
          __Raise_Format(YOYO_ERROR_DNS,("DNS couldn't resolve ip for name %s",host));
      }
    return ip;
  }        
#endif
  ;
  
void Tcp_Close(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( sok->skt != INVALID_SOCKET ) 
      {
#ifdef __windoze
        closesocket(sok->skt);
#else      
        close(sok->skt);
#endif
        sok->skt = -1;
      }
  }
#endif
  ;
  
void Tcp_Graceful_Close(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( sok->skt != INVALID_SOCKET ) 
      {
        shutdown(sok->skt,SD_SEND);
        Tcp_Close(sok);
      }
  }
#endif
  ;

void YOYO_TCPSOK_Destruct(YOYO_TCPSOK *sok)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    Tcp_Graceful_Close(sok);
    __Destruct(sok);
  }
#endif
  ;
  
int Tcp_Read(YOYO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YOYO_TCPIP_BUILTIN  
  {
    byte_t *b = out;
    int cc = count;
    while ( cc )
      {
        int q = recv(sok->skt,b,cc,0);
        if ( q < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YOYO_ERROR_IO,(__yoTa("tcp recv failed with error %s",0),
                                          Tcp_Format_Error_Code(err)));
          }
        STRICT_REQUIRE( q <= cc );
        cc -= q;
        b += q;
        if ( count-cc >= mincount )
          break;
      }
    return count-cc;
  }
#endif
  ;

int Tcp_Write(YOYO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    byte_t *b = out;
    int cc = count;
    while ( cc )
      {
        int q = send(sok->skt,b,cc,0);
        if ( q < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YOYO_ERROR_IO,(__yoTa("tcp send failed with error %s",0),
                                          Tcp_Format_Error_Code(err)));
          }
        STRICT_REQUIRE( q <= cc );
        cc -= q;
        b += q;
        if ( q == 0 && count-cc >= mincount )
          break;
      }
    return count-cc;
  }
#endif
  ;
 
typedef void (*tcp_resolve_callback_t)(void *obj, int status, ipaddr_t ip);
typedef void (*tcp_recv_callback_t)(void *obj, int status, int count);
typedef void (*tcp_send_callback_t)(void *obj, int status);
typedef void (*tcp_accept_callback_t)(void *obj, int status, YOYO_TCPSOK *sok);
typedef void (*tcp_any_callback_t)(void *obj, int status, ...);
typedef void (*tcp_connect_callback_t)(void *obj,int status);

typedef struct _YOYO_TCP_IOT
  {
    socket_t skt;
    union 
      {
        uquad_t accum;
        ipaddr_t ip; 
        IPV4V6_ADDR_MIX addr;
      };
    union
      {
        int mincount;
        int port;
      };
    int err, count;
    void *obj, *dta;
    char *host;
    tcp_any_callback_t cbk;
    struct _YOYO_TCP_IOT *next;
  } YOYO_TCP_IOT;
 
#ifdef _YOYO_TCPIP_BUILTIN
static YOYO_TCP_IOT *Tcp_Iot_Pool = 0;
#endif

void YOYO_TCP_IOT_Destruct(YOYO_TCP_IOT *iot)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    free(iot->host);
    __Unrefe(iot->obj);
    iot->next = Tcp_Iot_Pool;
    Tcp_Iot_Pool = iot;
    __Destruct(iot);
  }
#endif
  ;

YOYO_TCP_IOT *Tcp_Alloc_Iot()
#ifdef _YOYO_TCPIP_BUILTIN
  {
    return __Object_Dtor(sizeof(YOYO_TCP_IOT),YOYO_TCP_IOT_Destruct);
  }
#endif
  ;
  
void Wrk_Tcp_Send(YOYO_TCP_IOT *iot)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    byte_t *b = iot->dta;
    int count = iot->count;
    int cc = count;
    while ( cc )
      {
        int q = send(iot->skt,b,cc,0);







|










|

|






|
|














|
|










|
|







|
|









|













|
|









|
















|



|

















|
|

|
|


|
|










|
|

|




|
|







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
      }
    return 0;
  }        
#endif
  ;

ipaddr_t Dns_Resolve(char *host)
#ifdef _YO_TCPIP_BUILTIN
  {
    ipaddr_t ip;

    _WSA_Init();

    switch ( Dns_IPv4_Resolve(host,&ip) )
      {
        case 0:
          break;
        case NO_RECOVERY:
          __Raise(YO_ERROR_DNS,"unrecoverable DNS error");
        default: 
          __Raise_Format(YO_ERROR_DNS,("DNS couldn't resolve ip for name %s",host));
      }
    return ip;
  }        
#endif
  ;
  
void Tcp_Close(YO_TCPSOK *sok)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( sok->skt != INVALID_SOCKET ) 
      {
#ifdef __windoze
        closesocket(sok->skt);
#else      
        close(sok->skt);
#endif
        sok->skt = -1;
      }
  }
#endif
  ;
  
void Tcp_Graceful_Close(YO_TCPSOK *sok)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( sok->skt != INVALID_SOCKET ) 
      {
        shutdown(sok->skt,SD_SEND);
        Tcp_Close(sok);
      }
  }
#endif
  ;

void YO_TCPSOK_Destruct(YO_TCPSOK *sok)
#ifdef _YO_TCPIP_BUILTIN
  {
    Tcp_Graceful_Close(sok);
    __Destruct(sok);
  }
#endif
  ;
  
int Tcp_Read(YO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YO_TCPIP_BUILTIN  
  {
    byte_t *b = out;
    int cc = count;
    while ( cc )
      {
        int q = recv(sok->skt,b,cc,0);
        if ( q < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YO_ERROR_IO,(__yoTa("tcp recv failed with error %s",0),
                                          Tcp_Format_Error_Code(err)));
          }
        STRICT_REQUIRE( q <= cc );
        cc -= q;
        b += q;
        if ( count-cc >= mincount )
          break;
      }
    return count-cc;
  }
#endif
  ;

int Tcp_Write(YO_TCPSOK *sok, void *out, int count, int mincount)
#ifdef _YO_TCPIP_BUILTIN
  {
    byte_t *b = out;
    int cc = count;
    while ( cc )
      {
        int q = send(sok->skt,b,cc,0);
        if ( q < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YO_ERROR_IO,(__yoTa("tcp send failed with error %s",0),
                                          Tcp_Format_Error_Code(err)));
          }
        STRICT_REQUIRE( q <= cc );
        cc -= q;
        b += q;
        if ( q == 0 && count-cc >= mincount )
          break;
      }
    return count-cc;
  }
#endif
  ;
 
typedef void (*tcp_resolve_callback_t)(void *obj, int status, ipaddr_t ip);
typedef void (*tcp_recv_callback_t)(void *obj, int status, int count);
typedef void (*tcp_send_callback_t)(void *obj, int status);
typedef void (*tcp_accept_callback_t)(void *obj, int status, YO_TCPSOK *sok);
typedef void (*tcp_any_callback_t)(void *obj, int status, ...);
typedef void (*tcp_connect_callback_t)(void *obj,int status);

typedef struct _YO_TCP_IOT
  {
    socket_t skt;
    union 
      {
        uquad_t accum;
        ipaddr_t ip; 
        IPV4V6_ADDR_MIX addr;
      };
    union
      {
        int mincount;
        int port;
      };
    int err, count;
    void *obj, *dta;
    char *host;
    tcp_any_callback_t cbk;
    struct _YO_TCP_IOT *next;
  } YO_TCP_IOT;
 
#ifdef _YO_TCPIP_BUILTIN
static YO_TCP_IOT *Tcp_Iot_Pool = 0;
#endif

void YO_TCP_IOT_Destruct(YO_TCP_IOT *iot)
#ifdef _YO_TCPIP_BUILTIN
  {
    free(iot->host);
    __Unrefe(iot->obj);
    iot->next = Tcp_Iot_Pool;
    Tcp_Iot_Pool = iot;
    __Destruct(iot);
  }
#endif
  ;

YO_TCP_IOT *Tcp_Alloc_Iot()
#ifdef _YO_TCPIP_BUILTIN
  {
    return __Object_Dtor(sizeof(YO_TCP_IOT),YO_TCP_IOT_Destruct);
  }
#endif
  ;
  
void Wrk_Tcp_Send(YO_TCP_IOT *iot)
#ifdef _YO_TCPIP_BUILTIN
  {
    byte_t *b = iot->dta;
    int count = iot->count;
    int cc = count;
    while ( cc )
      {
        int q = send(iot->skt,b,cc,0);
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
      }
    iot->count = count-cc;
    iot->err = 0;
  }
#endif
  ;
  
void Cbk_Tcp_Send(YOYO_TCPSOK *sok, YOYO_TCP_IOT *iot, int status)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( iot->err && sok->skt == INVALID_SOCKET )
      iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED);
    else if ( status || iot->err )
      iot->cbk(iot->obj,TCP_AIO_FAIL);
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE);
  }
#endif
  ;
    
void Tcp_Aio_Send(YOYO_TCPSOK *sok, void *out, int count, tcp_send_callback_t callback, void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    __Auto_Release 
      {
        YOYO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = (tcp_any_callback_t)callback;
        iot->mincount = iot->count = count;
        iot->dta = out;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Send,iot,Cbk_Tcp_Send,sok);
      }
  }
#endif
  ;

void Wrk_Tcp_Recv(YOYO_TCP_IOT *iot)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    byte_t *b = iot->dta;
    int count = iot->count;
    int cc = count;
    while ( cc )
      {
        int q = recv(iot->skt,b,cc,0);







|
|











|
|



|











|
|







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
      }
    iot->count = count-cc;
    iot->err = 0;
  }
#endif
  ;
  
void Cbk_Tcp_Send(YO_TCPSOK *sok, YO_TCP_IOT *iot, int status)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( iot->err && sok->skt == INVALID_SOCKET )
      iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED);
    else if ( status || iot->err )
      iot->cbk(iot->obj,TCP_AIO_FAIL);
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE);
  }
#endif
  ;
    
void Tcp_Aio_Send(YO_TCPSOK *sok, void *out, int count, tcp_send_callback_t callback, void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    __Auto_Release 
      {
        YO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = (tcp_any_callback_t)callback;
        iot->mincount = iot->count = count;
        iot->dta = out;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Send,iot,Cbk_Tcp_Send,sok);
      }
  }
#endif
  ;

void Wrk_Tcp_Recv(YO_TCP_IOT *iot)
#ifdef _YO_TCPIP_BUILTIN
  {
    byte_t *b = iot->dta;
    int count = iot->count;
    int cc = count;
    while ( cc )
      {
        int q = recv(iot->skt,b,cc,0);
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
      }
    iot->count = count-cc;
    iot->err = 0;
  }
#endif
  ;
  
void Cbk_Tcp_Recv(YOYO_TCPSOK *sok, YOYO_TCP_IOT *iot, int status)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( iot->err && sok->skt == INVALID_SOCKET )
      iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED,0);
    else if ( status || iot->err )
      iot->cbk(iot->obj,TCP_AIO_FAIL,0);
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE,iot->count);
  }
#endif
  ;
    
void Tcp_Aio_Recv(YOYO_TCPSOK *sok, void *out, int count, int mincount, tcp_recv_callback_t callback, void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    __Auto_Release 
      {
        YOYO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = (tcp_any_callback_t)callback;
        iot->count = count;
        iot->mincount = mincount?mincount:count;
        iot->dta = out;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Recv,iot,Cbk_Tcp_Recv,sok);
      }
  }
#endif
  ;
  
YOYO_TCPSOK *Tcp_Socket()
#ifdef _YOYO_TCPIP_BUILTIN  
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YOYO_TCPSOK_Destruct},
        {Oj_Close_OjMID,       Tcp_Close},
        {Oj_Read_OjMID,        Tcp_Read},
        {Oj_Write_OjMID,       Tcp_Write},
        //{Oj_Available_OjMID,   Tcp_Available},
        //{Oj_Eof_OjMID,         Tcp_Eof},
        {0}
      };

    YOYO_TCPSOK *sok = __Object(sizeof(YOYO_TCPSOK),funcs);
    sok->skt = INVALID_SOCKET;
    return sok;
  }
#endif
  ;

void Wrk_Tcp_Connect(YOYO_TCP_IOT *iot)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( iot->skt != INVALID_SOCKET )
      { 
        if ( 0 > connect(iot->skt,(struct sockaddr *)&iot->addr,iot->count) )
          iot->err = Tcp_Errno();
      }
  }
#endif
  ;
  
void Cbk_Tcp_Connect(YOYO_TCPSOK *sok, YOYO_TCP_IOT *iot, int status)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( iot->err || status )
      {
        Tcp_Close(sok);
        iot->cbk(iot->obj,TCP_AIO_FAIL);
      }
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE);
  }
#endif
  ;
        
#define Tcp_Ip_Connect(Sok,Ip,Port) Tcp_Ip_Connect_(0,Sok,Ip,Port,0,0)
#define Tcp_Aio_Ip_Connect(Sok,Ip,Port,callback,obj) Tcp_Ip_Connect_(1,Sok,Ip,Port,callback,obj)

int Tcp_Ip_Connect_(int use_aio, YOYO_TCPSOK *sok, ipaddr_t ip, int port, tcp_connect_callback_t callback, void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    socket_t skt;
    int conerr;
    int addr_len = 0;
    IPV4V6_ADDR_MIX addr;
    
    _WSA_Init();

    Tcp_Expand_Ip_Addr(&ip,port,&addr,&addr_len);
    sok->port = port;
    sok->ip   = ip;
    
    skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
    sok->skt = skt;

    if ( use_aio )
      {
        __Auto_Release
          {
            YOYO_TCP_IOT *iot = Tcp_Alloc_Iot();
            memcpy(&iot->addr,&addr,sizeof(addr));
            iot->count = addr_len;
            iot->skt = sok->skt;
            iot->cbk = callback;
            iot->obj = __Refe(obj);
            Tasque_Queue(Wrk_Tcp_Connect,iot,Cbk_Tcp_Connect,sok);
          }
        return 0;
      }
    else
      {
        conerr = (skt != INVALID_SOCKET ) ? connect(skt,(struct sockaddr*)&addr,addr_len) : -1;
        
        if ( conerr < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YOYO_ERROR_IO,
                            (__yoTa("tcp connection failed: sok %d, point %s:%d, error %s",0)
                            ,skt
                            ,Ip_Format(ip)
                            ,port
                            ,Tcp_Format_Error_Code(err)));
          }
          
        return 0;
      }
  }
#endif
  ;

  
void Wrk_Tcp_Resolve(YOYO_TCP_IOT *iot)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    iot->err = Dns_IPv4_Resolve(iot->host,&iot->ip);
  }
#endif
  ;
  
void Cbk_Tcp_Resolve(void *_, YOYO_TCP_IOT *iot, int status)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( iot->cbk ) 
      {
        if ( status )
          {
            iot->cbk(iot->obj,TCP_AIO_FAIL,0);
          }







|
|











|
|



|












|
|

|

|








|






|
|










|
|















|
|



















|
















|














|
|






|
|







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
      }
    iot->count = count-cc;
    iot->err = 0;
  }
#endif
  ;
  
void Cbk_Tcp_Recv(YO_TCPSOK *sok, YO_TCP_IOT *iot, int status)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( iot->err && sok->skt == INVALID_SOCKET )
      iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED,0);
    else if ( status || iot->err )
      iot->cbk(iot->obj,TCP_AIO_FAIL,0);
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE,iot->count);
  }
#endif
  ;
    
void Tcp_Aio_Recv(YO_TCPSOK *sok, void *out, int count, int mincount, tcp_recv_callback_t callback, void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    __Auto_Release 
      {
        YO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = (tcp_any_callback_t)callback;
        iot->count = count;
        iot->mincount = mincount?mincount:count;
        iot->dta = out;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Recv,iot,Cbk_Tcp_Recv,sok);
      }
  }
#endif
  ;
  
YO_TCPSOK *Tcp_Socket()
#ifdef _YO_TCPIP_BUILTIN  
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,    YO_TCPSOK_Destruct},
        {Oj_Close_OjMID,       Tcp_Close},
        {Oj_Read_OjMID,        Tcp_Read},
        {Oj_Write_OjMID,       Tcp_Write},
        //{Oj_Available_OjMID,   Tcp_Available},
        //{Oj_Eof_OjMID,         Tcp_Eof},
        {0}
      };

    YO_TCPSOK *sok = __Object(sizeof(YO_TCPSOK),funcs);
    sok->skt = INVALID_SOCKET;
    return sok;
  }
#endif
  ;

void Wrk_Tcp_Connect(YO_TCP_IOT *iot)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( iot->skt != INVALID_SOCKET )
      { 
        if ( 0 > connect(iot->skt,(struct sockaddr *)&iot->addr,iot->count) )
          iot->err = Tcp_Errno();
      }
  }
#endif
  ;
  
void Cbk_Tcp_Connect(YO_TCPSOK *sok, YO_TCP_IOT *iot, int status)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( iot->err || status )
      {
        Tcp_Close(sok);
        iot->cbk(iot->obj,TCP_AIO_FAIL);
      }
    else
      iot->cbk(iot->obj,TCP_AIO_COMPLETE);
  }
#endif
  ;
        
#define Tcp_Ip_Connect(Sok,Ip,Port) Tcp_Ip_Connect_(0,Sok,Ip,Port,0,0)
#define Tcp_Aio_Ip_Connect(Sok,Ip,Port,callback,obj) Tcp_Ip_Connect_(1,Sok,Ip,Port,callback,obj)

int Tcp_Ip_Connect_(int use_aio, YO_TCPSOK *sok, ipaddr_t ip, int port, tcp_connect_callback_t callback, void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    socket_t skt;
    int conerr;
    int addr_len = 0;
    IPV4V6_ADDR_MIX addr;
    
    _WSA_Init();

    Tcp_Expand_Ip_Addr(&ip,port,&addr,&addr_len);
    sok->port = port;
    sok->ip   = ip;
    
    skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
    sok->skt = skt;

    if ( use_aio )
      {
        __Auto_Release
          {
            YO_TCP_IOT *iot = Tcp_Alloc_Iot();
            memcpy(&iot->addr,&addr,sizeof(addr));
            iot->count = addr_len;
            iot->skt = sok->skt;
            iot->cbk = callback;
            iot->obj = __Refe(obj);
            Tasque_Queue(Wrk_Tcp_Connect,iot,Cbk_Tcp_Connect,sok);
          }
        return 0;
      }
    else
      {
        conerr = (skt != INVALID_SOCKET ) ? connect(skt,(struct sockaddr*)&addr,addr_len) : -1;
        
        if ( conerr < 0 )
          {
            int err = Tcp_Errno();
            __Raise_Format(YO_ERROR_IO,
                            (__yoTa("tcp connection failed: sok %d, point %s:%d, error %s",0)
                            ,skt
                            ,Ip_Format(ip)
                            ,port
                            ,Tcp_Format_Error_Code(err)));
          }
          
        return 0;
      }
  }
#endif
  ;

  
void Wrk_Tcp_Resolve(YO_TCP_IOT *iot)
#ifdef _YO_TCPIP_BUILTIN
  {
    iot->err = Dns_IPv4_Resolve(iot->host,&iot->ip);
  }
#endif
  ;
  
void Cbk_Tcp_Resolve(void *_, YO_TCP_IOT *iot, int status)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( iot->cbk ) 
      {
        if ( status )
          {
            iot->cbk(iot->obj,TCP_AIO_FAIL,0);
          }
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
          iot->cbk(iot->obj,0,iot->ip);
      }
  }
#endif
  ;
   
void Tcp_Aio_Resolve(char *host, tcp_resolve_callback_t callback, void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    _WSA_Init();

    __Auto_Release
      { 
        YOYO_TCP_IOT *o = Tcp_Alloc_Iot();
        o->host = Str_Copy_Npl(host,-1);
        o->cbk = callback;
        o->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Resolve,o,Cbk_Tcp_Resolve,0);
      }
  }
#endif
  ;

typedef struct _YOYO_HOST_CONNECT
  {
    YOYO_TCPSOK *sok;
    int port;
    void *cbkobj;
    tcp_connect_callback_t callback;
  } YOYO_HOST_CONNECT;
  
void YOYO_HOST_CONNECT_Destruct(YOYO_HOST_CONNECT *o)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    __Unrefe(o->sok);
    __Unrefe(o->cbkobj);
    __Destruct(o);
  }
#endif
  ;
    
void Cbk_Tcp_Host_Connect(YOYO_HOST_CONNECT *o, int status, ipaddr_t ip)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    if ( status )
      ( o->callback ) ? o->callback( o->cbkobj, status ) : 0;
    else
      Tcp_Aio_Ip_Connect(o->sok,ip,o->port,o->callback,o->cbkobj);
  }
#endif
  ;
      
void Tcp_Connect(YOYO_TCPSOK *sok,char *host,int port)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    ipaddr_t ip = Dns_Resolve(host);
    Tcp_Ip_Connect(sok,ip,port);    
  }
#endif
  ;

void Tcp_Aio_Connect(YOYO_TCPSOK *sok,char *host,int port,tcp_connect_callback_t callback,void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    YOYO_HOST_CONNECT *o = __Object_Dtor(sizeof(YOYO_HOST_CONNECT),YOYO_HOST_CONNECT_Destruct);
    o->sok = __Refe(sok);
    o->port = port;
    o->cbkobj = __Refe(obj);
    o->callback = callback;
    Tcp_Aio_Resolve(host,Cbk_Tcp_Host_Connect,o);
  }
#endif
  ;

YOYO_TCPSOK *Tcp_Open(char *host, int port)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    YOYO_TCPSOK *sok = Tcp_Socket(0);
    Tcp_Connect(sok,host,port);
    return sok;
  }
#endif
  ;

YOYO_TCPSOK *Tcp_Listen(char *host, int port, int listlen)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    YOYO_TCPSOK *sok;
    ipaddr_t ip;
    int addr_len = 0;
    IPV4V6_ADDR_MIX addr;
    
    ip = Dns_Resolve(host);
    Tcp_Expand_Ip_Addr(&ip,port,&addr,&addr_len);
    
    sok = __Refe(Tcp_Socket(0));
    sok->port = port;
    sok->ip = ip;
    
    if ( INVALID_SOCKET == (sok->skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) )  goto sok_error;
    if ( -1 == bind(sok->skt,(struct sockaddr*)&addr,addr_len) ) goto sok_error;
    if ( -1 == listen(sok->skt,(listlen?listlen:SOMAXCONN)) ) goto sok_error;

    if ( sok->skt == INVALID_SOCKET )
      {       
    sok_error: 
        __Raise_Format(YOYO_ERROR_IO,
                        (__yoTa("tcp bind/listen failed: sok %d, point %s:%d, error %s",0)
                        ,sok->skt
                        ,Ip_Format(ip)
                        ,port
                        ,Tcp_Format_Error()));
      }
      
    return sok;
  }
#endif
  ;

#ifdef _YOYO_TCPIP_BUILTIN

void Cbk_Tcp_Accept(YOYO_TCPSOK *sok, YOYO_TCP_IOT *iot, int status)
  {
    if ( !status && !iot->err )
      {
        YOYO_TCPSOK *sok2 = Tcp_Socket();
        sok2->ip   = iot->ip;
        sok2->port = iot->port;
        sok2->skt  = iot->skt;
        iot->cbk(iot->obj,TCP_AIO_COMPLETE,sok2);
      }
    else
      {
        if ( sok->skt == INVALID_SOCKET )
          iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED);
        else
          iot->cbk(iot->obj,TCP_AIO_FAIL);
      }
  }

void Wrk_Tcp_Accept(YOYO_TCP_IOT *iot)
  {
    int skt,addr_len = sizeof(iot->addr);
    
    skt = accept(iot->skt,(struct sockaddr*)&iot->addr,&addr_len);
    
    if ( skt != INVALID_SOCKET )
      {







|





|









|

|



|

|
|








|
|









|
|







|
|

|









|
|

|






|
|

|


















|












|

|



|














|







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
          iot->cbk(iot->obj,0,iot->ip);
      }
  }
#endif
  ;
   
void Tcp_Aio_Resolve(char *host, tcp_resolve_callback_t callback, void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    _WSA_Init();

    __Auto_Release
      { 
        YO_TCP_IOT *o = Tcp_Alloc_Iot();
        o->host = Str_Copy_Npl(host,-1);
        o->cbk = callback;
        o->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Resolve,o,Cbk_Tcp_Resolve,0);
      }
  }
#endif
  ;

typedef struct _YO_HOST_CONNECT
  {
    YO_TCPSOK *sok;
    int port;
    void *cbkobj;
    tcp_connect_callback_t callback;
  } YO_HOST_CONNECT;
  
void YO_HOST_CONNECT_Destruct(YO_HOST_CONNECT *o)
#ifdef _YO_TCPIP_BUILTIN
  {
    __Unrefe(o->sok);
    __Unrefe(o->cbkobj);
    __Destruct(o);
  }
#endif
  ;
    
void Cbk_Tcp_Host_Connect(YO_HOST_CONNECT *o, int status, ipaddr_t ip)
#ifdef _YO_TCPIP_BUILTIN
  {
    if ( status )
      ( o->callback ) ? o->callback( o->cbkobj, status ) : 0;
    else
      Tcp_Aio_Ip_Connect(o->sok,ip,o->port,o->callback,o->cbkobj);
  }
#endif
  ;
      
void Tcp_Connect(YO_TCPSOK *sok,char *host,int port)
#ifdef _YO_TCPIP_BUILTIN
  {
    ipaddr_t ip = Dns_Resolve(host);
    Tcp_Ip_Connect(sok,ip,port);    
  }
#endif
  ;

void Tcp_Aio_Connect(YO_TCPSOK *sok,char *host,int port,tcp_connect_callback_t callback,void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    YO_HOST_CONNECT *o = __Object_Dtor(sizeof(YO_HOST_CONNECT),YO_HOST_CONNECT_Destruct);
    o->sok = __Refe(sok);
    o->port = port;
    o->cbkobj = __Refe(obj);
    o->callback = callback;
    Tcp_Aio_Resolve(host,Cbk_Tcp_Host_Connect,o);
  }
#endif
  ;

YO_TCPSOK *Tcp_Open(char *host, int port)
#ifdef _YO_TCPIP_BUILTIN
  {
    YO_TCPSOK *sok = Tcp_Socket(0);
    Tcp_Connect(sok,host,port);
    return sok;
  }
#endif
  ;

YO_TCPSOK *Tcp_Listen(char *host, int port, int listlen)
#ifdef _YO_TCPIP_BUILTIN
  {
    YO_TCPSOK *sok;
    ipaddr_t ip;
    int addr_len = 0;
    IPV4V6_ADDR_MIX addr;
    
    ip = Dns_Resolve(host);
    Tcp_Expand_Ip_Addr(&ip,port,&addr,&addr_len);
    
    sok = __Refe(Tcp_Socket(0));
    sok->port = port;
    sok->ip = ip;
    
    if ( INVALID_SOCKET == (sok->skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP)) )  goto sok_error;
    if ( -1 == bind(sok->skt,(struct sockaddr*)&addr,addr_len) ) goto sok_error;
    if ( -1 == listen(sok->skt,(listlen?listlen:SOMAXCONN)) ) goto sok_error;

    if ( sok->skt == INVALID_SOCKET )
      {       
    sok_error: 
        __Raise_Format(YO_ERROR_IO,
                        (__yoTa("tcp bind/listen failed: sok %d, point %s:%d, error %s",0)
                        ,sok->skt
                        ,Ip_Format(ip)
                        ,port
                        ,Tcp_Format_Error()));
      }
      
    return sok;
  }
#endif
  ;

#ifdef _YO_TCPIP_BUILTIN

void Cbk_Tcp_Accept(YO_TCPSOK *sok, YO_TCP_IOT *iot, int status)
  {
    if ( !status && !iot->err )
      {
        YO_TCPSOK *sok2 = Tcp_Socket();
        sok2->ip   = iot->ip;
        sok2->port = iot->port;
        sok2->skt  = iot->skt;
        iot->cbk(iot->obj,TCP_AIO_COMPLETE,sok2);
      }
    else
      {
        if ( sok->skt == INVALID_SOCKET )
          iot->cbk(iot->obj,TCP_AIO_FAIL|TCP_PERMANENT_ERROR|TCP_IS_CLOSED);
        else
          iot->cbk(iot->obj,TCP_AIO_FAIL);
      }
  }

void Wrk_Tcp_Accept(YO_TCP_IOT *iot)
  {
    int skt,addr_len = sizeof(iot->addr);
    
    skt = accept(iot->skt,(struct sockaddr*)&iot->addr,&addr_len);
    
    if ( skt != INVALID_SOCKET )
      {
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
      {
        iot->skt = INVALID_SOCKET;
        iot->err = Tcp_Errno();
      }
  }
#endif

void Tcp_Aio_Accept(YOYO_TCPSOK *sok, tcp_accept_callback_t callback, void *obj)
#ifdef _YOYO_TCPIP_BUILTIN
  {
    __Auto_Release
      {
        YOYO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = callback;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Accept,iot,Cbk_Tcp_Accept,sok);
      }
  }
#endif
  ;

#define Tcp_Shutdown(Sok) Tcp_Graceful_Close(Sok)

#endif /* C_once_F8F16072_F92E_49E7_A983_54F60965F4C9 */








|
|



|













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
      {
        iot->skt = INVALID_SOCKET;
        iot->err = Tcp_Errno();
      }
  }
#endif

void Tcp_Aio_Accept(YO_TCPSOK *sok, tcp_accept_callback_t callback, void *obj)
#ifdef _YO_TCPIP_BUILTIN
  {
    __Auto_Release
      {
        YO_TCP_IOT *iot = Tcp_Alloc_Iot();
        iot->skt = sok->skt;
        iot->cbk = callback;
        iot->obj = __Refe(obj);
        Tasque_Queue(Wrk_Tcp_Accept,iot,Cbk_Tcp_Accept,sok);
      }
  }
#endif
  ;

#define Tcp_Shutdown(Sok) Tcp_Graceful_Close(Sok)

#endif /* C_once_F8F16072_F92E_49E7_A983_54F60965F4C9 */

Changes to tests/httpd.c.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
      "r:|doc_root:,"
      "c:|cfg:|config:,"
      "e:|exec_root:,"
      ,PROG_EXIT_ON_ERROR);

    //__Try_Exit(0)
      {
        YOYO_WEBHOST *webhost = Webhost_Init();
        quad_t q = Get_System_Millis();
        __Auto_Release
          {
            int   port = 80;
            char *foo;
            char *host = "127.0.0.1";
            YOYO_XDATA *cfg;
    
            if ( Prog_Has_Opt("debug") ) Set_Logout_Opt(YOYO_LOG_DEBUG);
    
            Webhost_Add_Index(webhost,"index.html");
        
            if ( !!(foo = Prog_First_Opt("cfg",0)) )
              {
                cfg = Def_Parse_File(foo);
                Webhost_Config(webhost,cfg);







|






|

|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
      "r:|doc_root:,"
      "c:|cfg:|config:,"
      "e:|exec_root:,"
      ,PROG_EXIT_ON_ERROR);

    //__Try_Exit(0)
      {
        YO_WEBHOST *webhost = Webhost_Init();
        quad_t q = Get_System_Millis();
        __Auto_Release
          {
            int   port = 80;
            char *foo;
            char *host = "127.0.0.1";
            YO_XDATA *cfg;
    
            if ( Prog_Has_Opt("debug") ) Set_Logout_Opt(YO_LOG_DEBUG);
    
            Webhost_Add_Index(webhost,"index.html");
        
            if ( !!(foo = Prog_First_Opt("cfg",0)) )
              {
                cfg = Def_Parse_File(foo);
                Webhost_Config(webhost,cfg);
Changes to threads.hc.
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
typedef HANDLE thread_t;
#define INVALID_THREAD_VALIUE ((HANDLE)0)
#else
typedef pthread_t thread_t;
#endif

#ifdef _LIBYOYO
#define _YOYO_THREADS_BUILTIN
#endif

enum 
  {
    THREAD_STILL_ACTIVE = -1,
  };

typedef void (*thread_func_t)(void*);

#ifdef _YOYO_THREADS_BUILTIN
typedef struct _YOYO_THREAD_COOKIE
  {
    thread_func_t func;
    void *o;    
  } YOYO_THREAD_COOKIE;
static _Thread_Release_Cookie(YOYO_THREAD_COOKIE *cookie) 
  {
    free(cookie);
  }
static YOYO_THREAD_COOKIE *_Thread_Allocate_Cookie(thread_func_t func, void *o) 
  {
    YOYO_THREAD_COOKIE *cookie = malloc(sizeof(YOYO_THREAD_COOKIE));
    cookie->func = func;
    cookie->o = o;
    return cookie;
  }
static DWORD __stdcall _Thread_Proc(YOYO_THREAD_COOKIE *cookie)
  {
    thread_func_t func = cookie->func;
    void *o = cookie->o;    
    free(cookie);
    func(o);
    return 0;
  }
#endif

thread_t Thread_Get_Current()
#ifdef _YOYO_THREADS_BUILTIN
  {
  #ifdef __windoze
    return GetCurrentThread();
  #else
  #endif
  }
#endif;

thread_t Thread_Run(thread_func_t func, void *o, int stacksize)
#ifdef _YOYO_THREADS_BUILTIN
  {
    YOYO_THREAD_COOKIE *cookie = _Thread_Allocate_Cookie(func,o);
  #ifdef __windoze
    thread_t thr = CreateThread(0,stacksize,_Thread_Proc,cookie,0,0);
    if ( thr == INVALID_THREAD_VALIUE )
      _Thread_Release_Cookie(cookie);
    return thr;
  #else
  #endif
  }
#endif
  ;
 
#ifdef _YOYO_THREADS_BUILTIN
static void __No_Return _Thread_Raise_Error()
  {
    __Raise_System_Error();
  }
#endif
    
/* be sure thread is running */
thread_t Thread_Run_Sure(thread_func_t func, void *o, int stacksize)
#ifdef _YOYO_THREADS_BUILTIN
  {
    thread_t thr = Thread_Run(func,o,stacksize);
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        //WaitForSingleObject(thr,INFINITE);
    #else
    #endif  
      }
    else
      _Thread_Raise_Error();
    return thr;
  }
#endif
  ;
  
void Thread_Run_Close(thread_func_t func, void *o, int stacksize)
#ifdef _YOYO_THREADS_BUILTIN
  {
    thread_t thr = Thread_Run(func,o,stacksize);
    if ( thr != INVALID_THREAD_VALIUE )
      Thread_Close(thr);
    else
      _Thread_Raise_Error();
  }
#endif
  ;
  
int Thread_Close(thread_t thr)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
      #ifdef __windoze
        DWORD ecode;
        GetExitCodeThread(thr,&ecode);
        CloseHandle(thr);
        if ( ecode == STILL_ACTIVE ) ecode = THREAD_STILL_ACTIVE;
        return ecode;
      #else
      #endif
      }

    return 0;    
  }
#endif
  ;
    
int Thread_Join(thread_t thr)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        for(;;)
          {
            DWORD ecode;







|









|
|



|
|



|

|




|










|









|

|











|








|

















|











|



















|







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
typedef HANDLE thread_t;
#define INVALID_THREAD_VALIUE ((HANDLE)0)
#else
typedef pthread_t thread_t;
#endif

#ifdef _LIBYOYO
#define _YO_THREADS_BUILTIN
#endif

enum 
  {
    THREAD_STILL_ACTIVE = -1,
  };

typedef void (*thread_func_t)(void*);

#ifdef _YO_THREADS_BUILTIN
typedef struct _YO_THREAD_COOKIE
  {
    thread_func_t func;
    void *o;    
  } YO_THREAD_COOKIE;
static _Thread_Release_Cookie(YO_THREAD_COOKIE *cookie) 
  {
    free(cookie);
  }
static YO_THREAD_COOKIE *_Thread_Allocate_Cookie(thread_func_t func, void *o) 
  {
    YO_THREAD_COOKIE *cookie = malloc(sizeof(YO_THREAD_COOKIE));
    cookie->func = func;
    cookie->o = o;
    return cookie;
  }
static DWORD __stdcall _Thread_Proc(YO_THREAD_COOKIE *cookie)
  {
    thread_func_t func = cookie->func;
    void *o = cookie->o;    
    free(cookie);
    func(o);
    return 0;
  }
#endif

thread_t Thread_Get_Current()
#ifdef _YO_THREADS_BUILTIN
  {
  #ifdef __windoze
    return GetCurrentThread();
  #else
  #endif
  }
#endif;

thread_t Thread_Run(thread_func_t func, void *o, int stacksize)
#ifdef _YO_THREADS_BUILTIN
  {
    YO_THREAD_COOKIE *cookie = _Thread_Allocate_Cookie(func,o);
  #ifdef __windoze
    thread_t thr = CreateThread(0,stacksize,_Thread_Proc,cookie,0,0);
    if ( thr == INVALID_THREAD_VALIUE )
      _Thread_Release_Cookie(cookie);
    return thr;
  #else
  #endif
  }
#endif
  ;
 
#ifdef _YO_THREADS_BUILTIN
static void __No_Return _Thread_Raise_Error()
  {
    __Raise_System_Error();
  }
#endif
    
/* be sure thread is running */
thread_t Thread_Run_Sure(thread_func_t func, void *o, int stacksize)
#ifdef _YO_THREADS_BUILTIN
  {
    thread_t thr = Thread_Run(func,o,stacksize);
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        //WaitForSingleObject(thr,INFINITE);
    #else
    #endif  
      }
    else
      _Thread_Raise_Error();
    return thr;
  }
#endif
  ;
  
void Thread_Run_Close(thread_func_t func, void *o, int stacksize)
#ifdef _YO_THREADS_BUILTIN
  {
    thread_t thr = Thread_Run(func,o,stacksize);
    if ( thr != INVALID_THREAD_VALIUE )
      Thread_Close(thr);
    else
      _Thread_Raise_Error();
  }
#endif
  ;
  
int Thread_Close(thread_t thr)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
      #ifdef __windoze
        DWORD ecode;
        GetExitCodeThread(thr,&ecode);
        CloseHandle(thr);
        if ( ecode == STILL_ACTIVE ) ecode = THREAD_STILL_ACTIVE;
        return ecode;
      #else
      #endif
      }

    return 0;    
  }
#endif
  ;
    
int Thread_Join(thread_t thr)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        for(;;)
          {
            DWORD ecode;
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
      
    return 0;
  }
#endif
  ;
  
void __No_Return Thread_Exit(int ecode)
#ifdef _YOYO_THREADS_BUILTIN
  {
    #ifdef __windoze
      ExitThread(ecode);
    #else
    #endif
  }
#endif
  ;
    
void Thread_Terminate(thread_t thr)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
      #ifdef __windoze
        TerminateThread(thr,-1);
        CloseHandle(thr);
      #else
      #endif
      }
  } 
#endif
  ;
     
#ifdef __windoze

typedef struct _YOYO_THRSYNC
  {
    CRITICAL_SECTION *cs;
    HANDLE notify;
  } YOYO_THRSYNC;
  
void Thrsync_Free(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( l->cs )
      {
        DeleteCriticalSection(l->cs);
        free(l->cs);
        l->cs = 0;
      }
    if ( l->notify )
      {
        CloseHandle(l->notify);
        l->notify = 0;
      }
  }
#endif
  ;

void Thrsync_Init_CS(CRITICAL_SECTION * volatile *cs)
#ifdef _YOYO_THREADS_BUILTIN
  {
    CRITICAL_SECTION *ccs = malloc(sizeof(CRITICAL_SECTION));
    InitializeCriticalSection(ccs);
    if ( 0 != InterlockedCompareExchangePointer(cs,ccs,0) )
      {
        DeleteCriticalSection(ccs);
        free(ccs);
      }
  }
#endif
  ;
  
void Thrsync_Init_Notify(HANDLE volatile *notify)
#ifdef _YOYO_THREADS_BUILTIN
  {
    HANDLE h = CreateEvent(0,0,0,0);
    if ( 0 != InterlockedCompareExchangePointer(notify,h,0) )
      {
        CloseHandle(h);
      }
  }
#endif
  ;

void Nolock_Wait(YOYO_THRSYNC *l, long ms)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( !l->notify ) Thrsync_Init_Notify(&l->notify);
    WaitForSingleObject(l->notify,ms>=0?ms:INFINITE);
  }
#endif
  ;

void Nolock_Notify(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( !l->notify ) Thrsync_Init_Notify(&l->notify);
    SetEvent(l->notify);
  }
#endif
  ;

void Thrsync_Acquire(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( !l->cs ) Thrsync_Init_CS(&l->cs);
    EnterCriticalSection(l->cs);
  }
#endif
  ;

void Thrsync_Release(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( l->cs )
      LeaveCriticalSection(l->cs);
  }
#endif
  ;

void Unlock_Wait_Lock(YOYO_THRSYNC *l, long ms)
#ifdef _YOYO_THREADS_BUILTIN
  {
    Thrsync_Release(l);
    Nolock_Wait(l,ms);
    Thrsync_Acquire(l);
  }
#endif
  ;

void Unlock_Notify_Lock(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    Thrsync_Release(l);
    Nolock_Notify(l);
    Switch_to_Thread();
    Thrsync_Acquire(l);
  }
#endif
  ;

void YOYO_THRSYNC_Destruct(YOYO_THRSYNC *l)
#ifdef _YOYO_THREADS_BUILTIN
  {
    Thrsync_Free(l);
    __Destruct(l);
  }
#endif
  ;
  
YOYO_THRSYNC *Thrsync_Init()
#ifdef _YOYO_THREADS_BUILTIN
  {
    return __Object_Dtor(sizeof(YOYO_THRSYNC),YOYO_THRSYNC_Destruct);
  }
#endif
  ;
  
#define YOYO_THRSYNC_INIT { 0, 0}

/* __windoze way ends here */

#endif 

#define __Thr_Lock(l) \
              __Interlock_Opt(((void)0),l, \
                  Thrsync_Acquire,Thrsync_Release,Thrsync_Release)

#endif /*C_once_7BF4D1A1_7ED4_4CFB_AA04_0E72090D6614*/







|










|















|



|

|
|

















|













|










|
|







|
|







|
|







|
|







|
|








|
|









|
|







|
|

|




|










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
      
    return 0;
  }
#endif
  ;
  
void __No_Return Thread_Exit(int ecode)
#ifdef _YO_THREADS_BUILTIN
  {
    #ifdef __windoze
      ExitThread(ecode);
    #else
    #endif
  }
#endif
  ;
    
void Thread_Terminate(thread_t thr)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
      #ifdef __windoze
        TerminateThread(thr,-1);
        CloseHandle(thr);
      #else
      #endif
      }
  } 
#endif
  ;
     
#ifdef __windoze

typedef struct _YO_THRSYNC
  {
    CRITICAL_SECTION *cs;
    HANDLE notify;
  } YO_THRSYNC;
  
void Thrsync_Free(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( l->cs )
      {
        DeleteCriticalSection(l->cs);
        free(l->cs);
        l->cs = 0;
      }
    if ( l->notify )
      {
        CloseHandle(l->notify);
        l->notify = 0;
      }
  }
#endif
  ;

void Thrsync_Init_CS(CRITICAL_SECTION * volatile *cs)
#ifdef _YO_THREADS_BUILTIN
  {
    CRITICAL_SECTION *ccs = malloc(sizeof(CRITICAL_SECTION));
    InitializeCriticalSection(ccs);
    if ( 0 != InterlockedCompareExchangePointer(cs,ccs,0) )
      {
        DeleteCriticalSection(ccs);
        free(ccs);
      }
  }
#endif
  ;
  
void Thrsync_Init_Notify(HANDLE volatile *notify)
#ifdef _YO_THREADS_BUILTIN
  {
    HANDLE h = CreateEvent(0,0,0,0);
    if ( 0 != InterlockedCompareExchangePointer(notify,h,0) )
      {
        CloseHandle(h);
      }
  }
#endif
  ;

void Nolock_Wait(YO_THRSYNC *l, long ms)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( !l->notify ) Thrsync_Init_Notify(&l->notify);
    WaitForSingleObject(l->notify,ms>=0?ms:INFINITE);
  }
#endif
  ;

void Nolock_Notify(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( !l->notify ) Thrsync_Init_Notify(&l->notify);
    SetEvent(l->notify);
  }
#endif
  ;

void Thrsync_Acquire(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( !l->cs ) Thrsync_Init_CS(&l->cs);
    EnterCriticalSection(l->cs);
  }
#endif
  ;

void Thrsync_Release(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( l->cs )
      LeaveCriticalSection(l->cs);
  }
#endif
  ;

void Unlock_Wait_Lock(YO_THRSYNC *l, long ms)
#ifdef _YO_THREADS_BUILTIN
  {
    Thrsync_Release(l);
    Nolock_Wait(l,ms);
    Thrsync_Acquire(l);
  }
#endif
  ;

void Unlock_Notify_Lock(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    Thrsync_Release(l);
    Nolock_Notify(l);
    Switch_to_Thread();
    Thrsync_Acquire(l);
  }
#endif
  ;

void YO_THRSYNC_Destruct(YO_THRSYNC *l)
#ifdef _YO_THREADS_BUILTIN
  {
    Thrsync_Free(l);
    __Destruct(l);
  }
#endif
  ;
  
YO_THRSYNC *Thrsync_Init()
#ifdef _YO_THREADS_BUILTIN
  {
    return __Object_Dtor(sizeof(YO_THRSYNC),YO_THRSYNC_Destruct);
  }
#endif
  ;
  
#define YO_THRSYNC_INIT { 0, 0}

/* __windoze way ends here */

#endif 

#define __Thr_Lock(l) \
              __Interlock_Opt(((void)0),l, \
                  Thrsync_Acquire,Thrsync_Release,Thrsync_Release)

#endif /*C_once_7BF4D1A1_7ED4_4CFB_AA04_0E72090D6614*/
Changes to uname.hc.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

*/

#ifndef C_once_B6590472_37D1_4589_84F6_BFC339C3E407
#define C_once_B6590472_37D1_4589_84F6_BFC339C3E407

#ifdef _LIBYOYO
#define _YOYO_UNAME_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"

typedef struct _YOYO_CPUINFO
  {
    char id[16];
    char tag[64];
    unsigned family;
    unsigned model;
    unsigned stepping;
    unsigned revision;







|





|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

*/

#ifndef C_once_B6590472_37D1_4589_84F6_BFC339C3E407
#define C_once_B6590472_37D1_4589_84F6_BFC339C3E407

#ifdef _LIBYOYO
#define _YO_UNAME_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"

typedef struct _YO_CPUINFO
  {
    char id[16];
    char tag[64];
    unsigned family;
    unsigned model;
    unsigned stepping;
    unsigned revision;
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    unsigned PAE:1;
    unsigned X64:1;
    unsigned CX8:1;
    unsigned MSR:1;
    unsigned AES:1;
    unsigned RDRND:1;
    
  } YOYO_CPUINFO;

int cpuid(unsigned id, uint_t *rgs);

#ifdef _YOYO_UNAME_BUILTIN
  #if defined __GNUC__ && (defined __i386 || defined __x86_64)
    int cpuid(unsigned id, uint_t *rgs)
      {
        rgs[0] = id;
        asm volatile(
            "mov %%ebx, %%edi;"
            "cpuid;"







|



|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    unsigned PAE:1;
    unsigned X64:1;
    unsigned CX8:1;
    unsigned MSR:1;
    unsigned AES:1;
    unsigned RDRND:1;
    
  } YO_CPUINFO;

int cpuid(unsigned id, uint_t *rgs);

#ifdef _YO_UNAME_BUILTIN
  #if defined __GNUC__ && (defined __i386 || defined __x86_64)
    int cpuid(unsigned id, uint_t *rgs)
      {
        rgs[0] = id;
        asm volatile(
            "mov %%ebx, %%edi;"
            "cpuid;"
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
          __cpuid((int*)rgs,id);
          return 1;
        }*/
    #endif 
  #else
    int cpuid(unsigned id, uint_t *rgs) { return 0; }
  #endif
#endif /* _YOYO_UNAME_BUILTIN */

int Get_Cpu_Info(YOYO_CPUINFO *cpui)
#ifdef _YOYO_UNAME_BUILTIN
  {
    int i;
    uint_t r[4];
    memset(cpui,0,sizeof(*cpui));

    if ( !cpuid(0,r) ) return 0;
    







|

|
|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
          __cpuid((int*)rgs,id);
          return 1;
        }*/
    #endif 
  #else
    int cpuid(unsigned id, uint_t *rgs) { return 0; }
  #endif
#endif /* _YO_UNAME_BUILTIN */

int Get_Cpu_Info(YO_CPUINFO *cpui)
#ifdef _YO_UNAME_BUILTIN
  {
    int i;
    uint_t r[4];
    memset(cpui,0,sizeof(*cpui));

    if ( !cpuid(0,r) ) return 0;
    
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    }
    
    return 1;
  }
#endif
  ;
  
char *Format_Cpu_Info(YOYO_CPUINFO *cpui)
#ifdef _YOYO_UNAME_BUILTIN
  {
    char *ret = 0;
    YOYO_CPUINFO _cpui;
    
    if ( !cpui )
      {
        cpui = &_cpui;
        if ( !Get_Cpu_Info(cpui) )
          return Str_Copy("unknown");
      }







|
|


|







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    }
    
    return 1;
  }
#endif
  ;
  
char *Format_Cpu_Info(YO_CPUINFO *cpui)
#ifdef _YO_UNAME_BUILTIN
  {
    char *ret = 0;
    YO_CPUINFO _cpui;
    
    if ( !cpui )
      {
        cpui = &_cpui;
        if ( !Get_Cpu_Info(cpui) )
          return Str_Copy("unknown");
      }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
      
    return ret;
  }
#endif
  ;
  
char *Get_OS_Target()
#ifdef _YOYO_UNAME_BUILTIN
  {
  #ifdef __windoze 
    return "windows";
  #elif defined __APPLE__
    return "darwin";
  #elif defined __linux__
    return "linux";







|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
      
    return ret;
  }
#endif
  ;
  
char *Get_OS_Target()
#ifdef _YO_UNAME_BUILTIN
  {
  #ifdef __windoze 
    return "windows";
  #elif defined __APPLE__
    return "darwin";
  #elif defined __linux__
    return "linux";
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    return "unknown";
  #endif
  }
#endif
  ;
  
char *Get_OS_Name()
#ifdef _YOYO_UNAME_BUILTIN
  {
  #ifdef __windoze
    char *osname = 0;
    __Auto_Ptr(osname)
      {
        unsigned Maj,Min;
        OSVERSIONINFOEX osinfo;







|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
    return "unknown";
  #endif
  }
#endif
  ;
  
char *Get_OS_Name()
#ifdef _YO_UNAME_BUILTIN
  {
  #ifdef __windoze
    char *osname = 0;
    __Auto_Ptr(osname)
      {
        unsigned Maj,Min;
        OSVERSIONINFOEX osinfo;
Changes to url.hc.
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
#ifndef C_once_36F09FA7_8AEC_4584_91B3_D25C37490B80
#define C_once_36F09FA7_8AEC_4584_91B3_D25C37490B80

#include "yoyo.hc"
#include "string.hc"

#ifdef _LIBYOYO
#define _YOYO_URL_BUILTIN
#endif

enum 
  {
    URLX_UNKNOWN  = 0,
    URLX_HTTP     = 80,
    URLX_HTTPS    = 443,
    URLX_FILE     = -1,
  };

typedef struct _YOYO_URL 
  {
    char *host, *user, *passw, *query, *args, *anchor, *uri, *endpoint;
    int   port, proto;
    YOYO_DICTO *argv;
  } YOYO_URL;

void YOYO_URL_Destruct(YOYO_URL *url)
#ifdef _YOYO_URL_BUILTIN
  {
    free(url->host);
    free(url->user);
    free(url->passw);
    free(url->query);
    free(url->args);
    free(url->anchor);
    free(url->uri);
    free(url->endpoint);
    __Unrefe(url->argv);
    __Destruct(url);
  }
#endif
  ;
  
int Url_Proto(char *S)
#ifdef _YOYO_URL_BUILTIN
  {
    if ( !strcmp_I(S,"http")  )  return URLX_HTTP;
    if ( !strcmp_I(S,"https") )  return URLX_HTTPS;
    if ( !strcmp_I(S,"file")  )  return URLX_FILE;
    return URLX_UNKNOWN;
  }
#endif
  ;
  
enum 
  {
    URLX_PARSE_NOHOST = 1,
    URLX_PARSE_ARGUMENTS = 2,
  };

#define Url_Parse(Url) Url_Parse_(Url,0)
#define Url_Parse_Uri(Url) Url_Parse_(Url,URLX_PARSE_NOHOST)
#define Url_Parse_Full(Url) Url_Parse_(Url,URLX_PARSE_ARGUMENTS)
YOYO_URL *Url_Parse_(char *url,int flags)
#ifdef _YOYO_URL_BUILTIN
  {
    YOYO_URL *urlout = 0;
    if ( url ) __Auto_Ptr(urlout)
      {
        /* proto://user:passwd@host:port/query#anchor?args */
      
        char *p;
        char *pS = url;
        







|










|



|
|

|
|
















|


















|
|

|







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
#ifndef C_once_36F09FA7_8AEC_4584_91B3_D25C37490B80
#define C_once_36F09FA7_8AEC_4584_91B3_D25C37490B80

#include "yoyo.hc"
#include "string.hc"

#ifdef _LIBYOYO
#define _YO_URL_BUILTIN
#endif

enum 
  {
    URLX_UNKNOWN  = 0,
    URLX_HTTP     = 80,
    URLX_HTTPS    = 443,
    URLX_FILE     = -1,
  };

typedef struct _YO_URL 
  {
    char *host, *user, *passw, *query, *args, *anchor, *uri, *endpoint;
    int   port, proto;
    YO_DICTO *argv;
  } YO_URL;

void YO_URL_Destruct(YO_URL *url)
#ifdef _YO_URL_BUILTIN
  {
    free(url->host);
    free(url->user);
    free(url->passw);
    free(url->query);
    free(url->args);
    free(url->anchor);
    free(url->uri);
    free(url->endpoint);
    __Unrefe(url->argv);
    __Destruct(url);
  }
#endif
  ;
  
int Url_Proto(char *S)
#ifdef _YO_URL_BUILTIN
  {
    if ( !strcmp_I(S,"http")  )  return URLX_HTTP;
    if ( !strcmp_I(S,"https") )  return URLX_HTTPS;
    if ( !strcmp_I(S,"file")  )  return URLX_FILE;
    return URLX_UNKNOWN;
  }
#endif
  ;
  
enum 
  {
    URLX_PARSE_NOHOST = 1,
    URLX_PARSE_ARGUMENTS = 2,
  };

#define Url_Parse(Url) Url_Parse_(Url,0)
#define Url_Parse_Uri(Url) Url_Parse_(Url,URLX_PARSE_NOHOST)
#define Url_Parse_Full(Url) Url_Parse_(Url,URLX_PARSE_ARGUMENTS)
YO_URL *Url_Parse_(char *url,int flags)
#ifdef _YO_URL_BUILTIN
  {
    YO_URL *urlout = 0;
    if ( url ) __Auto_Ptr(urlout)
      {
        /* proto://user:passwd@host:port/query#anchor?args */
      
        char *p;
        char *pS = url;
        
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
                pS = p+1; ++p;
                while ( *p && Isdigit(*p) ) ++p;
                if ( *p == '/' || !*p )
                  { 
                    port = strtol(pS,0,10); 
                  }
                else
                  __Raise(YOYO_ERROR_ILLFORMED,__yoTa("invalid port value",0));
                pS = p;
              }
            else if ( !*p || *p == '/' )
              {
                host = Str_Range(pS,p);
                pS = p;
              }







|







166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
                pS = p+1; ++p;
                while ( *p && Isdigit(*p) ) ++p;
                if ( *p == '/' || !*p )
                  { 
                    port = strtol(pS,0,10); 
                  }
                else
                  __Raise(YO_ERROR_ILLFORMED,__yoTa("invalid port value",0));
                pS = p;
              }
            else if ( !*p || *p == '/' )
              {
                host = Str_Range(pS,p);
                pS = p;
              }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
        if ( *p == '?' ) 
          {
            pS = ++p;
            while ( *p ) ++p;
            args = Str_Range(pS,p);
          }
                          
        urlout = __Object_Dtor(sizeof(YOYO_URL),YOYO_URL_Destruct);
        urlout->args  = __Retain(args);
        urlout->anchor= __Retain(anchor);
        urlout->query = __Retain(query);
        urlout->uri   = __Retain(uri);
        urlout->host  = __Retain(host);
        urlout->passw = __Retain(passw);
        urlout->user  = __Retain(user);







|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
        if ( *p == '?' ) 
          {
            pS = ++p;
            while ( *p ) ++p;
            args = Str_Range(pS,p);
          }
                          
        urlout = __Object_Dtor(sizeof(YO_URL),YO_URL_Destruct);
        urlout->args  = __Retain(args);
        urlout->anchor= __Retain(anchor);
        urlout->query = __Retain(query);
        urlout->uri   = __Retain(uri);
        urlout->host  = __Retain(host);
        urlout->passw = __Retain(passw);
        urlout->user  = __Retain(user);
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
          }
          
        urlout->endpoint = __Retain(endpoint);
        
        if ( flags & URLX_PARSE_ARGUMENTS )
          {
            int i;
            YOYO_ARRAY *a = Str_Split(urlout->args,"&");
            urlout->argv = __Refe(Dicto_Ptrs());
            for ( i = 0; i < a->count; ++i )
              {
                char *v = 0;
                char *p = strchr(a->at[i],'=');
                if ( p )
                  {
                    v = p+1;
                    *p = 0;
                  }
                Dicto_Put(urlout->argv,a->at[i],Str_Copy_Npl(v,-1));
              }
          }
      }
      
    return urlout;
  }
#endif
  ;

typedef struct _YOYO_URL_COMPOSER
  {
    char *S;
    int  capacity;
  } YOYO_URL_COMPOSER;

void Url_Compose_Dicto_Fitler(char *name, void *val, void *o)
#ifdef _YOYO_URL_BUILTIN
  {
    char **inout  = &((YOYO_URL_COMPOSER*)o)->S;
    int *capacity = &((YOYO_URL_COMPOSER*)o)->capacity;
    int count     = *inout?strlen(*inout):0;
    count += __Elm_Append(inout,count,"&",1,1,capacity);
    count += __Elm_Append(inout,count,name,strlen(name),1,capacity);
    if ( val )
      {
        int i, iE = strlen(val);
        char C[4];







|




















|



|


|

|
|







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
          }
          
        urlout->endpoint = __Retain(endpoint);
        
        if ( flags & URLX_PARSE_ARGUMENTS )
          {
            int i;
            YO_ARRAY *a = Str_Split(urlout->args,"&");
            urlout->argv = __Refe(Dicto_Ptrs());
            for ( i = 0; i < a->count; ++i )
              {
                char *v = 0;
                char *p = strchr(a->at[i],'=');
                if ( p )
                  {
                    v = p+1;
                    *p = 0;
                  }
                Dicto_Put(urlout->argv,a->at[i],Str_Copy_Npl(v,-1));
              }
          }
      }
      
    return urlout;
  }
#endif
  ;

typedef struct _YO_URL_COMPOSER
  {
    char *S;
    int  capacity;
  } YO_URL_COMPOSER;

void Url_Compose_Dicto_Fitler(char *name, void *val, void *o)
#ifdef _YO_URL_BUILTIN
  {
    char **inout  = &((YO_URL_COMPOSER*)o)->S;
    int *capacity = &((YO_URL_COMPOSER*)o)->capacity;
    int count     = *inout?strlen(*inout):0;
    count += __Elm_Append(inout,count,"&",1,1,capacity);
    count += __Elm_Append(inout,count,name,strlen(name),1,capacity);
    if ( val )
      {
        int i, iE = strlen(val);
        char C[4];
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
              }
          }
      }
  }
#endif
  ;
  
char *Url_Compose(char *url, YOYO_DICTO *params)
#ifdef _YOYO_URL_BUILTIN
  {
    YOYO_URL_COMPOSER cmps = { 0, 0 };
    int i, q = __Elm_Append(&cmps.S,0,url,strlen(url),1,&cmps.capacity);
    
    for ( i = 0; i < q ; ++i )
      if ( cmps.S[i] == '?' ) break;
    if ( i == q ) i = -1;
    
    if ( params )







|
|

|







285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
              }
          }
      }
  }
#endif
  ;
  
char *Url_Compose(char *url, YO_DICTO *params)
#ifdef _YO_URL_BUILTIN
  {
    YO_URL_COMPOSER cmps = { 0, 0 };
    int i, q = __Elm_Append(&cmps.S,0,url,strlen(url),1,&cmps.capacity);
    
    for ( i = 0; i < q ; ++i )
      if ( cmps.S[i] == '?' ) break;
    if ( i == q ) i = -1;
    
    if ( params )
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
      }
        
    return cmps.S;
  }
#endif
  ;
  
char *Url_Xform_Encode(YOYO_DICTO *params)
#ifdef _YOYO_URL_BUILTIN
  {
    if ( params )
      {
        YOYO_URL_COMPOSER cmps = { 0, 0 };
        Dicto_Apply(params,Url_Compose_Dicto_Fitler,&cmps);
        
        if ( cmps.S && cmps.S[0] ) 
          {
            STRICT_REQUIRE(cmps.S[0] == '&');
            cmps.S[0] = '?';
          }







|
|



|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
      }
        
    return cmps.S;
  }
#endif
  ;
  
char *Url_Xform_Encode(YO_DICTO *params)
#ifdef _YO_URL_BUILTIN
  {
    if ( params )
      {
        YO_URL_COMPOSER cmps = { 0, 0 };
        Dicto_Apply(params,Url_Compose_Dicto_Fitler,&cmps);
        
        if ( cmps.S && cmps.S[0] ) 
          {
            STRICT_REQUIRE(cmps.S[0] == '&');
            cmps.S[0] = '?';
          }
Changes to webcfg.hc.
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#ifndef C_once_A719E9E5_B5AB_4A78_A061_34860A495936
#define C_once_A719E9E5_B5AB_4A78_A061_34860A495936

#include "webhost.hc"
#include "xdata.hc"

#ifdef _LIBYOYO
#define _YOYO_WEBCFG_BUILTIN
#endif

YOYO_WEBHOST *Webhost_Config(YOYO_WEBHOST *host, YOYO_XDATA *cfg)
#ifdef _YOYO_WEBCFG_BUILTIN
  {
    char *foo;

    if ( !host ) host = Webhost_Init();

    foo = cfg?Xnode_Value_Get_Str(&cfg->root,"doc_root",0):0;
    if ( !foo ) foo = Current_Directory();







|


|
|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#ifndef C_once_A719E9E5_B5AB_4A78_A061_34860A495936
#define C_once_A719E9E5_B5AB_4A78_A061_34860A495936

#include "webhost.hc"
#include "xdata.hc"

#ifdef _LIBYOYO
#define _YO_WEBCFG_BUILTIN
#endif

YO_WEBHOST *Webhost_Config(YO_WEBHOST *host, YO_XDATA *cfg)
#ifdef _YO_WEBCFG_BUILTIN
  {
    char *foo;

    if ( !host ) host = Webhost_Init();

    foo = cfg?Xnode_Value_Get_Str(&cfg->root,"doc_root",0):0;
    if ( !foo ) foo = Current_Directory();
Changes to webget.hc.
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

#ifndef C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136
#define C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136

#include "yoyo.hc"
#include "httpx.hc"

#ifdef _LIBYOYO
#define _YOYO_WEBGET_BUILTIN
#endif

enum { 
  WEBGET_FILE_BLOCK_SIZE = 128*KILOBYTE, 
  //WEBGET_BLOCKS_PER_WRK  = 8, 
  WEBGET_WORKERS_COUNT   = 3,
  WEBGET_SIGNATURE       = __FOUR_CHARS('W','G','E','T'),
  WEBGET_FINISHED        = 200,
  WEBGET_PARTIAL         = 206,
  WEBGET_FAILED          = 404,       
  WEBGET_STARTED         = 100,       
  WEBGET_BAD_STATEMAP    = 1001,
  WEBGET_BAD_OUTPUT      = 1002,
};

struct _YOYO_WEBGET;
typedef void (*prior_callback_t)(void *obj, int status, int pos, int len, struct _YOYO_WEBGET *webget);
typedef int (*webget_callback_t)(void *obj, int status, int foo, struct _YOYO_WEBGET *webget);

typedef struct _YOYO_WEBGET_STATE
  {
    struct 
      {
        u32_t signature;
        u32_t ready;
        u32_t block_size;
        u32_t file_length;
        u32_t map_length;
        byte_t md5[16];
        union 
          {
            byte_t *map;
            quad_t _;
          };
     } h;
    byte_t map[1];
  } YOYO_WEBGET_STATE;

  
typedef struct _YOYO_WEBGET_PRIOR
  {
    int offs, len;
    prior_callback_t callback;
    void *cbkobj;
    struct _YOYO_WEBGET_PRIOR *next;
  } YOYO_WEBGET_PRIOR;

typedef struct _YOYO_WEBGET
  {
    YOYO_WEBGET_STATE *state;
    char *statemap;
    char *source;
    int workers_cnt;
    int workers_max;
    webget_callback_t callback;
    void *cbkobj;
    char *output;
    void *outstrm;
    YOYO_WEBGET_PRIOR *prior;
    char *fail_reason;
    int  httpx_fail_status;
    int aborting: 1;
    int ondemand: 1;
  } YOYO_WEBGET;

typedef struct _YOYO_WEBGET_WKR
  {
    YOYO_WEBGET *webget;
    int offs, len;
    YOYO_BUFFER *bf;
  } YOYO_WEBGET_WRK;

void YOYO_WEBGET_PRIOR_Destruct(YOYO_WEBGET_PRIOR *prior)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Unrefe(prior->cbkobj);
    __Unrefe(prior->next);
    __Destruct(prior);
  }
#endif
  ;
   
void YOYO_WEBGET_WRK_Destruct(YOYO_WEBGET_WRK *wrk)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Unrefe(wrk->bf);
    __Unrefe(wrk->webget);
    __Destruct(wrk);
  }
#endif
  ;
  
int Webget_Range_Ready(YOYO_WEBGET *webget, int rng_offs, int rng_len)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int i,j;
    YOYO_WEBGET_STATE *st = webget->state;

    if ( rng_len )
      {
        j = (Yo_Mini(rng_offs+rng_len,st->h.file_length)+st->h.block_size-1)/st->h.block_size;
        i = rng_offs/st->h.block_size;
        for ( ; i < j; ++i )
          {
            if ( !(st->map[i/8] & (1<<i%8)) )
              {
                return 0;
              }
          }
      }
  
    return 1;
  }
#endif
  ;
  
int _Webget_St_Next(YOYO_WEBGET_STATE *st, int *len, int rng_offs, int rng_len)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int i,j,n;

    if ( rng_len )
      {
        j = (Yo_Mini(rng_offs+rng_len,st->h.file_length)+st->h.block_size-1)/st->h.block_size;
        i = rng_offs/st->h.block_size;








|















|
|
|

|
















|


|




|
|

|

|








|




|

|

|

|
|

|
|








|
|








|
|


|



















|
|







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

#ifndef C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136
#define C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136

#include "yoyo.hc"
#include "httpx.hc"

#ifdef _LIBYOYO
#define _YO_WEBGET_BUILTIN
#endif

enum { 
  WEBGET_FILE_BLOCK_SIZE = 128*KILOBYTE, 
  //WEBGET_BLOCKS_PER_WRK  = 8, 
  WEBGET_WORKERS_COUNT   = 3,
  WEBGET_SIGNATURE       = __FOUR_CHARS('W','G','E','T'),
  WEBGET_FINISHED        = 200,
  WEBGET_PARTIAL         = 206,
  WEBGET_FAILED          = 404,       
  WEBGET_STARTED         = 100,       
  WEBGET_BAD_STATEMAP    = 1001,
  WEBGET_BAD_OUTPUT      = 1002,
};

struct _YO_WEBGET;
typedef void (*prior_callback_t)(void *obj, int status, int pos, int len, struct _YO_WEBGET *webget);
typedef int (*webget_callback_t)(void *obj, int status, int foo, struct _YO_WEBGET *webget);

typedef struct _YO_WEBGET_STATE
  {
    struct 
      {
        u32_t signature;
        u32_t ready;
        u32_t block_size;
        u32_t file_length;
        u32_t map_length;
        byte_t md5[16];
        union 
          {
            byte_t *map;
            quad_t _;
          };
     } h;
    byte_t map[1];
  } YO_WEBGET_STATE;

  
typedef struct _YO_WEBGET_PRIOR
  {
    int offs, len;
    prior_callback_t callback;
    void *cbkobj;
    struct _YO_WEBGET_PRIOR *next;
  } YO_WEBGET_PRIOR;

typedef struct _YO_WEBGET
  {
    YO_WEBGET_STATE *state;
    char *statemap;
    char *source;
    int workers_cnt;
    int workers_max;
    webget_callback_t callback;
    void *cbkobj;
    char *output;
    void *outstrm;
    YO_WEBGET_PRIOR *prior;
    char *fail_reason;
    int  httpx_fail_status;
    int aborting: 1;
    int ondemand: 1;
  } YO_WEBGET;

typedef struct _YO_WEBGET_WKR
  {
    YO_WEBGET *webget;
    int offs, len;
    YO_BUFFER *bf;
  } YO_WEBGET_WRK;

void YO_WEBGET_PRIOR_Destruct(YO_WEBGET_PRIOR *prior)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Unrefe(prior->cbkobj);
    __Unrefe(prior->next);
    __Destruct(prior);
  }
#endif
  ;
   
void YO_WEBGET_WRK_Destruct(YO_WEBGET_WRK *wrk)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Unrefe(wrk->bf);
    __Unrefe(wrk->webget);
    __Destruct(wrk);
  }
#endif
  ;
  
int Webget_Range_Ready(YO_WEBGET *webget, int rng_offs, int rng_len)
#ifdef _YO_WEBGET_BUILTIN
  {
    int i,j;
    YO_WEBGET_STATE *st = webget->state;

    if ( rng_len )
      {
        j = (Yo_Mini(rng_offs+rng_len,st->h.file_length)+st->h.block_size-1)/st->h.block_size;
        i = rng_offs/st->h.block_size;
        for ( ; i < j; ++i )
          {
            if ( !(st->map[i/8] & (1<<i%8)) )
              {
                return 0;
              }
          }
      }
  
    return 1;
  }
#endif
  ;
  
int _Webget_St_Next(YO_WEBGET_STATE *st, int *len, int rng_offs, int rng_len)
#ifdef _YO_WEBGET_BUILTIN
  {
    int i,j,n;

    if ( rng_len )
      {
        j = (Yo_Mini(rng_offs+rng_len,st->h.file_length)+st->h.block_size-1)/st->h.block_size;
        i = rng_offs/st->h.block_size;
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
   exit:
    *len = 0;
    return 0;
  }
#endif
  ;
  
void _Webget_St_Ready(YOYO_WEBGET_STATE *st,int offs)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    int len = Yo_Mini(st->h.block_size,st->h.file_length-offs);
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    STRICT_REQUIRE(st->h.map[bno/8]&(1<<(bno%8)) != 0);
    STRICT_REQUIRE(st->map[bno/8]&(1<<(bno%8)) == 0);
    st->map[bno/8] |= (1 << (bno%8));
    st->h.ready += len;
  }
#endif
  ;
  
int _Webget_St_Is_Ready(YOYO_WEBGET_STATE *st,int offs)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    return !! (st->map[bno/8] & (1 << (bno%8)));
  }
#endif
  ;
  
int _Webget_St_In_Process(YOYO_WEBGET_STATE *st,int offs)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    return !! (st->h.map[bno/8] & (1 << (bno%8)));
  }
#endif
  ;
  
void _Webget_Init_Statemap(YOYO_WEBGET *webget, int length, byte_t *md5)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET_STATE *st=0;
    int map_length = 0;
    
    STRICT_REQUIRE(!webget->state);
    
    map_length = (length+WEBGET_FILE_BLOCK_SIZE-1)/WEBGET_FILE_BLOCK_SIZE;
    map_length = (map_length + 7)/8;
    st = __Zero_Malloc_Npl(sizeof(st->h)+map_length+20);
    st->h.block_size = WEBGET_FILE_BLOCK_SIZE;
    st->h.file_length = length;
    st->h.map_length = map_length;
    st->h.map = __Zero_Malloc_Npl(map_length);
    webget->state = st;
  }
#endif
  ;
    
int _Webget_Completed_Test_1(YOYO_WEBGET_STATE *st, char *stmap, char *output)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int completed = 0;
    memset(st,0,sizeof(*st));
    if ( stmap ) __Auto_Release
      if ( File_Exists(stmap) )
        {
          void *f = Cfile_Open(stmap,"r"); 
          Oj_Read_Full(f,st,sizeof(YOYO_WEBGET_STATE));
          if ( st->h.signature == WEBGET_SIGNATURE
            && st->h.ready == st->h.file_length ) 
            {
              YOYO_FILE_STATS fst = {0};
              if ( File_Get_Stats(output,&fst,1)->f.exists
                && fst.length == st->h.file_length ) 
                completed = 1;
            }
        }
    return completed;
  }
#endif
  ;

int _Webget_Completed_Test(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET_STATE st = {0};
    return _Webget_Completed_Test_1(&st,webget->statemap,webget->output);
  }
#endif
  ;
    
void _Webget_Load_Statemap(YOYO_WEBGET *webget, int length, byte_t *md5)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Try_Except
      if ( webget->statemap ) __Auto_Release
        {
          STRICT_REQUIRE( !webget->state );
          if ( File_Exists(webget->statemap) )
            {
              void *f = Cfile_Open(webget->statemap,"r"); 
              YOYO_BUFFER *bf = Oj_Read_All(f);
              if ( bf->count >= sizeof(YOYO_WEBGET_STATE)+20 )
                {
                  YOYO_WEBGET_STATE *wst = (YOYO_WEBGET_STATE *)bf->at;
                  int state_L = sizeof(wst->h)+wst->h.map_length;
                  if ( state_L + 20 == bf->count && wst->h.signature == WEBGET_SIGNATURE )
                    {
                      byte_t b20[20];
                      Sha1_Digest(wst,state_L,b20);
                      if ( !memcmp(b20,bf->at+state_L,20) )
                        {







|
|














|
|










|
|










|
|

|
















|
|







|



|










|
|

|





|
|








|
|

|







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
   exit:
    *len = 0;
    return 0;
  }
#endif
  ;
  
void _Webget_St_Ready(YO_WEBGET_STATE *st,int offs)
#ifdef _YO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    int len = Yo_Mini(st->h.block_size,st->h.file_length-offs);
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    STRICT_REQUIRE(st->h.map[bno/8]&(1<<(bno%8)) != 0);
    STRICT_REQUIRE(st->map[bno/8]&(1<<(bno%8)) == 0);
    st->map[bno/8] |= (1 << (bno%8));
    st->h.ready += len;
  }
#endif
  ;
  
int _Webget_St_Is_Ready(YO_WEBGET_STATE *st,int offs)
#ifdef _YO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    return !! (st->map[bno/8] & (1 << (bno%8)));
  }
#endif
  ;
  
int _Webget_St_In_Process(YO_WEBGET_STATE *st,int offs)
#ifdef _YO_WEBGET_BUILTIN
  {
    int bno = offs/st->h.block_size;
    STRICT_REQUIRE(offs%st->h.block_size == 0);
    STRICT_REQUIRE(offs<st->h.file_length);
    STRICT_REQUIRE(bno/8<st->h.map_length);
    return !! (st->h.map[bno/8] & (1 << (bno%8)));
  }
#endif
  ;
  
void _Webget_Init_Statemap(YO_WEBGET *webget, int length, byte_t *md5)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET_STATE *st=0;
    int map_length = 0;
    
    STRICT_REQUIRE(!webget->state);
    
    map_length = (length+WEBGET_FILE_BLOCK_SIZE-1)/WEBGET_FILE_BLOCK_SIZE;
    map_length = (map_length + 7)/8;
    st = __Zero_Malloc_Npl(sizeof(st->h)+map_length+20);
    st->h.block_size = WEBGET_FILE_BLOCK_SIZE;
    st->h.file_length = length;
    st->h.map_length = map_length;
    st->h.map = __Zero_Malloc_Npl(map_length);
    webget->state = st;
  }
#endif
  ;
    
int _Webget_Completed_Test_1(YO_WEBGET_STATE *st, char *stmap, char *output)
#ifdef _YO_WEBGET_BUILTIN
  {
    int completed = 0;
    memset(st,0,sizeof(*st));
    if ( stmap ) __Auto_Release
      if ( File_Exists(stmap) )
        {
          void *f = Cfile_Open(stmap,"r"); 
          Oj_Read_Full(f,st,sizeof(YO_WEBGET_STATE));
          if ( st->h.signature == WEBGET_SIGNATURE
            && st->h.ready == st->h.file_length ) 
            {
              YO_FILE_STATS fst = {0};
              if ( File_Get_Stats(output,&fst,1)->f.exists
                && fst.length == st->h.file_length ) 
                completed = 1;
            }
        }
    return completed;
  }
#endif
  ;

int _Webget_Completed_Test(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET_STATE st = {0};
    return _Webget_Completed_Test_1(&st,webget->statemap,webget->output);
  }
#endif
  ;
    
void _Webget_Load_Statemap(YO_WEBGET *webget, int length, byte_t *md5)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Try_Except
      if ( webget->statemap ) __Auto_Release
        {
          STRICT_REQUIRE( !webget->state );
          if ( File_Exists(webget->statemap) )
            {
              void *f = Cfile_Open(webget->statemap,"r"); 
              YO_BUFFER *bf = Oj_Read_All(f);
              if ( bf->count >= sizeof(YO_WEBGET_STATE)+20 )
                {
                  YO_WEBGET_STATE *wst = (YO_WEBGET_STATE *)bf->at;
                  int state_L = sizeof(wst->h)+wst->h.map_length;
                  if ( state_L + 20 == bf->count && wst->h.signature == WEBGET_SIGNATURE )
                    {
                      byte_t b20[20];
                      Sha1_Digest(wst,state_L,b20);
                      if ( !memcmp(b20,bf->at+state_L,20) )
                        {
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
      ;
    if ( !webget->state )
      _Webget_Init_Statemap(webget,length,md5);
  }
#endif
  ;
  
void _Webget_Write_Statemap(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Try_Except
      if ( webget->statemap ) __Auto_Release
        {
          byte_t b20[20];
          int state_L = sizeof(webget->state->h)+webget->state->h.map_length;
          void *f = Cfile_Open(webget->statemap,"Pw+");
          webget->state->h.signature = WEBGET_SIGNATURE;
          Oj_Write_Full(f,webget->state,state_L);
          Sha1_Digest(webget->state,state_L,b20);
          Oj_Write_Full(f,b20,20);
        }
    __Except
      ;
  }
#endif
  ;
    
void _Webget_Prior_Deque(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    STRICT_REQUIRE(webget->prior!=0);
    if ( webget->prior ) __Auto_Release
      {
        YOYO_WEBGET_PRIOR *prior = __Pool_RefPtr(webget->prior);
        webget->prior = prior->next;
        prior->next = 0;
      }
  }
#endif
  ;
  
#define _Webget_Prior_Finished(Webget) _Webget_Prior_Exit(Webget,WEBGET_FINISHED);
#define _Webget_Prior_Failed(Webget) _Webget_Prior_Exit(Webget,WEBGET_FAILED);
void _Webget_Prior_Exit(YOYO_WEBGET *webget,int status)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    STRICT_REQUIRE(webget->prior!=0);
    if ( webget->prior ) __Auto_Release
      {
        YOYO_WEBGET_PRIOR *prior = __Pool_RefPtr(webget->prior);
        webget->prior = prior->next;
        prior->next = 0;
        if ( prior->callback ) 
          prior->callback(prior->cbkobj,status,prior->offs,prior->len,webget);
      }
  }
#endif
  ;
  
void Webget_Priority_Part(YOYO_WEBGET *webget, int pos, int len, prior_callback_t callback, void *obj)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET_PRIOR *prior = __Object_Dtor(sizeof(YOYO_WEBGET_PRIOR),YOYO_WEBGET_PRIOR_Destruct);
    YOYO_WEBGET_PRIOR **last = &webget->prior;
    prior->offs = pos;
    prior->len  = len;
    prior->callback = callback;
    prior->cbkobj = __Refe(obj);
    while ( *last ) last = &(*last)->next;
    *last = __Refe(prior);
  }
#endif
  ;
  
int Webget_Ready(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.ready;
    return 0;
  }
#endif
  ;
  
int Webget_Done(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.ready == webget->state->h.file_length;
    return 0;
  }
#endif
  ;
  
int Webget_Length(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.file_length;
    return 0;
  }
#endif
  ;
  
int Webget_Block_Length(YOYO_WEBGET *webget, int offs)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET_STATE *st = webget->state;
    if ( st && offs < st->h.file_length )
      return Yo_Mini(st->h.block_size,st->h.file_length-offs);
    return 0;
  }
#endif
  ;
  
#define Webget_Wrk_Query_Next(Wrk,Httpx) Webget_Wrk_Query(Wrk,Httpx,0)
#define Webget_Wrk_Query_Retry(Wrk,Httpx) Webget_Wrk_Query(Wrk,Httpx,1)

void Cbk_Webget_Alert_Callback(YOYO_WEBGET_WRK *wrk, int status);
void Cbk_Webget_Get_Callback(void *obj, YOYO_HTTPX *httpx, int status);
void Webget_Wrk_Query(YOYO_WEBGET_WRK *wrk, YOYO_HTTPX *httpx, int retry)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET *webget = wrk->webget;
    YOYO_WEBGET_STATE *st = webget->state;
    
    __Gogo
      {
        YOYO_WEBGET_PRIOR **prior = &webget->prior;
        
        while ( *prior )
          {
            if ( !Webget_Range_Ready(webget,(*prior)->offs,(*prior)->len) ) 
              prior = &(*prior)->next;
            else
              __Auto_Release
                {
                  YOYO_WEBGET_PRIOR *p = __Pool_RefPtr(*prior);
                  *prior = p->next;
                  p->next = 0;
                  if ( p->callback )
                    p->callback(p->cbkobj,WEBGET_FINISHED,p->offs,p->len,wrk->webget);
                }
          }
      }
      
    if ( !httpx || !httpx->keepalive )
      httpx = Httpx_Client_Callback(webget->source,HTTPX_ASYNC|HTTPX_KEEPALIVE,Cbk_Webget_Get_Callback,wrk);
    
    if ( !retry )
      {
        YOYO_WEBGET_PRIOR *prior = webget->prior;
        wrk->len = 0;
        while ( prior )
          {
            wrk->offs = _Webget_St_Next(st,&wrk->len,prior->offs,prior->len);
            if ( wrk->len )
              break;
            prior = prior->next;







|
|


















|
|




|









|
|




|









|
|

|
|










|
|








|
|








|
|








|
|

|










|
|
|
|

|
|



|








|













|







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
      ;
    if ( !webget->state )
      _Webget_Init_Statemap(webget,length,md5);
  }
#endif
  ;
  
void _Webget_Write_Statemap(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Try_Except
      if ( webget->statemap ) __Auto_Release
        {
          byte_t b20[20];
          int state_L = sizeof(webget->state->h)+webget->state->h.map_length;
          void *f = Cfile_Open(webget->statemap,"Pw+");
          webget->state->h.signature = WEBGET_SIGNATURE;
          Oj_Write_Full(f,webget->state,state_L);
          Sha1_Digest(webget->state,state_L,b20);
          Oj_Write_Full(f,b20,20);
        }
    __Except
      ;
  }
#endif
  ;
    
void _Webget_Prior_Deque(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    STRICT_REQUIRE(webget->prior!=0);
    if ( webget->prior ) __Auto_Release
      {
        YO_WEBGET_PRIOR *prior = __Pool_RefPtr(webget->prior);
        webget->prior = prior->next;
        prior->next = 0;
      }
  }
#endif
  ;
  
#define _Webget_Prior_Finished(Webget) _Webget_Prior_Exit(Webget,WEBGET_FINISHED);
#define _Webget_Prior_Failed(Webget) _Webget_Prior_Exit(Webget,WEBGET_FAILED);
void _Webget_Prior_Exit(YO_WEBGET *webget,int status)
#ifdef _YO_WEBGET_BUILTIN
  {
    STRICT_REQUIRE(webget->prior!=0);
    if ( webget->prior ) __Auto_Release
      {
        YO_WEBGET_PRIOR *prior = __Pool_RefPtr(webget->prior);
        webget->prior = prior->next;
        prior->next = 0;
        if ( prior->callback ) 
          prior->callback(prior->cbkobj,status,prior->offs,prior->len,webget);
      }
  }
#endif
  ;
  
void Webget_Priority_Part(YO_WEBGET *webget, int pos, int len, prior_callback_t callback, void *obj)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET_PRIOR *prior = __Object_Dtor(sizeof(YO_WEBGET_PRIOR),YO_WEBGET_PRIOR_Destruct);
    YO_WEBGET_PRIOR **last = &webget->prior;
    prior->offs = pos;
    prior->len  = len;
    prior->callback = callback;
    prior->cbkobj = __Refe(obj);
    while ( *last ) last = &(*last)->next;
    *last = __Refe(prior);
  }
#endif
  ;
  
int Webget_Ready(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.ready;
    return 0;
  }
#endif
  ;
  
int Webget_Done(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.ready == webget->state->h.file_length;
    return 0;
  }
#endif
  ;
  
int Webget_Length(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( webget->state )
      return webget->state->h.file_length;
    return 0;
  }
#endif
  ;
  
int Webget_Block_Length(YO_WEBGET *webget, int offs)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET_STATE *st = webget->state;
    if ( st && offs < st->h.file_length )
      return Yo_Mini(st->h.block_size,st->h.file_length-offs);
    return 0;
  }
#endif
  ;
  
#define Webget_Wrk_Query_Next(Wrk,Httpx) Webget_Wrk_Query(Wrk,Httpx,0)
#define Webget_Wrk_Query_Retry(Wrk,Httpx) Webget_Wrk_Query(Wrk,Httpx,1)

void Cbk_Webget_Alert_Callback(YO_WEBGET_WRK *wrk, int status);
void Cbk_Webget_Get_Callback(void *obj, YO_HTTPX *httpx, int status);
void Webget_Wrk_Query(YO_WEBGET_WRK *wrk, YO_HTTPX *httpx, int retry)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET *webget = wrk->webget;
    YO_WEBGET_STATE *st = webget->state;
    
    __Gogo
      {
        YO_WEBGET_PRIOR **prior = &webget->prior;
        
        while ( *prior )
          {
            if ( !Webget_Range_Ready(webget,(*prior)->offs,(*prior)->len) ) 
              prior = &(*prior)->next;
            else
              __Auto_Release
                {
                  YO_WEBGET_PRIOR *p = __Pool_RefPtr(*prior);
                  *prior = p->next;
                  p->next = 0;
                  if ( p->callback )
                    p->callback(p->cbkobj,WEBGET_FINISHED,p->offs,p->len,wrk->webget);
                }
          }
      }
      
    if ( !httpx || !httpx->keepalive )
      httpx = Httpx_Client_Callback(webget->source,HTTPX_ASYNC|HTTPX_KEEPALIVE,Cbk_Webget_Get_Callback,wrk);
    
    if ( !retry )
      {
        YO_WEBGET_PRIOR *prior = webget->prior;
        wrk->len = 0;
        while ( prior )
          {
            wrk->offs = _Webget_St_Next(st,&wrk->len,prior->offs,prior->len);
            if ( wrk->len )
              break;
            prior = prior->next;
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
        else if ( webget->ondemand )
          {
            Tasque_Alert(0,Cbk_Webget_Alert_Callback,wrk);
          } 
      }
    else
      { 
        YOYO_DICTO *hdrs = Httpx_Hdrs_Set_Range(0,wrk->offs,wrk->len);
        wrk->bf->count = 0;
        Httpx_Query(httpx,HTTPX_GET,0,hdrs,0,Buffer_As_File(wrk->bf),st->h.block_size);
      }
  }
#endif
  ;
  
void _Terminate_All_Wrks(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    //
  }
#endif
  ;
  
void _Webget_Abort(YOYO_WEBGET *webget, char *reason)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Enter_Once(webget->aborting)
      {
        webget->fail_reason = Str_Copy_Npl(reason,-1);
        _Terminate_All_Wrks(webget);
        while ( webget->prior )
          _Webget_Prior_Failed(webget);
        if ( webget->callback )
          webget->callback(webget->cbkobj,WEBGET_FAILED,0,webget);
      }
  }
#endif
  ;
  
void Cbk_Webget_Alert_Callback(YOYO_WEBGET_WRK *wrk, int status)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( !HTTPX_SUCCEEDED(status) )
      {
        _Webget_Abort(wrk->webget,__yoTa("alert error",0));  
      }
    else    
       Webget_Wrk_Query_Next(wrk,0);
  }
#endif
  ;
  
void Cbk_Webget_Get_Callback(void *obj, YOYO_HTTPX *httpx, int status)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET_WRK *wrk = obj;
    if ( !HTTPX_SUCCEEDED(status) )
      {
        if ( !httpx->interrupted && !(status&HTTPX_PERMANENT_ERROR))
          {
            Webget_Wrk_Query_Retry(wrk,0);
          }
        else __Auto_Release
          {
            _Webget_Abort(wrk->webget,__yoTa("permanent error",0));  
          }
      }
    else if ( httpx->state == HTTPX_FINISHED )
      {
        if ( httpx->status == 206 )
          {
            YOYO_WEBGET *webget = wrk->webget;
            void *ostrm = wrk->webget->outstrm; 
            Oj_Seek(ostrm,wrk->offs,0);
            Oj_Write_Full(ostrm,wrk->bf->at,wrk->len);
            Oj_Flush(ostrm);
            _Webget_St_Ready(wrk->webget->state,wrk->offs);
            _Webget_Write_Statemap(wrk->webget);
            







|







|
|






|
|














|
|











|
|

|















|







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
        else if ( webget->ondemand )
          {
            Tasque_Alert(0,Cbk_Webget_Alert_Callback,wrk);
          } 
      }
    else
      { 
        YO_DICTO *hdrs = Httpx_Hdrs_Set_Range(0,wrk->offs,wrk->len);
        wrk->bf->count = 0;
        Httpx_Query(httpx,HTTPX_GET,0,hdrs,0,Buffer_As_File(wrk->bf),st->h.block_size);
      }
  }
#endif
  ;
  
void _Terminate_All_Wrks(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    //
  }
#endif
  ;
  
void _Webget_Abort(YO_WEBGET *webget, char *reason)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Enter_Once(webget->aborting)
      {
        webget->fail_reason = Str_Copy_Npl(reason,-1);
        _Terminate_All_Wrks(webget);
        while ( webget->prior )
          _Webget_Prior_Failed(webget);
        if ( webget->callback )
          webget->callback(webget->cbkobj,WEBGET_FAILED,0,webget);
      }
  }
#endif
  ;
  
void Cbk_Webget_Alert_Callback(YO_WEBGET_WRK *wrk, int status)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( !HTTPX_SUCCEEDED(status) )
      {
        _Webget_Abort(wrk->webget,__yoTa("alert error",0));  
      }
    else    
       Webget_Wrk_Query_Next(wrk,0);
  }
#endif
  ;
  
void Cbk_Webget_Get_Callback(void *obj, YO_HTTPX *httpx, int status)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET_WRK *wrk = obj;
    if ( !HTTPX_SUCCEEDED(status) )
      {
        if ( !httpx->interrupted && !(status&HTTPX_PERMANENT_ERROR))
          {
            Webget_Wrk_Query_Retry(wrk,0);
          }
        else __Auto_Release
          {
            _Webget_Abort(wrk->webget,__yoTa("permanent error",0));  
          }
      }
    else if ( httpx->state == HTTPX_FINISHED )
      {
        if ( httpx->status == 206 )
          {
            YO_WEBGET *webget = wrk->webget;
            void *ostrm = wrk->webget->outstrm; 
            Oj_Seek(ostrm,wrk->offs,0);
            Oj_Write_Full(ostrm,wrk->bf->at,wrk->len);
            Oj_Flush(ostrm);
            _Webget_St_Ready(wrk->webget->state,wrk->offs);
            _Webget_Write_Statemap(wrk->webget);
            
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
            _Webget_Abort(wrk->webget,httpx->status_text);
          }
      }
  }
#endif
  ;
  
void Webget_Start_Worker(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( !Webget_Done(webget) )
      {
        YOYO_WEBGET_WRK *wrk = __Object_Dtor(sizeof(YOYO_WEBGET_WRK),YOYO_WEBGET_WRK_Destruct);
        wrk->webget = __Refe(webget);
        wrk->bf = __Refe(Buffer_Reserve(0,webget->state?webget->state->h.block_size:0));
        ++webget->workers_cnt;
        Webget_Wrk_Query_Next(wrk,0);
      }
  }
#endif
  ;
  
void _Webget_Start_Workers(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    int i;
    if ( Webget_Done(webget) )
      {
        while ( webget->prior ) __Auto_Release
          {
            YOYO_WEBGET_PRIOR *p = __Pool_RefPtr(webget->prior);
            webget->prior = p->next;
            p->next = 0;
            p->callback(webget->cbkobj,WEBGET_FINISHED,p->offs,p->len,webget);
          }
          
        if ( webget->callback )
          webget->callback(webget->cbkobj,WEBGET_FINISHED,0,webget);
      }
    else
      for ( i = 0; i < webget->workers_max; ++i )
        Webget_Start_Worker(webget);
  }
#endif
  ;
  
void _Webget_Query_Head(YOYO_WEBGET *webget);
void Cbk_Webget_Head_Callback(void *obj, YOYO_HTTPX *httpx, int status)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET *webget = obj;
    if ( !HTTPX_SUCCEEDED(status) )
      {
        if ( !httpx->interrupted && !(status&HTTPX_PERMANENT_ERROR) )
          {
            _Webget_Query_Head(webget);
          }
        else







|
|



|









|
|






|















|
|
|

|







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
            _Webget_Abort(wrk->webget,httpx->status_text);
          }
      }
  }
#endif
  ;
  
void Webget_Start_Worker(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( !Webget_Done(webget) )
      {
        YO_WEBGET_WRK *wrk = __Object_Dtor(sizeof(YO_WEBGET_WRK),YO_WEBGET_WRK_Destruct);
        wrk->webget = __Refe(webget);
        wrk->bf = __Refe(Buffer_Reserve(0,webget->state?webget->state->h.block_size:0));
        ++webget->workers_cnt;
        Webget_Wrk_Query_Next(wrk,0);
      }
  }
#endif
  ;
  
void _Webget_Start_Workers(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    int i;
    if ( Webget_Done(webget) )
      {
        while ( webget->prior ) __Auto_Release
          {
            YO_WEBGET_PRIOR *p = __Pool_RefPtr(webget->prior);
            webget->prior = p->next;
            p->next = 0;
            p->callback(webget->cbkobj,WEBGET_FINISHED,p->offs,p->len,webget);
          }
          
        if ( webget->callback )
          webget->callback(webget->cbkobj,WEBGET_FINISHED,0,webget);
      }
    else
      for ( i = 0; i < webget->workers_max; ++i )
        Webget_Start_Worker(webget);
  }
#endif
  ;
  
void _Webget_Query_Head(YO_WEBGET *webget);
void Cbk_Webget_Head_Callback(void *obj, YO_HTTPX *httpx, int status)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET *webget = obj;
    if ( !HTTPX_SUCCEEDED(status) )
      {
        if ( !httpx->interrupted && !(status&HTTPX_PERMANENT_ERROR) )
          {
            _Webget_Query_Head(webget);
          }
        else
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
            _Webget_Abort(webget,httpx->status_text);
          }
      }
  }
#endif
  ;
  
void _Webget_Query_Head(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_HTTPX *httpx = Httpx_Client_Callback(webget->source,HTTPX_ASYNC,Cbk_Webget_Head_Callback,webget);
    Httpx_Query(httpx,HTTPX_HEAD,0,0,0,0,0);
  }
#endif
  ;
  
void YOYO_WEBGET_Destruct(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    __Unrefe(webget->cbkobj);
    __Unrefe(webget->outstrm);
    if ( webget->state )
      free(webget->state->h.map);
    free(webget->state);
    free(webget->statemap);
    free(webget->source);
    free(webget->fail_reason);
    free(webget->output);
    
    while ( webget->prior )
      _Webget_Prior_Failed(webget);
      
    __Destruct(webget);
  }
#endif
  ;
  
YOYO_WEBGET *Webget_Init(
  char *url, char *output, char *statemap, 
  webget_callback_t callback, void *obj,
  int workers)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET *webget = __Object_Dtor(sizeof(YOYO_WEBGET),YOYO_WEBGET_Destruct);
    webget->statemap = statemap?Str_Copy_Npl(statemap,-1):0;
    webget->output   = output?Str_Copy_Npl(output,-1):0;
    webget->callback = callback;
    webget->cbkobj   = __Refe(obj);
    webget->workers_max = workers>0?workers:WEBGET_WORKERS_COUNT;
    webget->source   = Str_Copy_Npl(url,-1);
    return webget;
  }
#endif
  ;
  
void Webget_Start(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    if ( !webget->state )
      {
        if ( !_Webget_Completed_Test(webget) )
          _Webget_Query_Head(webget);
        else
          {







|
|

|





|
|



















|



|

|











|
|







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
            _Webget_Abort(webget,httpx->status_text);
          }
      }
  }
#endif
  ;
  
void _Webget_Query_Head(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_HTTPX *httpx = Httpx_Client_Callback(webget->source,HTTPX_ASYNC,Cbk_Webget_Head_Callback,webget);
    Httpx_Query(httpx,HTTPX_HEAD,0,0,0,0,0);
  }
#endif
  ;
  
void YO_WEBGET_Destruct(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    __Unrefe(webget->cbkobj);
    __Unrefe(webget->outstrm);
    if ( webget->state )
      free(webget->state->h.map);
    free(webget->state);
    free(webget->statemap);
    free(webget->source);
    free(webget->fail_reason);
    free(webget->output);
    
    while ( webget->prior )
      _Webget_Prior_Failed(webget);
      
    __Destruct(webget);
  }
#endif
  ;
  
YO_WEBGET *Webget_Init(
  char *url, char *output, char *statemap, 
  webget_callback_t callback, void *obj,
  int workers)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET *webget = __Object_Dtor(sizeof(YO_WEBGET),YO_WEBGET_Destruct);
    webget->statemap = statemap?Str_Copy_Npl(statemap,-1):0;
    webget->output   = output?Str_Copy_Npl(output,-1):0;
    webget->callback = callback;
    webget->cbkobj   = __Refe(obj);
    webget->workers_max = workers>0?workers:WEBGET_WORKERS_COUNT;
    webget->source   = Str_Copy_Npl(url,-1);
    return webget;
  }
#endif
  ;
  
void Webget_Start(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    if ( !webget->state )
      {
        if ( !_Webget_Completed_Test(webget) )
          _Webget_Query_Head(webget);
        else
          {
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
      }
    else if ( !webget->workers_cnt )
      _Webget_Start_Workers(webget);
  }
#endif
  ;
    
void Webget_Stop(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
  }
#endif
  ;
  
void Webget_Abort(YOYO_WEBGET *webget)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    _Webget_Abort(webget,__yoTa("manual abort",0));
  }
#endif
  ;
    
YOYO_WEBGET *Webget_Download(char *url, char *output, webget_callback_t callback, void *obj)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET *webget = 0;
    __Auto_Ptr(webget)
      {
        webget = Webget_Init(url,output,0,callback,obj,WEBGET_WORKERS_COUNT);
        Webget_Start(webget);
      }
    return webget;
  }
#endif
  ;
  
YOYO_WEBGET *Webget_Reget(char *url, char *output, char *statemap, webget_callback_t callback, void *obj)
#ifdef _YOYO_WEBGET_BUILTIN
  {
    YOYO_WEBGET *webget = 0;
    __Auto_Ptr(webget)
      {
        webget = Webget_Init(url,output,statemap,callback,obj,WEBGET_WORKERS_COUNT);
        Webget_Start(webget);
      }
    return webget;
  }
#endif
  ;

#endif /*C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136*/








|
|





|
|






|
|

|










|
|

|












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
      }
    else if ( !webget->workers_cnt )
      _Webget_Start_Workers(webget);
  }
#endif
  ;
    
void Webget_Stop(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
  }
#endif
  ;
  
void Webget_Abort(YO_WEBGET *webget)
#ifdef _YO_WEBGET_BUILTIN
  {
    _Webget_Abort(webget,__yoTa("manual abort",0));
  }
#endif
  ;
    
YO_WEBGET *Webget_Download(char *url, char *output, webget_callback_t callback, void *obj)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET *webget = 0;
    __Auto_Ptr(webget)
      {
        webget = Webget_Init(url,output,0,callback,obj,WEBGET_WORKERS_COUNT);
        Webget_Start(webget);
      }
    return webget;
  }
#endif
  ;
  
YO_WEBGET *Webget_Reget(char *url, char *output, char *statemap, webget_callback_t callback, void *obj)
#ifdef _YO_WEBGET_BUILTIN
  {
    YO_WEBGET *webget = 0;
    __Auto_Ptr(webget)
      {
        webget = Webget_Init(url,output,statemap,callback,obj,WEBGET_WORKERS_COUNT);
        Webget_Start(webget);
      }
    return webget;
  }
#endif
  ;

#endif /*C_once_A680A0EB_B8EE_4F96_B06B_74BA1C9C8136*/

Changes to webhost.hc.
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

#include "httpd.hc"
#include "mime.hc"
#include "pipex.hc"
#include "logout.hc"

#ifdef _LIBYOYO
#define _YOYO_WEBHOST_BUILTIN
#endif

enum { WEBHOST_VERSION = 100 };

typedef struct _YOYO_WEBHOST
  {
    char *doc_root;
    char *exec_root;
    YOYO_ARRAY *indexes;
    
    int disable_index: 1;
    
  } YOYO_WEBHOST;
  
void YOYO_WEBHOST_Destruct(YOYO_WEBHOST *host)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    __Unrefe(host->indexes);
    free(host->doc_root);
    free(host->exec_root);
    __Destruct(host);
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Init()
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    YOYO_WEBHOST *host = __Object_Dtor(sizeof(YOYO_WEBHOST),YOYO_WEBHOST_Destruct);
    host->indexes = __Refe(Array_Pchars());
    return host;
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Set_Doc_Root(YOYO_WEBHOST *host, char *doc_root)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    free(host->doc_root);
    host->doc_root = doc_root?Str_Copy_Npl(doc_root,-1):0;
    return host;
  }
#endif
  ;
  
YOYO_WEBHOST *Webhost_Set_Exec_Root(YOYO_WEBHOST *host, char *exec_root)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    free(host->exec_root);
    host->exec_root = exec_root?Str_Copy_Npl(exec_root,-1):0;
    return host;
  }
#endif
  ;

YOYO_WEBHOST *Webhost_Add_Index(YOYO_WEBHOST *host, char *index)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    Array_Push(host->indexes,Str_Copy_Npl(index,-1));
    return host;
  }
#endif
  ;
  
char *Webhost_Conenttype_Of(char *path)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int code = Mime_Code_Of_Path(path,YOYO_MIME_OCTS);
    return Mime_String_Of(code);
  }
#endif
  ;
  
int Webhost_Is_Executable(YOYO_BUFFER *bf, int L, YOYO_ARRAY *extL)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int i;
    
    for ( i = 0; i < extL->count; ++i )
      {
        char *ext = extL->at[i];
        int j = strlen(ext);
        if ( L > j && !strncmp_I(bf->at+(L-j),ext,j) )
          {
            YOYO_FILE_STATS stats = {0};
            if ( File_Get_Stats(bf->at,&stats,1)->f.exists )
              {
                if ( !stats.f.is_directory )
                  return 1;
              }
            break;
          }
      }
    
    return 0;
  }
#endif
  ;
   
int Webhost_Find_Executable_1(YOYO_BUFFER *bf, int L, YOYO_ARRAY *extL)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int i;
    YOYO_FILE_STATS stats = {0};
    
    bf->at[L] = 0;
    
    if ( File_Get_Stats(bf->at,&stats,1)->f.exists && !stats.f.is_directory )
      return Webhost_Is_Executable(bf,L,extL);
        
    for ( i = 0; i < extL->count; ++i )







|




|



|



|

|
|









|
|

|






|
|








|
|








|
|








|

|





|
|









|














|
|


|







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

#include "httpd.hc"
#include "mime.hc"
#include "pipex.hc"
#include "logout.hc"

#ifdef _LIBYOYO
#define _YO_WEBHOST_BUILTIN
#endif

enum { WEBHOST_VERSION = 100 };

typedef struct _YO_WEBHOST
  {
    char *doc_root;
    char *exec_root;
    YO_ARRAY *indexes;
    
    int disable_index: 1;
    
  } YO_WEBHOST;
  
void YO_WEBHOST_Destruct(YO_WEBHOST *host)
#ifdef _YO_WEBHOST_BUILTIN
  {
    __Unrefe(host->indexes);
    free(host->doc_root);
    free(host->exec_root);
    __Destruct(host);
  }
#endif
  ;
  
YO_WEBHOST *Webhost_Init()
#ifdef _YO_WEBHOST_BUILTIN
  {
    YO_WEBHOST *host = __Object_Dtor(sizeof(YO_WEBHOST),YO_WEBHOST_Destruct);
    host->indexes = __Refe(Array_Pchars());
    return host;
  }
#endif
  ;
  
YO_WEBHOST *Webhost_Set_Doc_Root(YO_WEBHOST *host, char *doc_root)
#ifdef _YO_WEBHOST_BUILTIN
  {
    free(host->doc_root);
    host->doc_root = doc_root?Str_Copy_Npl(doc_root,-1):0;
    return host;
  }
#endif
  ;
  
YO_WEBHOST *Webhost_Set_Exec_Root(YO_WEBHOST *host, char *exec_root)
#ifdef _YO_WEBHOST_BUILTIN
  {
    free(host->exec_root);
    host->exec_root = exec_root?Str_Copy_Npl(exec_root,-1):0;
    return host;
  }
#endif
  ;

YO_WEBHOST *Webhost_Add_Index(YO_WEBHOST *host, char *index)
#ifdef _YO_WEBHOST_BUILTIN
  {
    Array_Push(host->indexes,Str_Copy_Npl(index,-1));
    return host;
  }
#endif
  ;
  
char *Webhost_Conenttype_Of(char *path)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int code = Mime_Code_Of_Path(path,YO_MIME_OCTS);
    return Mime_String_Of(code);
  }
#endif
  ;
  
int Webhost_Is_Executable(YO_BUFFER *bf, int L, YO_ARRAY *extL)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int i;
    
    for ( i = 0; i < extL->count; ++i )
      {
        char *ext = extL->at[i];
        int j = strlen(ext);
        if ( L > j && !strncmp_I(bf->at+(L-j),ext,j) )
          {
            YO_FILE_STATS stats = {0};
            if ( File_Get_Stats(bf->at,&stats,1)->f.exists )
              {
                if ( !stats.f.is_directory )
                  return 1;
              }
            break;
          }
      }
    
    return 0;
  }
#endif
  ;
   
int Webhost_Find_Executable_1(YO_BUFFER *bf, int L, YO_ARRAY *extL)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int i;
    YO_FILE_STATS stats = {0};
    
    bf->at[L] = 0;
    
    if ( File_Get_Stats(bf->at,&stats,1)->f.exists && !stats.f.is_directory )
      return Webhost_Is_Executable(bf,L,extL);
        
    for ( i = 0; i < extL->count; ++i )
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
    
    return 0;
  }
#endif
  ;
  
char *Webhost_Find_Executable(char *execdir, char *query, char **script, char **pathinfo)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    char *fpath = 0;
    
    __Auto_Ptr(fpath)
      {
        int i, L;

        YOYO_ARRAY *extL = Str_Split(getenv("PATHEXT"),";");
        YOYO_ARRAY *patL = Str_Split(query,"/");
        YOYO_BUFFER *bf  = Buffer_Acquire(Path_Normilize_Npl(execdir));
        
        L = bf->count;
        
        for ( i = 0; i < patL->count; ++i )
          {
            if ( *(char*)patL->at[i] == 0 ) continue;
            Buffer_Grow(bf,L+1);
            bf->at[L] = YOYO_PATH_SEPARATOR;
            Buffer_Append(bf,patL->at[i],-1);
            L = bf->count;
            if ( Webhost_Find_Executable_1(bf,L,extL) )
              {
                int j;
                L = bf->count+1;
                Buffer_Fill_Append(bf,'\0',1);







|







|
|
|







|







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
    
    return 0;
  }
#endif
  ;
  
char *Webhost_Find_Executable(char *execdir, char *query, char **script, char **pathinfo)
#ifdef _YO_WEBHOST_BUILTIN
  {
    char *fpath = 0;
    
    __Auto_Ptr(fpath)
      {
        int i, L;

        YO_ARRAY *extL = Str_Split(getenv("PATHEXT"),";");
        YO_ARRAY *patL = Str_Split(query,"/");
        YO_BUFFER *bf  = Buffer_Acquire(Path_Normilize_Npl(execdir));
        
        L = bf->count;
        
        for ( i = 0; i < patL->count; ++i )
          {
            if ( *(char*)patL->at[i] == 0 ) continue;
            Buffer_Grow(bf,L+1);
            bf->at[L] = YO_PATH_SEPARATOR;
            Buffer_Append(bf,patL->at[i],-1);
            L = bf->count;
            if ( Webhost_Find_Executable_1(bf,L,extL) )
              {
                int j;
                L = bf->count+1;
                Buffer_Fill_Append(bf,'\0',1);
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
      }
      
    return fpath;    
  }
#endif
  ;
    
void Webhost_Setup_Environment(YOYO_WEBHOST *host, YOYO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YOYO_URL *url)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    __Auto_Release
      {    
        char *method = 0;
        
        putenv("GATEWAY_INTERFACE=CGI/1.1");
        putenv("SERVER_PROTOCOL=HTTP/1.1");







|
|







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
      }
      
    return fpath;    
  }
#endif
  ;
    
void Webhost_Setup_Environment(YO_WEBHOST *host, YO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YO_URL *url)
#ifdef _YO_WEBHOST_BUILTIN
  {
    __Auto_Release
      {    
        char *method = 0;
        
        putenv("GATEWAY_INTERFACE=CGI/1.1");
        putenv("SERVER_PROTOCOL=HTTP/1.1");
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
        //putenv("SERVER_NAME");
        //putenv("SERVER_PORT");
      } 
  }
#endif
  ;
  
int Webhost_CGI_Headers(YOYO_HTTPD_REQUEST *rqst, void *strm)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = HTTPD_SUCCESS;
    for (;;)
      {
        static char s_Content_Type[] = "Content-Type:";
        static char s_Content_Length[] = "Content-Length:";
        static char s_Location[] = "Location:";







|
|







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
        //putenv("SERVER_NAME");
        //putenv("SERVER_PORT");
      } 
  }
#endif
  ;
  
int Webhost_CGI_Headers(YO_HTTPD_REQUEST *rqst, void *strm)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int retcode = HTTPD_SUCCESS;
    for (;;)
      {
        static char s_Content_Type[] = "Content-Type:";
        static char s_Content_Length[] = "Content-Length:";
        static char s_Location[] = "Location:";
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
          }
      }
    return retcode;
  }
#endif
  ;
    
typedef struct _YOYO_WEBHOST_CGIST
  {
    YOYO_WEBHOST *host;
    YOYO_HTTPD_REQUEST *rqst;
    YOYO_URL *url;
    YOYO_PIPEX *pipex;
    char *path;
    char *script;
    char *pathinfo;
  } YOYO_WEBHOST_CGIST;

void YOYO_WEBHOST_CGIST_Destruct(YOYO_WEBHOST_CGIST *st)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    __Unrefe(st->host);
    __Unrefe(st->url);
    __Unrefe(st->rqst);
    __Unrefe(st->pipex);
    free(st->path);
    __Destruct(st);
  }
#endif
  ;
  
YOYO_WEBHOST_CGIST *Webhost_CGI_State(YOYO_WEBHOST *host, YOYO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YOYO_URL *url)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    YOYO_WEBHOST_CGIST *st = __Object_Dtor(sizeof(YOYO_WEBHOST_CGIST),YOYO_WEBHOST_CGIST_Destruct);
    st->host = __Refe(host);
    st->url  = __Refe(url);
    st->rqst = __Refe(rqst);
    st->path = path;
    st->script = script;
    st->pathinfo = pathinfo;
    return st;
  }
#endif
  ;
    
void Webhost_Check_CGI_Status(YOYO_WEBHOST_CGIST *st, int error)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    if ( error ) return;
    
    __Auto_Release 
      {
        __Try_Except
          {
            if (  Pipex_Exit_Code(st->pipex) == PIPEX_STILL_ACTIVE )
              {
                Tasque_Alert(0,Webhost_Check_CGI_Status,st);
              }
            else
              if ( st->pipex->exitcode == 0 )
                {
                  YOYO_HTTPD_REQUEST *rqst = st->rqst;
                  YOYO_BUFFER *bf = Buffer_Init(0);
                  YOYO_BUFFER_FILE *fbf = Buffer_As_File(bf);
                  __Unrefe(rqst->outstrm);
                  rqst->outstrm_type = Mime_String_Of_Npl(YOYO_MIME_HTML);
                  rqst->outstrm = __Refe(st->pipex->fout);
                  Oj_Seek(rqst->outstrm,0,0);
                  retcode = Webhost_CGI_Headers(rqst,rqst->outstrm);
                  rqst->outstrm_length = Oj_Available(rqst->outstrm);
                }
              else
                {







|

|
|
|
|



|

|
|











|
|

|











|
|
















|
|
|

|







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
          }
      }
    return retcode;
  }
#endif
  ;
    
typedef struct _YO_WEBHOST_CGIST
  {
    YO_WEBHOST *host;
    YO_HTTPD_REQUEST *rqst;
    YO_URL *url;
    YO_PIPEX *pipex;
    char *path;
    char *script;
    char *pathinfo;
  } YO_WEBHOST_CGIST;

void YO_WEBHOST_CGIST_Destruct(YO_WEBHOST_CGIST *st)
#ifdef _YO_WEBHOST_BUILTIN
  {
    __Unrefe(st->host);
    __Unrefe(st->url);
    __Unrefe(st->rqst);
    __Unrefe(st->pipex);
    free(st->path);
    __Destruct(st);
  }
#endif
  ;
  
YO_WEBHOST_CGIST *Webhost_CGI_State(YO_WEBHOST *host, YO_HTTPD_REQUEST *rqst, char *path, char *script, char *pathinfo, YO_URL *url)
#ifdef _YO_WEBHOST_BUILTIN
  {
    YO_WEBHOST_CGIST *st = __Object_Dtor(sizeof(YO_WEBHOST_CGIST),YO_WEBHOST_CGIST_Destruct);
    st->host = __Refe(host);
    st->url  = __Refe(url);
    st->rqst = __Refe(rqst);
    st->path = path;
    st->script = script;
    st->pathinfo = pathinfo;
    return st;
  }
#endif
  ;
    
void Webhost_Check_CGI_Status(YO_WEBHOST_CGIST *st, int error)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    if ( error ) return;
    
    __Auto_Release 
      {
        __Try_Except
          {
            if (  Pipex_Exit_Code(st->pipex) == PIPEX_STILL_ACTIVE )
              {
                Tasque_Alert(0,Webhost_Check_CGI_Status,st);
              }
            else
              if ( st->pipex->exitcode == 0 )
                {
                  YO_HTTPD_REQUEST *rqst = st->rqst;
                  YO_BUFFER *bf = Buffer_Init(0);
                  YO_BUFFER_FILE *fbf = Buffer_As_File(bf);
                  __Unrefe(rqst->outstrm);
                  rqst->outstrm_type = Mime_String_Of_Npl(YO_MIME_HTML);
                  rqst->outstrm = __Refe(st->pipex->fout);
                  Oj_Seek(rqst->outstrm,0,0);
                  retcode = Webhost_CGI_Headers(rqst,rqst->outstrm);
                  rqst->outstrm_length = Oj_Available(rqst->outstrm);
                }
              else
                {
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
        
    if ( retcode )
      Httpd_Continue_Request(st->rqst,retcode);
  }
#endif
  ;
  
int Webhost_Execute_CGI(YOYO_WEBHOST_CGIST *st)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    __Auto_Release 
      {
        char *curdir = Current_Directory();
        







|
|







407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
        
    if ( retcode )
      Httpd_Continue_Request(st->rqst,retcode);
  }
#endif
  ;
  
int Webhost_Execute_CGI(YO_WEBHOST_CGIST *st)
#ifdef _YO_WEBHOST_BUILTIN
  {
    int retcode = 0;
    
    __Auto_Release 
      {
        char *curdir = Current_Directory();
        
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
      }
      
    return retcode;
  }
#endif
  ;
    
int Webhost_Callback(void *_host, YOYO_HTTPD_REQUEST *rqst, int status)
#ifdef _YOYO_WEBHOST_BUILTIN
  {
    YOYO_WEBHOST *host = _host;
    
    if ( status == HTTPD_RQST_CONNECT )
      {
        Log_Debug("[%p] CONNECT %s:%d",rqst,rqst->remote_addr,rqst->remote_port);
        return HTTPD_ACCEPT;
      }
    else if ( status == HTTPD_RQST_POSTDTA )
      return HTTPD_ACCEPT;
    else if ( status == HTTPD_RQST_PERFORM )
      {
        YOYO_FILE_STATS stats = {0};
        YOYO_URL *url = Url_Parse_Uri(rqst->uri);
        char *path = 0;
        int rng_pos, rng_len;

        Log_Info("[%p] %s/1.%d %s",rqst,Httpd_Method_String(rqst->method),rqst->httpver,rqst->uri);
        Logout_Debug(Dicto_Format(rqst->qhdr,Buffer_Print,0,1));
        
        if ( rqst->instrm_length && Log_Level(YOYO_LOG_INFO) )
          {
            enum { MAX_L = 60 };
            int i, L = Yo_Minu(MAX_L,rqst->instrm_length);
            byte_t *b = __Zero_Malloc(MAX_L+1);
            Oj_Seek(rqst->instrm,0,0);
            Oj_Read(rqst->instrm,b,L,L);
            Oj_Seek(rqst->instrm,0,0);







|
|

|










|
|






|







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
      }
      
    return retcode;
  }
#endif
  ;
    
int Webhost_Callback(void *_host, YO_HTTPD_REQUEST *rqst, int status)
#ifdef _YO_WEBHOST_BUILTIN
  {
    YO_WEBHOST *host = _host;
    
    if ( status == HTTPD_RQST_CONNECT )
      {
        Log_Debug("[%p] CONNECT %s:%d",rqst,rqst->remote_addr,rqst->remote_port);
        return HTTPD_ACCEPT;
      }
    else if ( status == HTTPD_RQST_POSTDTA )
      return HTTPD_ACCEPT;
    else if ( status == HTTPD_RQST_PERFORM )
      {
        YO_FILE_STATS stats = {0};
        YO_URL *url = Url_Parse_Uri(rqst->uri);
        char *path = 0;
        int rng_pos, rng_len;

        Log_Info("[%p] %s/1.%d %s",rqst,Httpd_Method_String(rqst->method),rqst->httpver,rqst->uri);
        Logout_Debug(Dicto_Format(rqst->qhdr,Buffer_Print,0,1));
        
        if ( rqst->instrm_length && Log_Level(YO_LOG_INFO) )
          {
            enum { MAX_L = 60 };
            int i, L = Yo_Minu(MAX_L,rqst->instrm_length);
            byte_t *b = __Zero_Malloc(MAX_L+1);
            Oj_Seek(rqst->instrm,0,0);
            Oj_Read(rqst->instrm,b,L,L);
            Oj_Seek(rqst->instrm,0,0);
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
                        path = path1;
                        goto open_file;
                      }
                  }
                /* list directory */
                if ( !host->disable_index )
                  {
                    YOYO_BUFFER *obf = Buffer_Init(0);
                    YOYO_ARRAY *L = File_List_Directory(path,0);
                    for ( i = 0; i < L->count; ++i )
                      {
                        Buffer_Printf(obf,"<a href=\"%s%s\">%s</a><br>",url->query,L->at[i],L->at[i]);
                      }
                    rqst->outstrm = __Refe(Buffer_As_File(obf));
                    rqst->outstrm_length = obf->count;
                    rqst->outstrm_type = Mime_String_Of_Npl(YOYO_MIME_HTML);
                    return HTTPD_SUCCESS;
                  }
                return HTTPD_NOTFOUND;
              }
          open_file:  
          
            rqst->outstrm_type = Str_Copy_Npl(Webhost_Conenttype_Of(path),-1);







|
|






|







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
                        path = path1;
                        goto open_file;
                      }
                  }
                /* list directory */
                if ( !host->disable_index )
                  {
                    YO_BUFFER *obf = Buffer_Init(0);
                    YO_ARRAY *L = File_List_Directory(path,0);
                    for ( i = 0; i < L->count; ++i )
                      {
                        Buffer_Printf(obf,"<a href=\"%s%s\">%s</a><br>",url->query,L->at[i],L->at[i]);
                      }
                    rqst->outstrm = __Refe(Buffer_As_File(obf));
                    rqst->outstrm_length = obf->count;
                    rqst->outstrm_type = Mime_String_Of_Npl(YO_MIME_HTML);
                    return HTTPD_SUCCESS;
                  }
                return HTTPD_NOTFOUND;
              }
          open_file:  
          
            rqst->outstrm_type = Str_Copy_Npl(Webhost_Conenttype_Of(path),-1);
Changes to winlpc.hc.
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
#ifdef __windoze

#include "string.hc"
#include "xntdef.hc"
#include "winlpc.inc"

#ifdef _LIBYOYO
#define _YOYO_WINLPC_BUILTIN
#endif

enum 
  { 
    WINLPC_MAX_CONINFO_LENGTH = 260, 
    WINLPC_MAX_DATA_LENGTH = 328, 
  };

typedef struct _YOYO_LPCPORT
  {
    HANDLE handle;
    void  *tag;
    int    waitable;
  } YOYO_LPCPORT;

#define Lpc_Is_Connected(Port) ((Port)->handle != 0)
  
long Lpc_Create_Port(YOYO_LPCPORT *port, char *name, int waitable)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    OBJECT_ATTRIBUTES oa; 
    UNICODE_STRING us_name;
    wchar_t wname[256]; 
    
    memset(port,0,sizeof(*port));







|








|




|



|
|







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
#ifdef __windoze

#include "string.hc"
#include "xntdef.hc"
#include "winlpc.inc"

#ifdef _LIBYOYO
#define _YO_WINLPC_BUILTIN
#endif

enum 
  { 
    WINLPC_MAX_CONINFO_LENGTH = 260, 
    WINLPC_MAX_DATA_LENGTH = 328, 
  };

typedef struct _YO_LPCPORT
  {
    HANDLE handle;
    void  *tag;
    int    waitable;
  } YO_LPCPORT;

#define Lpc_Is_Connected(Port) ((Port)->handle != 0)
  
long Lpc_Create_Port(YO_LPCPORT *port, char *name, int waitable)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    OBJECT_ATTRIBUTES oa; 
    UNICODE_STRING us_name;
    wchar_t wname[256]; 
    
    memset(port,0,sizeof(*port));
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

    return ntst;
  }
#endif
  ;

long Lpc_Connect_Port(
  YOYO_LPCPORT *port, char *name, 
  LPC_SECTION_OWNER_MEMORY *clntmem, LPC_SECTION_MEMORY *servmem)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    UNICODE_STRING us_name;
    wchar_t wname[256];
    
    SECURITY_QUALITY_OF_SERVICE sqos = { 
        sizeof(SECURITY_QUALITY_OF_SERVICE), 







|

|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

    return ntst;
  }
#endif
  ;

long Lpc_Connect_Port(
  YO_LPCPORT *port, char *name, 
  LPC_SECTION_OWNER_MEMORY *clntmem, LPC_SECTION_MEMORY *servmem)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    UNICODE_STRING us_name;
    wchar_t wname[256];
    
    SECURITY_QUALITY_OF_SERVICE sqos = { 
        sizeof(SECURITY_QUALITY_OF_SERVICE), 
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    ntst = NtConnectPort(&port->handle, &us_name, &sqos, clntmem, servmem, 0, 0, 0);
    return ntst;
  }
#endif
  ;
  
long Lpc_Accept_Port_(
  YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *rpl, void *tag, int accept,
  LPC_SECTION_MEMORY *clntmem, LPC_SECTION_OWNER_MEMORY *servmem)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    memset(port,0,sizeof(*port));
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};







|

|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    ntst = NtConnectPort(&port->handle, &us_name, &sqos, clntmem, servmem, 0, 0, 0);
    return ntst;
  }
#endif
  ;
  
long Lpc_Accept_Port_(
  YO_LPCPORT *port, LPC_MESSAGE_HEADER *rpl, void *tag, int accept,
  LPC_SECTION_MEMORY *clntmem, LPC_SECTION_OWNER_MEMORY *servmem)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    memset(port,0,sizeof(*port));
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};
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
    ntst = NtCompleteConnectPort(port->handle);
    return ntst;
  }
#endif
  ;
  
long Lpc_Accept_Port(
  YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *msg, void *tag,
  LPC_SECTION_MEMORY *clntmem, LPC_SECTION_OWNER_MEMORY *servmem)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    ntst = Lpc_Accept_Port_(port,msg,tag,1,clntmem,servmem);
    port->tag = tag;
    return ntst;
  }
#endif
  ;
  
long Lpc_Refuse_Port(LPC_MESSAGE_HEADER *msg)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    YOYO_LPCPORT port;
    ntst = Lpc_Accept_Port_(&port,msg,0,0,0,0);
    if ( port.handle ) NtClose(port.handle);
    return ntst;
  }
#endif
  ;
  
long Lpc_Replay_Port(YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *rpl)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    REQUIRE( port->handle != 0 );
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};







|

|










|


|







|
|







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
    ntst = NtCompleteConnectPort(port->handle);
    return ntst;
  }
#endif
  ;
  
long Lpc_Accept_Port(
  YO_LPCPORT *port, LPC_MESSAGE_HEADER *msg, void *tag,
  LPC_SECTION_MEMORY *clntmem, LPC_SECTION_OWNER_MEMORY *servmem)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    ntst = Lpc_Accept_Port_(port,msg,tag,1,clntmem,servmem);
    port->tag = tag;
    return ntst;
  }
#endif
  ;
  
long Lpc_Refuse_Port(LPC_MESSAGE_HEADER *msg)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    YO_LPCPORT port;
    ntst = Lpc_Accept_Port_(&port,msg,0,0,0,0);
    if ( port.handle ) NtClose(port.handle);
    return ntst;
  }
#endif
  ;
  
long Lpc_Replay_Port(YO_LPCPORT *port, LPC_MESSAGE_HEADER *rpl)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    REQUIRE( port->handle != 0 );
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};
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
  #endif
      ntst = NtReplyPort(port->handle,rpl);
    return ntst;
  }
#endif
  ;
  
long Lpc_Request_Port(YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
    REQUIRE( port->handle != 0 );
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        rqst64.Hdr.DataLength  = rqst->DataLength;
        rqst64.Hdr.TotalLength = sizeof(rqst64.Hdr) + rqst->DataLength;
        memcpy(rqst64.Data,rqst+1,rqst->DataLength);
        ntst = NtRequestPort(port->handle,(void*)&rqst64);
      }
    else
  #endif
      ntst = NtRequestPort(port->handle,rqst);
    return ntst;
  }
#endif
  ;

long Lpc_Reply_Wait_Receive_Port(YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst, void *ctx)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        ntst = NtReplyWaitReceivePort(port->handle, ctx, 0, (void*)&rqst64);







|
|




















|
|







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
  #endif
      ntst = NtReplyPort(port->handle,rpl);
    return ntst;
  }
#endif
  ;
  
long Lpc_Request_Port(YO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
    REQUIRE( port->handle != 0 );
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        rqst64.Hdr.DataLength  = rqst->DataLength;
        rqst64.Hdr.TotalLength = sizeof(rqst64.Hdr) + rqst->DataLength;
        memcpy(rqst64.Data,rqst+1,rqst->DataLength);
        ntst = NtRequestPort(port->handle,(void*)&rqst64);
      }
    else
  #endif
      ntst = NtRequestPort(port->handle,rqst);
    return ntst;
  }
#endif
  ;

long Lpc_Reply_Wait_Receive_Port(YO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst, void *ctx)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        ntst = NtReplyWaitReceivePort(port->handle, ctx, 0, (void*)&rqst64);
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
  #endif
      ntst = NtReplyWaitReceivePort(port->handle, ctx, 0, rqst);
    return ntst;
  }
#endif
  ;
  
long Lpc_Wait_Port(YOYO_LPCPORT *port, unsigned ms)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    if ( port->waitable )
      {
        long st;
        st = WaitForSingleObject(port->handle, ms);
        return st;
      }
    else
      return 0;
  }
#endif
  ;
  
long Lpc_Request_Wait_Reply_Port(YOYO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst, LPC_MESSAGE_HEADER *rpl)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    long ntst;
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};







|
|













|
|







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
  #endif
      ntst = NtReplyWaitReceivePort(port->handle, ctx, 0, rqst);
    return ntst;
  }
#endif
  ;
  
long Lpc_Wait_Port(YO_LPCPORT *port, unsigned ms)
#ifdef _YO_WINLPC_BUILTIN
  {
    if ( port->waitable )
      {
        long st;
        st = WaitForSingleObject(port->handle, ms);
        return st;
      }
    else
      return 0;
  }
#endif
  ;
  
long Lpc_Request_Wait_Reply_Port(YO_LPCPORT *port, LPC_MESSAGE_HEADER *rqst, LPC_MESSAGE_HEADER *rpl)
#ifdef _YO_WINLPC_BUILTIN
  {
    long ntst;
  #ifndef __x86_64
    if ( Is_WOW64() )
      {
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rqst64 = {0};
        struct { LPC_MESSAGE_HEADER64 Hdr; byte_t Data[WINLPC_MAX_DATA_LENGTH]; } rpl64  = {0};
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  #endif
      ntst = NtRequestWaitReplyPort(port->handle, rqst, rpl);
    return ntst;
  }
#endif
  ;

void Lpc_Close_Port(YOYO_LPCPORT *port)
#ifdef _YOYO_WINLPC_BUILTIN
  {
    if ( port && port->handle )
      {
        NtClose(port->handle);
        port->handle = 0;
      }
  }







|
|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  #endif
      ntst = NtRequestWaitReplyPort(port->handle, rqst, rpl);
    return ntst;
  }
#endif
  ;

void Lpc_Close_Port(YO_LPCPORT *port)
#ifdef _YO_WINLPC_BUILTIN
  {
    if ( port && port->handle )
      {
        NtClose(port->handle);
        port->handle = 0;
      }
  }
Changes to winreg.hc.
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

*/

#ifndef C_once_C5685DBF_3A67_41C0_895B_A26B0D757AE7
#define C_once_C5685DBF_3A67_41C0_895B_A26B0D757AE7

#ifdef _LIBYOYO
#define _YOYO_WINREG_BUILTIN
#endif

#include "yoyo.hc"

#ifdef __windoze
#include "string.hc"
#include "buffer.hc"
#include "file.hc"

typedef struct _YOYO_WINREG
  {
    HKEY hkey;
    char *name;
  } YOYO_WINREG;

void WinReg_Close(YOYO_WINREG *o)
#ifdef _YOYO_WINREG_BUILTIN
  {
    if ( o->hkey )
      RegCloseKey(o->hkey);
    o->hkey = 0;
  }
#endif
  ;

void WinReg_Destruct(YOYO_WINREG *o)
#ifdef _YOYO_WINREG_BUILTIN
  {
    WinReg_Close(o);
    free(o->name);
    Yo_Object_Destruct(o);
  }
#endif
  ;

char *WinReg_Query_String(YOYO_WINREG *o,char *opt)
#ifdef _YOYO_WINREG_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        wchar_t *buf = 0;
        DWORD ltype = REG_SZ;
        long err = 0;
        DWORD L = 0;

        if ( ERROR_SUCCESS != (err=RegQueryValueExW(o->hkey,name,0,&ltype,0,&L)) )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));

        if ( ltype != REG_SZ )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': is not string value",(opt?opt:""),o->name));

        //buf = Yo_Malloc((L+1)*sizeof(wchar_t));
        buf = Yo_Malloc(L+2);
        buf[L/sizeof(wchar_t)] = 0;
        
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,(LPBYTE)buf,&L)) )
          ret = Str_Unicode_To_Utf8(buf);
        else
          if ( err != ERROR_FILE_NOT_FOUND )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_String(YOYO_WINREG *o,char *opt,char *val)
#ifdef _YOYO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        wchar_t *str  = val?Str_Utf8_To_Unicode(val):L"";
        DWORD ltype = REG_SZ;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,(LPBYTE)str,(Str_Length(val)+1)*sizeof(wchar_t))) )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

ulong_t WinReg_Query_Dword(YOYO_WINREG *o,char *opt)
#ifdef _YOYO_WINREG_BUILTIN
  {
    ulong_t ret = 0;
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD buf = 0;
        DWORD ltype = REG_DWORD;
        long err = 0;
        DWORD L = 4;
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,(LPBYTE)&buf,&L)) )
          ret = buf;
        else
          if ( err != ERROR_FILE_NOT_FOUND )
            __Raise(YOYO_ERROR_IO,
              __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_Dword(YOYO_WINREG *o,char *opt,ulong_t val)
#ifdef _YOYO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD ltype = REG_DWORD;
        DWORD buf = val;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,(LPBYTE)&buf,4)) )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

YOYO_BUFFER *WinReg_Query_Binary(YOYO_WINREG *o,char *opt)
#ifdef _YOYO_WINREG_BUILTIN
  {
    void *ret = 0;
    __Auto_Ptr(ret)
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        YOYO_BUFFER *bf;
        DWORD ltype = REG_SZ;
        long err = 0;
        DWORD L = 0;
        RegQueryValueExW(o->hkey,name,0,&ltype,0,&L);
        bf = Buffer_Init(L);
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,bf->at,&L)) )
          ret = bf;
        else
          if ( err != ERROR_FILE_NOT_FOUND )
            __Raise(YOYO_ERROR_IO,
              __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_Binary(YOYO_WINREG *o,char *opt,void *val, int val_len)
#ifdef _YOYO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD ltype = REG_BINARY;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,val,val_len)) )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

void WinReg_Delete_Value(YOYO_WINREG *o,char *opt)
#ifdef _YOYO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        int err;
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        if ( ERROR_SUCCESS != (err=RegDeleteValueW(o->hkey,name)) )
          __Raise(YOYO_ERROR_IO,
            __Format("failed to delete value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

YOYO_WINREG *WinReg_Object_Init()
#ifdef _YOYO_WINREG_BUILTIN
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,  WinReg_Destruct},
        {Oj_Close_OjMID,     WinReg_Close},
        {0}};
    return __Object(sizeof(YOYO_WINREG),funcs);
  }
#endif
  ;
  
void *WinReg_Open_Or_Create_Hkey(HKEY master, char *subkey, int create_if_need, char *parent_name)
#ifdef _YOYO_WINREG_BUILTIN
  {
    YOYO_WINREG *ret = 0;
    __Auto_Ptr(ret)
      {
        int err;
        wchar_t *name;
        
        ret = WinReg_Object_Init();
        name = Str_Utf8_To_Unicode(subkey);
        if ( parent_name )
          ret->name = Str_Join_Npl_2('\\',parent_name,subkey);
        else
          ret->name = Str_Concat_Npl(Yo_Format("%08x\\",master),subkey);
        
        if ( create_if_need )
          {
            if ( ERROR_SUCCESS != (err = RegCreateKeyExW(master,name,0,0,0,KEY_ALL_ACCESS,0,&ret->hkey,0)) )
              __Raise(YOYO_ERROR_IO,
                __Format("failed to create winreg key '%s': error %08x",ret->name,err));
          }
        else
          {
            if ( ERROR_SUCCESS != (err = RegOpenKeyExW(master,name,0,KEY_ALL_ACCESS,&ret->hkey)) )
              __Raise(YOYO_ERROR_IO,
                __Format("failed to open winreg key '%s': error %08x",ret->name,err));
          }
      }
    return ret;
  }
#endif
  ;

void *WinReg_Open_Or_Create_Hkey_Obj(YOYO_WINREG *obj, char *subkey, int create_if_need)
#ifdef _YOYO_WINREG_BUILTIN
  {
    return WinReg_Open_Or_Create_Hkey(obj->hkey,subkey,create_if_need,obj->name);
  }
#endif
  ;

void *WinReg_Open_Or_Create(char *subkey, int create_if_need)
#ifdef _YOYO_WINREG_BUILTIN
  {
    int i;
    HKEY master = 0;
    char *name = 0;
    char *parent = 0;
    static char *str_vars[3] =
        {"\\CURRENT_USER\\","\\LOCAL_MACHINE\\","\\CLASSES_ROOT\\"};
    static HKEY hkey_vars[3] =
        {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT};
    for ( i = 0; i < 3; ++i )
      if ( Str_Starts_With(subkey,str_vars[i]) )
        {
          name = subkey+strlen(str_vars[i]);
          master = hkey_vars[i];
          parent = str_vars[i];
          break;
        }

    if ( !master )
      __Raise(YOYO_ERROR_DOESNT_EXIST,
        __Format("registry key '%s' doesn't exist",subkey));
    
    return WinReg_Open_Or_Create_Hkey(master,name,create_if_need,parent);
  }
#endif
  ;

YOYO_WINREG *WinReg_Assign(HKEY key, char *name)
#ifdef _YOYO_WINREG_BUILTIN
  {
    YOYO_WINREG *rkey = WinReg_Object_Init();
    rkey->hkey = key;
    rkey->name = Str_Copy_Npl(name,-1);
    return rkey;
  }
#endif
  ;








|









|



|

|
|








|
|








|
|











|



|










|







|
|








|






|
|













|







|
|








|






|
|





|









|







|
|







|






|
|






|






|
|

|




|





|

|















|





|








|
|







|



















|







|
|

|







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

*/

#ifndef C_once_C5685DBF_3A67_41C0_895B_A26B0D757AE7
#define C_once_C5685DBF_3A67_41C0_895B_A26B0D757AE7

#ifdef _LIBYOYO
#define _YO_WINREG_BUILTIN
#endif

#include "yoyo.hc"

#ifdef __windoze
#include "string.hc"
#include "buffer.hc"
#include "file.hc"

typedef struct _YO_WINREG
  {
    HKEY hkey;
    char *name;
  } YO_WINREG;

void WinReg_Close(YO_WINREG *o)
#ifdef _YO_WINREG_BUILTIN
  {
    if ( o->hkey )
      RegCloseKey(o->hkey);
    o->hkey = 0;
  }
#endif
  ;

void WinReg_Destruct(YO_WINREG *o)
#ifdef _YO_WINREG_BUILTIN
  {
    WinReg_Close(o);
    free(o->name);
    Yo_Object_Destruct(o);
  }
#endif
  ;

char *WinReg_Query_String(YO_WINREG *o,char *opt)
#ifdef _YO_WINREG_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        wchar_t *buf = 0;
        DWORD ltype = REG_SZ;
        long err = 0;
        DWORD L = 0;

        if ( ERROR_SUCCESS != (err=RegQueryValueExW(o->hkey,name,0,&ltype,0,&L)) )
          __Raise(YO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));

        if ( ltype != REG_SZ )
          __Raise(YO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': is not string value",(opt?opt:""),o->name));

        //buf = Yo_Malloc((L+1)*sizeof(wchar_t));
        buf = Yo_Malloc(L+2);
        buf[L/sizeof(wchar_t)] = 0;
        
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,(LPBYTE)buf,&L)) )
          ret = Str_Unicode_To_Utf8(buf);
        else
          if ( err != ERROR_FILE_NOT_FOUND )
          __Raise(YO_ERROR_IO,
            __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_String(YO_WINREG *o,char *opt,char *val)
#ifdef _YO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        wchar_t *str  = val?Str_Utf8_To_Unicode(val):L"";
        DWORD ltype = REG_SZ;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,(LPBYTE)str,(Str_Length(val)+1)*sizeof(wchar_t))) )
          __Raise(YO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

ulong_t WinReg_Query_Dword(YO_WINREG *o,char *opt)
#ifdef _YO_WINREG_BUILTIN
  {
    ulong_t ret = 0;
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD buf = 0;
        DWORD ltype = REG_DWORD;
        long err = 0;
        DWORD L = 4;
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,(LPBYTE)&buf,&L)) )
          ret = buf;
        else
          if ( err != ERROR_FILE_NOT_FOUND )
            __Raise(YO_ERROR_IO,
              __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_Dword(YO_WINREG *o,char *opt,ulong_t val)
#ifdef _YO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD ltype = REG_DWORD;
        DWORD buf = val;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,(LPBYTE)&buf,4)) )
          __Raise(YO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

YO_BUFFER *WinReg_Query_Binary(YO_WINREG *o,char *opt)
#ifdef _YO_WINREG_BUILTIN
  {
    void *ret = 0;
    __Auto_Ptr(ret)
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        YO_BUFFER *bf;
        DWORD ltype = REG_SZ;
        long err = 0;
        DWORD L = 0;
        RegQueryValueExW(o->hkey,name,0,&ltype,0,&L);
        bf = Buffer_Init(L);
        if ( ERROR_SUCCESS == (err=RegQueryValueExW(o->hkey,name,0,&ltype,bf->at,&L)) )
          ret = bf;
        else
          if ( err != ERROR_FILE_NOT_FOUND )
            __Raise(YO_ERROR_IO,
              __Format("failed to query value '%s' of '%s': error %08x", (opt?opt:""),o->name,err));
      }
    return ret;
  }
#endif
  ;

void WinReg_Set_Binary(YO_WINREG *o,char *opt,void *val, int val_len)
#ifdef _YO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        DWORD ltype = REG_BINARY;
        long err = 0;
        if ( ERROR_SUCCESS != (err=RegSetValueExW(o->hkey,name,0,ltype,val,val_len)) )
          __Raise(YO_ERROR_IO,
            __Format("failed to set value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

void WinReg_Delete_Value(YO_WINREG *o,char *opt)
#ifdef _YO_WINREG_BUILTIN
  {
    __Auto_Release
      {
        int err;
        wchar_t *name = opt?Str_Utf8_To_Unicode(opt):L"";
        if ( ERROR_SUCCESS != (err=RegDeleteValueW(o->hkey,name)) )
          __Raise(YO_ERROR_IO,
            __Format("failed to delete value '%s' of '%s': error %08x",(opt?opt:""),o->name,err));
      }
  }
#endif
  ;

YO_WINREG *WinReg_Object_Init()
#ifdef _YO_WINREG_BUILTIN
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,  WinReg_Destruct},
        {Oj_Close_OjMID,     WinReg_Close},
        {0}};
    return __Object(sizeof(YO_WINREG),funcs);
  }
#endif
  ;
  
void *WinReg_Open_Or_Create_Hkey(HKEY master, char *subkey, int create_if_need, char *parent_name)
#ifdef _YO_WINREG_BUILTIN
  {
    YO_WINREG *ret = 0;
    __Auto_Ptr(ret)
      {
        int err;
        wchar_t *name;
        
        ret = WinReg_Object_Init();
        name = Str_Utf8_To_Unicode(subkey);
        if ( parent_name )
          ret->name = Str_Join_Npl_2('\\',parent_name,subkey);
        else
          ret->name = Str_Concat_Npl(Yo_Format("%08x\\",master),subkey);
        
        if ( create_if_need )
          {
            if ( ERROR_SUCCESS != (err = RegCreateKeyExW(master,name,0,0,0,KEY_ALL_ACCESS,0,&ret->hkey,0)) )
              __Raise(YO_ERROR_IO,
                __Format("failed to create winreg key '%s': error %08x",ret->name,err));
          }
        else
          {
            if ( ERROR_SUCCESS != (err = RegOpenKeyExW(master,name,0,KEY_ALL_ACCESS,&ret->hkey)) )
              __Raise(YO_ERROR_IO,
                __Format("failed to open winreg key '%s': error %08x",ret->name,err));
          }
      }
    return ret;
  }
#endif
  ;

void *WinReg_Open_Or_Create_Hkey_Obj(YO_WINREG *obj, char *subkey, int create_if_need)
#ifdef _YO_WINREG_BUILTIN
  {
    return WinReg_Open_Or_Create_Hkey(obj->hkey,subkey,create_if_need,obj->name);
  }
#endif
  ;

void *WinReg_Open_Or_Create(char *subkey, int create_if_need)
#ifdef _YO_WINREG_BUILTIN
  {
    int i;
    HKEY master = 0;
    char *name = 0;
    char *parent = 0;
    static char *str_vars[3] =
        {"\\CURRENT_USER\\","\\LOCAL_MACHINE\\","\\CLASSES_ROOT\\"};
    static HKEY hkey_vars[3] =
        {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT};
    for ( i = 0; i < 3; ++i )
      if ( Str_Starts_With(subkey,str_vars[i]) )
        {
          name = subkey+strlen(str_vars[i]);
          master = hkey_vars[i];
          parent = str_vars[i];
          break;
        }

    if ( !master )
      __Raise(YO_ERROR_DOESNT_EXIST,
        __Format("registry key '%s' doesn't exist",subkey));
    
    return WinReg_Open_Or_Create_Hkey(master,name,create_if_need,parent);
  }
#endif
  ;

YO_WINREG *WinReg_Assign(HKEY key, char *name)
#ifdef _YO_WINREG_BUILTIN
  {
    YO_WINREG *rkey = WinReg_Object_Init();
    rkey->hkey = key;
    rkey->name = Str_Copy_Npl(name,-1);
    return rkey;
  }
#endif
  ;

Changes to x86dis.hc.
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

*/

#ifndef C_once_EC2E6B0C_F482_4C6B_8955_074DA127943C
#define C_once_EC2E6B0C_F482_4C6B_8955_074DA127943C

#ifdef _LIBYOYO
#define _YOYO_X86DIS_BUILTIN
#endif

#include "yoyo.hc"

typedef struct _YOYO_X86_INST
  {
    byte_t const *op;
    int rOffs_offset;
    int rOffs_size;
    int rOffs_rel;
    int rOffs_seg;
    int op_length;
    int is_rjc   :1;
    int is_rcall :1;
    int is_rjmp  :1;
  } YOYO_X86_INST;

#ifdef _YOYO_X86DIS_BUILTIN
enum
  {
    X86DIS_HAS_MODRM   = 0x010,
    X86DIS_JMP_REL1    = 0x020,
    X86DIS_JMP_REL4    = 0x040,
    X86DIS_JMP_ADDR6   = 0x080,
    // -1 invalid







|




|










|

|







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

*/

#ifndef C_once_EC2E6B0C_F482_4C6B_8955_074DA127943C
#define C_once_EC2E6B0C_F482_4C6B_8955_074DA127943C

#ifdef _LIBYOYO
#define _YO_X86DIS_BUILTIN
#endif

#include "yoyo.hc"

typedef struct _YO_X86_INST
  {
    byte_t const *op;
    int rOffs_offset;
    int rOffs_size;
    int rOffs_rel;
    int rOffs_seg;
    int op_length;
    int is_rjc   :1;
    int is_rcall :1;
    int is_rjmp  :1;
  } YO_X86_INST;

#ifdef _YO_X86DIS_BUILTIN
enum
  {
    X86DIS_HAS_MODRM   = 0x010,
    X86DIS_JMP_REL1    = 0x020,
    X86DIS_JMP_REL4    = 0x040,
    X86DIS_JMP_ADDR6   = 0x080,
    // -1 invalid
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

    // 0F F8
    /*xMMX*/ X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,-1,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,
  };

#endif

int X86_Inst_Length(void *inst_ptr,YOYO_X86_INST *out_info)
#ifdef _YOYO_X86DIS_BUILTIN
  {
    short code_info;
    int o_16 = 0, a_16 = 0;
    byte_t *op = inst_ptr;
    YOYO_X86_INST info;
    memset(&info,0,sizeof(info));

    code_info = X86dis_Opcodes_Info[*op];
    info.op_length = 1;

  loop:
    if ( code_info < 0 )







|
|




|







354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

    // 0F F8
    /*xMMX*/ X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,-1,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,X86DIS_HAS_MODRM,
  };

#endif

int X86_Inst_Length(void *inst_ptr,YO_X86_INST *out_info)
#ifdef _YO_X86DIS_BUILTIN
  {
    short code_info;
    int o_16 = 0, a_16 = 0;
    byte_t *op = inst_ptr;
    YO_X86_INST info;
    memset(&info,0,sizeof(info));

    code_info = X86dis_Opcodes_Info[*op];
    info.op_length = 1;

  loop:
    if ( code_info < 0 )
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
    if ( out_info ) *out_info = info;
    return info.op_length;
  }
#endif
  ;
  
int X86_Steal_Five_Bytes(byte_t *code, byte_t *f)
#ifdef _YOYO_X86DIS_BUILTIN
  {
    int orign_len = 0;

    while ( orign_len < 5 )
      {
        YOYO_X86_INST ifn;
        int l = X86_Inst_Length(f+orign_len,&ifn);
        if ( l == 0 ) return 0; // oops, is there unknown instruction ?

        if ( ifn.is_rjmp && ifn.rOffs_size == 1 && !orign_len)
          f += ifn.rOffs_rel;
        else
          {







|





|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
    if ( out_info ) *out_info = info;
    return info.op_length;
  }
#endif
  ;
  
int X86_Steal_Five_Bytes(byte_t *code, byte_t *f)
#ifdef _YO_X86DIS_BUILTIN
  {
    int orign_len = 0;

    while ( orign_len < 5 )
      {
        YO_X86_INST ifn;
        int l = X86_Inst_Length(f+orign_len,&ifn);
        if ( l == 0 ) return 0; // oops, is there unknown instruction ?

        if ( ifn.is_rjmp && ifn.rOffs_size == 1 && !orign_len)
          f += ifn.rOffs_rel;
        else
          {
Changes to xdata.hc.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

*/

#ifndef C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95
#define C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95

#ifdef _LIBYOYO
#define _YOYO_XDATA_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "dicto.hc"

#define XNODE_MAX_NAME_INDEX_PTR  ((char*)0x07fff)







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

*/

#ifndef C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95
#define C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95

#ifdef _LIBYOYO
#define _YO_XDATA_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "dicto.hc"

#define XNODE_MAX_NAME_INDEX_PTR  ((char*)0x07fff)
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
    XVALUE_OPT_VALTYPE_FLT_ARR  = 0x08008,
    XVALUE_OPT_VALTYPE_REFNODE  = 0x08009,
    XVALUE_OPT_VALTYPE_MASK     = 0x0800f,
    XVALUE_OPT_IS_VALUE         = 0x08000,
    XVALUE_DOWN_REFNODE         = 0x0ffff,
  };

struct _YOYO_XNODE;
struct _YOYO_XDATA;
struct _YOYO_XVALUE_BINARY;

typedef struct _YOYO_XNODE
  {
    ushort_t tag;
    ushort_t opt;
    ushort_t next;
    ushort_t down; 
    union       
      {
        char   *txt;
        double  flt;
        long    dec;
        byte_t  bval;
        YOYO_BUFFER *binary;
        YOYO_ARRAY  *strarr;
        struct _YOYO_XDATA *xdata;
        struct _YOYO_XNODE *refval;
        char   holder[Yo_MAX(sizeof(double),sizeof(void*))];
      };
  } YOYO_XNODE;

typedef YOYO_XNODE YOYO_XVALUE;

typedef struct _YOYO_XDATA
  {
    struct _YOYO_XNODE root;    
    struct _YOYO_XNODE *nodes[XNODE_NUMBER_OF_NODE_LISTS];
    char **tags;
    YOYO_DICTO *dicto;
    ushort_t last_tag;
    ushort_t last_node;
  } YOYO_XDATA;

void *YOYO_XDATA_RAISE_DOESNT_EXIST 
#ifdef _YOYO_XDATA_BUILTIN
  = (void*)-1
#endif
  ;

#define Number_Of_Nodes_In_List(No) (1<<(5+(No)))

void Xvalue_Purge(YOYO_XVALUE *val)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t tp = val->opt & XVALUE_OPT_VALTYPE_MASK;
    
    switch ( tp )
      {
        case XVALUE_OPT_VALTYPE_STR:
          free(val->txt);
          break;
        case XVALUE_OPT_VALTYPE_BIN:
          free(val->binary);
          break;
        case XVALUE_OPT_VALTYPE_NONE:
        case XVALUE_OPT_VALTYPE_INT:
        case XVALUE_OPT_VALTYPE_FLT:
        case XVALUE_OPT_VALTYPE_LIT:
          break;
        default:
          __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
      }
      
    val->opt = XVALUE_OPT_VALTYPE_NONE;
    val->down = 0;
    memset(val->holder,0,sizeof(val->holder));
  }
#endif
  ;
  
char *Xvalue_Copy_Str(YOYO_XVALUE *val, char *dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return Str_From_Int(val->dec);
          case XVALUE_OPT_VALTYPE_FLT:          
            return Str_From_Flt(val->flt);
          case XVALUE_OPT_VALTYPE_STR:
            return Str_Copy(val->txt);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_Copy((char*)&val->down);
          case XVALUE_OPT_VALTYPE_NONE:
            return Str_Copy("");
          case XVALUE_OPT_VALTYPE_BOOL:
            return Str_From_Bool(val->bval);
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval?Str_Copy(dfltval):0;
  }
#endif
  ;
  
char *Xvalue_Get_Str(YOYO_XVALUE *val, char *dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_STR:
            return ( val->txt[0] ) ? val->txt : dfltval;
          case XVALUE_OPT_VALTYPE_LIT:
            return (char*)&val->down;
          case XVALUE_OPT_VALTYPE_NONE:
            return "";
          case XVALUE_OPT_VALTYPE_BOOL:
            if ( val->bval )
              return "yes";
            else
              return "no";
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;

YOYO_BUFFER *Xvalue_Get_Binary(YOYO_XVALUE *val)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_BIN:
            return val->binary;
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return 0;
  }
#endif
  ;

long Xvalue_Get_Int(YOYO_XVALUE *val, long dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return val->dec;
          case XVALUE_OPT_VALTYPE_FLT:          
            return (long)val->flt;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Int_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Int_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          case XVALUE_OPT_VALTYPE_BOOL:
            return val->bval;
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
double Xvalue_Get_Flt(YOYO_XVALUE *val, double dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return (double)val->dec;
          case XVALUE_OPT_VALTYPE_FLT:          
            return val->flt;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Flt_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Flt_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
int Xvalue_Get_Bool(YOYO_XVALUE *val, int dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return val->dec?1:0;
          case XVALUE_OPT_VALTYPE_BOOL:
            return val->bval;
          case XVALUE_OPT_VALTYPE_FLT:          
            return val->flt?1:0;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Bool_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Bool_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          default:
            __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
void Xvalue_Set_Str(YOYO_XVALUE *val, char *S, int L)
#ifdef _YOYO_XDATA_BUILTIN
  {
    Xvalue_Purge(val);
    if ( L < 0 ) L = S?strlen(S):0;
    if ( L >= sizeof(val->down)+sizeof(val->holder) )
      {
        val->txt = Str_Copy_Npl(S,L);
        val->opt = XVALUE_OPT_VALTYPE_STR;
      }
    else
      {
        if (L) memcpy((char*)&val->down,S,L);
        /* already filled by 0 in Xvalue_Purge //((char*)&val->down)[L] = 0; */
        val->opt = XVALUE_OPT_VALTYPE_LIT;
      }
  }
#endif
  ;
  
void Xvalue_Put_Str(YOYO_XVALUE *val, __Acquire char *S)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    //STRICT_REQUIRE( S != 0 );
    Xvalue_Purge(val);
    val->txt = S?S:Str_Copy_Npl("",0);
    val->opt = XVALUE_OPT_VALTYPE_STR;
  }
#endif
  ;
  
void Xvalue_Set_Or_Put_Str(YOYO_XVALUE *val, char *S)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int L = S?strlen(S):0;
    if ( L >= sizeof(val->down)+sizeof(val->holder) )
      Xvalue_Put_Str(val,__Retain(S));
    else
      {
        Xvalue_Purge(val);
        if (L) memcpy((char*)&val->down,S,L);
        /* already filled by 0 in Xvalue_Purge //((char*)&val->down)[L] = 0; */
        val->opt = XVALUE_OPT_VALTYPE_LIT;
      }
  }
#endif
  ;
  
void Xvalue_Put_Binary(YOYO_XVALUE *val, __Acquire YOYO_BUFFER *bf)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    STRICT_REQUIRE( bf != 0 );
    Xvalue_Purge(val);
    val->binary = bf;
    val->opt = XVALUE_OPT_VALTYPE_BIN;
  }
#endif
  ;

void Xvalue_Set_Binary(YOYO_XVALUE *val, void *S, int L)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_BUFFER *bf = Buffer_Copy(S,L);
    Xvalue_Put_Binary(val,bf);
  }
#endif
  ;

void Xvalue_Put_Flt_Array(YOYO_XVALUE *val, __Acquire YOYO_BUFFER *bf)
#ifdef _YOYO_XDATA_BUILTIN
  {
    Xvalue_Put_Binary(val,bf);
    val->opt = XVALUE_OPT_VALTYPE_FLT_ARR;
  }
#endif
  ;

void Xvalue_Put_Str_Array(YOYO_XVALUE *val, __Acquire YOYO_ARRAY *arr)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    STRICT_REQUIRE( arr != 0 );
    Xvalue_Purge(val);
    val->strarr = arr;
    val->opt = XVALUE_OPT_VALTYPE_STR_ARR;
  }
#endif
  ;

void Xvalue_Set_Int(YOYO_XVALUE *val, long i)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->dec = i;
    val->opt = XVALUE_OPT_VALTYPE_INT;
  }
#endif
  ;

void Xvalue_Set_Flt(YOYO_XVALUE *val, double d)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->flt = d;
    val->opt = XVALUE_OPT_VALTYPE_FLT;
  }
#endif
  ;

void Xvalue_Set_Bool(YOYO_XVALUE *val, int b)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->bval = b?1:0;
    val->opt = XVALUE_OPT_VALTYPE_BOOL;
  }
#endif
  ;

int Xdata_Idxref_No(YOYO_XDATA *doc, ushort_t idx, int *no)
#ifdef _YOYO_XDATA_BUILTIN
  {
    --idx;
    
    if ( idx >= 32 )
      {
        int ref = Bitcount_Of(idx);
        *no  = idx - (1<<(ref-1)); //((1<<ref)-(1<<(ref-1)));
        STRICT_REQUIRE(ref >= 5);
        STRICT_REQUIRE(ref < XNODE_NUMBER_OF_NODE_LISTS+5);
        return ref-5;
      }
    else
      {
        *no = idx;
        return 0;
      }
  }
#endif
  ;

void *Xdata_Idxref(YOYO_XDATA *doc, ushort_t idx)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( doc );
    STRICT_REQUIRE( idx );
    __Gogo
      {
        YOYO_XNODE *n;
        int no;
        int ref = Xdata_Idxref_No(doc,idx,&no);
        n = doc->nodes[ref]+no;
        return n;
      }
  }
#endif
  ;

void YOYO_XDATA_Destruct(YOYO_XDATA *self)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int i,j;
    
    for ( i = 0; i < XNODE_NUMBER_OF_NODE_LISTS; ++i )
      if ( self->nodes[i] )
        {
          for ( j = 0; j < Number_Of_Nodes_In_List(i); ++j )
            {
              YOYO_XNODE *r = self->nodes[i]+j;
              if ( !(r->opt&XVALUE_OPT_IS_VALUE) && r->down == XVALUE_DOWN_REFNODE )
                {
                  YOYO_XNODE *ref = Xdata_Idxref(r->xdata,r->opt);
                  STRICT_REQUIRE(ref->opt ==  XVALUE_OPT_VALTYPE_REFNODE);
                  r->down = 0;
                  __Unrefe(ref->refval);
                }
              else if (((r->opt&XVALUE_OPT_VALTYPE_MASK) == XVALUE_OPT_VALTYPE_STR
                  || (r->opt&XVALUE_OPT_VALTYPE_MASK) == XVALUE_OPT_VALTYPE_BIN ))
                Xvalue_Purge(r);
            }
          free(self->nodes[i]);
        }
    free(self->tags);
    __Unrefe(self->dicto);
    __Destruct(self);
  }
#endif
  ;

YOYO_XDATA *Xnode_Get_Xdata(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( node->opt&XVALUE_OPT_IS_VALUE )
      __Raise(YOYO_ERROR_INVALID_PARAM,0);
    return node->xdata;
  }
#endif
  ;

#define Xnode_Resolve_Name(Node,Name,Cine) Xdata_Resolve_Node(Node->xdata,tag,Cine)
char *Xdata_Resolve_Name(YOYO_XDATA *doc, char *tag, int create_if_doesnt_exist)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( tag && tag > XNODE_MAX_NAME_INDEX_PTR )
      {
        char *q;
        q = Dicto_Get(doc->dicto,tag,0);
        if ( q )
          ;







|
|
|

|











|
|
|
|


|

|

|

|
|

|


|

|
|






|
|

















|









|
|

















|






|
|
















|






|
|







|






|
|

















|






|
|















|






|
|

















|






|
|


















|
|










|
|















|
|










|
|

|





|
|







|
|










|
|









|
|









|
|









|
|




















|
|





|









|
|








|


|

















|
|


|






|
|







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
    XVALUE_OPT_VALTYPE_FLT_ARR  = 0x08008,
    XVALUE_OPT_VALTYPE_REFNODE  = 0x08009,
    XVALUE_OPT_VALTYPE_MASK     = 0x0800f,
    XVALUE_OPT_IS_VALUE         = 0x08000,
    XVALUE_DOWN_REFNODE         = 0x0ffff,
  };

struct _YO_XNODE;
struct _YO_XDATA;
struct _YO_XVALUE_BINARY;

typedef struct _YO_XNODE
  {
    ushort_t tag;
    ushort_t opt;
    ushort_t next;
    ushort_t down; 
    union       
      {
        char   *txt;
        double  flt;
        long    dec;
        byte_t  bval;
        YO_BUFFER *binary;
        YO_ARRAY  *strarr;
        struct _YO_XDATA *xdata;
        struct _YO_XNODE *refval;
        char   holder[Yo_MAX(sizeof(double),sizeof(void*))];
      };
  } YO_XNODE;

typedef YO_XNODE YO_XVALUE;

typedef struct _YO_XDATA
  {
    struct _YO_XNODE root;    
    struct _YO_XNODE *nodes[XNODE_NUMBER_OF_NODE_LISTS];
    char **tags;
    YO_DICTO *dicto;
    ushort_t last_tag;
    ushort_t last_node;
  } YO_XDATA;

void *YO_XDATA_RAISE_DOESNT_EXIST 
#ifdef _YO_XDATA_BUILTIN
  = (void*)-1
#endif
  ;

#define Number_Of_Nodes_In_List(No) (1<<(5+(No)))

void Xvalue_Purge(YO_XVALUE *val)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t tp = val->opt & XVALUE_OPT_VALTYPE_MASK;
    
    switch ( tp )
      {
        case XVALUE_OPT_VALTYPE_STR:
          free(val->txt);
          break;
        case XVALUE_OPT_VALTYPE_BIN:
          free(val->binary);
          break;
        case XVALUE_OPT_VALTYPE_NONE:
        case XVALUE_OPT_VALTYPE_INT:
        case XVALUE_OPT_VALTYPE_FLT:
        case XVALUE_OPT_VALTYPE_LIT:
          break;
        default:
          __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
      }
      
    val->opt = XVALUE_OPT_VALTYPE_NONE;
    val->down = 0;
    memset(val->holder,0,sizeof(val->holder));
  }
#endif
  ;
  
char *Xvalue_Copy_Str(YO_XVALUE *val, char *dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return Str_From_Int(val->dec);
          case XVALUE_OPT_VALTYPE_FLT:          
            return Str_From_Flt(val->flt);
          case XVALUE_OPT_VALTYPE_STR:
            return Str_Copy(val->txt);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_Copy((char*)&val->down);
          case XVALUE_OPT_VALTYPE_NONE:
            return Str_Copy("");
          case XVALUE_OPT_VALTYPE_BOOL:
            return Str_From_Bool(val->bval);
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval?Str_Copy(dfltval):0;
  }
#endif
  ;
  
char *Xvalue_Get_Str(YO_XVALUE *val, char *dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_STR:
            return ( val->txt[0] ) ? val->txt : dfltval;
          case XVALUE_OPT_VALTYPE_LIT:
            return (char*)&val->down;
          case XVALUE_OPT_VALTYPE_NONE:
            return "";
          case XVALUE_OPT_VALTYPE_BOOL:
            if ( val->bval )
              return "yes";
            else
              return "no";
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;

YO_BUFFER *Xvalue_Get_Binary(YO_XVALUE *val)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_BIN:
            return val->binary;
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return 0;
  }
#endif
  ;

long Xvalue_Get_Int(YO_XVALUE *val, long dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return val->dec;
          case XVALUE_OPT_VALTYPE_FLT:          
            return (long)val->flt;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Int_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Int_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          case XVALUE_OPT_VALTYPE_BOOL:
            return val->bval;
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
double Xvalue_Get_Flt(YO_XVALUE *val, double dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return (double)val->dec;
          case XVALUE_OPT_VALTYPE_FLT:          
            return val->flt;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Flt_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Flt_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
int Xvalue_Get_Bool(YO_XVALUE *val, int dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( val )
      switch (val->opt&XVALUE_OPT_VALTYPE_MASK) 
        {
          case XVALUE_OPT_VALTYPE_INT:
            return val->dec?1:0;
          case XVALUE_OPT_VALTYPE_BOOL:
            return val->bval;
          case XVALUE_OPT_VALTYPE_FLT:          
            return val->flt?1:0;
          case XVALUE_OPT_VALTYPE_STR:
            return Str_To_Bool_Dflt(val->txt,dfltval);
          case XVALUE_OPT_VALTYPE_LIT:
            return Str_To_Bool_Dflt((char*)&val->down,dfltval);
          case XVALUE_OPT_VALTYPE_NONE:
            return 0;
          default:
            __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
        }
    return dfltval;
  }
#endif
  ;
  
void Xvalue_Set_Str(YO_XVALUE *val, char *S, int L)
#ifdef _YO_XDATA_BUILTIN
  {
    Xvalue_Purge(val);
    if ( L < 0 ) L = S?strlen(S):0;
    if ( L >= sizeof(val->down)+sizeof(val->holder) )
      {
        val->txt = Str_Copy_Npl(S,L);
        val->opt = XVALUE_OPT_VALTYPE_STR;
      }
    else
      {
        if (L) memcpy((char*)&val->down,S,L);
        /* already filled by 0 in Xvalue_Purge //((char*)&val->down)[L] = 0; */
        val->opt = XVALUE_OPT_VALTYPE_LIT;
      }
  }
#endif
  ;
  
void Xvalue_Put_Str(YO_XVALUE *val, __Acquire char *S)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    //STRICT_REQUIRE( S != 0 );
    Xvalue_Purge(val);
    val->txt = S?S:Str_Copy_Npl("",0);
    val->opt = XVALUE_OPT_VALTYPE_STR;
  }
#endif
  ;
  
void Xvalue_Set_Or_Put_Str(YO_XVALUE *val, char *S)
#ifdef _YO_XDATA_BUILTIN
  {
    int L = S?strlen(S):0;
    if ( L >= sizeof(val->down)+sizeof(val->holder) )
      Xvalue_Put_Str(val,__Retain(S));
    else
      {
        Xvalue_Purge(val);
        if (L) memcpy((char*)&val->down,S,L);
        /* already filled by 0 in Xvalue_Purge //((char*)&val->down)[L] = 0; */
        val->opt = XVALUE_OPT_VALTYPE_LIT;
      }
  }
#endif
  ;
  
void Xvalue_Put_Binary(YO_XVALUE *val, __Acquire YO_BUFFER *bf)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    STRICT_REQUIRE( bf != 0 );
    Xvalue_Purge(val);
    val->binary = bf;
    val->opt = XVALUE_OPT_VALTYPE_BIN;
  }
#endif
  ;

void Xvalue_Set_Binary(YO_XVALUE *val, void *S, int L)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_BUFFER *bf = Buffer_Copy(S,L);
    Xvalue_Put_Binary(val,bf);
  }
#endif
  ;

void Xvalue_Put_Flt_Array(YO_XVALUE *val, __Acquire YO_BUFFER *bf)
#ifdef _YO_XDATA_BUILTIN
  {
    Xvalue_Put_Binary(val,bf);
    val->opt = XVALUE_OPT_VALTYPE_FLT_ARR;
  }
#endif
  ;

void Xvalue_Put_Str_Array(YO_XVALUE *val, __Acquire YO_ARRAY *arr)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( val != 0 );
    STRICT_REQUIRE( arr != 0 );
    Xvalue_Purge(val);
    val->strarr = arr;
    val->opt = XVALUE_OPT_VALTYPE_STR_ARR;
  }
#endif
  ;

void Xvalue_Set_Int(YO_XVALUE *val, long i)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->dec = i;
    val->opt = XVALUE_OPT_VALTYPE_INT;
  }
#endif
  ;

void Xvalue_Set_Flt(YO_XVALUE *val, double d)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->flt = d;
    val->opt = XVALUE_OPT_VALTYPE_FLT;
  }
#endif
  ;

void Xvalue_Set_Bool(YO_XVALUE *val, int b)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE ( val );
    Xvalue_Purge(val);
    val->bval = b?1:0;
    val->opt = XVALUE_OPT_VALTYPE_BOOL;
  }
#endif
  ;

int Xdata_Idxref_No(YO_XDATA *doc, ushort_t idx, int *no)
#ifdef _YO_XDATA_BUILTIN
  {
    --idx;
    
    if ( idx >= 32 )
      {
        int ref = Bitcount_Of(idx);
        *no  = idx - (1<<(ref-1)); //((1<<ref)-(1<<(ref-1)));
        STRICT_REQUIRE(ref >= 5);
        STRICT_REQUIRE(ref < XNODE_NUMBER_OF_NODE_LISTS+5);
        return ref-5;
      }
    else
      {
        *no = idx;
        return 0;
      }
  }
#endif
  ;

void *Xdata_Idxref(YO_XDATA *doc, ushort_t idx)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( doc );
    STRICT_REQUIRE( idx );
    __Gogo
      {
        YO_XNODE *n;
        int no;
        int ref = Xdata_Idxref_No(doc,idx,&no);
        n = doc->nodes[ref]+no;
        return n;
      }
  }
#endif
  ;

void YO_XDATA_Destruct(YO_XDATA *self)
#ifdef _YO_XDATA_BUILTIN
  {
    int i,j;
    
    for ( i = 0; i < XNODE_NUMBER_OF_NODE_LISTS; ++i )
      if ( self->nodes[i] )
        {
          for ( j = 0; j < Number_Of_Nodes_In_List(i); ++j )
            {
              YO_XNODE *r = self->nodes[i]+j;
              if ( !(r->opt&XVALUE_OPT_IS_VALUE) && r->down == XVALUE_DOWN_REFNODE )
                {
                  YO_XNODE *ref = Xdata_Idxref(r->xdata,r->opt);
                  STRICT_REQUIRE(ref->opt ==  XVALUE_OPT_VALTYPE_REFNODE);
                  r->down = 0;
                  __Unrefe(ref->refval);
                }
              else if (((r->opt&XVALUE_OPT_VALTYPE_MASK) == XVALUE_OPT_VALTYPE_STR
                  || (r->opt&XVALUE_OPT_VALTYPE_MASK) == XVALUE_OPT_VALTYPE_BIN ))
                Xvalue_Purge(r);
            }
          free(self->nodes[i]);
        }
    free(self->tags);
    __Unrefe(self->dicto);
    __Destruct(self);
  }
#endif
  ;

YO_XDATA *Xnode_Get_Xdata(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( node->opt&XVALUE_OPT_IS_VALUE )
      __Raise(YO_ERROR_INVALID_PARAM,0);
    return node->xdata;
  }
#endif
  ;

#define Xnode_Resolve_Name(Node,Name,Cine) Xdata_Resolve_Node(Node->xdata,tag,Cine)
char *Xdata_Resolve_Name(YO_XDATA *doc, char *tag, int create_if_doesnt_exist)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( tag && tag > XNODE_MAX_NAME_INDEX_PTR )
      {
        char *q;
        q = Dicto_Get(doc->dicto,tag,0);
        if ( q )
          ;
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
    else
      return tag;
  }
#endif
  ;

void *Xdata_Init()
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XDATA *doc = __Object_Dtor(sizeof(YOYO_XDATA),YOYO_XDATA_Destruct);
    doc->dicto = __Refe(Dicto_Init());
    doc->root.xdata = doc;
    doc->root.tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(doc,"root",1);
    return doc;
  }
#endif
  ;

char *Xnode_Get_Tag(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( node->tag > 0 && node->tag <= node->xdata->last_tag );

    return node->xdata->tags[node->tag-1];
  }
#endif
  ;
  
int Xnode_Tag_Is(YOYO_XNODE *node, char *tag_name)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t tag;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( node->tag > 0 && node->tag <= node->xdata->last_tag );
     
    tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(node->xdata,tag_name,0);
    return node->tag == tag;
  }
#endif
  ;

YOYO_XNODE *Xnode_Refacc(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( !(node->opt&XVALUE_OPT_IS_VALUE) && node->down == XVALUE_DOWN_REFNODE )
      {
        YOYO_XNODE *ref = Xdata_Idxref(node->xdata,node->opt);
        STRICT_REQUIRE(ref->opt ==  XVALUE_OPT_VALTYPE_REFNODE);
        node = ref->refval;
      }
    return node;
  }
#endif
  ;

char *Xnode_Value_Get_Tag(YOYO_XNODE *node,YOYO_XVALUE *value)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( value );

    node = Xnode_Refacc(node);

    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( (value->opt&XVALUE_OPT_IS_VALUE) != 0 );
    STRICT_REQUIRE( value->tag > 0 && value->tag <= node->xdata->last_tag );
    
    return node->xdata->tags[value->tag-1];
  }
#endif
  ;

YOYO_XNODE *Xnode_Down(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Refacc(node);
    if ( node->down )
      return Xdata_Idxref(node->xdata,node->down);

    return 0;
  }
#endif
  ;

YOYO_XVALUE *Xnode_First_Value(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

    node = Xnode_Refacc(node);
    if ( node->opt )
      return (YOYO_XVALUE*)Xdata_Idxref(node->xdata,node->opt);
  
    return 0;
  }
#endif
  ;

YOYO_XVALUE *Xnode_Next_Value(YOYO_XNODE *node, YOYO_XVALUE *value)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( value );
    STRICT_REQUIRE( (value->opt&XVALUE_OPT_IS_VALUE) != 0 );

    node = Xnode_Refacc(node);
    if ( value->next )
      return (YOYO_XVALUE*)Xdata_Idxref(node->xdata,value->next);
  
    return 0;
  }
#endif
  ;

YOYO_XNODE *Xnode_Next(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

    if ( node->next )
      {
        YOYO_XNODE *n = Xdata_Idxref(node->xdata,node->next);
        STRICT_REQUIRE( n != node );
        return n;
      }
      
    return 0;
  }
#endif
  ;

YOYO_XNODE *Xnode_Last(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n = 0;

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Down(node);
    
    while ( node ) 
      {
        n = node;
        node = Xnode_Next(node);
      }
    
    return n;
  }
#endif
  ;

int Xnode_Count(YOYO_XNODE *node)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int i = 0;

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Down(node);
    
    while ( node ) 
      {
        ++i;
        node = Xnode_Next(node);
      }
    
    return i;
  }
#endif
  ;

void *Xdata_Allocate(YOYO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int no,ref,newidx;
    YOYO_XNODE *n;
    
    STRICT_REQUIRE( doc );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( idx );
    
    newidx = ++doc->last_node;
    ref = Xdata_Idxref_No(doc,newidx,&no);
    if ( !doc->nodes[ref] )
      {
        int count = sizeof(YOYO_XNODE)*Number_Of_Nodes_In_List(ref);
        doc->nodes[ref] = __Malloc_Npl(count);
        memset(doc->nodes[ref],0xff,count);
      }

    *idx = newidx;
    n = doc->nodes[ref]+no;
    memset(n,0,sizeof(YOYO_XNODE));
    n->tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(doc,tag,1);
    return n;
  }
#endif
  ;

YOYO_XNODE *Xdata_Create_Node(YOYO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n = Xdata_Allocate(doc,tag,idx);
    n->xdata = doc;
    return n;
  }
#endif
  ;

YOYO_XVALUE *Xdata_Create_Value(YOYO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n = Xdata_Allocate(doc,tag,idx);
    n->opt = XVALUE_OPT_VALTYPE_NONE;
    return n;
  }
#endif
  ;

YOYO_XNODE *Xnode_Append(YOYO_XNODE *node, char *tag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t idx;
    YOYO_XNODE *n;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    n = Xdata_Create_Node(node->xdata,tag,&idx);

    if ( node->down )
      {
        YOYO_XNODE *last = Xnode_Last(node);
        last->next = idx;
      }
    else
      {
        node->down = idx;
      }

    STRICT_REQUIRE( n->next != idx );
    return n;
  }
#endif
  ;

YOYO_XNODE *Xnode_Append_Refnode(YOYO_XNODE *node, char *tagname, YOYO_XNODE *ref)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n;
    YOYO_XNODE *v;
    
    STRICT_REQUIRE( ref );
    STRICT_REQUIRE( (ref->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    if ( !tagname ) tagname = Xnode_Get_Tag(ref);
    n = Xnode_Append(node,tagname);
    v = Xdata_Allocate(node->xdata,".refout.",&n->opt);
    n->down = XVALUE_DOWN_REFNODE;
    v->opt = XVALUE_OPT_VALTYPE_REFNODE;
    v->refval = ref;
    __Refe( v->refval );
    return n;
  }
#endif
  ;

YOYO_XNODE *Xnode_Insert(YOYO_XNODE *node, char *tag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t idx;
    YOYO_XNODE *n;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    n = Xdata_Create_Node(node->xdata,tag,&idx);
    n->next = node->down;
    node->down = idx;
      
    STRICT_REQUIRE( n->next != idx );
    
    return n;
  }
#endif
  ;

YOYO_XNODE *Xnode_Down_If(YOYO_XNODE *node, char *tag_name)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t tag;
    YOYO_XNODE *n;
      
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag_name );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );








|

|








|
|










|
|













|
|



|








|
|















|
|













|
|






|






|
|








|






|
|






|









|
|

|

















|
|



















|
|


|









|






|






|
|

|






|
|

|






|
|


|









|













|
|

|
|
















|
|


|
















|
|


|







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
    else
      return tag;
  }
#endif
  ;

void *Xdata_Init()
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XDATA *doc = __Object_Dtor(sizeof(YO_XDATA),YO_XDATA_Destruct);
    doc->dicto = __Refe(Dicto_Init());
    doc->root.xdata = doc;
    doc->root.tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(doc,"root",1);
    return doc;
  }
#endif
  ;

char *Xnode_Get_Tag(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( node->tag > 0 && node->tag <= node->xdata->last_tag );

    return node->xdata->tags[node->tag-1];
  }
#endif
  ;
  
int Xnode_Tag_Is(YO_XNODE *node, char *tag_name)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t tag;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( node->tag > 0 && node->tag <= node->xdata->last_tag );
     
    tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(node->xdata,tag_name,0);
    return node->tag == tag;
  }
#endif
  ;

YO_XNODE *Xnode_Refacc(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( !(node->opt&XVALUE_OPT_IS_VALUE) && node->down == XVALUE_DOWN_REFNODE )
      {
        YO_XNODE *ref = Xdata_Idxref(node->xdata,node->opt);
        STRICT_REQUIRE(ref->opt ==  XVALUE_OPT_VALTYPE_REFNODE);
        node = ref->refval;
      }
    return node;
  }
#endif
  ;

char *Xnode_Value_Get_Tag(YO_XNODE *node,YO_XVALUE *value)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( value );

    node = Xnode_Refacc(node);

    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( (value->opt&XVALUE_OPT_IS_VALUE) != 0 );
    STRICT_REQUIRE( value->tag > 0 && value->tag <= node->xdata->last_tag );
    
    return node->xdata->tags[value->tag-1];
  }
#endif
  ;

YO_XNODE *Xnode_Down(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Refacc(node);
    if ( node->down )
      return Xdata_Idxref(node->xdata,node->down);

    return 0;
  }
#endif
  ;

YO_XVALUE *Xnode_First_Value(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

    node = Xnode_Refacc(node);
    if ( node->opt )
      return (YO_XVALUE*)Xdata_Idxref(node->xdata,node->opt);
  
    return 0;
  }
#endif
  ;

YO_XVALUE *Xnode_Next_Value(YO_XNODE *node, YO_XVALUE *value)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    STRICT_REQUIRE( value );
    STRICT_REQUIRE( (value->opt&XVALUE_OPT_IS_VALUE) != 0 );

    node = Xnode_Refacc(node);
    if ( value->next )
      return (YO_XVALUE*)Xdata_Idxref(node->xdata,value->next);
  
    return 0;
  }
#endif
  ;

YO_XNODE *Xnode_Next(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

    if ( node->next )
      {
        YO_XNODE *n = Xdata_Idxref(node->xdata,node->next);
        STRICT_REQUIRE( n != node );
        return n;
      }
      
    return 0;
  }
#endif
  ;

YO_XNODE *Xnode_Last(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n = 0;

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Down(node);
    
    while ( node ) 
      {
        n = node;
        node = Xnode_Next(node);
      }
    
    return n;
  }
#endif
  ;

int Xnode_Count(YO_XNODE *node)
#ifdef _YO_XDATA_BUILTIN
  {
    int i = 0;

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    node = Xnode_Down(node);
    
    while ( node ) 
      {
        ++i;
        node = Xnode_Next(node);
      }
    
    return i;
  }
#endif
  ;

void *Xdata_Allocate(YO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YO_XDATA_BUILTIN
  {
    int no,ref,newidx;
    YO_XNODE *n;
    
    STRICT_REQUIRE( doc );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( idx );
    
    newidx = ++doc->last_node;
    ref = Xdata_Idxref_No(doc,newidx,&no);
    if ( !doc->nodes[ref] )
      {
        int count = sizeof(YO_XNODE)*Number_Of_Nodes_In_List(ref);
        doc->nodes[ref] = __Malloc_Npl(count);
        memset(doc->nodes[ref],0xff,count);
      }

    *idx = newidx;
    n = doc->nodes[ref]+no;
    memset(n,0,sizeof(YO_XNODE));
    n->tag = (ushort_t)(longptr_t)Xdata_Resolve_Name(doc,tag,1);
    return n;
  }
#endif
  ;

YO_XNODE *Xdata_Create_Node(YO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n = Xdata_Allocate(doc,tag,idx);
    n->xdata = doc;
    return n;
  }
#endif
  ;

YO_XVALUE *Xdata_Create_Value(YO_XDATA *doc, char *tag, ushort_t *idx)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n = Xdata_Allocate(doc,tag,idx);
    n->opt = XVALUE_OPT_VALTYPE_NONE;
    return n;
  }
#endif
  ;

YO_XNODE *Xnode_Append(YO_XNODE *node, char *tag)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t idx;
    YO_XNODE *n;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    n = Xdata_Create_Node(node->xdata,tag,&idx);

    if ( node->down )
      {
        YO_XNODE *last = Xnode_Last(node);
        last->next = idx;
      }
    else
      {
        node->down = idx;
      }

    STRICT_REQUIRE( n->next != idx );
    return n;
  }
#endif
  ;

YO_XNODE *Xnode_Append_Refnode(YO_XNODE *node, char *tagname, YO_XNODE *ref)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n;
    YO_XNODE *v;
    
    STRICT_REQUIRE( ref );
    STRICT_REQUIRE( (ref->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    if ( !tagname ) tagname = Xnode_Get_Tag(ref);
    n = Xnode_Append(node,tagname);
    v = Xdata_Allocate(node->xdata,".refout.",&n->opt);
    n->down = XVALUE_DOWN_REFNODE;
    v->opt = XVALUE_OPT_VALTYPE_REFNODE;
    v->refval = ref;
    __Refe( v->refval );
    return n;
  }
#endif
  ;

YO_XNODE *Xnode_Insert(YO_XNODE *node, char *tag)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t idx;
    YO_XNODE *n;
    
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    n = Xdata_Create_Node(node->xdata,tag,&idx);
    n->next = node->down;
    node->down = idx;
      
    STRICT_REQUIRE( n->next != idx );
    
    return n;
  }
#endif
  ;

YO_XNODE *Xnode_Down_If(YO_XNODE *node, char *tag_name)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t tag;
    YO_XNODE *n;
      
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( tag_name );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
      }
      
    return 0;
  }
#endif
  ;

YOYO_XNODE *Xnode_Next_If(YOYO_XNODE *node, char *tag_name)
#ifdef _YOYO_XDATA_BUILTIN
  {
    ushort_t tag;
    YOYO_XNODE *n;
      
    n = Xnode_Refacc(node);
    
    STRICT_REQUIRE( n );
    STRICT_REQUIRE( tag_name );
    STRICT_REQUIRE( (n->opt&XVALUE_OPT_IS_VALUE) == 0 );
    







|
|


|







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
      }
      
    return 0;
  }
#endif
  ;

YO_XNODE *Xnode_Next_If(YO_XNODE *node, char *tag_name)
#ifdef _YO_XDATA_BUILTIN
  {
    ushort_t tag;
    YO_XNODE *n;
      
    n = Xnode_Refacc(node);
    
    STRICT_REQUIRE( n );
    STRICT_REQUIRE( tag_name );
    STRICT_REQUIRE( (n->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
  ((Xnode_Opt_Of_Value(Node,Valtag)&XVALUE_OPT_VALTYPE_MASK) \
    == XVALUE_OPT_VALTYPE_STR)

#define Xnode_Value_Is_None(Node,Valtag) \
  ((Xnode_Opt_Of_Value(Node,Valtag)&XVALUE_OPT_VALTYPE_MASK) \
    == XVALUE_OPT_VALTYPE_NONE)

YOYO_XVALUE *Xnode_Value(YOYO_XNODE *node, char *valtag_S, int create_if_dnt_exist)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *value = 0;
    YOYO_XDATA  *doc;
    ushort_t *next;
    ushort_t valtag;
    
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( valtag_S );







|
|

|
|







886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
  ((Xnode_Opt_Of_Value(Node,Valtag)&XVALUE_OPT_VALTYPE_MASK) \
    == XVALUE_OPT_VALTYPE_STR)

#define Xnode_Value_Is_None(Node,Valtag) \
  ((Xnode_Opt_Of_Value(Node,Valtag)&XVALUE_OPT_VALTYPE_MASK) \
    == XVALUE_OPT_VALTYPE_NONE)

YO_XVALUE *Xnode_Value(YO_XNODE *node, char *valtag_S, int create_if_dnt_exist)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *value = 0;
    YO_XDATA  *doc;
    ushort_t *next;
    ushort_t valtag;
    
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( valtag_S );
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
      valtag = (ushort_t)(longptr_t)valtag_S;
      
    next = &node->opt;
    if ( valtag ) 
      {
        while ( *next )
          {
            value = (YOYO_XVALUE *)Xdata_Idxref(doc,*next);
            STRICT_REQUIRE( value != 0 );
            if ( value->tag == valtag )
              goto found;
            next = &value->next;
          }
    
        STRICT_REQUIRE( !*next );







|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
      valtag = (ushort_t)(longptr_t)valtag_S;
      
    next = &node->opt;
    if ( valtag ) 
      {
        while ( *next )
          {
            value = (YO_XVALUE *)Xdata_Idxref(doc,*next);
            STRICT_REQUIRE( value != 0 );
            if ( value->tag == valtag )
              goto found;
            next = &value->next;
          }
    
        STRICT_REQUIRE( !*next );
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
      
  found:
    return value;
  }
#endif
  ;
  
YOYO_XVALUE *Xnode_Match_Value(YOYO_XNODE *node, char *patt)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XDATA  *doc;
    ushort_t *next;
    
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( patt );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    doc = node->xdata;
    next = &node->opt;

    while ( *next )
      {
        YOYO_XVALUE *value = (YOYO_XVALUE *)Xdata_Idxref(doc,*next);
        STRICT_REQUIRE( value != 0 );
        if ( Str_Match( Xnode_Value_Get_Tag(node,value), patt ) )
          return value;
      }

    return 0;
  }
#endif
  ;

int Xnode_Opt_Of_Value(YOYO_XNODE *node, char *valtag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    if ( val )
      return val->opt;
    return 0; 
  }
#endif
  ;
  

long Xnode_Value_Get_Int(YOYO_XNODE *node, char *valtag, long dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Int(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Int(YOYO_XNODE *node, char *valtag, long i)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Int(val,i);
  }
#endif
  ;
  
int Xnode_Value_Get_Bool(YOYO_XNODE *node, char *valtag, int dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Bool(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Bool(YOYO_XNODE *node, char *valtag, int i)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Bool(val,i);
  }
#endif
  ;

double Xnode_Value_Get_Flt(YOYO_XNODE *node, char *valtag, double dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Flt(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Flt(YOYO_XNODE *node, char *valtag, double d)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Flt(val,d);
  }
#endif
  ;
  
char *Xnode_Value_Get_Str(YOYO_XNODE *node, char *valtag, char *dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Str(val,dfltval);
  }
#endif
  ;
  
char *Xnode_Value_Copy_Str(YOYO_XNODE *node, char *valtag, char *dfltval)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Copy_Str(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Str(YOYO_XNODE *node, char *valtag, char *S)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val;
    val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Str(val,S,-1);
  }
#endif
  ;
  
void Xnode_Value_Put_Str(YOYO_XNODE *node, char *valtag, __Acquire char *S)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val;
    __Pool(S);
    val = Xnode_Value(node,valtag,1);
    Xvalue_Put_Str(val,__Retain(S));
  }
#endif
  ;
  
void Xnode_Value_Put_Binary(YOYO_XNODE *node,char *valtag, YOYO_BUFFER *bf)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    Xvalue_Put_Binary(val,__Refe(bf));
  }
#endif
  ;

void Xnode_Value_Set_Binary(YOYO_XNODE *node,char *valtag, void *data, int len)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    Xvalue_Set_Binary(val,data,len);
  }
#endif
  ;
  
YOYO_BUFFER *Xnode_Value_Get_Binary(YOYO_XNODE *node,char *valtag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Binary(val);
  }
#endif
  ;
  
YOYO_BUFFER *Xnode_Value_Copy_Binary(YOYO_XNODE *node,char *valtag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *val = Xnode_Value(node,valtag,0);
    YOYO_BUFFER *bf = Xvalue_Get_Binary(val);
    if ( bf )
      return Buffer_Copy(bf->at,bf->count);
    return 0;
  }
#endif
  ;

enum
  {
    YOYO_XNODE_QUERY_EQUAL = 1,
    YOYO_XNODE_QUERY_NAMED = 2,
    YOYO_XNODE_QUERY_MATCH = 3,
  };

int Xnode_Query_Chop_Op(char **query, char *elm, int elm_size)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int patt = YOYO_XNODE_QUERY_EQUAL;
    int i = 0;
    
    if ( !query || !*query || !**query )
      return 0;
      
    while ( **query )
      {
        if ( i >= elm_size - 1 ) __Raise(YOYO_ERROR_OUT_OF_RANGE,0);
        if ( **query != '.' )
          {
            char c = *(*query)++;
            if ( c == '*' || c == '[' || c == '?' )
              patt = YOYO_XNODE_QUERY_MATCH;
            else if ( c == '@' && patt < YOYO_XNODE_QUERY_MATCH )
              patt = YOYO_XNODE_QUERY_NAMED;
            elm[i++] = c;
          }
        else
          {
            ++*query;
            break;
          }
      }
      
    elm[i] = 0;
    if (!**query) *query = 0;
    return patt;
  }
#endif
  ;

YOYO_XNODE *Xnode_Down_If_Named(YOYO_XNODE *node, char *named_tag)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n;
    int tag_len = 0;
    char *name;
    char *tag;
      
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );







|
|

|













|










|
|

|








|
|

|





|
|

|





|
|

|





|
|

|





|
|

|





|
|

|





|
|

|





|
|

|





|
|

|






|
|

|







|
|

|





|
|

|





|
|

|





|
|

|
|









|
|
|



|

|







|




|
|
|
















|
|

|







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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
      
  found:
    return value;
  }
#endif
  ;
  
YO_XVALUE *Xnode_Match_Value(YO_XNODE *node, char *patt)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XDATA  *doc;
    ushort_t *next;
    
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
    STRICT_REQUIRE( patt );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );
    
    doc = node->xdata;
    next = &node->opt;

    while ( *next )
      {
        YO_XVALUE *value = (YO_XVALUE *)Xdata_Idxref(doc,*next);
        STRICT_REQUIRE( value != 0 );
        if ( Str_Match( Xnode_Value_Get_Tag(node,value), patt ) )
          return value;
      }

    return 0;
  }
#endif
  ;

int Xnode_Opt_Of_Value(YO_XNODE *node, char *valtag)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    if ( val )
      return val->opt;
    return 0; 
  }
#endif
  ;
  

long Xnode_Value_Get_Int(YO_XNODE *node, char *valtag, long dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Int(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Int(YO_XNODE *node, char *valtag, long i)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Int(val,i);
  }
#endif
  ;
  
int Xnode_Value_Get_Bool(YO_XNODE *node, char *valtag, int dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Bool(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Bool(YO_XNODE *node, char *valtag, int i)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Bool(val,i);
  }
#endif
  ;

double Xnode_Value_Get_Flt(YO_XNODE *node, char *valtag, double dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Flt(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Flt(YO_XNODE *node, char *valtag, double d)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Flt(val,d);
  }
#endif
  ;
  
char *Xnode_Value_Get_Str(YO_XNODE *node, char *valtag, char *dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Str(val,dfltval);
  }
#endif
  ;
  
char *Xnode_Value_Copy_Str(YO_XNODE *node, char *valtag, char *dfltval)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Copy_Str(val,dfltval);
  }
#endif
  ;
  
void Xnode_Value_Set_Str(YO_XNODE *node, char *valtag, char *S)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val;
    val = Xnode_Value(node,valtag,1);
    Xvalue_Set_Str(val,S,-1);
  }
#endif
  ;
  
void Xnode_Value_Put_Str(YO_XNODE *node, char *valtag, __Acquire char *S)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val;
    __Pool(S);
    val = Xnode_Value(node,valtag,1);
    Xvalue_Put_Str(val,__Retain(S));
  }
#endif
  ;
  
void Xnode_Value_Put_Binary(YO_XNODE *node,char *valtag, YO_BUFFER *bf)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    Xvalue_Put_Binary(val,__Refe(bf));
  }
#endif
  ;

void Xnode_Value_Set_Binary(YO_XNODE *node,char *valtag, void *data, int len)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    Xvalue_Set_Binary(val,data,len);
  }
#endif
  ;
  
YO_BUFFER *Xnode_Value_Get_Binary(YO_XNODE *node,char *valtag)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    return Xvalue_Get_Binary(val);
  }
#endif
  ;
  
YO_BUFFER *Xnode_Value_Copy_Binary(YO_XNODE *node,char *valtag)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *val = Xnode_Value(node,valtag,0);
    YO_BUFFER *bf = Xvalue_Get_Binary(val);
    if ( bf )
      return Buffer_Copy(bf->at,bf->count);
    return 0;
  }
#endif
  ;

enum
  {
    YO_XNODE_QUERY_EQUAL = 1,
    YO_XNODE_QUERY_NAMED = 2,
    YO_XNODE_QUERY_MATCH = 3,
  };

int Xnode_Query_Chop_Op(char **query, char *elm, int elm_size)
#ifdef _YO_XDATA_BUILTIN
  {
    int patt = YO_XNODE_QUERY_EQUAL;
    int i = 0;
    
    if ( !query || !*query || !**query )
      return 0;
      
    while ( **query )
      {
        if ( i >= elm_size - 1 ) __Raise(YO_ERROR_OUT_OF_RANGE,0);
        if ( **query != '.' )
          {
            char c = *(*query)++;
            if ( c == '*' || c == '[' || c == '?' )
              patt = YO_XNODE_QUERY_MATCH;
            else if ( c == '@' && patt < YO_XNODE_QUERY_MATCH )
              patt = YO_XNODE_QUERY_NAMED;
            elm[i++] = c;
          }
        else
          {
            ++*query;
            break;
          }
      }
      
    elm[i] = 0;
    if (!**query) *query = 0;
    return patt;
  }
#endif
  ;

YO_XNODE *Xnode_Down_If_Named(YO_XNODE *node, char *named_tag)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n;
    int tag_len = 0;
    char *name;
    char *tag;
      
    node = Xnode_Refacc(node);

    STRICT_REQUIRE( node );
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
      }
      
    return n;
  }
#endif
  ;

YOYO_XNODE *Xnode_Down_Match(YOYO_XNODE *node, char *patt)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *n;
    char tag_patt[128];
    char name_patt[128];
      
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( patt );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );








|
|

|







1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
      }
      
    return n;
  }
#endif
  ;

YO_XNODE *Xnode_Down_Match(YO_XNODE *node, char *patt)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *n;
    char tag_patt[128];
    char name_patt[128];
      
    STRICT_REQUIRE( node );
    STRICT_REQUIRE( patt );
    STRICT_REQUIRE( (node->opt&XVALUE_OPT_IS_VALUE) == 0 );

1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
        int i;
        char *p = patt;
        for ( ; *p; ++p )
          if ( *p  == '@' )
            {
              i = p-patt;
              if ( i > sizeof(tag_patt)-1 )
                __Raise(YOYO_ERROR_OUT_OF_RANGE,0);
              memcpy(tag_patt,patt,i); tag_patt[i] = 0;
              i = 0;
              ++p;
              for ( ; *p && i < sizeof(name_patt)-1; ++i )
                name_patt[i] = p[i];
              if ( *p )
                __Raise(YOYO_ERROR_OUT_OF_RANGE,0);
              name_patt[i] = 0;
              break;
            }
      }

    while ( n )
      {
        if ( !tag_patt[0] || Str_Match(Xnode_Get_Tag(n),tag_patt) )
          if ( !name_patt[0] || Str_Match_Nocase(Xnode_Value_Get_Str(n,"@",0),name_patt) )
            break;
        n = Xnode_Next(n);
      }
      
    return n;
  }
#endif
  ;

YOYO_XVALUE *Xnode_Deep_Value(YOYO_XNODE *n, char *query)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XNODE *nn;
    int qtype;
    char elm[128];
    
    while( 0 != (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( qtype == YOYO_XNODE_QUERY_MATCH )
          __Raise(YOYO_ERROR_ILLFORMED,
            __yoTa("Xnode_Deep_Value not supports matching requests",0));
          
        if ( !query && qtype != YOYO_XNODE_QUERY_NAMED ) /* looking for value? */
          {
            STRICT_REQUIRE( qtype == YOYO_XNODE_QUERY_EQUAL );
            return Xnode_Value(n,elm,1);
          }
          
        if ( qtype == YOYO_XNODE_QUERY_NAMED )
          nn = Xnode_Down_If_Named(n,elm);
        else /* qtype == YOYO_XNODE_QUERY_EQUAL */
          nn = Xnode_Down_If(n,elm);
      
        if ( !nn )
          {
            if ( qtype == YOYO_XNODE_QUERY_EQUAL ) lb_trivial_append:
              nn = Xnode_Append(n,elm);
            else /* qtype == YOYO_XNODE_QUERY_NAMED */
              {
                char *c = strchr(elm,'@');
                if ( !c ) goto lb_trivial_append;
                *c = 0; ++c;
                nn = Xnode_Append(n,(!elm[0]?"node":elm));
                Xnode_Value_Set_Str(nn,"@",c);
              }
          }
          
        n = nn;
      }
    
    return Xnode_Value(n,"$",1);
  }
#endif
  ;
  
YOYO_XNODE *Xnode_Query_Node(YOYO_XNODE *n, char *query)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int qtype;
    char elm[128];
    
    while( n && (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( qtype == YOYO_XNODE_QUERY_MATCH )
          n = Xnode_Down_Match(n,elm);
        else if ( qtype == YOYO_XNODE_QUERY_NAMED )
          n = Xnode_Down_If_Named(n,elm);
        else /* qtype == YOYO_XNODE_QUERY_EQUAL */
          n = Xnode_Down_If(n,elm);
      }

    return n;
  }
#endif
  ;

YOYO_XVALUE *Xnode_Query_Value(YOYO_XNODE *n, char *query)
#ifdef _YOYO_XDATA_BUILTIN
  {
    int qtype;
    char elm[128];
    
    while( n && (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( !query && qtype != YOYO_XNODE_QUERY_NAMED ) /* looking for value? */
          {
            YOYO_XVALUE *value;
            if ( qtype == YOYO_XNODE_QUERY_EQUAL )
              value = Xnode_Value(n,elm,0);
            else /* qtype == YOYO_XNODE_QUERY_MATCH */
              value = Xnode_Match_Value(n,elm);
            if ( value )
              return value;
          }
        
        if ( qtype == YOYO_XNODE_QUERY_MATCH )
          n = Xnode_Down_Match(n,elm);
        else if ( qtype == YOYO_XNODE_QUERY_NAMED )
          n = Xnode_Down_If_Named(n,elm);
        else /* qtype == YOYO_XNODE_QUERY_EQUAL */
          n = Xnode_Down_If(n,elm);
      }
    
    if ( n )
      return Xnode_Value(n,"$",0);
    
    return 0;
  }
#endif
  ;

char *Xvalue_Str_Bf(YOYO_XVALUE *value,YOYO_BUFFER *bf)
#ifdef _YOYO_XDATA_BUILTIN
  {
    if ( value )
      {
        int start = bf->count;
        char *S = Xvalue_Get_Str(value,0);
        if ( S )
          Buffer_Append(bf,S,-1);







|






|


















|
|

|





|
|


|

|



|

|




|

|

















|
|






|

|

|








|
|






|

|
|

|





|

|

|











|
|







1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
        int i;
        char *p = patt;
        for ( ; *p; ++p )
          if ( *p  == '@' )
            {
              i = p-patt;
              if ( i > sizeof(tag_patt)-1 )
                __Raise(YO_ERROR_OUT_OF_RANGE,0);
              memcpy(tag_patt,patt,i); tag_patt[i] = 0;
              i = 0;
              ++p;
              for ( ; *p && i < sizeof(name_patt)-1; ++i )
                name_patt[i] = p[i];
              if ( *p )
                __Raise(YO_ERROR_OUT_OF_RANGE,0);
              name_patt[i] = 0;
              break;
            }
      }

    while ( n )
      {
        if ( !tag_patt[0] || Str_Match(Xnode_Get_Tag(n),tag_patt) )
          if ( !name_patt[0] || Str_Match_Nocase(Xnode_Value_Get_Str(n,"@",0),name_patt) )
            break;
        n = Xnode_Next(n);
      }
      
    return n;
  }
#endif
  ;

YO_XVALUE *Xnode_Deep_Value(YO_XNODE *n, char *query)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XNODE *nn;
    int qtype;
    char elm[128];
    
    while( 0 != (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( qtype == YO_XNODE_QUERY_MATCH )
          __Raise(YO_ERROR_ILLFORMED,
            __yoTa("Xnode_Deep_Value not supports matching requests",0));
          
        if ( !query && qtype != YO_XNODE_QUERY_NAMED ) /* looking for value? */
          {
            STRICT_REQUIRE( qtype == YO_XNODE_QUERY_EQUAL );
            return Xnode_Value(n,elm,1);
          }
          
        if ( qtype == YO_XNODE_QUERY_NAMED )
          nn = Xnode_Down_If_Named(n,elm);
        else /* qtype == YO_XNODE_QUERY_EQUAL */
          nn = Xnode_Down_If(n,elm);
      
        if ( !nn )
          {
            if ( qtype == YO_XNODE_QUERY_EQUAL ) lb_trivial_append:
              nn = Xnode_Append(n,elm);
            else /* qtype == YO_XNODE_QUERY_NAMED */
              {
                char *c = strchr(elm,'@');
                if ( !c ) goto lb_trivial_append;
                *c = 0; ++c;
                nn = Xnode_Append(n,(!elm[0]?"node":elm));
                Xnode_Value_Set_Str(nn,"@",c);
              }
          }
          
        n = nn;
      }
    
    return Xnode_Value(n,"$",1);
  }
#endif
  ;
  
YO_XNODE *Xnode_Query_Node(YO_XNODE *n, char *query)
#ifdef _YO_XDATA_BUILTIN
  {
    int qtype;
    char elm[128];
    
    while( n && (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( qtype == YO_XNODE_QUERY_MATCH )
          n = Xnode_Down_Match(n,elm);
        else if ( qtype == YO_XNODE_QUERY_NAMED )
          n = Xnode_Down_If_Named(n,elm);
        else /* qtype == YO_XNODE_QUERY_EQUAL */
          n = Xnode_Down_If(n,elm);
      }

    return n;
  }
#endif
  ;

YO_XVALUE *Xnode_Query_Value(YO_XNODE *n, char *query)
#ifdef _YO_XDATA_BUILTIN
  {
    int qtype;
    char elm[128];
    
    while( n && (qtype=Xnode_Query_Chop_Op(&query,elm,sizeof(elm))) )
      {
        if ( !query && qtype != YO_XNODE_QUERY_NAMED ) /* looking for value? */
          {
            YO_XVALUE *value;
            if ( qtype == YO_XNODE_QUERY_EQUAL )
              value = Xnode_Value(n,elm,0);
            else /* qtype == YO_XNODE_QUERY_MATCH */
              value = Xnode_Match_Value(n,elm);
            if ( value )
              return value;
          }
        
        if ( qtype == YO_XNODE_QUERY_MATCH )
          n = Xnode_Down_Match(n,elm);
        else if ( qtype == YO_XNODE_QUERY_NAMED )
          n = Xnode_Down_If_Named(n,elm);
        else /* qtype == YO_XNODE_QUERY_EQUAL */
          n = Xnode_Down_If(n,elm);
      }
    
    if ( n )
      return Xnode_Value(n,"$",0);
    
    return 0;
  }
#endif
  ;

char *Xvalue_Str_Bf(YO_XVALUE *value,YO_BUFFER *bf)
#ifdef _YO_XDATA_BUILTIN
  {
    if ( value )
      {
        int start = bf->count;
        char *S = Xvalue_Get_Str(value,0);
        if ( S )
          Buffer_Append(bf,S,-1);
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
#endif
  ;
  
/*
  be carrefull when assume non-null result as succeeded
  if add empty string to empty buffer, retvalue will be 0
*/
char *Xnode_Query_Str_Bf(YOYO_BUFFER *bf, YOYO_XNODE *n, char *query)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *value = Xnode_Query_Value(n,query);
    return Xvalue_Str_Bf(value,bf);
  }
#endif
  ;

char *Xnode_Query_Str_Dflt(YOYO_XNODE *n, char *query, char *dflt)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Get_Str(value,dflt);
      
    return dflt;
  }
#endif
  ;

char *Xnode_Query_Str_Copy(YOYO_XNODE *n, char *query)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Copy_Str(value,"");
      
    return 0;
  }
#endif
  ;

int Xnode_Query_Int(YOYO_XNODE *n, char *query, int dflt)
#ifdef _YOYO_XDATA_BUILTIN
  {
    YOYO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Get_Int(value,dflt);
      
    return dflt;
  }
#endif
  ;

#endif /*C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95*/








|
|

|





|
|

|










|
|

|










|
|

|












1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
#endif
  ;
  
/*
  be carrefull when assume non-null result as succeeded
  if add empty string to empty buffer, retvalue will be 0
*/
char *Xnode_Query_Str_Bf(YO_BUFFER *bf, YO_XNODE *n, char *query)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *value = Xnode_Query_Value(n,query);
    return Xvalue_Str_Bf(value,bf);
  }
#endif
  ;

char *Xnode_Query_Str_Dflt(YO_XNODE *n, char *query, char *dflt)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Get_Str(value,dflt);
      
    return dflt;
  }
#endif
  ;

char *Xnode_Query_Str_Copy(YO_XNODE *n, char *query)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Copy_Str(value,"");
      
    return 0;
  }
#endif
  ;

int Xnode_Query_Int(YO_XNODE *n, char *query, int dflt)
#ifdef _YO_XDATA_BUILTIN
  {
    YO_XVALUE *value;
    
    value = Xnode_Query_Value(n,query);
    if ( value )
      return Xvalue_Get_Int(value,dflt);
      
    return dflt;
  }
#endif
  ;

#endif /*C_once_E46D6A8A_889E_4AE9_9F89_5B0AB5263C95*/

Changes to xddb.hc.
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
*/

#ifndef C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB
#define C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB

#include "mime.hc"
#include "xdata.hc"


#ifdef _LIBYOYO
#define _YOYO_XDDB_BUILTIN
#endif

#ifdef _YOYO_XDDB_BUILTIN
# define _YOYO_XDDB_BUILTIN_CODE(Code) Code
# define _YOYO_XDDB_EXTERN 
#else
# define _YOYO_XDDB_BUILTIN_CODE(Code)
# define _YOYO_XDDB_EXTERN extern 
#endif

typedef struct _YOYO_XDDB
  {
    int doc_format;
  } YOYO_XDDB;

enum
  {
    YOYO_XDDB_DOC_TEXT   = 'A',
    YOYO_XDDB_DOC_BINARY = 'B',
    YOYO_XDDB_DOC_ZIPPED = 'Z',
    YOYO_XDDB_MAX_KEYLEN = 128,
    YOYO_XDDB_UUID_LENGTH = 9,





  };



char *Xddb_Get_Key(YOYO_XDATA *doc)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    return Xnode_Value_Get_Str(&doc->root,"$key$",0);
  }
#endif
  ;
  
int Xddb_Get_Revision(YOYO_XDATA *doc)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    return Xnode_Value_Get_Int((YOYO_XNODE*)doc,"$rev$",0);
  }
#endif
  ;
  
void Xddb_Set_Revision(YOYO_XDATA *doc, int rev)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    Xnode_Value_Set_Int((YOYO_XNODE*)doc,"$rev$",rev);
  }
#endif
  ;

YOYO_XDATA *Xddb_Binary_Decode(byte_t *at,int count,int zipped)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    YOYO_XDATA *doc = Xdata_Init();
    return doc;
  }
#endif
  ;

void Xddb_Binary_Encode_Into(YOYO_BUFFER *bf, YOYO_XDATA *doc, int zipped)
#ifdef _YOYO_XDDB_BUILTIN 
  {
  }
#endif
  ;

YOYO_BUFFER *Xddb_Encode(YOYO_XDDB *xddb, YOYO_XDATA *doc)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    char prefix[] = ".,.,.,.,_\n\n\n";
    YOYO_BUFFER *bf = Buffer_Init(0);
    
    Unsigned_To_Hex8(Xddb_Get_Revision(doc),prefix);
    prefix[8] = (char)xddb->doc_format;
    Buffer_Append(bf,prefix,12);
    
    if ( xddb->doc_format == YOYO_XDDB_DOC_TEXT )
      Def_Format_Into(bf,&doc->root,0);
    else if ( xddb->doc_format == YOYO_XDDB_DOC_BINARY )
      Xddb_Binary_Encode_Into(bf,doc,0);
    else if ( xddb->doc_format == YOYO_XDDB_DOC_ZIPPED )
      Xddb_Binary_Encode_Into(bf,doc,1);
    else
      __Raise(YOYO_ERROR_INCONSISTENT,__yoTa("unsupported document format",0));
      
    return bf;
  }
#endif
  ;

YOYO_XDATA *Xddb_Decode(YOYO_XDDB *xddb, byte_t *at,int count)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    YOYO_XDATA *doc = 0;
    
    if ( count < 12 ) 
      __Raise(YOYO_ERROR_CORRUPTED,__yoTa("document is corrupted",0));
    
    switch ( at[8] )
      {
        case YOYO_XDDB_DOC_TEXT:
          doc = Def_Parse_Str(at+9); /* Yes, 9! Not 12!! */
          break;
        case YOYO_XDDB_DOC_BINARY:
          doc = Xdata_Co_Binary_Decode(at+12,count-12,0);
          break;
        case YOYO_XDDB_DOC_ZIPPED:
          doc = Xdata_Co_Binary_Decode(at+12,count-12,1);
          break;
        default:
          __Raise(YOYO_ERROR_INCONSISTENT,__yoTa("unsupported document format",0));
      }
    return doc;
  }
#endif
  ;

#define Xddb_Build_Unique_Key() __Pool(Xddb_Build_Unique_Key_Npl());
char *Xddb_Build_Unique_Key_Npl()
#ifdef _YOYO_XDDB_BUILTIN 
  {
    int pid = getpid();
    time_t tmx = time(0);
    double clo = clock();
    
    byte_t uuid[YOYO_XDATA_CO_UUID_LENGTH] = {0,0,0,0,0,0,0,0}; /* 8 bytes garanty */
    char   out[(YOYO_XDATA_CO_UUID_LENGTH*8+5)/6 + 3 ] = {'=','=',0};
    
    Unsigned_To_Two(pid,uuid);
    Unsigned_To_Four((uint_t)tmx,uuid+2);
    Unsigned_To_Two((uint_t)((clo/CLOCKS_PER_SEC)*10000),uuid+6);
    System_Random(uuid+6,sizeof(uuid)-6);
    Str_Xbit_Encode(uuid,sizeof(uuid)*8,6,Str_6bit_Encoding_Table,out+2);
    
    STRICT_REQUIRE( out[sizeof(out)-1] == 0 );
    
    return __Memcopy_Npl(out,sizeof(out));
  }
#endif
  ;

_YOYO_XDDB_EXTERN char Xddb_Delete_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_delete/@*"); 
void Xddb_Delete(void *xddb, char *key) _YOYO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Delete_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

_YOYO_XDDB_EXTERN char Xddb_Get_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_get/@**"); 
void *Xddb_Get(void *xddb, char *key, YOYO_XDATA *dflt) _YOYO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Get_OjMID,YO_RAISE_ERROR))
        (xddb,key,dflt); });






_YOYO_XDDB_EXTERN char Xddb_Store_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_store/@*i"); 
int Xddb_Store(void *xddb, YOYO_XDATA *doc, int strict_revision) _YOYO_XDDB_BUILTIN_CODE(
  { return ((int(*)(void*,void*,int))Yo_Find_Method_Of(&xddb,Xddb_Store_OjMID,YO_RAISE_ERROR))
        (xddb,doc,strict_revision); });

#define Xddb_Update(Xddb,Doc) Xddb_Store(Xddb,Doc,1)
#define Xddb_Unique(Xddb,Doc) Xddb_Overwrite(Xddb,Doc,0)

int Xddb_Overwrite(YOYO_XDDB *xddb, YOYO_XDATA *doc, char *key)
#ifdef _YOYO_XDDB_BUILTIN 
  {
    if ( key )
      Xnode_Value_Set_Str(&doc->root,"$key$",key);
    else if ( !Xnode_Value_Get_Str(&doc->root,"$key$",0) )
      {
        char *k = Xddb_Build_Unique_Key_Npl();
        Xnode_Value_Put_Str(&doc->root,"$key$",k);
      }
    return Xddb_Store(xddb,doc,0);
  }
#endif
  ;





























_YOYO_XDDB_EXTERN char Xddb_Strm_Cancel_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_strm_cancel/@"); 
void Xddb_Strm_Cancel(void *strm) _YOYO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*))Yo_Find_Method_Of(&strm,Xddb_Strm_Cancel_OjMID,YO_RAISE_ERROR))
        (strm); });

_YOYO_XDDB_EXTERN char Xddb_Strm_Commit_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_strm_commit/@*i"); 
char *Xddb_Strm_Commit(void *strm, char *key, int overwrite) _YOYO_XDDB_BUILTIN_CODE(
  { return ((char*(*)(void*,void*,int))Yo_Find_Method_Of(&strm,Xddb_Strm_Commit_OjMID,YO_RAISE_ERROR))
        (strm,key,overwrite); });

#define Xddb_Strm_Commit_Overwrite(Strm,Key) Xddb_Strm_Commit(Strm,Key,1)
#define Xddb_Strm_Commit_New(Strm,Key) Xddb_Strm_Commit(Strm,Key,0)
#define Xddb_Strm_Commit_Unique(Strm) Xddb_Strm_Commit(Strm,0,0)

_YOYO_XDDB_EXTERN char Xddb_Strm_Open_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_strm_open/@*"); 
void *Xddb_Strm_Open(void *xddb, char *key) _YOYO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Strm_Open_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

_YOYO_XDDB_EXTERN char Xddb_Strm_Create_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_strm_create/@i"); 
void *Xddb_Strm_Create(void *xddb, int mime) _YOYO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,int))Yo_Find_Method_Of(&xddb,Xddb_Strm_Create_OjMID,YO_RAISE_ERROR))
        (xddb,mime); });

_YOYO_XDDB_EXTERN char Xddb_Strm_Delete_OjMID[] _YOYO_XDDB_BUILTIN_CODE( = "xddb_strm_delete/@*"); 
void Xddb_Strm_Delete(void *xddb,char *key) _YOYO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Strm_Delete_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

#endif /* C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB */









>


|


|
|
|

|
|


|


|



|
|
|
|
|
>
>
>
>
>


>
>
|
|






|
|

|




|
|

|




|
|

|





|
|





|
|


|





|

|
|
|
|

|






|
|

|


|



|


|
<
<
|
|


|








|





|
|














|
|



|
|



>
>
>
>
>
|
|




<

|
|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|



|
|







|
|



|
|



|
|






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
*/

#ifndef C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB
#define C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB

#include "mime.hc"
#include "xdata.hc"
#include "xdef.hc"

#ifdef _LIBYOYO
#define _YO_XDDB_BUILTIN
#endif

#ifdef _YO_XDDB_BUILTIN
# define _YO_XDDB_BUILTIN_CODE(Code) Code
# define _YO_XDDB_EXTERN 
#else
# define _YO_XDDB_BUILTIN_CODE(Code)
# define _YO_XDDB_EXTERN extern 
#endif

typedef struct _YO_XDDB
  {
    int doc_format;
  } YO_XDDB;

enum
  {
    XDDB_FORMAT_TEXT          = 'A',
    XDDB_FORMAT_BINARY        = 'B',
    XDDB_FORMAT_ZIPPED        = 'Z',
    YO_XDDB_MAX_KEYLEN      = 128,
    YO_XDDB_UUID_LENGTH     = 9,
    XDDB_OPEN_EXISTING        = 0,
    XDDB_OPEN_READONLY        = 1,
    XDDB_CREATE_IF_NOT_EXISTS = 2,
    XDDB_CREATE_NEW           = 3,
    XDDB_CREATE_ALWAYS        = 4,
  };

#define XDDB_RAISE_IF_DSNT_EXSIS ((void*)1)

char *Xddb_Get_Key(YO_XDATA *doc)
#ifdef _YO_XDDB_BUILTIN 
  {
    return Xnode_Value_Get_Str(&doc->root,"$key$",0);
  }
#endif
  ;
  
int Xddb_Get_Revision(YO_XDATA *doc)
#ifdef _YO_XDDB_BUILTIN 
  {
    return Xnode_Value_Get_Int((YO_XNODE*)doc,"$rev$",0);
  }
#endif
  ;
  
void Xddb_Set_Revision(YO_XDATA *doc, int rev)
#ifdef _YO_XDDB_BUILTIN 
  {
    Xnode_Value_Set_Int((YO_XNODE*)doc,"$rev$",rev);
  }
#endif
  ;

YO_XDATA *Xddb_Binary_Decode(byte_t *at,int count,int zipped)
#ifdef _YO_XDDB_BUILTIN 
  {
    YO_XDATA *doc = Xdata_Init();
    return doc;
  }
#endif
  ;

void Xddb_Binary_Encode_Into(YO_BUFFER *bf, YO_XDATA *doc, int zipped)
#ifdef _YO_XDDB_BUILTIN 
  {
  }
#endif
  ;

YO_BUFFER *Xddb_Encode(YO_XDDB *xddb, YO_XDATA *doc)
#ifdef _YO_XDDB_BUILTIN 
  {
    char prefix[] = ".,.,.,.,_\n\n\n";
    YO_BUFFER *bf = Buffer_Init(0);
    
    Unsigned_To_Hex8(Xddb_Get_Revision(doc),prefix);
    prefix[8] = (char)xddb->doc_format;
    Buffer_Append(bf,prefix,12);
    
    if ( xddb->doc_format == XDDB_FORMAT_TEXT )
      Def_Format_Into(bf,&doc->root,0);
    else if ( xddb->doc_format == XDDB_FORMAT_BINARY )
      ;//Xdata_Binary_Encode_Into(bf,doc,0);
    else if ( xddb->doc_format == XDDB_FORMAT_ZIPPED )
      ;//Xdata_Binary_Encode_Into(bf,doc,1);
    else
      __Raise(YO_ERROR_INCONSISTENT,__yoTa("unsupported document format",0));
      
    return bf;
  }
#endif
  ;

YO_XDATA *Xddb_Decode(YO_XDDB *xddb, byte_t *at,int count)
#ifdef _YO_XDDB_BUILTIN 
  {
    YO_XDATA *doc = 0;
    
    if ( count < 12 ) 
      __Raise(YO_ERROR_CORRUPTED,__yoTa("document is corrupted",0));
    
    switch ( at[8] )
      {
        case XDDB_FORMAT_TEXT:
          doc = Def_Parse_Str(at+9); /* Yes, 9! Not 12!! */
          break;
        case XDDB_FORMAT_BINARY:


        case XDDB_FORMAT_ZIPPED:
          //doc = Xdata_Binary_Decode(at+12,count-12);
          break;
        default:
          __Raise(YO_ERROR_INCONSISTENT,__yoTa("unsupported document format",0));
      }
    return doc;
  }
#endif
  ;

#define Xddb_Build_Unique_Key() __Pool(Xddb_Build_Unique_Key_Npl());
char *Xddb_Build_Unique_Key_Npl()
#ifdef _YO_XDDB_BUILTIN 
  {
    int pid = getpid();
    time_t tmx = time(0);
    double clo = clock();
    
    byte_t uuid[YO_XDDB_UUID_LENGTH] = {0,0,0,0,0,0,0,0}; /* 8 bytes garanty */
    char   out[(YO_XDDB_UUID_LENGTH*8+5)/6 + 3 ] = {'=','=',0};
    
    Unsigned_To_Two(pid,uuid);
    Unsigned_To_Four((uint_t)tmx,uuid+2);
    Unsigned_To_Two((uint_t)((clo/CLOCKS_PER_SEC)*10000),uuid+6);
    System_Random(uuid+6,sizeof(uuid)-6);
    Str_Xbit_Encode(uuid,sizeof(uuid)*8,6,Str_6bit_Encoding_Table,out+2);
    
    STRICT_REQUIRE( out[sizeof(out)-1] == 0 );
    
    return __Memcopy_Npl(out,sizeof(out));
  }
#endif
  ;

_YO_XDDB_EXTERN char Xddb_Delete_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_delete/@*"); 
void Xddb_Delete(YO_XDDB *xddb, char *key) _YO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Delete_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

_YO_XDDB_EXTERN char Xddb_Get_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_get/@**"); 
void *Xddb_Get(YO_XDDB *xddb, char *key, YO_XDATA *dflt) _YO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Get_OjMID,YO_RAISE_ERROR))
        (xddb,key,dflt); });

_YO_XDDB_EXTERN char Xddb_Has_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_has/@*"); 
int Xddb_Has(YO_XDDB *xddb, char *key) _YO_XDDB_BUILTIN_CODE(
  { return ((int(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Has_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

_YO_XDDB_EXTERN char Xddb_Store_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_store/@*i"); 
int Xddb_Store(YO_XDDB *xddb, YO_XDATA *doc, int strict_revision) _YO_XDDB_BUILTIN_CODE(
  { return ((int(*)(void*,void*,int))Yo_Find_Method_Of(&xddb,Xddb_Store_OjMID,YO_RAISE_ERROR))
        (xddb,doc,strict_revision); });

#define Xddb_Update(Xddb,Doc) Xddb_Store(Xddb,Doc,1)


int Xddb_Overwrite(YO_XDDB *xddb, YO_XDATA *doc, char *key)
#ifdef _YO_XDDB_BUILTIN 
  {
    if ( key )
      Xnode_Value_Set_Str(&doc->root,"$key$",key);
    else if ( !Xnode_Value_Get_Str(&doc->root,"$key$",0) )
      {
        char *k = Xddb_Build_Unique_Key_Npl();
        Xnode_Value_Put_Str(&doc->root,"$key$",k);
      }
    return Xddb_Store(xddb,doc,0);
  }
#endif
  ;

char *Xddb_Unique(YO_XDDB *xddb, YO_XDATA *doc)
#ifdef _YO_XDDB_BUILTIN 
  {
    Xddb_Overwrite(xddb,doc,0);
    return Str_Copy(Xddb_Get_Key(doc));
  }
#endif
  ;
    
_YO_XDDB_EXTERN char Xddb_Source_String_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_source_string/@"); 
char *Xddb_Source_String(void *xddb) _YO_XDDB_BUILTIN_CODE(
  { return ((char*(*)(void*))Yo_Find_Method_Of(&xddb,Xddb_Source_String_OjMID,YO_RAISE_ERROR))
        (xddb); });

char *Xddb_Format_String(YO_XDDB *xddb)
#ifdef _YO_XDDB_BUILTIN 
  {
    switch ( xddb->doc_format )
      {
      case XDDB_FORMAT_TEXT:   return "text";
      case XDDB_FORMAT_BINARY: return "binary";
      case XDDB_FORMAT_ZIPPED: return "zipped";
      }
    return "unknown";
  }
#endif
  ;
  
_YO_XDDB_EXTERN char Xddb_Strm_Cancel_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_strm_cancel/@"); 
void Xddb_Strm_Cancel(void *strm) _YO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*))Yo_Find_Method_Of(&strm,Xddb_Strm_Cancel_OjMID,YO_RAISE_ERROR))
        (strm); });

_YO_XDDB_EXTERN char Xddb_Strm_Commit_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_strm_commit/@*i"); 
char *Xddb_Strm_Commit(void *strm, char *key, int overwrite) _YO_XDDB_BUILTIN_CODE(
  { return ((char*(*)(void*,void*,int))Yo_Find_Method_Of(&strm,Xddb_Strm_Commit_OjMID,YO_RAISE_ERROR))
        (strm,key,overwrite); });

#define Xddb_Strm_Commit_Overwrite(Strm,Key) Xddb_Strm_Commit(Strm,Key,1)
#define Xddb_Strm_Commit_New(Strm,Key) Xddb_Strm_Commit(Strm,Key,0)
#define Xddb_Strm_Commit_Unique(Strm) Xddb_Strm_Commit(Strm,0,0)

_YO_XDDB_EXTERN char Xddb_Strm_Open_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_strm_open/@*"); 
void *Xddb_Strm_Open(YO_XDDB *xddb, char *key) _YO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Strm_Open_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

_YO_XDDB_EXTERN char Xddb_Strm_Create_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_strm_create/@i"); 
void *Xddb_Strm_Create(YO_XDDB *xddb, int mime) _YO_XDDB_BUILTIN_CODE(
  { return ((void*(*)(void*,int))Yo_Find_Method_Of(&xddb,Xddb_Strm_Create_OjMID,YO_RAISE_ERROR))
        (xddb,mime); });

_YO_XDDB_EXTERN char Xddb_Strm_Delete_OjMID[] _YO_XDDB_BUILTIN_CODE( = "xddb_strm_delete/@*"); 
void Xddb_Strm_Delete(YO_XDDB *xddb, char *key) _YO_XDDB_BUILTIN_CODE(
  { ((void(*)(void*,void*))Yo_Find_Method_Of(&xddb,Xddb_Strm_Delete_OjMID,YO_RAISE_ERROR))
        (xddb,key); });

#endif /* C_once_63CF3893_FBF5_4DA0_9B2D_792FE7BBBCAB */


Changes to xddbfs.hc.
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

#ifndef C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF
#define C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF

#include "xddb.hc"
#include "file.hc"
#include "datetime.hc"


#ifdef _LIBYOYO
#define _YOYO_XDDBFS_BUILTIN
#endif

typedef struct _YOYO_XDDBFS
  {
    YOYO_XDDB xddb;
    char *basepath;
    int  jur_fd;
    int  fs_depth;
  } YOYO_XDDBFS;

void YOYO_XDDBFS_Destruct(YOYO_XDDBFS *xddb)
  {
    if ( xddb->jur_fd >= 0 ) close(xddb->jur_fd);
    free(xddb->basepath);
    __Destruct(xddb);
  };

typedef struct _YOYO_XDDBFS_STREAM
  {
    YOYO_XDDBFS *xddb;
    char *key;
    char *tmp_path;
    int  mimetype;
    int  length;
    int  finished;
    int  fd;
    int  curpos;
  } YOYO_XDDBFS_STREAM;
  
typedef struct _YOYO_XDDBFS_STREAM_HEADER
  {
    char cr;
    char nl;
    char mimetype[4];
    char length[8];
    char lastacs[8];
    char created[8];
    char compressed;
    char keylen[2];
    char key[YOYO_XDDB_MAX_KEYLEN];
    char nulterm;
  } YOYO_XDDBFS_STREAM_HEADER;

void YOYO_XDDBFS_STREAM_Destruct(YOYO_XDDBFS_STREAM *strm)
  {
    if ( strm->tmp_path )
      {
        utf8_unlink(strm->tmp_path);
        free(strm->tmp_path);
      }
    if ( strm->fd >= 0 ) close(strm->fd);
    free(strm->key);
    __Unrefe(strm->xddb);
    __Destruct(strm);    
  };

char *Xddbfs_Tmp_File_Path_Sfx(YOYO_XDDBFS *xdb, char *sfx)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    char *S = Xddb_Build_Unique_Key();
    if ( sfx )
      S = Str_Concat(S,sfx);
    return Str_Join_3('/',xdb->basepath,"tmp",S);
  }
#endif
  ;

char *Xddbfs_File_Path_Sfx_Md5(YOYO_XDDBFS *xddb, byte_t *md5, char *sfx)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    char *S = 0;
    int i;
    char md5_hex[33] = {0};
    char hash[4*3] = "\0\0/\0\0/\0\0/\0\0";
    for ( i = 0; i < 16; ++i )
      Str_Hex_Byte(md5[i],0,md5_hex+i*2);







>


|


|

|



|

|






|

|







|

|









|

|

|












|
|









|
|







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

#ifndef C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF
#define C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF

#include "xddb.hc"
#include "file.hc"
#include "datetime.hc"
#include "md5.hc"

#ifdef _LIBYOYO
#define _YO_XDDBFS_BUILTIN
#endif

typedef struct _YO_XDDBFS
  {
    YO_XDDB xddb;
    char *basepath;
    int  jur_fd;
    int  fs_depth;
  } YO_XDDBFS;

void YO_XDDBFS_Destruct(YO_XDDBFS *xddb)
  {
    if ( xddb->jur_fd >= 0 ) close(xddb->jur_fd);
    free(xddb->basepath);
    __Destruct(xddb);
  };

typedef struct _YO_XDDBFS_STREAM
  {
    YO_XDDBFS *xddb;
    char *key;
    char *tmp_path;
    int  mimetype;
    int  length;
    int  finished;
    int  fd;
    int  curpos;
  } YO_XDDBFS_STREAM;
  
typedef struct _YO_XDDBFS_STREAM_HEADER
  {
    char cr;
    char nl;
    char mimetype[4];
    char length[8];
    char lastacs[8];
    char created[8];
    char compressed;
    char keylen[2];
    char key[YO_XDDB_MAX_KEYLEN];
    char nulterm;
  } YO_XDDBFS_STREAM_HEADER;

void YO_XDDBFS_STREAM_Destruct(YO_XDDBFS_STREAM *strm)
  {
    if ( strm->tmp_path )
      {
        utf8_unlink(strm->tmp_path);
        free(strm->tmp_path);
      }
    if ( strm->fd >= 0 ) close(strm->fd);
    free(strm->key);
    __Unrefe(strm->xddb);
    __Destruct(strm);    
  };

char *Xddbfs_Tmp_File_Path_Sfx(YO_XDDBFS *xdb, char *sfx)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    char *S = Xddb_Build_Unique_Key();
    if ( sfx )
      S = Str_Concat(S,sfx);
    return Str_Join_3('/',xdb->basepath,"tmp",S);
  }
#endif
  ;

char *Xddbfs_File_Path_Sfx_Md5(YO_XDDBFS *xddb, byte_t *md5, char *sfx)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    char *S = 0;
    int i;
    char md5_hex[33] = {0};
    char hash[4*3] = "\0\0/\0\0/\0\0/\0\0";
    for ( i = 0; i < 16; ++i )
      Str_Hex_Byte(md5[i],0,md5_hex+i*2);
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

    return S;
  }
#endif
  ;
  
#define Xddbfs_File_Path(Co,Key) Xddbfs_File_Path_Sfx(Co,Key,0)
char *Xddbfs_File_Path_Sfx(YOYO_XDDBFS *xddb, char *key, char *sfx)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    char *S = 0;
    int i;

    if ( xddb->fs_depth < 0 )
      {
        int L = strlen(key);
        S = Str_Copy(key,L);
        for ( i = 0; i < L; ++i )
          {
            if ( S[i] == '/' )
              S[i] = '|';
            else if ( S[i] == '?' ) 
              S[i] = '&';
            else if ( S[i] == '*' ) 







|
|







|







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

    return S;
  }
#endif
  ;
  
#define Xddbfs_File_Path(Co,Key) Xddbfs_File_Path_Sfx(Co,Key,0)
char *Xddbfs_File_Path_Sfx(YO_XDDBFS *xddb, char *key, char *sfx)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    char *S = 0;
    int i;

    if ( xddb->fs_depth < 0 )
      {
        int L = strlen(key);
        S = Str_Copy_L(key,L);
        for ( i = 0; i < L; ++i )
          {
            if ( S[i] == '/' )
              S[i] = '|';
            else if ( S[i] == '?' ) 
              S[i] = '&';
            else if ( S[i] == '*' ) 
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
      }
      
    return S;
  }
#endif
  ;

YOYO_BUFFER *Xddbfs_Read_Id(YOYO_XDDBFS *xddb, char *coid, int count)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    YOYO_BUFFER *bf = 0;
    YOYO_FILE_STATS st = {0};
    File_Get_Stats(coid,&st,0);
        
    if ( st.f.exists )
      {
        void *foj = Cfile_Open_Raw(coid,"rb");
        if ( !foj )
          Raise_If_File_Error("open",coid);
        if ( count < 0 )







|
|

|
|
|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
      }
      
    return S;
  }
#endif
  ;

YO_BUFFER *Xddbfs_Read_Id(YO_XDDBFS *xddb, char *coid, int count)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    YO_BUFFER *bf = 0;
    YO_FILE_STATS st = {0};
    File_Get_Stats(coid,&st,1);
        
    if ( st.f.exists )
      {
        void *foj = Cfile_Open_Raw(coid,"rb");
        if ( !foj )
          Raise_If_File_Error("open",coid);
        if ( count < 0 )
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
      }
    
    return bf;
  }
#endif
  ;

void Xddbfs_Write_Id(YOYO_XDDBFS *xddb, char *coid, void *data, int count)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    void *foj = Cfile_Open(coid,"w+bP");
    Cfile_Write(foj,data,count,count);
    Cfile_Close(foj);
  }
#endif
  ;

YOYO_XDATA *Xddbfs_Get(YOYO_XDDBFS *xddb, char *key, YOYO_XDATA *dflt)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    YOYO_XDATA *doc = dflt;
    
    __Auto_Ptr(doc)
      {
        char *coid;
        YOYO_BUFFER *bf;
        
        coid = Xddbfs_File_Path(xddb,key);
        __Pfd_Lock(&xddb->jur_fd)
          bf = Xddbfs_Read_Id(xddb,coid,-1);
        
        if ( bf )
          doc = Xddb_Decode(xddb,bf->at,bf->count);
      }
    


    return doc;
  }
#endif
  ;

void Xddbfs_Delete(YOYO_XDDBFS *xddb, char *key)
#ifdef _YOYO_XDDBFS_BUILTIN 


















  {
    __Auto_Release
      {
        char *coid = Xddbfs_File_Path(xddb,key);
        __Pfd_Lock(&xddb->jur_fd)
          File_Unlink(coid,0);
      }
  }
#endif
  ;

int Xddbfs_Store(YOYO_XDDBFS *xddb, YOYO_XDATA *doc, int strict_revision)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    int revision = 0; 
    
    __Auto_Release
      {
        //byte_t md5[16];
        char *key;
        char *coid;
        YOYO_BUFFER *bf;
        
        key = Xnode_Value_Get_Str(&doc->root,"$key$",0);
        if ( !key )
          __Raise(YOYO_ERROR_ILLFORMED,"$key$ property doesn't present or has invalid value");
        
        //Md5_Sign_Data(key,strlen(key),md5);
        coid = Xddbfs_File_Path(xddb,key);
        
        __Pfd_Lock(&xddb->jur_fd)
          {
            bf = Xddbfs_Read_Id(xddb,coid,8);
            if ( bf ) revision = Hex8_To_Unsigned(bf->at);
            
            if ( strict_revision )
              if ( revision && revision != Xdata_Get_Revision(doc) )
                __Raise(YOYO_ERROR_INCONSISTENT,
                  __Format("Inconsistent revision of document '%s', store:%d != docu:%d",
                           coid,
                           revision,
                           Xdata_Get_Revision(doc)));              
            
            ++revision;
            Xdata_Set_Revision(doc,revision);
            bf = Xddb_Encode(xddb,doc);
            Xddbfs_Write_Id(xddb,coid,bf->at,bf->count);
          }
      }
      
    return revision;
  }
#endif
  ;

void Xddbfs_Strm_Delete(YOYO_XDDBFS *co, char *key)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    __Auto_Release
      {
        char *path = Xddbfs_File_Path_Sfx(co,key,".strm");
        File_Unlink(path,0);
      }
  }
#endif
  ;

char *Xddbfs_Strm_Commit(YOYO_XDDBFS_STREAM *strm, char *key, int overwrite)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    __Auto_Ptr(key)
      {
        int keylen; 
        char *coid;
        YOYO_XDATA_CO_FS_STRM_HEADER hdr = {0};
        uint_t now;

        if ( key && strlen(key) > YOYO_XDATA_CO_MAX_FS_KEYLEN )
          __Raise_Format(YOYO_ERROR_ILLFORMED,
              (__yoTa("key to long, max key len is %d symbols",0),YOYO_XDATA_CO_MAX_FS_KEYLEN));
        
        if ( strm->key )
          __Raise(YOYO_ERROR_IO,__yoTa("stream already commited",0));
          
        if ( strm->fd >= 0 )
          {
            now = Get_Curr_Date();
            Unsigned_To_Hex8(now,hdr.created);
            Unsigned_To_Hex8(now,hdr.lastacs);
            hdr.compressed = '.';







|
|








|
|

|




|






|


>
>





|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
|








|



|










|
|



|


|
|









|
|










|
|





|


|
|
|


|







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
      }
    
    return bf;
  }
#endif
  ;

void Xddbfs_Write_Id(YO_XDDBFS *xddb, char *coid, void *data, int count)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    void *foj = Cfile_Open(coid,"w+bP");
    Cfile_Write(foj,data,count,count);
    Cfile_Close(foj);
  }
#endif
  ;

YO_XDATA *Xddbfs_Get(YO_XDDBFS *xddb, char *key, YO_XDATA *dflt)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    YO_XDATA *doc = dflt;
    
    __Auto_Ptr(doc)
      {
        char *coid;
        YO_BUFFER *bf;
        
        coid = Xddbfs_File_Path(xddb,key);
        __Pfd_Lock(&xddb->jur_fd)
          bf = Xddbfs_Read_Id(xddb,coid,-1);
        
        if ( bf )
          doc = Xddb_Decode(&xddb->xddb,bf->at,bf->count);
      }
    
    if ( doc == XDDB_RAISE_IF_DSNT_EXSIS )
      __Raise_Format(YO_ERROR_DSNT_EXIST,(__yoTa("Xddbfs doesn't have document '%s'",0),key));
    return doc;
  }
#endif
  ;

int Xddbfs_Has(YO_XDDBFS *xddb, char *key)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    int exists = 0;
    __Auto_Release
      {
        char *coid;
        YO_BUFFER *bf;
        YO_FILE_STATS st = {0};
        coid = Xddbfs_File_Path(xddb,key);
        File_Get_Stats(coid,&st,1);
        exists = st.f.exists;        
      }
    return exists;
  }
#endif
  ;

void Xddbfs_Delete(YO_XDDBFS *xddb, char *key)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    __Auto_Release
      {
        char *coid = Xddbfs_File_Path(xddb,key);
        __Pfd_Lock(&xddb->jur_fd)
          File_Unlink(coid,0);
      }
  }
#endif
  ;

int Xddbfs_Store(YO_XDDBFS *xddb, YO_XDATA *doc, int strict_revision)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    int revision = 0; 
    
    __Auto_Release
      {
        //byte_t md5[16];
        char *key;
        char *coid;
        YO_BUFFER *bf;
        
        key = Xnode_Value_Get_Str(&doc->root,"$key$",0);
        if ( !key )
          __Raise(YO_ERROR_ILLFORMED,"$key$ property doesn't present or has invalid value");
        
        //Md5_Sign_Data(key,strlen(key),md5);
        coid = Xddbfs_File_Path(xddb,key);
        
        __Pfd_Lock(&xddb->jur_fd)
          {
            bf = Xddbfs_Read_Id(xddb,coid,8);
            if ( bf ) revision = Hex8_To_Unsigned(bf->at);
            
            if ( strict_revision )
              if ( revision && revision != Xddb_Get_Revision(doc) )
                __Raise(YO_ERROR_INCONSISTENT,
                  __Format("Inconsistent revision of document '%s', store:%d != docu:%d",
                           coid,
                           revision,
                           Xddb_Get_Revision(doc)));              
            
            ++revision;
            Xddb_Set_Revision(doc,revision);
            bf = Xddb_Encode(&xddb->xddb,doc);
            Xddbfs_Write_Id(xddb,coid,bf->at,bf->count);
          }
      }
      
    return revision;
  }
#endif
  ;

void Xddbfs_Strm_Delete(YO_XDDBFS *co, char *key)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    __Auto_Release
      {
        char *path = Xddbfs_File_Path_Sfx(co,key,".strm");
        File_Unlink(path,0);
      }
  }
#endif
  ;

char *Xddbfs_Strm_Commit(YO_XDDBFS_STREAM *strm, char *key, int overwrite)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    __Auto_Ptr(key)
      {
        int keylen; 
        char *coid;
        YO_XDDBFS_STREAM_HEADER hdr = {0};
        uint_t now;

        if ( key && strlen(key) > YO_XDDB_MAX_KEYLEN )
          __Raise_Format(YO_ERROR_ILLFORMED,
              (__yoTa("key to long, max key len is %d symbols",0),YO_XDDB_MAX_KEYLEN));
        
        if ( strm->key )
          __Raise(YO_ERROR_IO,__yoTa("stream already commited",0));
          
        if ( strm->fd >= 0 )
          {
            now = Get_Curr_Date();
            Unsigned_To_Hex8(now,hdr.created);
            Unsigned_To_Hex8(now,hdr.lastacs);
            hdr.compressed = '.';
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
            
            coid = Xddbfs_File_Path_Sfx(strm->xddb,strm->key,".strm");
            if ( File_Exists(coid) )
              {
                if ( overwrite ) 
                  File_Unlink(coid,0);
                else
                  __Raise(YOYO_ERROR_IO,__yoTa("stream conflicts with one exist",0));
              }
            Create_Required_Dirs(coid);
            File_Rename(strm->tmp_path,coid);
          }
        else
          __Raise(YOYO_ERROR_IO,__yoTa("stream is not ready",0));
      }
      
    return strm->key;
  }
#endif
  ;

int Xddbfs_Strm_Read(YOYO_XDDBFS_STREAM *strm,void *data, int count,int mincount)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    int i;
    
    if ( !strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YOYO_ERROR_IO,__yoTa("stream alrady closed",0));
    if ( count > strm->length - strm->curpos )
      count = strm->length - strm->curpos;
    
    for ( i=0; i<count; )
      {
        int j = read(strm->fd,(char*)data+i,count-i);
        if ( j < 0 )
          {
            int err = errno;
            __Raise(YOYO_ERROR_IO,
              __Format(__yoTa("failed to read stream: %s",0),strerror(err)));
          }
        else if ( j )
          i+=j;
        else
          break;
      }
    
    if ( i < mincount )
      __Raise(YOYO_ERROR_IO_EOF,__yoTa("doesn't have enough bytes",0));
      
    strm->curpos += i;
    return i;
  }
#endif
  ;

int Xddbfs_Strm_Write(YOYO_XDDBFS_STREAM *strm,void *data, int count,int mincount)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    int i;
    
    if ( strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("readonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YOYO_ERROR_IO,__yoTa("stream alrady closed",0));
    
    for ( i=0; i<count; )
      {
        int j = write(strm->fd,(char*)data+i,count-i);
        if ( j < 0 )
          {
            int err = errno;
            __Raise(YOYO_ERROR_IO,__Format(__yoTa("failed to write stream: %s",0),strerror(err)));
          }
        else
          i+=j;
      }
    
    strm->length += i;
    return i;
  }
#endif
  ;

void Xddbfs_Strm_Rewind(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YOYO_ERROR_IO,__yoTa("stream alrady closed",0));
    Lseek_Raise(strm->fd,0);
    strm->curpos = 0;
  }
#endif
  ;

void Xddbfs_Strm_Skip(YOYO_XDDBFS_STREAM *strm, int count)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YOYO_ERROR_IO,__yoTa("stream alrady closed",0));
    if ( count > strm->length - strm->curpos )
      __Raise(YOYO_ERROR_IO,__yoTa("skip out of stream",0));
    if ( count )
      Lseek_Raise(strm->fd,strm->curpos+count);
    strm->curpos += count;
  }
#endif
  ;

int Xddbfs_Strm_Available(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YOYO_ERROR_IO,__yoTa("stream alrady closed",0));
    return strm->length - strm->curpos;
  }
#endif
  ;

int Xddbfs_Strm_Mimetype(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    return strm->mimetype;
  }
#endif
  ;

int Xddbfs_Strm_Length(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YOYO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    return strm->length;
  }
#endif
  ;

void Xddbfs_Strm_Close(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    if ( strm->fd >= 0 ) 
      {
        close(strm->fd);
        strm->fd = -1;
      }
  }
#endif
  ;

int Xddbfs_Strm_Eof(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    return !Xddbfs_Strm_Available(strm);
  }
#endif
  ;

void Xddbfs_Strm_Cancel(YOYO_XDDBFS_STREAM *strm)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    Xddbfs_Strm_Close(strm);
  }
#endif
  ;

YOYO_XDDBFS_STREAM *Xddbfs_Strm_Init(YOYO_XDDBFS *xddb, char *key, int mimetype, int mknew)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,       YOYO_XDDBFS_STREAM_Destruct},
        {Oj_Close_OjMID,          Xddbfs_Strm_Close},
        {Oj_Read_OjMID,           Xddbfs_Strm_Read},
        {Oj_Write_OjMID,          Xddbfs_Strm_Write},
        {Oj_Available_OjMID,      Xddbfs_Strm_Available},
        {Oj_Eof_OjMID,            Xddbfs_Strm_Eof},
        {Oj_Length_OjMID,         Xddbfs_Strm_Length},
        {Xddb_Strm_Cancel_OjMID,  Xddbfs_Strm_Cancel},
        {Xddb_Strm_Commit_OjMID,  Xddbfs_Strm_Commit},
        {Oj_Mimetype_Of_OjMID,    Xddbfs_Strm_Mimetype},
        {0}
      };
    YOYO_XDDBFS_STREAM *self = __Object(sizeof(YOYO_XDDBFS_STREAM),funcs);
    self->fd = -1;
    self->xddb = __Refe(xddb);

    if ( mknew )
      {
        if ( key )
          __Raise(YOYO_ERROR_INVALID_PARAM,__yoTa("key can't be specified on stream creation",0));
        self->mimetype = mimetype;
        self->tmp_path = __Retain(Xddbfs_Tmp_File_Path_Sfx(xddb,".strm"));
        if ( mknew != - 1)
          {
            self->fd = Open_File(self->tmp_path,O_CREAT|O_WRONLY);
            if ( self->fd < 0 )
              {
                int err = errno;
                __Raise_Format(YOYO_ERROR_IO,
                      (__yoTa("failed to create temprary file '%s': %s",0),self->tmp_path,strerror(err)));
              }
          }
      }
    else
      {
        char *coid;
        coid = Xdata_Co_Fs_File_Path_Sfx(xddb,key,".strm");

        self->key = Str_Copy_Npl(key,-1);
        self->finished = 1;
        self->fd = Open_File(coid,O_RDONLY);
        if ( self->fd < 0 )
          {
            int err = errno;
            __Raise_Format(YOYO_ERROR_DOESNT_EXIST,
                  (__yoTa("failed to open stream object '%s'(%s): %s",0),key,coid,strerror(err)));
          }
        __Gogo
          {
            int keylen;
            YOYO_XDATA_CO_FS_STRM_HEADER hdr = {0};
            Lseek_Raise(self->fd,-sizeof(hdr));
            Read_Into_Raise(self->fd,&hdr,sizeof(hdr));
            Lseek_Raise(self->fd,0);
            self->mimetype = Four_To_Unsigned(hdr.mimetype);
            self->length = Hex8_To_Unsigned(hdr.length);
            keylen = Hex2_To_Unsigned(hdr.keylen);
            if ( keylen < sizeof(hdr.key) )
              hdr.key[keylen] = 0;
            hdr.nulterm = 0;
            if ( keylen != strlen(self->key) || 0 != strncmp(self->key,hdr.key,keylen) )
              __Raise_Format(YOYO_ERROR_CORRUPTED,
                  (__yoTa("failed to open stream '%s': specified key does not match to '%s'/%d",0),key,hdr.key,keylen));
          }
      }
    return self;
  }
#endif
  ;

YOYO_XDDBFS_STREAM *Xddbfs_Strm_Open(YOYO_XDDBFS *xddb, char *key)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    return Xddbfs_Strm_Init(xddb,key,0,0);
  }
#endif
  ;
    
YOYO_XDDBFS_STREAM *Xddbfs_Strm_Create(YOYO_XDDBFS *xddb, int mimetype)
#ifdef _YOYO_XDDBFS_BUILTIN 
  {
    return Xddbfs_Strm_Init(xddb,,mimetype,1);
  }




#ifdef _YOYO_XDDBFS_BUILTIN 




  ;
  
YOYO_XDATA_CO *Xddbfs_Open(char *path, int create_new, int format, int depth)
#ifdef _YOYO_XDATACO_BUILTIN 
  {
    static YOYO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,       YOYO_XDDBFS_Destruct},
        {Xddb_Delete_OjMID,       Xddbfs_Delete},
        {Xddb_Get_OjMID,          Xddbfs_Get},

        {Xddb_Store_OjMID,        Xddbfs_Store},
        {Xddb_Strm_Open_OjMID,    Xddbfs_Strm_Open},
        {Xddb_Strm_Create_OjMID,  Xddbfs_Strm_Create},
        {Xddb_Strm_Delete_OjMID,  Xddbfs_Strm_Delete},

        {0}
      };

    YOYO_XDATA *xcf;
    YOYO_XDDBFS *xddb = 0;
    YOYO_FILE_STATS bp_stats = {0};
    YOYO_FILE_STATS jr_stats = {0};
    YOYO_FILE_STATS cf_stats = {0};
    char *cf_name,*jr_name,*tmp_dir;
    
    if ( !format ) format = YOYO_XDDB_DOC_TEXT;
    if ( depth & ( depth != 1 && depth != 2 && depth != 4 ) )
      __Raise_Format(YOYO_ERROR_INVALID_PARAM,(__yoTa("invalid depth value %d",0),depth));
    
    __Auto_Ptr(xddb)
      {
        cf_name = Str_Join_2('/',path,".coconf");
        jr_name = Str_Join_2('/',path,".cojur");
        tmp_dir = Str_Join_2('/',path,"tmp");
    
        File_Get_Stats(path,&bp_stats,1);
        File_Get_Stats(cf_name,&cf_stats,1);
        File_Get_Stats(jr_name,&jr_stats,1);
    
        if ( create_new )
          {








            int foo;
            if ( jr_stats.f.exists )
              __Raise_Format(YOYO_ERROR_ALREADY_EXISTS,
                              (__yoTa("collection '%s' already exists",0),path));
            if ( !cf_stats.f.exists ) __Auto_Release 
              {
                char *cf = __Format(__yoTa("depth = %d\nformat = %d\n",0),depth,format);
                int cf_len = strlen(cf);
                Cfile_Write(Cfile_Open(cf_name,"nP"),cf,cf_len,cf_len);
              }
            foo = open(jr_name,O_CREAT|O_WRONLY,0660);
            if ( foo >= 0 )
              close(foo);
            else
              Raise_If_File_Error(__yoTa("create",0),jr_name);
          }
        else
          {
            if ( !bp_stats.f.exists || !cf_stats.f.exists || !jr_stats.f.exists )
              __Raise_Format(YOYO_ERROR_DOESNT_EXIST,
                              (__yoTa("collection '%s' doesn't exist",0),path));
          }
        
        xcf = Def_Parse_File(cf_name);
        xddb = __Object(sizeof(YOYO_XDDBFS),funcs);
        xddb->basepath = Str_Copy_Npl(path,-1);
        xddb->fs_depth = Xnode_Value_Get_Int(xcf,"depth",0);
        xddb->xddb.doc_format = Xnode_Value_Get_Int(xcf,"format",0);
        
        xddb->jur_fd = open(jr_name,O_WRONLY|O_APPEND);
        if ( xddb->jur_fd < 0 ) 
          Raise_If_File_Error("open",jr_name); 
        
        if ( !File_Exists(tmp_dir) )
          Create_Directory(tmp_dir);
      }
      
    return xddb;
  }
#endif
  ;

#endif /* C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF */








|





|







|
|




|

|









|









|







|
|




|

|







|











|
|


|

|






|
|


|

|

|







|
|


|

|





|
|






|
|


|





|
|










|
|






|
|






|
|

|

|











|






|








|







|







|





|










|








|
|






|
|

|

>
>
>
>
|
>
>
>
>

|
|
|

|

|


>




>



|
|
|
|
|


|

|










|
|

>
>
>
>
>
>
>
>

|
|
















|



|
|












|






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
            
            coid = Xddbfs_File_Path_Sfx(strm->xddb,strm->key,".strm");
            if ( File_Exists(coid) )
              {
                if ( overwrite ) 
                  File_Unlink(coid,0);
                else
                  __Raise(YO_ERROR_IO,__yoTa("stream conflicts with one exist",0));
              }
            Create_Required_Dirs(coid);
            File_Rename(strm->tmp_path,coid);
          }
        else
          __Raise(YO_ERROR_IO,__yoTa("stream is not ready",0));
      }
      
    return strm->key;
  }
#endif
  ;

int Xddbfs_Strm_Read(YO_XDDBFS_STREAM *strm,void *data, int count,int mincount)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    int i;
    
    if ( !strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YO_ERROR_IO,__yoTa("stream alrady closed",0));
    if ( count > strm->length - strm->curpos )
      count = strm->length - strm->curpos;
    
    for ( i=0; i<count; )
      {
        int j = read(strm->fd,(char*)data+i,count-i);
        if ( j < 0 )
          {
            int err = errno;
            __Raise(YO_ERROR_IO,
              __Format(__yoTa("failed to read stream: %s",0),strerror(err)));
          }
        else if ( j )
          i+=j;
        else
          break;
      }
    
    if ( i < mincount )
      __Raise(YO_ERROR_IO_EOF,__yoTa("doesn't have enough bytes",0));
      
    strm->curpos += i;
    return i;
  }
#endif
  ;

int Xddbfs_Strm_Write(YO_XDDBFS_STREAM *strm,void *data, int count,int mincount)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    int i;
    
    if ( strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("readonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YO_ERROR_IO,__yoTa("stream alrady closed",0));
    
    for ( i=0; i<count; )
      {
        int j = write(strm->fd,(char*)data+i,count-i);
        if ( j < 0 )
          {
            int err = errno;
            __Raise(YO_ERROR_IO,__Format(__yoTa("failed to write stream: %s",0),strerror(err)));
          }
        else
          i+=j;
      }
    
    strm->length += i;
    return i;
  }
#endif
  ;

void Xddbfs_Strm_Rewind(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YO_ERROR_IO,__yoTa("stream alrady closed",0));
    Lseek_Raise(strm->fd,0);
    strm->curpos = 0;
  }
#endif
  ;

void Xddbfs_Strm_Skip(YO_XDDBFS_STREAM *strm, int count)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YO_ERROR_IO,__yoTa("stream alrady closed",0));
    if ( count > strm->length - strm->curpos )
      __Raise(YO_ERROR_IO,__yoTa("skip out of stream",0));
    if ( count )
      Lseek_Raise(strm->fd,strm->curpos+count);
    strm->curpos += count;
  }
#endif
  ;

int Xddbfs_Strm_Available(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    if ( strm->fd < 0 )
      __Raise(YO_ERROR_IO,__yoTa("stream alrady closed",0));
    return strm->length - strm->curpos;
  }
#endif
  ;

int Xddbfs_Strm_Mimetype(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    return strm->mimetype;
  }
#endif
  ;

int Xddbfs_Strm_Length(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    if ( !strm->finished )
      __Raise(YO_ERROR_ACCESS_DENAIED,__yoTa("writeonly stream!",0));
    return strm->length;
  }
#endif
  ;

void Xddbfs_Strm_Close(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    if ( strm->fd >= 0 ) 
      {
        close(strm->fd);
        strm->fd = -1;
      }
  }
#endif
  ;

int Xddbfs_Strm_Eof(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    return !Xddbfs_Strm_Available(strm);
  }
#endif
  ;

void Xddbfs_Strm_Cancel(YO_XDDBFS_STREAM *strm)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    Xddbfs_Strm_Close(strm);
  }
#endif
  ;

YO_XDDBFS_STREAM *Xddbfs_Strm_Init(YO_XDDBFS *xddb, char *key, int mimetype, int mknew)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,       YO_XDDBFS_STREAM_Destruct},
        {Oj_Close_OjMID,          Xddbfs_Strm_Close},
        {Oj_Read_OjMID,           Xddbfs_Strm_Read},
        {Oj_Write_OjMID,          Xddbfs_Strm_Write},
        {Oj_Available_OjMID,      Xddbfs_Strm_Available},
        {Oj_Eof_OjMID,            Xddbfs_Strm_Eof},
        {Oj_Length_OjMID,         Xddbfs_Strm_Length},
        {Xddb_Strm_Cancel_OjMID,  Xddbfs_Strm_Cancel},
        {Xddb_Strm_Commit_OjMID,  Xddbfs_Strm_Commit},
        {Oj_Mimetype_Of_OjMID,    Xddbfs_Strm_Mimetype},
        {0}
      };
    YO_XDDBFS_STREAM *self = __Object(sizeof(YO_XDDBFS_STREAM),funcs);
    self->fd = -1;
    self->xddb = __Refe(xddb);

    if ( mknew )
      {
        if ( key )
          __Raise(YO_ERROR_INVALID_PARAM,__yoTa("key can't be specified on stream creation",0));
        self->mimetype = mimetype;
        self->tmp_path = __Retain(Xddbfs_Tmp_File_Path_Sfx(xddb,".strm"));
        if ( mknew != - 1)
          {
            self->fd = Open_File(self->tmp_path,O_CREAT|O_WRONLY);
            if ( self->fd < 0 )
              {
                int err = errno;
                __Raise_Format(YO_ERROR_IO,
                      (__yoTa("failed to create temprary file '%s': %s",0),self->tmp_path,strerror(err)));
              }
          }
      }
    else
      {
        char *coid;
        coid = Xddbfs_File_Path_Sfx(xddb,key,".strm");

        self->key = Str_Copy_Npl(key,-1);
        self->finished = 1;
        self->fd = Open_File(coid,O_RDONLY);
        if ( self->fd < 0 )
          {
            int err = errno;
            __Raise_Format(YO_ERROR_DOESNT_EXIST,
                  (__yoTa("failed to open stream object '%s'(%s): %s",0),key,coid,strerror(err)));
          }
        __Gogo
          {
            int keylen;
            YO_XDDBFS_STREAM_HEADER hdr = {0};
            Lseek_Raise(self->fd,-sizeof(hdr));
            Read_Into_Raise(self->fd,&hdr,sizeof(hdr));
            Lseek_Raise(self->fd,0);
            self->mimetype = Four_To_Unsigned(hdr.mimetype);
            self->length = Hex8_To_Unsigned(hdr.length);
            keylen = Hex2_To_Unsigned(hdr.keylen);
            if ( keylen < sizeof(hdr.key) )
              hdr.key[keylen] = 0;
            hdr.nulterm = 0;
            if ( keylen != strlen(self->key) || 0 != strncmp(self->key,hdr.key,keylen) )
              __Raise_Format(YO_ERROR_CORRUPTED,
                  (__yoTa("failed to open stream '%s': specified key does not match to '%s'/%d",0),key,hdr.key,keylen));
          }
      }
    return self;
  }
#endif
  ;

YO_XDDBFS_STREAM *Xddbfs_Strm_Open(YO_XDDBFS *xddb, char *key)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    return Xddbfs_Strm_Init(xddb,key,0,0);
  }
#endif
  ;
    
YO_XDDBFS_STREAM *Xddbfs_Strm_Create(YO_XDDBFS *xddb, int mimetype)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    return Xddbfs_Strm_Init(xddb,0,mimetype,1);
  }
#endif 
  ;
  
char *Xddbfs_Source_String(YO_XDDBFS *xddb)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    return __Format("fs:%s:%d",xddb->basepath,xddb->fs_depth);
  } 
#endif 
  ;

YO_XDDB *Xddbfs_Open(char *path, int create_new, int format, int depth)
#ifdef _YO_XDDBFS_BUILTIN 
  {
    static YO_FUNCTABLE funcs[] = 
      { {0},
        {Oj_Destruct_OjMID,       YO_XDDBFS_Destruct},
        {Xddb_Delete_OjMID,       Xddbfs_Delete},
        {Xddb_Get_OjMID,          Xddbfs_Get},
        {Xddb_Has_OjMID,          Xddbfs_Has},
        {Xddb_Store_OjMID,        Xddbfs_Store},
        {Xddb_Strm_Open_OjMID,    Xddbfs_Strm_Open},
        {Xddb_Strm_Create_OjMID,  Xddbfs_Strm_Create},
        {Xddb_Strm_Delete_OjMID,  Xddbfs_Strm_Delete},
        {Xddb_Source_String_OjMID,Xddbfs_Source_String},
        {0}
      };

    YO_XNODE *xcf;
    YO_XDDBFS *xddb = 0;
    YO_FILE_STATS bp_stats = {0};
    YO_FILE_STATS jr_stats = {0};
    YO_FILE_STATS cf_stats = {0};
    char *cf_name,*jr_name,*tmp_dir;
    
    if ( !format ) format = XDDB_FORMAT_TEXT;
    if ( depth & ( depth != 1 && depth != 2 && depth != 4 ) )
      __Raise_Format(YO_ERROR_INVALID_PARAM,(__yoTa("invalid depth value %d",0),depth));
    
    __Auto_Ptr(xddb)
      {
        cf_name = Str_Join_2('/',path,".coconf");
        jr_name = Str_Join_2('/',path,".cojur");
        tmp_dir = Str_Join_2('/',path,"tmp");
    
        File_Get_Stats(path,&bp_stats,1);
        File_Get_Stats(cf_name,&cf_stats,1);
        File_Get_Stats(jr_name,&jr_stats,1);
        
        if ( create_new == XDDB_CREATE_ALWAYS && jr_stats.f.exists )
          {
            File_Unlink(path,1);
            File_Get_Stats(jr_name,&jr_stats,1);
            File_Get_Stats(cf_name,&cf_stats,1);
            File_Get_Stats(jr_name,&jr_stats,1);
          }
           
        if ( create_new != XDDB_OPEN_EXISTING && create_new != XDDB_OPEN_READONLY )
          {
            int foo;
            if ( jr_stats.f.exists && create_new == XDDB_CREATE_NEW )
              __Raise_Format(YO_ERROR_ALREADY_EXISTS,
                              (__yoTa("collection '%s' already exists",0),path));
            if ( !cf_stats.f.exists ) __Auto_Release 
              {
                char *cf = __Format(__yoTa("depth = %d\nformat = %d\n",0),depth,format);
                int cf_len = strlen(cf);
                Cfile_Write(Cfile_Open(cf_name,"nP"),cf,cf_len,cf_len);
              }
            foo = open(jr_name,O_CREAT|O_WRONLY,0660);
            if ( foo >= 0 )
              close(foo);
            else
              Raise_If_File_Error(__yoTa("create",0),jr_name);
          }
        else
          {
            if ( !bp_stats.f.exists || !cf_stats.f.exists || !jr_stats.f.exists )
              __Raise_Format(YO_ERROR_DOESNT_EXIST,
                              (__yoTa("collection '%s' doesn't exist",0),path));
          }
        
        xcf = &Def_Parse_File(cf_name)->root;
        xddb = __Object(sizeof(YO_XDDBFS),funcs);
        xddb->basepath = Str_Copy_Npl(path,-1);
        xddb->fs_depth = Xnode_Value_Get_Int(xcf,"depth",0);
        xddb->xddb.doc_format = Xnode_Value_Get_Int(xcf,"format",0);
        
        xddb->jur_fd = open(jr_name,O_WRONLY|O_APPEND);
        if ( xddb->jur_fd < 0 ) 
          Raise_If_File_Error("open",jr_name); 
        
        if ( !File_Exists(tmp_dir) )
          Create_Directory(tmp_dir);
      }
      
    return &xddb->xddb;
  }
#endif
  ;

#endif /* C_once_BAF0727D_FCA6_445A_8E5A_0EEAA9374EEF */

Changes to xdef.hc.
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

*/

#ifndef C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF
#define C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF

#ifdef _LIBYOYO
#define _YOYO_XDEF_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "xdata.hc"
#include "file.hc"

enum
  {
    YOYO_XDEF_INDENT_WIDTH = 2,
    XDEF_FORMAT_XDEF = 0,
    XDEF_FORMAT_JSON = 0x100,
    XDEF_FORMAT_MASK = 0x300,
  };

typedef struct _YOYO_XDEF_STATE
  {
    char *text;
    int lineno;
  } YOYO_XDEF_STATE;

void Def_Parse_Skip_Spaces(YOYO_XDEF_STATE *st)
#ifdef _YOYO_XDEF_BUILTIN
  {
    while ( *st->text && Isspace(*st->text) )
      {
        if ( *st->text == '\n' ) ++st->lineno;
        ++st->text;
      }
  }
#endif
  ;

char *Def_Parse_Get_Literal(YOYO_XDEF_STATE *st)
#ifdef _YOYO_XDEF_BUILTIN
  {
    int capacity = 127;
    int len = 0;
    char *out = 0;
    
    if ( *st->text == '"' || *st->text == '\'')
      {







|










|





|



|

|
|










|
|







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

*/

#ifndef C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF
#define C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF

#ifdef _LIBYOYO
#define _YO_XDEF_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "xdata.hc"
#include "file.hc"

enum
  {
    YO_XDEF_INDENT_WIDTH = 2,
    XDEF_FORMAT_XDEF = 0,
    XDEF_FORMAT_JSON = 0x100,
    XDEF_FORMAT_MASK = 0x300,
  };

typedef struct _YO_XDEF_STATE
  {
    char *text;
    int lineno;
  } YO_XDEF_STATE;

void Def_Parse_Skip_Spaces(YO_XDEF_STATE *st)
#ifdef _YO_XDEF_BUILTIN
  {
    while ( *st->text && Isspace(*st->text) )
      {
        if ( *st->text == '\n' ) ++st->lineno;
        ++st->text;
      }
  }
#endif
  ;

char *Def_Parse_Get_Literal(YO_XDEF_STATE *st)
#ifdef _YO_XDEF_BUILTIN
  {
    int capacity = 127;
    int len = 0;
    char *out = 0;
    
    if ( *st->text == '"' || *st->text == '\'')
      {
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
                else if ( *st->text == 'n' )
                  __Vector_Append(&out,&len,&capacity,"\n",1);
                else if ( *st->text == 'r' )
                  __Vector_Append(&out,&len,&capacity,"\r",1);
                else if ( *st->text == 't' )
                  __Vector_Append(&out,&len,&capacity,"\t",1);
                else 
                  __Raise(YOYO_ERROR_ILLFORMED,__Format("invalid esc sequence at line %d",st->lineno));
              }
            else
              __Vector_Append(&out,&len,&capacity,st->text,1);
          }
          
        if ( *st->text == brk ) ++st->text;
      }







|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
                else if ( *st->text == 'n' )
                  __Vector_Append(&out,&len,&capacity,"\n",1);
                else if ( *st->text == 'r' )
                  __Vector_Append(&out,&len,&capacity,"\r",1);
                else if ( *st->text == 't' )
                  __Vector_Append(&out,&len,&capacity,"\t",1);
                else 
                  __Raise(YO_ERROR_ILLFORMED,__Format("invalid esc sequence at line %d",st->lineno));
              }
            else
              __Vector_Append(&out,&len,&capacity,st->text,1);
          }
          
        if ( *st->text == brk ) ++st->text;
      }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
    
    return out;
  }
#endif
  ;


char *Def_Parse_Get_Node_Literal(YOYO_XDEF_STATE *st)
#ifdef _YOYO_XDEF_BUILTIN
  {
    if ( *st->text == '"' || *st->text == '\'' )
      return Def_Parse_Get_Literal(st);
    else
      {
        int capacity = 127;
        int len = 0;







|
|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
    
    return out;
  }
#endif
  ;


char *Def_Parse_Get_Node_Literal(YO_XDEF_STATE *st)
#ifdef _YO_XDEF_BUILTIN
  {
    if ( *st->text == '"' || *st->text == '\'' )
      return Def_Parse_Get_Literal(st);
    else
      {
        int capacity = 127;
        int len = 0;
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
  ;

typedef struct
  {
    int type;
    union
      {
        YOYO_ARRAY  *arr;
        YOYO_BUFFER *dat;
        char   *txt;
        int     dec;
        double  flt;
      };
  } YOYO_XDEF_VALUE;

void Def_Parse_Get_Value(YOYO_XDEF_STATE *st, YOYO_XDEF_VALUE *val)
#ifdef _YOYO_XDEF_BUILTIN
  {
    if ( *st->text == '[' )
      {
        ++st->text;
        if ( st->text[1] == '[' ) /* binary data */
          {
            byte_t b;
            val->dat = Buffer_Init(0);
            Def_Parse_Skip_Spaces(st);
            
            while ( Isxdigit(*st->text) )
              {
                if ( !Isxdigit(st->text[1]) )
                  __Raise(YOYO_ERROR_ILLFORMED,
                      __Format("expected hex byte value at line %d",st->lineno));
                
                b = Str_Unhex_Byte(st->text,0,0);
                Buffer_Append(val->dat,&b,1);
                st->text += 2;
                Def_Parse_Skip_Spaces(st);
              }
            
            if ( !*st->text || *st->text != ']' || st->text[1] != ']' )
              __Raise(YOYO_ERROR_ILLFORMED,
                  __Format("expected ']]' at line %d",st->lineno));
            
            val->type = XVALUE_OPT_VALTYPE_BIN;
            st->text += 2;
          }
        else /* array */
          { 
            YOYO_XDEF_VALUE lval;
            Def_Parse_Skip_Spaces(st);
            Def_Parse_Get_Value(st,&lval);
            if ( lval.type == XVALUE_OPT_VALTYPE_STR )
              {
                val->arr = Array_Ptrs();
                val->type= XVALUE_OPT_VALTYPE_STR_ARR;
                Array_Push(val->arr,__Retain(lval.txt));







|
|




|

|
|













|









|







|







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
  ;

typedef struct
  {
    int type;
    union
      {
        YO_ARRAY  *arr;
        YO_BUFFER *dat;
        char   *txt;
        int     dec;
        double  flt;
      };
  } YO_XDEF_VALUE;

void Def_Parse_Get_Value(YO_XDEF_STATE *st, YO_XDEF_VALUE *val)
#ifdef _YO_XDEF_BUILTIN
  {
    if ( *st->text == '[' )
      {
        ++st->text;
        if ( st->text[1] == '[' ) /* binary data */
          {
            byte_t b;
            val->dat = Buffer_Init(0);
            Def_Parse_Skip_Spaces(st);
            
            while ( Isxdigit(*st->text) )
              {
                if ( !Isxdigit(st->text[1]) )
                  __Raise(YO_ERROR_ILLFORMED,
                      __Format("expected hex byte value at line %d",st->lineno));
                
                b = Str_Unhex_Byte(st->text,0,0);
                Buffer_Append(val->dat,&b,1);
                st->text += 2;
                Def_Parse_Skip_Spaces(st);
              }
            
            if ( !*st->text || *st->text != ']' || st->text[1] != ']' )
              __Raise(YO_ERROR_ILLFORMED,
                  __Format("expected ']]' at line %d",st->lineno));
            
            val->type = XVALUE_OPT_VALTYPE_BIN;
            st->text += 2;
          }
        else /* array */
          { 
            YO_XDEF_VALUE lval;
            Def_Parse_Skip_Spaces(st);
            Def_Parse_Get_Value(st,&lval);
            if ( lval.type == XVALUE_OPT_VALTYPE_STR )
              {
                val->arr = Array_Ptrs();
                val->type= XVALUE_OPT_VALTYPE_STR_ARR;
                Array_Push(val->arr,__Retain(lval.txt));
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
              {
                ++st->text;
                Def_Parse_Skip_Spaces(st);
                Def_Parse_Get_Value(st,&lval);
                if ( val->type == XVALUE_OPT_VALTYPE_STR )
                  {
                    if ( val->type != XVALUE_OPT_VALTYPE_STR )
                      __Raise(YOYO_ERROR_ILLFORMED,
                              __Format("expected string value at line %d",st->lineno));
                    Array_Push(val->arr,__Retain(lval.txt));
                  }
                else /* XVALUE_OPT_VALUETYPE_FLT_ARR */
                  {
                    
                    if ( lval.type == XVALUE_OPT_VALTYPE_INT )
                      {
                        double f = lval.dec;
                        Buffer_Append(val->dat,&f,sizeof(double));
                      }
                    else if ( lval.type == XVALUE_OPT_VALTYPE_FLT )
                        Buffer_Append(val->dat,&lval.flt,sizeof(double));
                    else
                      __Raise(YOYO_ERROR_ILLFORMED,
                              __Format("expected numeric value at line %d",st->lineno));
                  }
                Def_Parse_Skip_Spaces(st);
              }
            
            if ( *st->text != ']' )
              __Raise(YOYO_ERROR_ILLFORMED,
                  __Format("expected ']' at line %d",st->lineno));
                  
            ++st->text;
          }
      }
    else if ( *st->text == '#' )
      {







|














|






|







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
              {
                ++st->text;
                Def_Parse_Skip_Spaces(st);
                Def_Parse_Get_Value(st,&lval);
                if ( val->type == XVALUE_OPT_VALTYPE_STR )
                  {
                    if ( val->type != XVALUE_OPT_VALTYPE_STR )
                      __Raise(YO_ERROR_ILLFORMED,
                              __Format("expected string value at line %d",st->lineno));
                    Array_Push(val->arr,__Retain(lval.txt));
                  }
                else /* XVALUE_OPT_VALUETYPE_FLT_ARR */
                  {
                    
                    if ( lval.type == XVALUE_OPT_VALTYPE_INT )
                      {
                        double f = lval.dec;
                        Buffer_Append(val->dat,&f,sizeof(double));
                      }
                    else if ( lval.type == XVALUE_OPT_VALTYPE_FLT )
                        Buffer_Append(val->dat,&lval.flt,sizeof(double));
                    else
                      __Raise(YO_ERROR_ILLFORMED,
                              __Format("expected numeric value at line %d",st->lineno));
                  }
                Def_Parse_Skip_Spaces(st);
              }
            
            if ( *st->text != ']' )
              __Raise(YO_ERROR_ILLFORMED,
                  __Format("expected ']' at line %d",st->lineno));
                  
            ++st->text;
          }
      }
    else if ( *st->text == '#' )
      {
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
          || (Str_Starts_With(st->text+1,"0") && (l = 2)) )
          {
            val->dec = 0;
            val->type = XVALUE_OPT_VALTYPE_BOOL;
            st->text += l;
          }
        else
          __Raise(YOYO_ERROR_ILLFORMED,
              __Format("expected boolean value at line %d",st->lineno));
      }
    else if ( !Isdigit(*st->text) 
            && ( (*st->text != '.' && *st->text != '-') || !Isdigit(st->text[1]) ) )
      {
        val->txt = Def_Parse_Get_Literal(st);
        val->type = XVALUE_OPT_VALTYPE_STR;







|







278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
          || (Str_Starts_With(st->text+1,"0") && (l = 2)) )
          {
            val->dec = 0;
            val->type = XVALUE_OPT_VALTYPE_BOOL;
            st->text += l;
          }
        else
          __Raise(YO_ERROR_ILLFORMED,
              __Format("expected boolean value at line %d",st->lineno));
      }
    else if ( !Isdigit(*st->text) 
            && ( (*st->text != '.' && *st->text != '-') || !Isdigit(st->text[1]) ) )
      {
        val->txt = Def_Parse_Get_Literal(st);
        val->type = XVALUE_OPT_VALTYPE_STR;
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
              }
          }

        if ( *st->text 
          && !Isspace(*st->text) && *st->text != ')' 
          && *st->text != '}' && *st->text != ',' && *st->text != ']' )
      invalid_numeric:
          __Raise(YOYO_ERROR_ILLFORMED,
              __Format("invalid numeric value at line %d",st->lineno));
      }
  }
#endif
  ;

void Def_Parse_In_Node_Set_Value(YOYO_XNODE *n, char *name, YOYO_XDEF_VALUE *val)
#ifdef _YOYO_XDEF_BUILTIN
  {
    YOYO_XVALUE *xv = Xnode_Value(n,name,1);;
    switch ( val->type )
      {
        case XVALUE_OPT_VALTYPE_INT:
          Xvalue_Set_Int(xv,val->dec);
          break;
        case XVALUE_OPT_VALTYPE_BOOL:
          Xvalue_Set_Bool(xv,val->dec);







|






|
|

|







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
              }
          }

        if ( *st->text 
          && !Isspace(*st->text) && *st->text != ')' 
          && *st->text != '}' && *st->text != ',' && *st->text != ']' )
      invalid_numeric:
          __Raise(YO_ERROR_ILLFORMED,
              __Format("invalid numeric value at line %d",st->lineno));
      }
  }
#endif
  ;

void Def_Parse_In_Node_Set_Value(YO_XNODE *n, char *name, YO_XDEF_VALUE *val)
#ifdef _YO_XDEF_BUILTIN
  {
    YO_XVALUE *xv = Xnode_Value(n,name,1);;
    switch ( val->type )
      {
        case XVALUE_OPT_VALTYPE_INT:
          Xvalue_Set_Int(xv,val->dec);
          break;
        case XVALUE_OPT_VALTYPE_BOOL:
          Xvalue_Set_Bool(xv,val->dec);
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
        case XVALUE_OPT_VALTYPE_FLT_ARR:
          Xvalue_Put_Flt_Array(xv,__Refe(val->dat));
          break;
        case XVALUE_OPT_VALTYPE_STR_ARR:
          Xvalue_Put_Str_Array(xv,__Refe(val->arr));
          break;
        default:
          __Raise(YOYO_ERROR_UNEXPECTED_VALUE,0);
      }
      
  }
#endif
  ;

void Def_Parse_In_Node( YOYO_XDEF_STATE *st, YOYO_XNODE *n )
#ifdef _YOYO_XDEF_BUILTIN
  {
    Def_Parse_Skip_Spaces(st);
    
    for ( ; *st->text && *st->text != '}' ; Def_Parse_Skip_Spaces(st) ) 
      {
        int go_deeper = 0;
        YOYO_XNODE *nn = 0;
        
        __Auto_Release
          {
            YOYO_XDEF_VALUE value = {0};
            char *name; 
            
            name = Def_Parse_Get_Literal(st);
            Def_Parse_Skip_Spaces(st);

            if ( *st->text == '(' )
              {
                char *dflt;
                ++st->text;
                Def_Parse_Skip_Spaces(st);
                dflt = Def_Parse_Get_Node_Literal(st);
                Def_Parse_Skip_Spaces(st);
                if ( *st->text != ')' )
                  __Raise(YOYO_ERROR_ILLFORMED,__Format("expected ')' at line %d",st->lineno));
                ++st->text;
                Def_Parse_Skip_Spaces(st);

                nn = Xnode_Append(n,name);
                Xnode_Value_Set_Str(nn,"@",dflt);
                name = 0;
              }







|






|
|






|



|













|







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
        case XVALUE_OPT_VALTYPE_FLT_ARR:
          Xvalue_Put_Flt_Array(xv,__Refe(val->dat));
          break;
        case XVALUE_OPT_VALTYPE_STR_ARR:
          Xvalue_Put_Str_Array(xv,__Refe(val->arr));
          break;
        default:
          __Raise(YO_ERROR_UNEXPECTED_VALUE,0);
      }
      
  }
#endif
  ;

void Def_Parse_In_Node( YO_XDEF_STATE *st, YO_XNODE *n )
#ifdef _YO_XDEF_BUILTIN
  {
    Def_Parse_Skip_Spaces(st);
    
    for ( ; *st->text && *st->text != '}' ; Def_Parse_Skip_Spaces(st) ) 
      {
        int go_deeper = 0;
        YO_XNODE *nn = 0;
        
        __Auto_Release
          {
            YO_XDEF_VALUE value = {0};
            char *name; 
            
            name = Def_Parse_Get_Literal(st);
            Def_Parse_Skip_Spaces(st);

            if ( *st->text == '(' )
              {
                char *dflt;
                ++st->text;
                Def_Parse_Skip_Spaces(st);
                dflt = Def_Parse_Get_Node_Literal(st);
                Def_Parse_Skip_Spaces(st);
                if ( *st->text != ')' )
                  __Raise(YO_ERROR_ILLFORMED,__Format("expected ')' at line %d",st->lineno));
                ++st->text;
                Def_Parse_Skip_Spaces(st);

                nn = Xnode_Append(n,name);
                Xnode_Value_Set_Str(nn,"@",dflt);
                name = 0;
              }
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
              
          }
        
        if ( go_deeper )
          {
            Def_Parse_In_Node(st,nn);
            if ( *st->text != '}' )
              __Raise(YOYO_ERROR_ILLFORMED,__Format("expected '}' at line %d",st->lineno));
            ++st->text;
          }
      }
  }
#endif
  ;

YOYO_XDATA *Def_Parse_Str(char *text)
#ifdef _YOYO_XDEF_BUILTIN
  {
    YOYO_XDEF_STATE st = { text, 1 };
    YOYO_XDATA *doc = Xdata_Init();
    Def_Parse_In_Node(&st,&doc->root);
    return doc;
  }
#endif
  ;

YOYO_XDATA *Def_Parse_File(char *filename)
#ifdef _YOYO_XDEF_BUILTIN
  {
    YOYO_XDATA *ret = 0;
    
    __Auto_Ptr(ret)
      {
        YOYO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"rt"));
        ret = Def_Parse_Str((char*)bf->at);
      }
    return ret;
  }
#endif
  ;

void Def_Format_Node_In_Depth(YOYO_BUFFER *bf, YOYO_XNODE *r, int flags, int indent)
#ifdef _YOYO_XDEF_BUILTIN
  {
    __Gogo
      {
        YOYO_XVALUE *val = Xnode_First_Value(r);
        for ( ; val; val = Xnode_Next_Value(r,val) )
          {
            char *tag = Xnode_Value_Get_Tag(r,val);
            
            Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
            if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
              {
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf,tag,-1);
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf," : ",3);
              }







|







|
|

|
|






|
|

|



|







|
|



|




|







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
              
          }
        
        if ( go_deeper )
          {
            Def_Parse_In_Node(st,nn);
            if ( *st->text != '}' )
              __Raise(YO_ERROR_ILLFORMED,__Format("expected '}' at line %d",st->lineno));
            ++st->text;
          }
      }
  }
#endif
  ;

YO_XDATA *Def_Parse_Str(char *text)
#ifdef _YO_XDEF_BUILTIN
  {
    YO_XDEF_STATE st = { text, 1 };
    YO_XDATA *doc = Xdata_Init();
    Def_Parse_In_Node(&st,&doc->root);
    return doc;
  }
#endif
  ;

YO_XDATA *Def_Parse_File(char *filename)
#ifdef _YO_XDEF_BUILTIN
  {
    YO_XDATA *ret = 0;
    
    __Auto_Ptr(ret)
      {
        YO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"rt"));
        ret = Def_Parse_Str((char*)bf->at);
      }
    return ret;
  }
#endif
  ;

void Def_Format_Node_In_Depth(YO_BUFFER *bf, YO_XNODE *r, int flags, int indent)
#ifdef _YO_XDEF_BUILTIN
  {
    __Gogo
      {
        YO_XVALUE *val = Xnode_First_Value(r);
        for ( ; val; val = Xnode_Next_Value(r,val) )
          {
            char *tag = Xnode_Value_Get_Tag(r,val);
            
            Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
            if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
              {
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf,tag,-1);
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf," : ",3);
              }
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
                      int q = 0;
                      
                      Buffer_Append(bf,"[[",2);
                      
                      if ( val->binary->count > bytes_per_line )
                        {  
                          Buffer_Append(bf,"\n",1);
                          Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                        }
                        
                      while ( q < val->binary->count )
                        {
                          int l = val->binary->count - q;
                          if ( l > bytes_per_line ) l = bytes_per_line;
                          Buffer_Hex_Append(bf,val->binary->at+q,l);
                          q += l;
                          if ( q < val->binary->count )
                            {
                              Buffer_Append(bf,"\n",1);
                              Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                            }
                        }
                        
                      Buffer_Append(bf,"]]",2);
                    }
                  break;
                  
                case XVALUE_OPT_VALTYPE_STR_ARR:
                  {
                    int q = 0;
                    int count = Array_Count(val->strarr);
                    
                    Buffer_Append(bf,"[\n",2);
                    Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                      
                    for ( ; q < count; ++q )
                      {
                        Buffer_Append(bf,"\"",1);
                        Buffer_Quote_Append(bf,val->strarr->at[q],-1,'"');
                        Buffer_Fill_Append(bf,'"',1);
                        if ( q+1 < count ) Buffer_Fill_Append(bf,',',1);
                        Buffer_Fill_Append(bf,'\n',1);
                        Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                      }
                      
                    Buffer_Fill_Append(bf,']',1);
                    break;
                  }
                case XVALUE_OPT_VALTYPE_FLT_ARR:
                  {
                    int q = 0;
                    int nums_per_line = 5;
                    
                    Buffer_Fill_Append(bf,'[',1);
                    
                    if ( val->binary->count > nums_per_line*iszof_double )
                      {  
                        Buffer_Fill_Append(bf,'\n',1);
                        Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                      }
                      
                    while ( q+iszof_double <= val->binary->count )
                      {
                        int l = (val->binary->count - q)/iszof_double;
                        if ( l > nums_per_line ) l = nums_per_line;
                        for ( ; l > 0; --l )







|











|













|








|















|







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
                      int q = 0;
                      
                      Buffer_Append(bf,"[[",2);
                      
                      if ( val->binary->count > bytes_per_line )
                        {  
                          Buffer_Append(bf,"\n",1);
                          Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                        }
                        
                      while ( q < val->binary->count )
                        {
                          int l = val->binary->count - q;
                          if ( l > bytes_per_line ) l = bytes_per_line;
                          Buffer_Hex_Append(bf,val->binary->at+q,l);
                          q += l;
                          if ( q < val->binary->count )
                            {
                              Buffer_Append(bf,"\n",1);
                              Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                            }
                        }
                        
                      Buffer_Append(bf,"]]",2);
                    }
                  break;
                  
                case XVALUE_OPT_VALTYPE_STR_ARR:
                  {
                    int q = 0;
                    int count = Array_Count(val->strarr);
                    
                    Buffer_Append(bf,"[\n",2);
                    Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                      
                    for ( ; q < count; ++q )
                      {
                        Buffer_Append(bf,"\"",1);
                        Buffer_Quote_Append(bf,val->strarr->at[q],-1,'"');
                        Buffer_Fill_Append(bf,'"',1);
                        if ( q+1 < count ) Buffer_Fill_Append(bf,',',1);
                        Buffer_Fill_Append(bf,'\n',1);
                        Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                      }
                      
                    Buffer_Fill_Append(bf,']',1);
                    break;
                  }
                case XVALUE_OPT_VALTYPE_FLT_ARR:
                  {
                    int q = 0;
                    int nums_per_line = 5;
                    
                    Buffer_Fill_Append(bf,'[',1);
                    
                    if ( val->binary->count > nums_per_line*iszof_double )
                      {  
                        Buffer_Fill_Append(bf,'\n',1);
                        Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                      }
                      
                    while ( q+iszof_double <= val->binary->count )
                      {
                        int l = (val->binary->count - q)/iszof_double;
                        if ( l > nums_per_line ) l = nums_per_line;
                        for ( ; l > 0; --l )
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
                            q += iszof_double;
                            if ( q+iszof_double <= val->binary->count )
                            Buffer_Append(bf,",",1);
                          }
                        if ( q+iszof_double <= val->binary->count )
                          {
                            Buffer_Fill_Append(bf,'\n',1);
                            Buffer_Fill_Append(bf,' ',(indent+1)*YOYO_XDEF_INDENT_WIDTH);
                          }
                      }
                      
                    Buffer_Fill_Append(bf,']',1);
                    break;
                  }
              }
            
            if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
              if ( Xnode_Next_Value(r,val) || r->down )
                Buffer_Fill_Append(bf,',',1);
                
            Buffer_Fill_Append(bf,'\n',1);
          }
      }

    if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
      {
        u32_t *L;
        int i, ncount;
        YOYO_XNODE *n;
        r = Xnode_Refacc(r);
        n = Xnode_Down(r);
        if ( n )
          {
            ncount = Xnode_Count(r);
            L = alloca(32*ncount);
            L[0] = r->down|((u32_t)n->tag << 16);
            for ( i = 1; n->next; ++i ) 
              {
                YOYO_XNODE *nn = Xnode_Next(n);
                STRICT_REQUIRE(i<ncount);
                L[i] = n->next|((u32_t)nn->tag << 16);
                n = nn;
              }
            qsort(L,ncount,4,Compare_u32);
            for ( i = 0; i < ncount; )
              {
                char *tag = r->xdata->tags[(L[i]>>16)-1];
                n = Xdata_Idxref(r->xdata,L[i]&0x0ffff);
                Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf,tag,-1);
                if ( i + 1 < ncount && !((L[i]^L[i+1])>>16) )
                  {
                    Buffer_Append(bf,"\" : [",5);
                    for(;;) 
                      {
                        Buffer_Append(bf,"{\n",2);
                        Def_Format_Node_In_Depth(bf,n,flags,indent+1);
                        Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
                        Buffer_Fill_Append(bf,'}',1);
                        ++i;
                        if ( i < ncount && !((L[i-1]^L[i])>>16) )
                          {
                            Buffer_Fill_Append(bf,',',1);
                            Buffer_Fill_Append(bf,'\n',1);
                            Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
                            n = Xdata_Idxref(r->xdata,L[i]&0x0ffff);
                          }
                        else
                          break;
                      }
                    Buffer_Fill_Append(bf,']',1);
                  }
                else
                  {
                    Buffer_Append(bf,"\" : {\n",6);
                    Def_Format_Node_In_Depth(bf,n,flags,indent+1);
                    Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
                    Buffer_Fill_Append(bf,'}',1);
                    ++i;
                  }
                if ( i && i < ncount )
                  Buffer_Fill_Append(bf,',',1);
                Buffer_Fill_Append(bf,'\n',1);
              }
          }
      }
    else /* XDEF */
      {
        YOYO_XNODE *n = Xnode_Down(r);
        for ( ; n; n = Xnode_Next(n) )
          {
            Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
            Buffer_Append(bf,Xnode_Get_Tag(n),-1);
            Buffer_Append(bf," {\n",3);
            Def_Format_Node_In_Depth(bf,n,flags,indent+1);
            Buffer_Fill_Append(bf,' ',indent*YOYO_XDEF_INDENT_WIDTH);
            Buffer_Append(bf,"}\n",2);
          }
      }
  }
#endif
  ;

char *Def_Format_Into(YOYO_BUFFER *bf, YOYO_XNODE *r, int flags)
#ifdef _YOYO_XDEF_BUILTIN
  {
    int indent = (flags&0xff);
    if ( !bf ) bf = Buffer_Init(0);
    Def_Format_Node_In_Depth(bf,r,flags,indent);
    return (char*)bf->at;
  }
#endif
  ;
  
char *Def_Format(YOYO_XNODE *r, int flags)
#ifdef _YOYO_XDEF_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YOYO_BUFFER *bf = Buffer_Init(0);
        Def_Format_Into(bf,r,flags);
        ret = Buffer_Take_Data(bf);
      }
    return ret;
  }
#endif
  ;

void Def_Format_File(char *fname, YOYO_XNODE *r, int flags)
#ifdef _YOYO_XDEF_BUILTIN
  {
    __Auto_Release
      {
        YOYO_BUFFER *bf = Buffer_Init(0);
        Def_Format_Into(bf,r,flags);
        Oj_Write_Full(Cfile_Open(fname,"w+P"),bf->at,bf->count);
      }
  }
#endif
  ;

#endif /* C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF */








|




















|









|









|









|






|











|











|


|



|







|
|









|
|




|








|
|



|









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
                            q += iszof_double;
                            if ( q+iszof_double <= val->binary->count )
                            Buffer_Append(bf,",",1);
                          }
                        if ( q+iszof_double <= val->binary->count )
                          {
                            Buffer_Fill_Append(bf,'\n',1);
                            Buffer_Fill_Append(bf,' ',(indent+1)*YO_XDEF_INDENT_WIDTH);
                          }
                      }
                      
                    Buffer_Fill_Append(bf,']',1);
                    break;
                  }
              }
            
            if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
              if ( Xnode_Next_Value(r,val) || r->down )
                Buffer_Fill_Append(bf,',',1);
                
            Buffer_Fill_Append(bf,'\n',1);
          }
      }

    if ( (flags&XDEF_FORMAT_MASK) == XDEF_FORMAT_JSON )
      {
        u32_t *L;
        int i, ncount;
        YO_XNODE *n;
        r = Xnode_Refacc(r);
        n = Xnode_Down(r);
        if ( n )
          {
            ncount = Xnode_Count(r);
            L = alloca(32*ncount);
            L[0] = r->down|((u32_t)n->tag << 16);
            for ( i = 1; n->next; ++i ) 
              {
                YO_XNODE *nn = Xnode_Next(n);
                STRICT_REQUIRE(i<ncount);
                L[i] = n->next|((u32_t)nn->tag << 16);
                n = nn;
              }
            qsort(L,ncount,4,Compare_u32);
            for ( i = 0; i < ncount; )
              {
                char *tag = r->xdata->tags[(L[i]>>16)-1];
                n = Xdata_Idxref(r->xdata,L[i]&0x0ffff);
                Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
                Buffer_Fill_Append(bf,'"',1);
                Buffer_Append(bf,tag,-1);
                if ( i + 1 < ncount && !((L[i]^L[i+1])>>16) )
                  {
                    Buffer_Append(bf,"\" : [",5);
                    for(;;) 
                      {
                        Buffer_Append(bf,"{\n",2);
                        Def_Format_Node_In_Depth(bf,n,flags,indent+1);
                        Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
                        Buffer_Fill_Append(bf,'}',1);
                        ++i;
                        if ( i < ncount && !((L[i-1]^L[i])>>16) )
                          {
                            Buffer_Fill_Append(bf,',',1);
                            Buffer_Fill_Append(bf,'\n',1);
                            Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
                            n = Xdata_Idxref(r->xdata,L[i]&0x0ffff);
                          }
                        else
                          break;
                      }
                    Buffer_Fill_Append(bf,']',1);
                  }
                else
                  {
                    Buffer_Append(bf,"\" : {\n",6);
                    Def_Format_Node_In_Depth(bf,n,flags,indent+1);
                    Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
                    Buffer_Fill_Append(bf,'}',1);
                    ++i;
                  }
                if ( i && i < ncount )
                  Buffer_Fill_Append(bf,',',1);
                Buffer_Fill_Append(bf,'\n',1);
              }
          }
      }
    else /* XDEF */
      {
        YO_XNODE *n = Xnode_Down(r);
        for ( ; n; n = Xnode_Next(n) )
          {
            Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
            Buffer_Append(bf,Xnode_Get_Tag(n),-1);
            Buffer_Append(bf," {\n",3);
            Def_Format_Node_In_Depth(bf,n,flags,indent+1);
            Buffer_Fill_Append(bf,' ',indent*YO_XDEF_INDENT_WIDTH);
            Buffer_Append(bf,"}\n",2);
          }
      }
  }
#endif
  ;

char *Def_Format_Into(YO_BUFFER *bf, YO_XNODE *r, int flags)
#ifdef _YO_XDEF_BUILTIN
  {
    int indent = (flags&0xff);
    if ( !bf ) bf = Buffer_Init(0);
    Def_Format_Node_In_Depth(bf,r,flags,indent);
    return (char*)bf->at;
  }
#endif
  ;
  
char *Def_Format(YO_XNODE *r, int flags)
#ifdef _YO_XDEF_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YO_BUFFER *bf = Buffer_Init(0);
        Def_Format_Into(bf,r,flags);
        ret = Buffer_Take_Data(bf);
      }
    return ret;
  }
#endif
  ;

void Def_Format_File(char *fname, YO_XNODE *r, int flags)
#ifdef _YO_XDEF_BUILTIN
  {
    __Auto_Release
      {
        YO_BUFFER *bf = Buffer_Init(0);
        Def_Format_Into(bf,r,flags);
        Oj_Write_Full(Cfile_Open(fname,"w+P"),bf->at,bf->count);
      }
  }
#endif
  ;

#endif /* C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF */

Changes to xjson.hc.
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

*/

#ifndef C_once_9163E833_294D_46EF_8F36_5F86432BD5F8
#define C_once_9163E833_294D_46EF_8F36_5F86432BD5F8

#ifdef _LIBYOYO
#define _YOYO_JSON_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "xdata.hc"
#include "file.hc"
#include "ctoken.hc"
#include "xdef.hc"

void Json_Parse_Block(YOYO_CTOKST *a, YOYO_XNODE *n, YOYO_BUFFER *bf1, YOYO_BUFFER *bf2)
#ifdef _YOYO_JSON_BUILTIN
  {
    YOYO_XVALUE *val;
    YOYO_ARRAY *arr;
    YOYO_XNODE *n2;
    int tk;
    for(;;)
      {
        tk = Ctok_Token(a,bf1);
        if ( tk != YO_CTOKEN_CSTRING && tk != '}' )
          __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects string or '}' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        if ( tk == '}' )
          break;
          
        tk = Ctok_Token(a,0);
        if ( tk != ':' )
          __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects ':' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        tk = Ctok_Token(a,bf2);
        if ( tk == '{' )
          {
            n2 = Xnode_Append(n,bf1->at);
            Json_Parse_Block(a,n2,bf1,bf2);
          }
        else if ( tk == '[' )
          {
            tk = Ctok_Token(a,bf2);
            if ( tk == '{' ) 
              {
                n2 = Xnode_Append(n,bf1->at);
                for (;;)
                  {
                    Json_Parse_Block(a,n2,bf1,bf2);
                    tk = Ctok_Token(a,bf2);
                    if ( tk != ']' && tk != ',' )
                      __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects ']' or ',' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    if ( tk == ']' ) break;
                    if ( Ctok_Token(a,bf2) != '{' )
                      __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects '{' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    n2 = Xnode_Append(n,Xnode_Get_Tag(n2));
                  }
              }
            else if ( tk == ']' )
              {
                /* empty array */
                val = Xnode_Value(n,bf1->at,1);
                Xvalue_Put_Str_Array(val,__Retain(Array_Ptrs()));
              }
            else
              {
                /* array of strings */
                val = Xnode_Value(n,bf1->at,1);
                arr = Array_Ptrs();
                for (;;)
                  {
                    switch( tk )
                      {
                      dafault:
                        __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects value at %s:%d:%d",0),a->source,a->lineno,a->charno));
                      case YO_CTOKEN_CSTRING:
                      case YO_CTOKEN_DIGITS:
                      case YO_CTOKEN_XDIGITS:
                      case YO_CTOKEN_FLOAT:
                        Array_Push(arr,Str_Copy_Npl(bf2->at,-1));
                      }
                    tk = Ctok_Token(a,bf2);
                    if ( tk != ']' && tk != ',' )
                      __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects ']' or ',' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    if ( tk == ']' ) 
                      break;
                    tk = Ctok_Token(a,bf2);
                    if ( tk == '{' )
                      __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON disallow objects and values in one array at %s:%d:%d",0),a->source,a->lineno,a->charno));
                  }
                Xvalue_Put_Str_Array(val,__Retain(arr));
              }            
          }
        else
          {
            val = Xnode_Value(n,bf1->at,1);
            switch ( tk )
              {
              default:
              bad_value:
                __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects value at %s:%d:%d",0),a->source,a->lineno,a->charno));
              case YO_CTOKEN_CSTRING:
                Xvalue_Set_Str(val,bf2->at,-1);
                break;
              case YO_CTOKEN_DIGITS:
              case YO_CTOKEN_XDIGITS:
                Xvalue_Set_Int(val,strtol(bf2->at,0,0));
                break;







|










|
|

|
|
|





|





|

















|


|



















|








|




|











|







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

*/

#ifndef C_once_9163E833_294D_46EF_8F36_5F86432BD5F8
#define C_once_9163E833_294D_46EF_8F36_5F86432BD5F8

#ifdef _LIBYOYO
#define _YO_JSON_BUILTIN
#endif

#include "yoyo.hc"
#include "string.hc"
#include "buffer.hc"
#include "xdata.hc"
#include "file.hc"
#include "ctoken.hc"
#include "xdef.hc"

void Json_Parse_Block(YO_CTOKST *a, YO_XNODE *n, YO_BUFFER *bf1, YO_BUFFER *bf2)
#ifdef _YO_JSON_BUILTIN
  {
    YO_XVALUE *val;
    YO_ARRAY *arr;
    YO_XNODE *n2;
    int tk;
    for(;;)
      {
        tk = Ctok_Token(a,bf1);
        if ( tk != YO_CTOKEN_CSTRING && tk != '}' )
          __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects string or '}' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        if ( tk == '}' )
          break;
          
        tk = Ctok_Token(a,0);
        if ( tk != ':' )
          __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects ':' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        tk = Ctok_Token(a,bf2);
        if ( tk == '{' )
          {
            n2 = Xnode_Append(n,bf1->at);
            Json_Parse_Block(a,n2,bf1,bf2);
          }
        else if ( tk == '[' )
          {
            tk = Ctok_Token(a,bf2);
            if ( tk == '{' ) 
              {
                n2 = Xnode_Append(n,bf1->at);
                for (;;)
                  {
                    Json_Parse_Block(a,n2,bf1,bf2);
                    tk = Ctok_Token(a,bf2);
                    if ( tk != ']' && tk != ',' )
                      __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects ']' or ',' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    if ( tk == ']' ) break;
                    if ( Ctok_Token(a,bf2) != '{' )
                      __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects '{' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    n2 = Xnode_Append(n,Xnode_Get_Tag(n2));
                  }
              }
            else if ( tk == ']' )
              {
                /* empty array */
                val = Xnode_Value(n,bf1->at,1);
                Xvalue_Put_Str_Array(val,__Retain(Array_Ptrs()));
              }
            else
              {
                /* array of strings */
                val = Xnode_Value(n,bf1->at,1);
                arr = Array_Ptrs();
                for (;;)
                  {
                    switch( tk )
                      {
                      dafault:
                        __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects value at %s:%d:%d",0),a->source,a->lineno,a->charno));
                      case YO_CTOKEN_CSTRING:
                      case YO_CTOKEN_DIGITS:
                      case YO_CTOKEN_XDIGITS:
                      case YO_CTOKEN_FLOAT:
                        Array_Push(arr,Str_Copy_Npl(bf2->at,-1));
                      }
                    tk = Ctok_Token(a,bf2);
                    if ( tk != ']' && tk != ',' )
                      __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects ']' or ',' at %s:%d:%d",0),a->source,a->lineno,a->charno));
                    if ( tk == ']' ) 
                      break;
                    tk = Ctok_Token(a,bf2);
                    if ( tk == '{' )
                      __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON disallow objects and values in one array at %s:%d:%d",0),a->source,a->lineno,a->charno));
                  }
                Xvalue_Put_Str_Array(val,__Retain(arr));
              }            
          }
        else
          {
            val = Xnode_Value(n,bf1->at,1);
            switch ( tk )
              {
              default:
              bad_value:
                __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects value at %s:%d:%d",0),a->source,a->lineno,a->charno));
              case YO_CTOKEN_CSTRING:
                Xvalue_Set_Str(val,bf2->at,-1);
                break;
              case YO_CTOKEN_DIGITS:
              case YO_CTOKEN_XDIGITS:
                Xvalue_Set_Int(val,strtol(bf2->at,0,0));
                break;
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
                else goto bad_value;
                break;
              }
          }
          
        tk = Ctok_Token(a,0);
        if ( tk != ',' && tk != '}' )
          __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects ',' or '}' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        if ( tk == '}' )
          break;
      }
  }
#endif
  ;
  
YOYO_XDATA *Json_Parse_Text(char *text, char *source)
#ifdef _YOYO_JSON_BUILTIN
  {
    YOYO_CTOKST a; 
    YOYO_BUFFER *bf1,*bf2;
    YOYO_XNODE  *n = Xdata_Init();
    
    __Auto_Ptr(n)
      {
        Ctok_Init(&a,text,text+strlen(text),source);
        bf1 = Buffer_Init(0);
        bf2 = Buffer_Init(0);
        
        if ( Ctok_Token(&a,0) == '{' )
          Json_Parse_Block(&a,n,bf1,bf2);
        else
          __Raise_Format(YOYO_ERROR_ILLFORMED,(__yoTa("JSON expects '{' at %s:%d:%d",0),a.source,a.lineno,a.charno));
      }
      
    return n->xdata;
  }
#endif
  ;
  
YOYO_XDATA *Json_Parse_Str(char *text)
#ifdef _YOYO_JSON_BUILTIN
  {
    return Json_Parse_Text(text,__yoTa("<str>",0));
  }
#endif
  ;

YOYO_XDATA *Json_Parse_File(char *filename)
#ifdef _YOYO_JSON_BUILTIN
  {
    YOYO_XDATA *ret = 0;
    
    __Auto_Ptr(ret)
      {
        YOYO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"rt"));
        ret = Json_Parse_Text((char*)bf->at,filename);
      }
      
    return ret;
  }
#endif
  ;

char *Json_Format_Into(YOYO_BUFFER *bf, YOYO_XNODE *r, int flags)
#ifdef _YOYO_JSON_BUILTIN
  {
    int indent = (flags&0xff);
    if ( !bf ) bf = Buffer_Init(0);
    Buffer_Append(bf,"{\n",2);
    Def_Format_Node_In_Depth(bf,r,flags|XDEF_FORMAT_JSON,indent+1);
    Buffer_Append(bf,"\n}\n",3);
    return (char*)bf->at;
  }
#endif
  ;
  
char *Json_Format(YOYO_XNODE *r, int flags)
#ifdef _YOYO_JSON_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YOYO_BUFFER *bf = Buffer_Init(0);
        Json_Format_Into(bf,r,flags);
        ret = Buffer_Take_Data(bf);
      }
    return ret;
  }
#endif
  ;

void Json_Format_File(char *fname, YOYO_XNODE *r, int flags)
#ifdef _YOYO_JSON_BUILTIN
  {
    __Auto_Release
      {
        YOYO_BUFFER *bf = Buffer_Init(0);
        Json_Format_Into(bf,r,flags);
        Oj_Write_Full(Cfile_Open(fname,"w+P"),bf->at,bf->count);
      }
  }
#endif
  ;

#endif /* C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF */








|







|
|

|
|
|










|







|
|






|
|

|



|








|
|











|
|




|








|
|



|









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
                else goto bad_value;
                break;
              }
          }
          
        tk = Ctok_Token(a,0);
        if ( tk != ',' && tk != '}' )
          __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects ',' or '}' at %s:%d:%d",0),a->source,a->lineno,a->charno));
        if ( tk == '}' )
          break;
      }
  }
#endif
  ;
  
YO_XDATA *Json_Parse_Text(char *text, char *source)
#ifdef _YO_JSON_BUILTIN
  {
    YO_CTOKST a; 
    YO_BUFFER *bf1,*bf2;
    YO_XNODE  *n = Xdata_Init();
    
    __Auto_Ptr(n)
      {
        Ctok_Init(&a,text,text+strlen(text),source);
        bf1 = Buffer_Init(0);
        bf2 = Buffer_Init(0);
        
        if ( Ctok_Token(&a,0) == '{' )
          Json_Parse_Block(&a,n,bf1,bf2);
        else
          __Raise_Format(YO_ERROR_ILLFORMED,(__yoTa("JSON expects '{' at %s:%d:%d",0),a.source,a.lineno,a.charno));
      }
      
    return n->xdata;
  }
#endif
  ;
  
YO_XDATA *Json_Parse_Str(char *text)
#ifdef _YO_JSON_BUILTIN
  {
    return Json_Parse_Text(text,__yoTa("<str>",0));
  }
#endif
  ;

YO_XDATA *Json_Parse_File(char *filename)
#ifdef _YO_JSON_BUILTIN
  {
    YO_XDATA *ret = 0;
    
    __Auto_Ptr(ret)
      {
        YO_BUFFER *bf = Oj_Read_All(Cfile_Open(filename,"rt"));
        ret = Json_Parse_Text((char*)bf->at,filename);
      }
      
    return ret;
  }
#endif
  ;

char *Json_Format_Into(YO_BUFFER *bf, YO_XNODE *r, int flags)
#ifdef _YO_JSON_BUILTIN
  {
    int indent = (flags&0xff);
    if ( !bf ) bf = Buffer_Init(0);
    Buffer_Append(bf,"{\n",2);
    Def_Format_Node_In_Depth(bf,r,flags|XDEF_FORMAT_JSON,indent+1);
    Buffer_Append(bf,"\n}\n",3);
    return (char*)bf->at;
  }
#endif
  ;
  
char *Json_Format(YO_XNODE *r, int flags)
#ifdef _YO_JSON_BUILTIN
  {
    char *ret = 0;
    __Auto_Ptr(ret)
      {
        YO_BUFFER *bf = Buffer_Init(0);
        Json_Format_Into(bf,r,flags);
        ret = Buffer_Take_Data(bf);
      }
    return ret;
  }
#endif
  ;

void Json_Format_File(char *fname, YO_XNODE *r, int flags)
#ifdef _YO_JSON_BUILTIN
  {
    __Auto_Release
      {
        YO_BUFFER *bf = Buffer_Init(0);
        Json_Format_Into(bf,r,flags);
        Oj_Write_Full(Cfile_Open(fname,"w+P"),bf->at,bf->count);
      }
  }
#endif
  ;

#endif /* C_once_750A77B2_260B_4E33_B9EA_15F01DDD61FF */

Changes to xntdef.hc.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
*/

#ifndef C_once_D26A79BF_9E35_48C1_8D5B_03D5A42C3203
#define C_once_D26A79BF_9E35_48C1_8D5B_03D5A42C3203
#ifdef __windoze

#ifdef _LIBYOYO
#define _YOYO_XNTDEF_BUILTIN
#endif

typedef long NTSTATUS;

#define STATUS_NO_SUCH_FILE           ((NTSTATUS)0xC000000FL)
#define STATUS_BUFFER_OVERFLOW        ((NTSTATUS)0x80000005L)
#define STATUS_NO_MORE_FILES          ((NTSTATUS)0x80000006L)







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
*/

#ifndef C_once_D26A79BF_9E35_48C1_8D5B_03D5A42C3203
#define C_once_D26A79BF_9E35_48C1_8D5B_03D5A42C3203
#ifdef __windoze

#ifdef _LIBYOYO
#define _YO_XNTDEF_BUILTIN
#endif

typedef long NTSTATUS;

#define STATUS_NO_SUCH_FILE           ((NTSTATUS)0xC000000FL)
#define STATUS_BUFFER_OVERFLOW        ((NTSTATUS)0x80000005L)
#define STATUS_NO_MORE_FILES          ((NTSTATUS)0x80000006L)
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
    ULONG                   WaitingOnLoaderLock;
    PVOID                   StackCommit;
    PVOID                   StackCommitMax;
    PVOID                   StackReserved;
  } XTEB, *PXTEB;

XTEB *Query_TEB()
#ifdef _YOYO_XNTDEF_BUILTIN
  {
  #ifdef __GNUC__
  #else
    XTEB *teb;
    __asm mov eax, fs:[0x18] 
    __asm mov teb, eax
    return teb;
  #endif
  }
#endif
  ;
  
XPEB *Query_PEB()
#ifdef _YOYO_XNTDEF_BUILTIN
  {
    return Query_TEB()->Peb;  
  }
#endif
  ;

#define GET_NT_HEADERS(p) ((IMAGE_NT_HEADERS *)((byte_t*)p + ((IMAGE_DOS_HEADER*)p)->e_lfanew))

IMAGE_NT_HEADERS *Get_Nt_Headers(void *p)
#ifdef _YOYO_XNTDEF_BUILTIN
  {
    return GET_NT_HEADERS(p);
  }
#endif
  ;

int Is_WOW64()
#ifdef _YOYO_XNTDEF_BUILTIN
  {
    static int system_is = 0;
    if ( !system_is )
      {
        int (__stdcall *f_IsWow64Process)(HANDLE, int*) = 0;
        int is_wow64 = 0;
        f_IsWow64Process = (void *)GetProcAddress(GetModuleHandleA(__yoTa("kernel32.dll",0)),__yoTa("IsWow64Process",0));







|













|









|







|







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
    ULONG                   WaitingOnLoaderLock;
    PVOID                   StackCommit;
    PVOID                   StackCommitMax;
    PVOID                   StackReserved;
  } XTEB, *PXTEB;

XTEB *Query_TEB()
#ifdef _YO_XNTDEF_BUILTIN
  {
  #ifdef __GNUC__
  #else
    XTEB *teb;
    __asm mov eax, fs:[0x18] 
    __asm mov teb, eax
    return teb;
  #endif
  }
#endif
  ;
  
XPEB *Query_PEB()
#ifdef _YO_XNTDEF_BUILTIN
  {
    return Query_TEB()->Peb;  
  }
#endif
  ;

#define GET_NT_HEADERS(p) ((IMAGE_NT_HEADERS *)((byte_t*)p + ((IMAGE_DOS_HEADER*)p)->e_lfanew))

IMAGE_NT_HEADERS *Get_Nt_Headers(void *p)
#ifdef _YO_XNTDEF_BUILTIN
  {
    return GET_NT_HEADERS(p);
  }
#endif
  ;

int Is_WOW64()
#ifdef _YO_XNTDEF_BUILTIN
  {
    static int system_is = 0;
    if ( !system_is )
      {
        int (__stdcall *f_IsWow64Process)(HANDLE, int*) = 0;
        int is_wow64 = 0;
        f_IsWow64Process = (void *)GetProcAddress(GetModuleHandleA(__yoTa("kernel32.dll",0)),__yoTa("IsWow64Process",0));
Changes to yoyo.hc.
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

    Don't foget to use -rdynamic to see symbols in backtrace!

*/

#ifndef C_once_6973F3BA_26FA_434D_9ED9_FF5389CE421C
#define C_once_6973F3BA_26FA_434D_9ED9_FF5389CE421C
#define YOYO_CORE_VERSION 1000

#ifdef _LIBYOYO
#define _YOYO_CORE_BUILTIN
#endif

#if defined _MSC_VER && _MSC_VER > 1400
#pragma warning(disable:4996) /*The POSIX name for this item is deprecated*/
# ifndef _CRT_SECURE_NO_WARNINGS
#   define _CRT_SECURE_NO_WARNINGS
# endif







|


|







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

    Don't foget to use -rdynamic to see symbols in backtrace!

*/

#ifndef C_once_6973F3BA_26FA_434D_9ED9_FF5389CE421C
#define C_once_6973F3BA_26FA_434D_9ED9_FF5389CE421C
#define YO_CORE_VERSION 1000

#ifdef _LIBYOYO
#define _YO_CORE_BUILTIN
#endif

#if defined _MSC_VER && _MSC_VER > 1400
#pragma warning(disable:4996) /*The POSIX name for this item is deprecated*/
# ifndef _CRT_SECURE_NO_WARNINGS
#   define _CRT_SECURE_NO_WARNINGS
# endif
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
#else
# define __Yo_FILE__ 0
# define __Yo_Expr__(Expr) 0
# define Yo_Raise(Error,Msg,File,Line) _Yo_Raise(Error,Msg,0,0)
# define Yo_Fatal(Error,Msg,File,Line) _Yo_Fatal(Error,Msg,0,0)
#endif

#define YOYO_COMPOSE2(a,b) a##b
#define YOYO_COMPOSE3(a,b,c) a##b##_##c
#define YOYO_ID(Name,Line) YOYO_COMPOSE3(_YoYo_Label_,Name,Line)
#define YOYO_LOCAL_ID(Name) YOYO_ID(Name,__LINE__)

#ifdef _YOYO_CORE_BUILTIN
# define _YOYO_CORE_BUILTIN_CODE(Code) Code
# define _YOYO_CORE_EXTERN
#else
# define _YOYO_CORE_BUILTIN_CODE(Code)
# define _YOYO_CORE_EXTERN extern
#endif

#define Yo_MIN(a,b) ( (a) < (b) ? (a) : (b) )
#define Yo_MAX(a,b) ( (a) > (b) ? (a) : (b) )
#define Yo_ABS(a) ( (a) > 0 ? (a) : -(a) ) /* a > 0  does not produce warning on unsigned types */
#define Yo_ALIGNU(a,n) ( ((a) + ((n) - 1))&~((n) - 1) )

#define YOYO_REPN_2(Val)   Val,Val
#define YOYO_REPN_4(Val)   YOYO_REPN_2(Val),YOYO_REPN_2(Val)
#define YOYO_REPN_8(Val)   YOYO_REPN_4(Val),YOYO_REPN_4(Val)
#define YOYO_REPN_16(Val)  YOYO_REPN_8(Val),YOYO_REPN_8(Val)
#define YOYO_REPN_32(Val)  YOYO_REPN_16(Val),YOYO_REPN_16(Val)
#define YOYO_REPN_64(Val)  YOYO_REPN_32(Val),YOYO_REPN_32(Val)
#define YOYO_REPN_128(Val) YOYO_REPN_64(Val),YOYO_REPN_64(Val)
#define C32_BIT(No)        (1U<<No)
#define C64_BIT(No)        (1ULL<<No)

_YOYO_CORE_EXTERN char Oj_Destruct_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "~/@" );
_YOYO_CORE_EXTERN char Oj_Destruct_Element_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "~1/@" );
_YOYO_CORE_EXTERN char Oj_Compare_Elements_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "?2/**" );
_YOYO_CORE_EXTERN char Oj_Compare_Keys_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "?3/**" );
_YOYO_CORE_EXTERN char Oj_Clone_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "$=/@" );
_YOYO_CORE_EXTERN char Oj_Count_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = "$#/@" );
_YOYO_CORE_EXTERN char Oj_Set_Key_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">+S>/@*" );
_YOYO_CORE_EXTERN char Oj_Find_Key_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">?S>/@*" );
_YOYO_CORE_EXTERN char Oj_Take_Key_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">-S>/@*" );
_YOYO_CORE_EXTERN char Oj_Del_Key_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">~S>/@*" );
_YOYO_CORE_EXTERN char Oj_Set_Lkey_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">+L>/@L" );
_YOYO_CORE_EXTERN char Oj_Find_Lkey_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">?L>/@L" );
_YOYO_CORE_EXTERN char Oj_Take_Lkey_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">-L>/@L" );
_YOYO_CORE_EXTERN char Oj_Del_Lkey_OjMID[] _YOYO_CORE_BUILTIN_CODE ( = ">~L>/@L" );

enum
  {
    KILOBYTE = 1024,
    MEGABYTE = 1024*KILOBYTE,
    GIGABYTE = 1024*MEGABYTE,
  };

enum _YOYO_ERRORS
  {
    YOYO_FATAL_ERROR_GROUP          = 0x70000000,
    YOYO_USER_ERROR_GROUP           = 0x00010000,
    YOYO_IO_ERROR_GROUP             = 0x00020000,
    //YOYO_TCPIP_ERROR_GROUP          = 0x00040000,
    YOYO_RUNTIME_ERROR_GROUP        = 0x00080000,
    YOYO_SELFCHECK_ERROR_GROUP      = 0x00100000,
    YOYO_ENCODING_ERROR_GROUP       = 0x00200000,
    YOYO_ILLFORMED_ERROR_GROUP      = 0x00400000,
    YOYO_RANGE_ERROR_GROUP          = 0x00800000,
    YOYO_CORRUPTED_ERROR_GROUP      = 0x01000000,
    YOYO_STORAGE_ERROR_GROUP        = 0x02000000,
    //YOYO_SYSTEM_ERROR_GROUP         = 0x04000000,

    YOYO_XXXX_ERROR_GROUP           = 0x7fff0000,
    YO_RERAISE_CURRENT_ERROR        = 0x7fff7fff,

    YOYO_TRACED_ERROR_GROUP     = YOYO_FATAL_ERROR_GROUP
                                |YOYO_RANGE_ERROR_GROUP
                                |YOYO_SELFCHECK_ERROR_GROUP,

    YOYO_ERROR_BASE             = 0x00008000,
    YOYO_ERROR_USER             = YOYO_USER_ERROR_GROUP|0,

    YOYO_ERROR_OUT_OF_MEMORY    = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+1),
    YOYO_FATAL_ERROR            = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+2),
    YOYO_ERROR_DYNCO_CORRUPTED  = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+3),
    YOYO_ERROR_METHOD_NOT_FOUND = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+4),
    YOYO_ERROR_REQUIRE_FAILED   = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+5),
    YOYO_ERROR_ILLFORMED        = YOYO_ILLFORMED_ERROR_GROUP|(YOYO_ERROR_BASE+6),
    YOYO_ERROR_OUT_OF_POOL      = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+7),
    YOYO_ERROR_UNEXPECTED       = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+8),
    YOYO_ERROR_OUT_OF_RANGE     = YOYO_RANGE_ERROR_GROUP|(YOYO_ERROR_BASE+9),
    YOYO_ERROR_NULL_PTR         = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+10),
    YOYO_ERROR_CORRUPTED        = YOYO_CORRUPTED_ERROR_GROUP|(YOYO_ERROR_BASE+11),
    YOYO_ERROR_IO               = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+12),
    YOYO_ERROR_UNSORTABLE       = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+13),
    YOYO_ERROR_DOESNT_EXIST     = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+14),

    YOYO_ERROR_ACCESS_DENAIED   = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+15),
    YOYO_ERROR_NO_ENOUGH        = YOYO_ILLFORMED_ERROR_GROUP|(YOYO_ERROR_BASE+16),
    YOYO_ERROR_UNALIGNED        = YOYO_ILLFORMED_ERROR_GROUP|(YOYO_ERROR_BASE+17),
    YOYO_ERROR_COMPRESS_DATA    = YOYO_ENCODING_ERROR_GROUP|(YOYO_ERROR_BASE+18),
    YOYO_ERROR_ENCRYPT_DATA     = YOYO_ENCODING_ERROR_GROUP|(YOYO_ERROR_BASE+19),
    YOYO_ERROR_DECOMPRESS_DATA  = YOYO_ENCODING_ERROR_GROUP|(YOYO_ERROR_BASE+20),
    YOYO_ERROR_DECRYPT_DATA     = YOYO_ENCODING_ERROR_GROUP|(YOYO_ERROR_BASE+21),
    YOYO_ERROR_INVALID_PARAM    = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+22),
    YOYO_ERROR_UNEXPECTED_VALUE = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+23),
    YOYO_ERROR_ALREADY_EXISTS   = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+24),
    YOYO_ERROR_INCONSISTENT     = YOYO_STORAGE_ERROR_GROUP|(YOYO_ERROR_BASE+25),
    YOYO_ERROR_TO_BIG           = YOYO_STORAGE_ERROR_GROUP|(YOYO_ERROR_BASE+26),
    YOYO_ERROR_ZERODIVIDE       = YOYO_FATAL_ERROR_GROUP|(YOYO_ERROR_BASE+27),
    YOYO_ERROR_LIMIT_REACHED    = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+28),
    YOYO_ERROR_UNSUPPORTED      = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+29),
    YOYO_ERROR_IO_EOF           = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+30),
    YOYO_ERROR_DNS              = YOYO_IO_ERROR_GROUP|(YOYO_ERROR_BASE+31),
    YOYO_ERROR_SUBSYSTEM_INIT   = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+32),
    YOYO_ERROR_SYSTEM           = YOYO_RUNTIME_ERROR_GROUP|(YOYO_ERROR_BASE+33),
    YOYO_ERROR_SYNTAX           = YOYO_ILLFORMED_ERROR_GROUP|(YOYO_ERROR_BASE+34),

  };

#define YOYO_ERROR_IS_USER_ERROR(err) !(err&YOYO_XXXX_ERROR_GROUP)

enum _YOYO_FLAGS
  {
    YO_RAISE_ERROR            = 0x70000000,
    YO_PRINT_FLUSH            = 1,
    YO_PRINT_NEWLINE          = 2,
  };

__No_Return void _Yo_Fatal(int err,void *ctx,char *filename,int lineno);







|
|
|
|

|
|
|

|
|







|
|
|
|
|
|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|








|

|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>


|

|







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
#else
# define __Yo_FILE__ 0
# define __Yo_Expr__(Expr) 0
# define Yo_Raise(Error,Msg,File,Line) _Yo_Raise(Error,Msg,0,0)
# define Yo_Fatal(Error,Msg,File,Line) _Yo_Fatal(Error,Msg,0,0)
#endif

#define YO_COMPOSE2(a,b) a##b
#define YO_COMPOSE3(a,b,c) a##b##_##c
#define YO_ID(Name,Line) YO_COMPOSE3(_YoYo_Label_,Name,Line)
#define YO_LOCAL_ID(Name) YO_ID(Name,__LINE__)

#ifdef _YO_CORE_BUILTIN
# define _YO_CORE_BUILTIN_CODE(Code) Code
# define _YO_CORE_EXTERN
#else
# define _YO_CORE_BUILTIN_CODE(Code)
# define _YO_CORE_EXTERN extern
#endif

#define Yo_MIN(a,b) ( (a) < (b) ? (a) : (b) )
#define Yo_MAX(a,b) ( (a) > (b) ? (a) : (b) )
#define Yo_ABS(a) ( (a) > 0 ? (a) : -(a) ) /* a > 0  does not produce warning on unsigned types */
#define Yo_ALIGNU(a,n) ( ((a) + ((n) - 1))&~((n) - 1) )

#define YO_REPN_2(Val)   Val,Val
#define YO_REPN_4(Val)   YO_REPN_2(Val),YO_REPN_2(Val)
#define YO_REPN_8(Val)   YO_REPN_4(Val),YO_REPN_4(Val)
#define YO_REPN_16(Val)  YO_REPN_8(Val),YO_REPN_8(Val)
#define YO_REPN_32(Val)  YO_REPN_16(Val),YO_REPN_16(Val)
#define YO_REPN_64(Val)  YO_REPN_32(Val),YO_REPN_32(Val)
#define YO_REPN_128(Val) YO_REPN_64(Val),YO_REPN_64(Val)
#define C32_BIT(No)        (1U<<No)
#define C64_BIT(No)        (1ULL<<No)

_YO_CORE_EXTERN char Oj_Destruct_OjMID[] _YO_CORE_BUILTIN_CODE ( = "~/@" );
_YO_CORE_EXTERN char Oj_Destruct_Element_OjMID[] _YO_CORE_BUILTIN_CODE ( = "~1/@" );
_YO_CORE_EXTERN char Oj_Compare_Elements_OjMID[] _YO_CORE_BUILTIN_CODE ( = "?2/**" );
_YO_CORE_EXTERN char Oj_Compare_Keys_OjMID[] _YO_CORE_BUILTIN_CODE ( = "?3/**" );
_YO_CORE_EXTERN char Oj_Clone_OjMID[] _YO_CORE_BUILTIN_CODE ( = "$=/@" );
_YO_CORE_EXTERN char Oj_Count_OjMID[] _YO_CORE_BUILTIN_CODE ( = "$#/@" );
_YO_CORE_EXTERN char Oj_Set_Key_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">+S>/@*" );
_YO_CORE_EXTERN char Oj_Find_Key_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">?S>/@*" );
_YO_CORE_EXTERN char Oj_Take_Key_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">-S>/@*" );
_YO_CORE_EXTERN char Oj_Del_Key_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">~S>/@*" );
_YO_CORE_EXTERN char Oj_Set_Lkey_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">+L>/@L" );
_YO_CORE_EXTERN char Oj_Find_Lkey_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">?L>/@L" );
_YO_CORE_EXTERN char Oj_Take_Lkey_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">-L>/@L" );
_YO_CORE_EXTERN char Oj_Del_Lkey_OjMID[] _YO_CORE_BUILTIN_CODE ( = ">~L>/@L" );

enum
  {
    KILOBYTE = 1024,
    MEGABYTE = 1024*KILOBYTE,
    GIGABYTE = 1024*MEGABYTE,
  };

enum _YO_ERRORS
  {
    YO_FATAL_ERROR_GROUP          = 0x70000000,
    YO_USER_ERROR_GROUP           = 0x00010000,
    YO_IO_ERROR_GROUP             = 0x00020000,
    //YO_TCPIP_ERROR_GROUP          = 0x00040000,
    YO_RUNTIME_ERROR_GROUP        = 0x00080000,
    YO_SELFCHECK_ERROR_GROUP      = 0x00100000,
    YO_ENCODING_ERROR_GROUP       = 0x00200000,
    YO_ILLFORMED_ERROR_GROUP      = 0x00400000,
    YO_RANGE_ERROR_GROUP          = 0x00800000,
    YO_CORRUPTED_ERROR_GROUP      = 0x01000000,
    YO_STORAGE_ERROR_GROUP        = 0x02000000,
    //YO_SYSTEM_ERROR_GROUP         = 0x04000000,

    YO_XXXX_ERROR_GROUP           = 0x7fff0000,
    YO_RERAISE_CURRENT_ERROR      = 0x7fff7fff,

    YO_TRACED_ERROR_GROUP         = YO_FATAL_ERROR_GROUP
                                   |YO_RANGE_ERROR_GROUP
                                   |YO_SELFCHECK_ERROR_GROUP,

    YO_ERROR_BASE                 = 0x00008000,
    YO_ERROR_USER                 = YO_USER_ERROR_GROUP|0,

    YO_ERROR_OUT_OF_MEMORY    = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+1),
    YO_FATAL_ERROR            = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+2),
    YO_ERROR_DYNCO_CORRUPTED  = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+3),
    YO_ERROR_METHOD_NOT_FOUND = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+4),
    YO_ERROR_REQUIRE_FAILED   = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+5),
    YO_ERROR_ILLFORMED        = YO_ILLFORMED_ERROR_GROUP|(YO_ERROR_BASE+6),
    YO_ERROR_OUT_OF_POOL      = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+7),
    YO_ERROR_UNEXPECTED       = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+8),
    YO_ERROR_OUT_OF_RANGE     = YO_RANGE_ERROR_GROUP|(YO_ERROR_BASE+9),
    YO_ERROR_NULL_PTR         = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+10),
    YO_ERROR_CORRUPTED        = YO_CORRUPTED_ERROR_GROUP|(YO_ERROR_BASE+11),
    YO_ERROR_IO               = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+12),
    YO_ERROR_UNSORTABLE       = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+13),
    YO_ERROR_DOESNT_EXIST     = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+14),
    YO_ERROR_DSNT_EXIST       = YO_ERROR_DOESNT_EXIST,
    YO_ERROR_ACCESS_DENAIED   = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+15),
    YO_ERROR_NO_ENOUGH        = YO_ILLFORMED_ERROR_GROUP|(YO_ERROR_BASE+16),
    YO_ERROR_UNALIGNED        = YO_ILLFORMED_ERROR_GROUP|(YO_ERROR_BASE+17),
    YO_ERROR_COMPRESS_DATA    = YO_ENCODING_ERROR_GROUP|(YO_ERROR_BASE+18),
    YO_ERROR_ENCRYPT_DATA     = YO_ENCODING_ERROR_GROUP|(YO_ERROR_BASE+19),
    YO_ERROR_DECOMPRESS_DATA  = YO_ENCODING_ERROR_GROUP|(YO_ERROR_BASE+20),
    YO_ERROR_DECRYPT_DATA     = YO_ENCODING_ERROR_GROUP|(YO_ERROR_BASE+21),
    YO_ERROR_INVALID_PARAM    = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+22),
    YO_ERROR_UNEXPECTED_VALUE = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+23),
    YO_ERROR_ALREADY_EXISTS   = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+24),
    YO_ERROR_INCONSISTENT     = YO_STORAGE_ERROR_GROUP|(YO_ERROR_BASE+25),
    YO_ERROR_TO_BIG           = YO_STORAGE_ERROR_GROUP|(YO_ERROR_BASE+26),
    YO_ERROR_ZERODIVIDE       = YO_FATAL_ERROR_GROUP|(YO_ERROR_BASE+27),
    YO_ERROR_LIMIT_REACHED    = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+28),
    YO_ERROR_UNSUPPORTED      = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+29),
    YO_ERROR_IO_EOF           = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+30),
    YO_ERROR_DNS              = YO_IO_ERROR_GROUP|(YO_ERROR_BASE+31),
    YO_ERROR_SUBSYSTEM_INIT   = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+32),
    YO_ERROR_SYSTEM           = YO_RUNTIME_ERROR_GROUP|(YO_ERROR_BASE+33),
    YO_ERROR_SYNTAX           = YO_ILLFORMED_ERROR_GROUP|(YO_ERROR_BASE+34),
    YO_ERROR_TESUITE_FAIL     = YO_SELFCHECK_ERROR_GROUP|(YO_ERROR_BASE+35),
  };

#define YO_ERROR_IS_USER_ERROR(err) !(err&YO_XXXX_ERROR_GROUP)

enum _YO_FLAGS
  {
    YO_RAISE_ERROR            = 0x70000000,
    YO_PRINT_FLUSH            = 1,
    YO_PRINT_NEWLINE          = 2,
  };

__No_Return void _Yo_Fatal(int err,void *ctx,char *filename,int lineno);
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
# ifdef __GNUC__
# else
# endif
#endif

# define YO_MULTITHREADED(Expr) Expr

# define _xchg_YOYO_LOCAL_LX static int volatile YOYO_LOCAL_ID(lx)
# define _xchg_YOYO_LOCAL_ID_REF &YOYO_LOCAL_ID(lx)
# define __Xchg_Interlock \
              __Interlock_Opt( _xchg_YOYO_LOCAL_LX, _xchg_YOYO_LOCAL_ID_REF, \
                  Yo_Wait_Xchg_Lock,Yo_Xchg_Unlock,Yo_Xchg_Unlock_Proc)

# define __Xchg_Sync(Lx) \
              __Interlock_Opt(((void)0),Lx, \
                  Yo_Wait_Xchg_Lock,Yo_Xchg_Unlock,Yo_Xchg_Unlock_Proc)

# define Yo_Wait_Xchg_Lock(Ptr) while ( !Yo_Atomic_CmpXchg(Ptr,1,0) ) Switch_to_Thread()
# define Yo_Xchg_Unlock(Ptr) Yo_Atomic_CmpXchg(Ptr,0,1)

void Yo_Xchg_Unlock_Proc(int volatile *p) _YOYO_CORE_BUILTIN_CODE({Yo_Atomic_CmpXchg(p,0,1);});

/*# define __Mtx_Sync(Mtx) \
              __Interlock_Opt(((void)0),Mtx, \
                  Yo_Wait_Mtx_Lock,Yo_Mtx_Unlock,Yo_Mtx_Unlock_Proc)*/

#endif
  
#if defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__>=6) )
  #define __Static_Assert_S(expr,S) _Static_assert(expr,S)
#elif !defined _MSC_VER || _MSC_VER < 1600 || defined __ICL
  #define __Static_Assert_S(expr,S) \
    extern char YOYO_LOCAL_ID(__assert__)[(expr)?1:-1]
#else
  #define __Static_Assert_S(expr,S) static_assert(expr,S)
#endif

#define __Static_Assert(expr) __Static_Assert_S(expr,#expr)

#define REQUIRE(Expr) \
  if (Expr); else Yo_Fatal(YOYO_ERROR_REQUIRE_FAILED,__Yo_Expr__(Expr),__Yo_FILE__,__LINE__)
#define PANICA(msg) Yo_Fatal(YOYO_FATAL_ERROR,msg,__Yo_FILE__,__LINE__)

#ifdef _STRICT
# define STRICT_REQUIRE(Expr) REQUIRE(Expr)
# define STRICT_CHECK(Expr) (Expr)
#else
# define STRICT_REQUIRE(Expr) ((void)0)
# define STRICT_CHECK(Expr) (1)
#endif /* _STRICT */

#define Slist_Remove_By(ListPtr,Next,Val) Yo_Slist_Remove(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)),Val)
#define Slist_Remove(ListPtr,Val) Slist_Remove_By(ListPtr,next,Val)

void Yo_Slist_Remove(void **p, int offs_of_next, void *val)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( p ) 
      {
        while ( *p )
          {
            if ( *p == val )
              {







|
|

|









|











|







|
|













|







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
# ifdef __GNUC__
# else
# endif
#endif

# define YO_MULTITHREADED(Expr) Expr

# define _xchg_YO_LOCAL_LX static int volatile YO_LOCAL_ID(lx)
# define _xchg_YO_LOCAL_ID_REF &YO_LOCAL_ID(lx)
# define __Xchg_Interlock \
              __Interlock_Opt( _xchg_YO_LOCAL_LX, _xchg_YO_LOCAL_ID_REF, \
                  Yo_Wait_Xchg_Lock,Yo_Xchg_Unlock,Yo_Xchg_Unlock_Proc)

# define __Xchg_Sync(Lx) \
              __Interlock_Opt(((void)0),Lx, \
                  Yo_Wait_Xchg_Lock,Yo_Xchg_Unlock,Yo_Xchg_Unlock_Proc)

# define Yo_Wait_Xchg_Lock(Ptr) while ( !Yo_Atomic_CmpXchg(Ptr,1,0) ) Switch_to_Thread()
# define Yo_Xchg_Unlock(Ptr) Yo_Atomic_CmpXchg(Ptr,0,1)

void Yo_Xchg_Unlock_Proc(int volatile *p) _YO_CORE_BUILTIN_CODE({Yo_Atomic_CmpXchg(p,0,1);});

/*# define __Mtx_Sync(Mtx) \
              __Interlock_Opt(((void)0),Mtx, \
                  Yo_Wait_Mtx_Lock,Yo_Mtx_Unlock,Yo_Mtx_Unlock_Proc)*/

#endif
  
#if defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__>=6) )
  #define __Static_Assert_S(expr,S) _Static_assert(expr,S)
#elif !defined _MSC_VER || _MSC_VER < 1600 || defined __ICL
  #define __Static_Assert_S(expr,S) \
    extern char YO_LOCAL_ID(__assert__)[(expr)?1:-1]
#else
  #define __Static_Assert_S(expr,S) static_assert(expr,S)
#endif

#define __Static_Assert(expr) __Static_Assert_S(expr,#expr)

#define REQUIRE(Expr) \
  if (Expr); else Yo_Fatal(YO_ERROR_REQUIRE_FAILED,__Yo_Expr__(Expr),__Yo_FILE__,__LINE__)
#define PANICA(msg) Yo_Fatal(YO_FATAL_ERROR,msg,__Yo_FILE__,__LINE__)

#ifdef _STRICT
# define STRICT_REQUIRE(Expr) REQUIRE(Expr)
# define STRICT_CHECK(Expr) (Expr)
#else
# define STRICT_REQUIRE(Expr) ((void)0)
# define STRICT_CHECK(Expr) (1)
#endif /* _STRICT */

#define Slist_Remove_By(ListPtr,Next,Val) Yo_Slist_Remove(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)),Val)
#define Slist_Remove(ListPtr,Val) Slist_Remove_By(ListPtr,next,Val)

void Yo_Slist_Remove(void **p, int offs_of_next, void *val)
#ifdef _YO_CORE_BUILTIN
  {
    if ( p ) 
      {
        while ( *p )
          {
            if ( *p == val )
              {
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
#endif
  ;

#define Slist_Push_By(ListPtr,Next,Val) Yo_Slist_Push(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)),Val)
#define Slist_Push(ListPtr,Val) Slist_Push_By(ListPtr,next,Val)

void Yo_Slist_Push(void **p, int offs_of_next, void *val)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( p ) 
      {
        while ( *p )
          {
            p =  (void**)((byte_t*)*p + offs_of_next);
          }
        *p = val;
        *(void**)((byte_t*)*p + offs_of_next) = 0;
      }
  }
#endif
  ;
  
#define Slist_Pop_By(ListPtr,Next) Yo_Slist_Pop(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)))
#define Slist_Pop(ListPtr) Slist_Pop_By(ListPtr,next)

void *Yo_Slist_Pop(void **p, int offs_of_next)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *r = 0;
    
    if ( p )
      {
        r = *p;
        if ( r ) 







|


















|







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
#endif
  ;

#define Slist_Push_By(ListPtr,Next,Val) Yo_Slist_Push(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)),Val)
#define Slist_Push(ListPtr,Val) Slist_Push_By(ListPtr,next,Val)

void Yo_Slist_Push(void **p, int offs_of_next, void *val)
#ifdef _YO_CORE_BUILTIN
  {
    if ( p ) 
      {
        while ( *p )
          {
            p =  (void**)((byte_t*)*p + offs_of_next);
          }
        *p = val;
        *(void**)((byte_t*)*p + offs_of_next) = 0;
      }
  }
#endif
  ;
  
#define Slist_Pop_By(ListPtr,Next) Yo_Slist_Pop(ListPtr,(int)((size_t)(&(*ListPtr)->Next)-(size_t)(*ListPtr)))
#define Slist_Pop(ListPtr) Slist_Pop_By(ListPtr,next)

void *Yo_Slist_Pop(void **p, int offs_of_next)
#ifdef _YO_CORE_BUILTIN
  {
    void *r = 0;
    
    if ( p )
      {
        r = *p;
        if ( r ) 
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
#endif
  ;

#if defined __i386 || defined __x86_64
#define Eight_To_Quad(Eight)  (*(quad_t*)(Eight))
#else
quad_t Eight_To_Quad(void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    uint_t q0,q1;
    q0 =   (unsigned int)((unsigned char*)b)[0]
              | ((unsigned int)((unsigned char*)b)[1] << 8)
              | ((unsigned int)((unsigned char*)b)[2] << 16)
              | ((unsigned int)((unsigned char*)b)[3] << 24);
    b = (char*b)+4;







|







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
#endif
  ;

#if defined __i386 || defined __x86_64
#define Eight_To_Quad(Eight)  (*(quad_t*)(Eight))
#else
quad_t Eight_To_Quad(void *b)
#ifdef _YO_CORE_BUILTIN
  {
    uint_t q0,q1;
    q0 =   (unsigned int)((unsigned char*)b)[0]
              | ((unsigned int)((unsigned char*)b)[1] << 8)
              | ((unsigned int)((unsigned char*)b)[2] << 16)
              | ((unsigned int)((unsigned char*)b)[3] << 24);
    b = (char*b)+4;
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
  ;
#endif

#if defined __i386 || defined __x86_64
#define Quad_To_Eight(Q,Eight) ((*(quad_t*)(Eight)) = (Q))
#else
void Quad_To_Eight(quad_t q, void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
    p[2] = (byte_t)(q>>16);
    p[3] = (byte_t)(q>>24);
    p[4] = (byte_t)(q>>32);
    p[5] = (byte_t)(q>>40);
    p[6] = (byte_t)(q>>48);
    p[7] = (byte_t)(q>>56);
  }
#endif
  ;
#endif

#if defined __i386 || defined __x86_64
#define Four_To_Unsigned(Four)  (*(uint_t*)(Four))
#else
uint_t Four_To_Unsigned(void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    uint_t q =   p[0]
              |  (p[1] << 8)
              |  (p[2] << 16)
              |  (p[3] << 24);
    return q;
  }
#endif
  ;
#endif

#if defined __i386 || defined __x86_64
#define Unsigned_To_Four(Uval,Four) ((*(uint_t*)(Four)) = (Uval))
#else
void Unsigned_To_Four(uint_t q, void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
    p[2] = (byte_t)(q>>16);
    p[3] = (byte_t)(q>>24);
  }
#endif
  ;
#endif

uint_t Four_To_Unsigned_BE(void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    uint_t q =   p[3]
              |  (p[2] << 8)
              |  (p[1] << 16)
              |  (p[0] << 24);
    return q;
  }
#endif
  ;

void Unsigned_To_Four_BE(uint_t q, void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[3] = (byte_t)q;
    p[2] = (byte_t)(q>>8);
    p[1] = (byte_t)(q>>16);
    p[0] = (byte_t)(q>>24);
  }
#endif
  ;

uint_t Two_To_Unsigned(void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    uint_t q =   (unsigned int)((unsigned char*)b)[0]
              | ((unsigned int)((unsigned char*)b)[1] << 8);
    return q;
  }
#endif
  ;

void Unsigned_To_Two(uint_t q, void *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
  }
#endif
  ;

_YOYO_CORE_EXTERN byte_t Bitcount_8_Q[]
#ifdef _YOYO_CORE_BUILTIN
= {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,







|



















|
















|












|












|











|









|








|
|







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
  ;
#endif

#if defined __i386 || defined __x86_64
#define Quad_To_Eight(Q,Eight) ((*(quad_t*)(Eight)) = (Q))
#else
void Quad_To_Eight(quad_t q, void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
    p[2] = (byte_t)(q>>16);
    p[3] = (byte_t)(q>>24);
    p[4] = (byte_t)(q>>32);
    p[5] = (byte_t)(q>>40);
    p[6] = (byte_t)(q>>48);
    p[7] = (byte_t)(q>>56);
  }
#endif
  ;
#endif

#if defined __i386 || defined __x86_64
#define Four_To_Unsigned(Four)  (*(uint_t*)(Four))
#else
uint_t Four_To_Unsigned(void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    uint_t q =   p[0]
              |  (p[1] << 8)
              |  (p[2] << 16)
              |  (p[3] << 24);
    return q;
  }
#endif
  ;
#endif

#if defined __i386 || defined __x86_64
#define Unsigned_To_Four(Uval,Four) ((*(uint_t*)(Four)) = (Uval))
#else
void Unsigned_To_Four(uint_t q, void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
    p[2] = (byte_t)(q>>16);
    p[3] = (byte_t)(q>>24);
  }
#endif
  ;
#endif

uint_t Four_To_Unsigned_BE(void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    uint_t q =   p[3]
              |  (p[2] << 8)
              |  (p[1] << 16)
              |  (p[0] << 24);
    return q;
  }
#endif
  ;

void Unsigned_To_Four_BE(uint_t q, void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[3] = (byte_t)q;
    p[2] = (byte_t)(q>>8);
    p[1] = (byte_t)(q>>16);
    p[0] = (byte_t)(q>>24);
  }
#endif
  ;

uint_t Two_To_Unsigned(void *b)
#ifdef _YO_CORE_BUILTIN
  {
    uint_t q =   (unsigned int)((unsigned char*)b)[0]
              | ((unsigned int)((unsigned char*)b)[1] << 8);
    return q;
  }
#endif
  ;

void Unsigned_To_Two(uint_t q, void *b)
#ifdef _YO_CORE_BUILTIN
  {
    byte_t *p = b;
    p[0] = (byte_t)q;
    p[1] = (byte_t)(q>>8);
  }
#endif
  ;

_YO_CORE_EXTERN byte_t Bitcount_8_Q[]
#ifdef _YO_CORE_BUILTIN
= {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
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
   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
#endif
 ;

#define Bitcount_8(q) (Bitcount_8_Q[(q)&0x0ff])
uint_t Bitcount_Of( uint_t u )
#ifdef _YOYO_CORE_BUILTIN
    {
      int i;
      uint_t q;
      if ( u )
        for ( i = sizeof(u)*8-8; i >= 0; i-=8 )
          if ( !!(q = Bitcount_8(u>>i)) )
            return q+i;
      return 0;
    }
#endif
  ;

uint_t Min_Pow2(uint_t a)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( a ) --a;
    return 1<<Bitcount_Of(a);
  }
#endif
  ;

int Yo_Mini(int a, int b) _YOYO_CORE_BUILTIN_CODE({ return Yo_MIN(a,b); });
int Yo_Maxi(int a, int b) _YOYO_CORE_BUILTIN_CODE({ return Yo_MAX(a,b); });
uint_t Yo_Minu(uint_t a, uint_t b) _YOYO_CORE_BUILTIN_CODE({ return Yo_MIN(a,b); });
uint_t Yo_Maxu(uint_t a, uint_t b) _YOYO_CORE_BUILTIN_CODE({ return Yo_MAX(a,b); });
uint_t Yo_Absi(int a) _YOYO_CORE_BUILTIN_CODE({ return Yo_ABS(a); });

uint_t Align_To_Pow2(uint_t a, uint_t mod)
#ifdef _YOYO_CORE_BUILTIN
  {
    uint_t Q;
    if ( !mod ) mod = 1;
    Q = Min_Pow2(mod) - 1;
    return (a+Q)&~Q;
  }
#endif
  ;

int Compare_u32(void const *a, void const *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    return *(u32_t*)a - *(u32_t*)b;
  }
#endif
  ;

int Compare_Int(void const *a, void const *b)
#ifdef _YOYO_CORE_BUILTIN
  {
    return *(int*)a - *(int*)b;
  }
#endif
  ;


#ifdef __windoze
size_t malloc_size(void *p) _YOYO_CORE_BUILTIN_CODE({return _msize(p);});
#endif /* __windoze */

void *Yo_Malloc_Npl(int size)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *p;
    STRICT_REQUIRE(size >= 0);
    p = malloc(size);
    if ( !p )
      Yo_Fatal(YOYO_ERROR_OUT_OF_MEMORY,0,0,0);
    return p;
  }
#endif
  ;

void *Yo_Realloc_Npl(void *p,int size)
#ifdef _YOYO_CORE_BUILTIN
  {
    STRICT_REQUIRE(size >= 0);
    p = realloc(p,size);
    if ( !p )
      Yo_Fatal(YOYO_ERROR_OUT_OF_MEMORY,0,0,0);
    return p;
  }
#endif
  ;

void *Yo_Zero_Malloc_Npl(int size)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *p = Yo_Malloc_Npl(size);
    memset(p,0,size);
    return p;
  }
#endif
  ;

void *Yo_Resize_Npl(void *p,int size,int granularity)
#ifdef _YOYO_CORE_BUILTIN
  {
    int capacity = p?malloc_size(p):0;
    STRICT_REQUIRE(size >= 0);
    if ( !p || capacity < size )
      {
        if ( !granularity )
          capacity = Min_Pow2(size);
        else if ( granularity > 1 )
          {
            capacity = size+granularity-1;
            capacity -= capacity % granularity;
          }
        else
          capacity = size;
        p = realloc(p,capacity);
        if ( !p )
          Yo_Fatal(YOYO_ERROR_OUT_OF_MEMORY,0,0,0);
      }
    return p;
  }
#endif
  ;

void *Yo_Memcopy_Npl(void *src,int size)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *p;
    STRICT_REQUIRE(size >= 0);
    p = malloc(size);
    if ( !p )
      Yo_Fatal(YOYO_ERROR_OUT_OF_MEMORY,0,0,0);
    memcpy(p,src,size);
    return p;
  }
#endif
  ;

typedef struct _YOYO_AUTORELEASE
  {
    void *ptr;
    void (*cleanup)(void *);
  }
  YOYO_AUTORELEASE;

enum { YOYO_MAX_ERROR_BTRACE = 25 };

typedef struct _YOYO_ERROR_INFO
  {
    char *msg;
    char *filename;
    int  code;
    int  lineno;
    int  bt_count;
    void *bt_cbk[YOYO_MAX_ERROR_BTRACE];
  } YOYO_ERROR_INFO;

enum { YOYO_MAX_CS_COUNT = 7 };
enum { YOYO_INI_JB_COUNT = 5 };
enum { YOYO_EXT_JB_COUNT = 3 };
enum { YOYO_INI_POOL_COUNT = 256 };
enum { YOYO_EXT_POOL_COUNT = 128 };

typedef void (*Yo_JMPBUF_Unlock)(void *);

typedef struct _YOYO_JMPBUF_LOCK
  {
    void *cs;
    Yo_JMPBUF_Unlock unlock;
  } YOYO_JMPBUF_LOCK;

typedef struct _YOYO_JMPBUF
  {
    jmp_buf b;
    YOYO_JMPBUF_LOCK locks[YOYO_MAX_CS_COUNT];
    int auto_top;
  } YOYO_JMPBUF;

typedef struct _YOYO_C_SUPPORT_INFO
  {
    int auto_count;
    int auto_top;
    int jb_count;
    int jb_top;
    struct
      {
        unsigned unwinding: 1;
      } stats;
    YOYO_ERROR_INFO err;
    YOYO_AUTORELEASE *auto_pool;
    YOYO_JMPBUF jb[YOYO_INI_JB_COUNT];
  } YOYO_C_SUPPORT_INFO;

#ifdef _YOYO_CORE_BUILTIN
YO_TLS_DEFINE(Yo_Csup_Nfo_Tls);
#else
YO_TLS_DECLARE(Yo_Csup_Nfo_Tls);
#endif

YOYO_C_SUPPORT_INFO *Yo_Acquire_Csup_Nfo()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Malloc_Npl(sizeof(YOYO_C_SUPPORT_INFO));
    memset(nfo,0,sizeof(*nfo));
    nfo->jb_count = sizeof(nfo->jb)/sizeof(nfo->jb[0]);
    nfo->jb_top = -1;
    nfo->auto_pool = Yo_Malloc_Npl(sizeof(*nfo->auto_pool)*YOYO_INI_POOL_COUNT);
    nfo->auto_count = YOYO_INI_POOL_COUNT;
    nfo->auto_top = -1;
    Yo_Tls_Set(Yo_Csup_Nfo_Tls,nfo);
    return nfo;
  }
#endif
  ;

YOYO_C_SUPPORT_INFO *Yo_C_Support_Nfo()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( !nfo ) nfo = Yo_Acquire_Csup_Nfo();
    return nfo;
  }
#endif
  ;

YOYO_C_SUPPORT_INFO *Yo_Extend_Csup_JmpBuf()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    nfo = Yo_Realloc_Npl(nfo,sizeof(YOYO_C_SUPPORT_INFO)
              + (nfo->jb_count - YOYO_INI_JB_COUNT + YOYO_EXT_JB_COUNT)*sizeof(YOYO_JMPBUF));
    nfo->jb_count += YOYO_EXT_JB_COUNT;
    Yo_Tls_Set(Yo_Csup_Nfo_Tls,nfo);
    return nfo;
  }
#endif
  ;

void Yo_Extend_Csup_Autopool()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    uint_t ncount = nfo->auto_count + YOYO_EXT_POOL_COUNT;
    nfo->auto_pool = Yo_Realloc_Npl(nfo->auto_pool,sizeof(*nfo->auto_pool)*ncount);
    nfo->auto_count = ncount;
    //nfo->auto_top = ncount;
  }
#endif
  ;

void Yo_Pool_Marker_Tag(void *o) _YOYO_CORE_BUILTIN_CODE({});


YOYO_AUTORELEASE *Yo_Find_Ptr_In_Pool(YOYO_C_SUPPORT_INFO *nfo, void *p)
#ifdef _YOYO_CORE_BUILTIN
  {
    int n = nfo->auto_top;
    while ( n >= 0 )
      {
        if ( nfo->auto_pool[n].ptr == p )
          return &nfo->auto_pool[n];
        --n;
      }
    return 0;
  }
#endif
  ;

#define Yo_Push_Scope() Yo_Pool_Ptr(0,Yo_Pool_Marker_Tag)
#define Yo_Pool(Ptr) Yo_Pool_Ptr(Ptr,0)

void *Yo_Unrefe(void *p);
void *Yo_Pool_Ptr(void *ptr,void *cleanup)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( ptr || cleanup == Yo_Pool_Marker_Tag )
      {
        YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
        if ( !nfo ) nfo = Yo_Acquire_Csup_Nfo();
        STRICT_REQUIRE( (cleanup == Yo_Pool_Marker_Tag)
                      ||(cleanup == Yo_Unrefe)
                      ||!Yo_Find_Ptr_In_Pool(nfo,ptr) );

        ++nfo->auto_top;
        STRICT_REQUIRE(nfo->auto_top <= nfo->auto_count);







|













|







|
|
|
|
|


|










|







|








|



|





|






|




|






|









|
















|







|





|






|




|

|

|






|
|

|
|
|
|
|



|



|

|


|

|

|









|
|
|
|

|





|
|

|



|
|







|
|

|






|
|

|
|
|
|







|

|
|







|


|
|


















|



|







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
   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
#endif
 ;

#define Bitcount_8(q) (Bitcount_8_Q[(q)&0x0ff])
uint_t Bitcount_Of( uint_t u )
#ifdef _YO_CORE_BUILTIN
    {
      int i;
      uint_t q;
      if ( u )
        for ( i = sizeof(u)*8-8; i >= 0; i-=8 )
          if ( !!(q = Bitcount_8(u>>i)) )
            return q+i;
      return 0;
    }
#endif
  ;

uint_t Min_Pow2(uint_t a)
#ifdef _YO_CORE_BUILTIN
  {
    if ( a ) --a;
    return 1<<Bitcount_Of(a);
  }
#endif
  ;

int Yo_Mini(int a, int b) _YO_CORE_BUILTIN_CODE({ return Yo_MIN(a,b); });
int Yo_Maxi(int a, int b) _YO_CORE_BUILTIN_CODE({ return Yo_MAX(a,b); });
uint_t Yo_Minu(uint_t a, uint_t b) _YO_CORE_BUILTIN_CODE({ return Yo_MIN(a,b); });
uint_t Yo_Maxu(uint_t a, uint_t b) _YO_CORE_BUILTIN_CODE({ return Yo_MAX(a,b); });
uint_t Yo_Absi(int a) _YO_CORE_BUILTIN_CODE({ return Yo_ABS(a); });

uint_t Align_To_Pow2(uint_t a, uint_t mod)
#ifdef _YO_CORE_BUILTIN
  {
    uint_t Q;
    if ( !mod ) mod = 1;
    Q = Min_Pow2(mod) - 1;
    return (a+Q)&~Q;
  }
#endif
  ;

int Compare_u32(void const *a, void const *b)
#ifdef _YO_CORE_BUILTIN
  {
    return *(u32_t*)a - *(u32_t*)b;
  }
#endif
  ;

int Compare_Int(void const *a, void const *b)
#ifdef _YO_CORE_BUILTIN
  {
    return *(int*)a - *(int*)b;
  }
#endif
  ;


#ifdef __windoze
size_t malloc_size(void *p) _YO_CORE_BUILTIN_CODE({return _msize(p);});
#endif /* __windoze */

void *Yo_Malloc_Npl(int size)
#ifdef _YO_CORE_BUILTIN
  {
    void *p;
    STRICT_REQUIRE(size >= 0);
    p = malloc(size);
    if ( !p )
      Yo_Fatal(YO_ERROR_OUT_OF_MEMORY,0,0,0);
    return p;
  }
#endif
  ;

void *Yo_Realloc_Npl(void *p,int size)
#ifdef _YO_CORE_BUILTIN
  {
    STRICT_REQUIRE(size >= 0);
    p = realloc(p,size);
    if ( !p )
      Yo_Fatal(YO_ERROR_OUT_OF_MEMORY,0,0,0);
    return p;
  }
#endif
  ;

void *Yo_Zero_Malloc_Npl(int size)
#ifdef _YO_CORE_BUILTIN
  {
    void *p = Yo_Malloc_Npl(size);
    memset(p,0,size);
    return p;
  }
#endif
  ;

void *Yo_Resize_Npl(void *p,int size,int granularity)
#ifdef _YO_CORE_BUILTIN
  {
    int capacity = p?malloc_size(p):0;
    STRICT_REQUIRE(size >= 0);
    if ( !p || capacity < size )
      {
        if ( !granularity )
          capacity = Min_Pow2(size);
        else if ( granularity > 1 )
          {
            capacity = size+granularity-1;
            capacity -= capacity % granularity;
          }
        else
          capacity = size;
        p = realloc(p,capacity);
        if ( !p )
          Yo_Fatal(YO_ERROR_OUT_OF_MEMORY,0,0,0);
      }
    return p;
  }
#endif
  ;

void *Yo_Memcopy_Npl(void *src,int size)
#ifdef _YO_CORE_BUILTIN
  {
    void *p;
    STRICT_REQUIRE(size >= 0);
    p = malloc(size);
    if ( !p )
      Yo_Fatal(YO_ERROR_OUT_OF_MEMORY,0,0,0);
    memcpy(p,src,size);
    return p;
  }
#endif
  ;

typedef struct _YO_AUTORELEASE
  {
    void *ptr;
    void (*cleanup)(void *);
  }
  YO_AUTORELEASE;

enum { YO_MAX_ERROR_BTRACE = 25 };

typedef struct _YO_ERROR_INFO
  {
    char *msg;
    char *filename;
    int  code;
    int  lineno;
    int  bt_count;
    void *bt_cbk[YO_MAX_ERROR_BTRACE];
  } YO_ERROR_INFO;

enum { YO_MAX_CS_COUNT = 7 };
enum { YO_INI_JB_COUNT = 5 };
enum { YO_EXT_JB_COUNT = 3 };
enum { YO_INI_POOL_COUNT = 256 };
enum { YO_EXT_POOL_COUNT = 128 };

typedef void (*Yo_JMPBUF_Unlock)(void *);

typedef struct _YO_JMPBUF_LOCK
  {
    void *cs;
    Yo_JMPBUF_Unlock unlock;
  } YO_JMPBUF_LOCK;

typedef struct _YO_JMPBUF
  {
    jmp_buf b;
    YO_JMPBUF_LOCK locks[YO_MAX_CS_COUNT];
    int auto_top;
  } YO_JMPBUF;

typedef struct _YO_C_SUPPORT_INFO
  {
    int auto_count;
    int auto_top;
    int jb_count;
    int jb_top;
    struct
      {
        unsigned unwinding: 1;
      } stats;
    YO_ERROR_INFO err;
    YO_AUTORELEASE *auto_pool;
    YO_JMPBUF jb[YO_INI_JB_COUNT];
  } YO_C_SUPPORT_INFO;

#ifdef _YO_CORE_BUILTIN
YO_TLS_DEFINE(Yo_Csup_Nfo_Tls);
#else
YO_TLS_DECLARE(Yo_Csup_Nfo_Tls);
#endif

YO_C_SUPPORT_INFO *Yo_Acquire_Csup_Nfo()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Malloc_Npl(sizeof(YO_C_SUPPORT_INFO));
    memset(nfo,0,sizeof(*nfo));
    nfo->jb_count = sizeof(nfo->jb)/sizeof(nfo->jb[0]);
    nfo->jb_top = -1;
    nfo->auto_pool = Yo_Malloc_Npl(sizeof(*nfo->auto_pool)*YO_INI_POOL_COUNT);
    nfo->auto_count = YO_INI_POOL_COUNT;
    nfo->auto_top = -1;
    Yo_Tls_Set(Yo_Csup_Nfo_Tls,nfo);
    return nfo;
  }
#endif
  ;

YO_C_SUPPORT_INFO *Yo_C_Support_Nfo()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( !nfo ) nfo = Yo_Acquire_Csup_Nfo();
    return nfo;
  }
#endif
  ;

YO_C_SUPPORT_INFO *Yo_Extend_Csup_JmpBuf()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    nfo = Yo_Realloc_Npl(nfo,sizeof(YO_C_SUPPORT_INFO)
              + (nfo->jb_count - YO_INI_JB_COUNT + YO_EXT_JB_COUNT)*sizeof(YO_JMPBUF));
    nfo->jb_count += YO_EXT_JB_COUNT;
    Yo_Tls_Set(Yo_Csup_Nfo_Tls,nfo);
    return nfo;
  }
#endif
  ;

void Yo_Extend_Csup_Autopool()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    uint_t ncount = nfo->auto_count + YO_EXT_POOL_COUNT;
    nfo->auto_pool = Yo_Realloc_Npl(nfo->auto_pool,sizeof(*nfo->auto_pool)*ncount);
    nfo->auto_count = ncount;
    //nfo->auto_top = ncount;
  }
#endif
  ;

void Yo_Pool_Marker_Tag(void *o) _YO_CORE_BUILTIN_CODE({});


YO_AUTORELEASE *Yo_Find_Ptr_In_Pool(YO_C_SUPPORT_INFO *nfo, void *p)
#ifdef _YO_CORE_BUILTIN
  {
    int n = nfo->auto_top;
    while ( n >= 0 )
      {
        if ( nfo->auto_pool[n].ptr == p )
          return &nfo->auto_pool[n];
        --n;
      }
    return 0;
  }
#endif
  ;

#define Yo_Push_Scope() Yo_Pool_Ptr(0,Yo_Pool_Marker_Tag)
#define Yo_Pool(Ptr) Yo_Pool_Ptr(Ptr,0)

void *Yo_Unrefe(void *p);
void *Yo_Pool_Ptr(void *ptr,void *cleanup)
#ifdef _YO_CORE_BUILTIN
  {
    if ( ptr || cleanup == Yo_Pool_Marker_Tag )
      {
        YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
        if ( !nfo ) nfo = Yo_Acquire_Csup_Nfo();
        STRICT_REQUIRE( (cleanup == Yo_Pool_Marker_Tag)
                      ||(cleanup == Yo_Unrefe)
                      ||!Yo_Find_Ptr_In_Pool(nfo,ptr) );

        ++nfo->auto_top;
        STRICT_REQUIRE(nfo->auto_top <= nfo->auto_count);
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
#endif
  ;

#define Yo_Release(Pooled) ((void)Yo_Unpool((Pooled),1))
#define Yo_Retain(Pooled) Yo_Unpool((Pooled),0)

void *Yo_Unpool(void *pooled,int do_cleanup)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && pooled )
      {
        int n = nfo->auto_top;
        while ( n >= 0 )
          {
            if ( nfo->auto_pool[n].ptr == pooled )
              {
                YOYO_AUTORELEASE *q = &nfo->auto_pool[n];
                if ( do_cleanup && q->ptr ) q->cleanup(q->ptr);

                if ( nfo->jb_top < 0 || nfo->jb[nfo->jb_top].auto_top < n )
                  {
                    if ( nfo->auto_top != n )
                        memmove(nfo->auto_pool+n,nfo->auto_pool+n+1,(nfo->auto_top-n)*sizeof(*q));
                    --nfo->auto_top;







|

|







|







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
#endif
  ;

#define Yo_Release(Pooled) ((void)Yo_Unpool((Pooled),1))
#define Yo_Retain(Pooled) Yo_Unpool((Pooled),0)

void *Yo_Unpool(void *pooled,int do_cleanup)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && pooled )
      {
        int n = nfo->auto_top;
        while ( n >= 0 )
          {
            if ( nfo->auto_pool[n].ptr == pooled )
              {
                YO_AUTORELEASE *q = &nfo->auto_pool[n];
                if ( do_cleanup && q->ptr ) q->cleanup(q->ptr);

                if ( nfo->jb_top < 0 || nfo->jb[nfo->jb_top].auto_top < n )
                  {
                    if ( nfo->auto_top != n )
                        memmove(nfo->auto_pool+n,nfo->auto_pool+n+1,(nfo->auto_top-n)*sizeof(*q));
                    --nfo->auto_top;
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
      }
    return pooled;
  }
#endif
  ;

void *Yo_Unwind_Scope(void *pooled,int min_top,void *mark)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    int L = min_top>=0?min_top:0;
    //int counter = 0;
    if ( nfo )
      {
        YOYO_AUTORELEASE *q_p = 0;
        nfo->stats.unwinding = 1;
        while ( nfo->auto_top >= L )
          {
            YOYO_AUTORELEASE *q = &nfo->auto_pool[nfo->auto_top];
            STRICT_REQUIRE(nfo->auto_top <= nfo->auto_count);
            //printf("ptr: %p, cleanup: %p ?= pooled: %p, mark: %p\n", q->ptr, q->cleanup, pooled, mark);
            if ( q->ptr && (q->cleanup != Yo_Pool_Marker_Tag) )
              {
                if ( !pooled || q->ptr != pooled )
                  {
                    q->cleanup(q->ptr);







|

|




|



|







1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
      }
    return pooled;
  }
#endif
  ;

void *Yo_Unwind_Scope(void *pooled,int min_top,void *mark)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    int L = min_top>=0?min_top:0;
    //int counter = 0;
    if ( nfo )
      {
        YO_AUTORELEASE *q_p = 0;
        nfo->stats.unwinding = 1;
        while ( nfo->auto_top >= L )
          {
            YO_AUTORELEASE *q = &nfo->auto_pool[nfo->auto_top];
            STRICT_REQUIRE(nfo->auto_top <= nfo->auto_count);
            //printf("ptr: %p, cleanup: %p ?= pooled: %p, mark: %p\n", q->ptr, q->cleanup, pooled, mark);
            if ( q->ptr && (q->cleanup != Yo_Pool_Marker_Tag) )
              {
                if ( !pooled || q->ptr != pooled )
                  {
                    q->cleanup(q->ptr);
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
    return pooled;
  }
#endif
  ;

#define Yo_Refresh(Old,New) Yo_Refresh_Ptr(Old,New,0)
void *Yo_Refresh_Ptr(void *old,void *new,void *cleaner)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo;
    REQUIRE( new != 0 );
    if ( old && !!(nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls)) )
      {
        YOYO_AUTORELEASE *p = Yo_Find_Ptr_In_Pool(nfo,old);
        if ( !p ) Yo_Fatal(YOYO_ERROR_OUT_OF_POOL,old,0,0);
        p->ptr = new;
      }
    else
      Yo_Pool_Ptr(new,cleaner);
    return new;
  }
#endif
  ;

enum { YOYO_DEFAULT_PURGE_CAP = 5 };

int Yo_Pool_Purge(int *thold, int cap)
#ifdef _YOYO_CORE_BUILTIN
  {
    return 1;
  }
#endif
  ;

void Yo_Thread_Cleanup()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo;
    Yo_Unwind_Scope(0,-1,0);
    if ( !!(nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls)) )
      {
        free(nfo->err.msg);
        free(nfo->auto_pool);
        free(nfo);
        Yo_Tls_Set(Yo_Csup_Nfo_Tls,0);
      }
  }
#endif
  ;

void Yo_Global_Cleanup()
#ifdef _YOYO_CORE_BUILTIN
  {
  }
#endif
  ;

void *Yo_Malloc(unsigned size)
  _YOYO_CORE_BUILTIN_CODE({return Yo_Pool(Yo_Malloc_Npl(size));});
void *Yo_Realloc(void *p,unsigned size)
  _YOYO_CORE_BUILTIN_CODE({return Yo_Refresh(p,Yo_Realloc_Npl(p,size));});
void *Yo_Memcopy(void *p,unsigned size)
  _YOYO_CORE_BUILTIN_CODE({return Yo_Pool(Yo_Memcopy_Npl(p,size));});

void *Yo_Resize(void *p,unsigned size,int granularity)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *q = Yo_Resize_Npl(p,size,granularity);
    if ( p && q != p )
      Yo_Refresh(p,q);
    else if ( !p )
      Yo_Pool(q);
    return q;
  }
#endif
  ;

#if defined _YOYO_CORE_BUILTIN && defined __windoze && defined __VSCPRINTF
int _vscprintf(char *fmt,va_list va)
  {
    static char simulate[4096*4] = {0};
    return vsprintf(simulate,fmt,va);
  }
#endif

int Yo_Detect_Required_Buffer_Size(char *fmt,va_list va)
#ifdef _YOYO_CORE_BUILTIN
  {
  #ifdef __windoze
    return _vscprintf(fmt,va)+1;
  #else
    va_list qva;
    va_copy(qva,va);
    return vsnprintf(0,0,fmt,qva)+1;
  #endif
  }
#endif
  ;

char *Yo_Format_(char *fmt,va_list va)
#ifdef _YOYO_CORE_BUILTIN
  {
    int rq_len = Yo_Detect_Required_Buffer_Size(fmt,va)+1;
    char *b = Yo_Malloc_Npl(rq_len);
  #ifdef __windoze
    vsprintf(b,fmt,va);
  #else
    vsnprintf(b,rq_len,fmt,va);
  #endif
    return b;
  }
#endif
  ;

char *Yo_Format_Npl(char *fmt,...)
  _YOYO_CORE_BUILTIN_CODE({va_list va;char *t; va_start(va,fmt); t = Yo_Format_(fmt,va);va_end(va); return t;});

char *Yo_Format(char *fmt,...)
  _YOYO_CORE_BUILTIN_CODE({va_list va;char *t; va_start(va,fmt); t = Yo_Pool(Yo_Format_(fmt,va));va_end(va); return t;});

void Yo_Print_FILE(FILE *st, char *text, unsigned flags)
#ifdef _YOYO_CORE_BUILTIN
  {
    __Xchg_Interlock
      {
        fputs(text,st);
        if ( flags & YO_PRINT_NEWLINE ) fputc('\n',st);
        if ( flags & YO_PRINT_FLUSH ) fflush(st);
      }
  }
#endif
  ;

#define StdOut_Print(Text) Yo_Print_FILE(stdout,Text,YO_PRINT_FLUSH)
#define StdOut_Print_Nl(Text) Yo_Print_FILE(stdout,Text,YO_PRINT_FLUSH|YO_PRINT_NEWLINE)
#define StdErr_Print(Text) Yo_Print_FILE(stderr,Text,YO_PRINT_FLUSH)
#define StdErr_Print_Nl(Text) Yo_Print_FILE(stderr,Text,YO_PRINT_FLUSH|YO_PRINT_NEWLINE)

typedef struct _YOYO_FUNCTABLE
  {
    char *name;
    void *func;
  } YOYO_FUNCTABLE;

typedef struct _YOYO_CORE_DYNAMIC
  {
    longptr_t contsig;
    longptr_t typeid;
    YOYO_FUNCTABLE funcs[1];
  }
  YOYO_DYNAMIC;

typedef struct _YOYO_CORE_OBJECT
  {
    uint_t signature; /* YOYO_OBJECT_SIGNATURE */
    uint_t rc;
    YOYO_DYNAMIC *dynamic;
  }
  YOYO_OBJECT;

#define YOYO_BASE(Ptr)          ((YOYO_OBJECT*)(Ptr) - 1)
#define YOYO_RC(Ptr)            (YOYO_BASE(Ptr)->rc)
#define YOYO_SIGNAT(Ptr)        (YOYO_BASE(Ptr)->signature)
#define YOYO_SIGNAT_IS_OK(Ptr)  ((YOYO_BASE(Ptr)->signature&0x00ffffff) == YOYO_OBJECT_SIGNATURE_PFX)

void *Yo_Unrefe(void *p);

#ifdef _YOYO_CORE_BUILTIN
uint_t Yo_Typeid_Counter = 0;
#endif

enum { YOYO_DYNCO_NYD = 0x4e5944/*'NYD'*/, YOYO_DYNCO_ATS = 0x415453/*'ATS'*/ };

void *Yo_Clone_Dynamic( YOYO_DYNAMIC *dynco, int extra )
#ifdef _YOYO_CORE_BUILTIN
  {
    int count = dynco->contsig&0x0ff;
    int fc = count?count-1:0;
    int fcc = (count+extra)?count+extra-1:0;
    YOYO_DYNAMIC *d = Yo_Malloc_Npl(sizeof(YOYO_DYNAMIC)+sizeof(YOYO_FUNCTABLE)*fcc);
    *d = *dynco;
    if ( fc )
      memcpy(d->funcs+1,dynco->funcs+1,sizeof(YOYO_FUNCTABLE)*fc);
    d->contsig = (YOYO_DYNCO_NYD<<8)|count;
    return d;
  }
#endif
  ;

void *Yo_Extend_Dynamic( YOYO_DYNAMIC *dynco, int extra )
#ifdef _YOYO_CORE_BUILTIN
  {
    int count = dynco->contsig&0x0ff;
    int fcc = (count+extra)?count+extra-1:0;
    YOYO_DYNAMIC *d = Yo_Realloc_Npl(dynco,sizeof(YOYO_DYNAMIC)+sizeof(YOYO_FUNCTABLE)*fcc);
    return d;
  }
#endif
  ;

void *Yo_Object_Extend( void *o, char *func_name, void *func )
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_OBJECT *T = YOYO_BASE(o);
    YOYO_FUNCTABLE *f;
    if ( !T )
      Yo_Raise(YOYO_ERROR_NULL_PTR,__yoTa("failed to extend nullptr",0),__Yo_FILE__,__LINE__);

    if ( T->dynamic )
      {
        if ( (T->dynamic->contsig >> 8) == YOYO_DYNCO_ATS )
          T->dynamic = Yo_Clone_Dynamic(T->dynamic,1);
        else
          T->dynamic = Yo_Extend_Dynamic(T->dynamic,1);
      }
    else
      {
        T->dynamic = Yo_Malloc_Npl(sizeof(YOYO_DYNAMIC));
        T->dynamic->contsig = YOYO_DYNCO_NYD<<8;
      }

    T->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
    f = T->dynamic->funcs+(T->dynamic->contsig&0x0ff);
    ++T->dynamic->contsig;
    f->name = func_name;
    f->func = func;

    return o;
  }
#endif
  ;

enum 
  { 
    YOYO_OBJECT_SIGNATURE_PFX  =  0x00594f59, /*'YOY'*/  
    YOYO_OBJECT_SIGNATURE_HEAP =  0x4f594f59, /*'YOYO'*/  
    YOYO_MEMPOOL_PIECE_MAXSIZE = 1*KILOBYTE,
    YOYO_MEMPOOL_PIECE_ON_BLOCK= 16,
    YOYO_MEMPOOL_PIECE_STEP    = 64,
    YOYO_MEMPOOL_SLOTS_COUNT   = YOYO_MEMPOOL_PIECE_MAXSIZE/YOYO_MEMPOOL_PIECE_STEP,
  };

__Static_Assert(YOYO_MEMPOOL_SLOTS_COUNT <= 'O');

#ifdef _YOYO_CORE_BUILTIN
void *Yo_Mempool_Slots[YOYO_MEMPOOL_SLOTS_COUNT] = {0,};
int Yo_Mempool_Counts[YOYO_MEMPOOL_SLOTS_COUNT] = {0,};
#endif

void Yo_Mempool_Free(void *p,int plidx)
#ifdef _YOYO_CORE_BUILTIN
  {
    void **Q = p;
    STRICT_REQUIRE(plidx >= 0 && plidx <YOYO_MEMPOOL_SLOTS_COUNT); 
    for (;;)
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        *Q = *S;
        if ( Yo_Atomic_CmpXchg_Ptr(S,Q,*Q) ) break;
      }
  }
#endif
  ;
  
void Yo_Mempool_Extend(int plidx)
#ifdef _YOYO_CORE_BUILTIN
  {
    __Xchg_Interlock
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        if ( !*S )
          {
            int i,piece = (plidx+1)*YOYO_MEMPOOL_PIECE_STEP; 
            void **Q = Yo_Malloc_Npl(piece*YOYO_MEMPOOL_PIECE_ON_BLOCK);
            Yo_Mempool_Counts[plidx] += YOYO_MEMPOOL_PIECE_ON_BLOCK;
            for ( i=0; i < YOYO_MEMPOOL_PIECE_ON_BLOCK; ++i, Q = (void**)((byte_t*)Q + piece) )
              for (;;)
                {
                  *Q = *S;
                  if ( Yo_Atomic_CmpXchg_Ptr(S,Q,*Q) ) break;
                }
          }
      }
  }
#endif
  ;
  
void *Yo_Mempool_Zalloc(int plidx)
#ifdef _YOYO_CORE_BUILTIN
  {
    void **Q;
    STRICT_REQUIRE(plidx >= 0 && plidx <YOYO_MEMPOOL_SLOTS_COUNT); 
    for (;;)
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        Q = *S;
        if ( !Q ) 
          Yo_Mempool_Extend(plidx);
        else
          if ( Yo_Atomic_CmpXchg_Ptr(S,*Q,Q) ) break;
      }
    memset(Q,0,(plidx+1)*YOYO_MEMPOOL_PIECE_STEP);
    return Q;              
  }
#endif
  ;

YOYO_OBJECT *Yo_Object_Alloc(int size)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_OBJECT *o;
    if ( size + sizeof(YOYO_OBJECT) > YOYO_MEMPOOL_PIECE_MAXSIZE )
      {
        o = Yo_Zero_Malloc_Npl(sizeof(YOYO_OBJECT)+size);
        o->signature = YOYO_OBJECT_SIGNATURE_HEAP;
      }
    else
      {
        int plidx = (sizeof(YOYO_OBJECT)+size-1)/YOYO_MEMPOOL_PIECE_STEP;
        o = Yo_Mempool_Zalloc(plidx);
        o->signature = YOYO_OBJECT_SIGNATURE_PFX + (plidx<<24);
      }
    return o;
  }
#endif
  ;

void Yo_Object_Free(YOYO_OBJECT *o)
#ifdef _YOYO_CORE_BUILTIN
  {
    int plidx = o->signature >> 24;
    if ( plidx >= YOYO_MEMPOOL_SLOTS_COUNT ) 
      free(o);
    else
      Yo_Mempool_Free(o,plidx);
  }
#endif
  ;

void *Yo_Object_Clone(int size, void *orign)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_OBJECT *o;
    YOYO_OBJECT *T = YOYO_BASE(orign);
    if ( !T )
      Yo_Raise(YOYO_ERROR_NULL_PTR,__yoTa("failed to clone nullptr",0),__Yo_FILE__,__LINE__);

    o = Yo_Object_Alloc(size);
    o->rc = 1;
    memcpy(o+1,orign,size);

    if ( T->dynamic )
      {
        if ( (T->dynamic->contsig>>8) == YOYO_DYNCO_ATS )
          o->dynamic = T->dynamic;
        else
          {
            STRICT_REQUIRE( (T->dynamic->contsig>>8) == YOYO_DYNCO_NYD );
            o->dynamic = Yo_Clone_Dynamic(T->dynamic,0);
          }
      }
    else
      o->dynamic = 0;

    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

void *Yo_Object(int size,YOYO_FUNCTABLE *tbl)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_OBJECT *o = Yo_Object_Alloc(size);
    o->rc = 1;
    o->dynamic = (YOYO_DYNAMIC*)tbl;

    if ( tbl )
      {__Xchg_Interlock
        {
          YOYO_DYNAMIC *dynco = (YOYO_DYNAMIC*)tbl;
          if ( !dynco->contsig )
            {
              int count;
              for ( count = 0; tbl[count+1].name; ) { ++count; }
              dynco->contsig = (YOYO_DYNCO_ATS<<8)|count;
              dynco->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
            }
        }}

    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

ulong_t Yo_Align(ulong_t val)
#ifdef _YOYO_CORE_BUILTIN
  {
    return (val + 7)&~7;
  }
#endif
  ;

void *Yo_Object_Dtor(int size,void *dtor)
#ifdef _YOYO_CORE_BUILTIN
  {
    int Sz = Yo_Align(sizeof(YOYO_OBJECT)+size);
    YOYO_OBJECT *o = Yo_Object_Alloc(Sz+sizeof(YOYO_DYNAMIC));
    o->rc = 1;
    o->dynamic = (YOYO_DYNAMIC*)((char*)o + Sz);
    o->dynamic->contsig = (YOYO_DYNCO_ATS<<8)|1;
    o->dynamic->funcs[0].name = Oj_Destruct_OjMID;
    o->dynamic->funcs[0].func = dtor;
    o->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

void Yo_Object_Destruct(void *ptr)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( ptr )
      {
        YOYO_OBJECT *o = (YOYO_OBJECT *)ptr - 1;
        if ( o->dynamic && (o->dynamic->contsig>>8) == YOYO_DYNCO_NYD )
          free(o->dynamic);
        o->dynamic = 0;
        Yo_Object_Free(o);
      }
  }
#endif
  ;

void *Yo_Find_Method_In_Table(char *name,YOYO_FUNCTABLE *tbl,int count,int flags)
#ifdef _YOYO_CORE_BUILTIN
  {
    int i;
    for ( i = 0; i < count; ++i )
      if ( strcmp(tbl[i].name,name) == 0 )
        return tbl[i].func;
    return 0;
  }
#endif
  ;

void *Yo_Find_Method_Of(void **self,char *name,unsigned flags)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *o = *self;
    if ( o && STRICT_CHECK(YOYO_SIGNAT_IS_OK(o)) )
      {
        YOYO_DYNAMIC *dynco = YOYO_BASE(o)->dynamic;
        if ( dynco )
          {
            if ( 1 && STRICT_CHECK((dynco->contsig>>8) == YOYO_DYNCO_ATS || (dynco->contsig>>8) == YOYO_DYNCO_NYD) )
              {
                void *f = Yo_Find_Method_In_Table(name,dynco->funcs,(dynco->contsig&0x0ff),flags);
                if ( !f && (flags & YO_RAISE_ERROR) )
                  Yo_Raise(YOYO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
                return f;
              }
            else
              Yo_Fatal(YOYO_ERROR_DYNCO_CORRUPTED,o,__Yo_FILE__,__LINE__);
          }
        else if (flags & YO_RAISE_ERROR)
          Yo_Raise(YOYO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
      }
    else if (flags & YO_RAISE_ERROR)
      Yo_Raise(YOYO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
    return 0;
  }
#endif
  ;

void *Yo_Refe(void *p)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( p && STRICT_CHECK(YOYO_SIGNAT_IS_OK(p)) )
      Yo_Atomic_Increment(&YOYO_RC(p));
    return p;
  }
#endif
  ;

#ifdef _YOYO_CORE_BUILTIN
void *Yo_Unrefe(void *p)
  {
    if ( p && STRICT_CHECK(YOYO_SIGNAT_IS_OK(p))
           && !(Yo_Atomic_Decrement(&YOYO_RC(p))&0x7fffff) )
      {
        void (*destruct)(void *) = Yo_Find_Method_Of(&p,Oj_Destruct_OjMID,0);
        if ( !destruct )
          Yo_Object_Destruct(p);
        else
          destruct(p);
        return 0;
      }
    return p;
  }
#endif
  ;

void *Oj_Clone(void *p)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( p )
      {
        void *(*clone)(void *) = Yo_Find_Method_Of(&p,Oj_Clone_OjMID,YO_RAISE_ERROR);
        return clone(p);
      }
    return p;
  }
#endif
  ;

int Oj_Count(void *self)
#ifdef _YOYO_CORE_BUILTIN
  {
    int (*count)(void *) = Yo_Find_Method_Of(&self,Oj_Count_OjMID,YO_RAISE_ERROR);
    return count(self);
  }
#endif
  ;








|

|



|
|









|


|







|

|













|






|

|

|


|











|








|













|














|


|


|
















|



|

|



|

|

|

|

|

|

|
|
|
|



|



|

|
|




|


|
|





|
|



|






|

|
|

|



|






|
|















|
|
|
|
|
|


|

|
|
|



|


|











|






|
|
|
|












|


|









|





|
|

|
|

|
|



|

|






|
|


|








|

|
|

|







|



|











|
|

|

|




|




|










|







|

|
|

|
|









|



|
|








|
|











|


|

|


|



|



|


|


|






|

|
|





|


|
|














|












|







1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
    return pooled;
  }
#endif
  ;

#define Yo_Refresh(Old,New) Yo_Refresh_Ptr(Old,New,0)
void *Yo_Refresh_Ptr(void *old,void *new,void *cleaner)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo;
    REQUIRE( new != 0 );
    if ( old && !!(nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls)) )
      {
        YO_AUTORELEASE *p = Yo_Find_Ptr_In_Pool(nfo,old);
        if ( !p ) Yo_Fatal(YO_ERROR_OUT_OF_POOL,old,0,0);
        p->ptr = new;
      }
    else
      Yo_Pool_Ptr(new,cleaner);
    return new;
  }
#endif
  ;

enum { YO_DEFAULT_PURGE_CAP = 5 };

int Yo_Pool_Purge(int *thold, int cap)
#ifdef _YO_CORE_BUILTIN
  {
    return 1;
  }
#endif
  ;

void Yo_Thread_Cleanup()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo;
    Yo_Unwind_Scope(0,-1,0);
    if ( !!(nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls)) )
      {
        free(nfo->err.msg);
        free(nfo->auto_pool);
        free(nfo);
        Yo_Tls_Set(Yo_Csup_Nfo_Tls,0);
      }
  }
#endif
  ;

void Yo_Global_Cleanup()
#ifdef _YO_CORE_BUILTIN
  {
  }
#endif
  ;

void *Yo_Malloc(unsigned size)
  _YO_CORE_BUILTIN_CODE({return Yo_Pool(Yo_Malloc_Npl(size));});
void *Yo_Realloc(void *p,unsigned size)
  _YO_CORE_BUILTIN_CODE({return Yo_Refresh(p,Yo_Realloc_Npl(p,size));});
void *Yo_Memcopy(void *p,unsigned size)
  _YO_CORE_BUILTIN_CODE({return Yo_Pool(Yo_Memcopy_Npl(p,size));});

void *Yo_Resize(void *p,unsigned size,int granularity)
#ifdef _YO_CORE_BUILTIN
  {
    void *q = Yo_Resize_Npl(p,size,granularity);
    if ( p && q != p )
      Yo_Refresh(p,q);
    else if ( !p )
      Yo_Pool(q);
    return q;
  }
#endif
  ;

#if defined _YO_CORE_BUILTIN && defined __windoze && defined __VSCPRINTF
int _vscprintf(char *fmt,va_list va)
  {
    static char simulate[4096*4] = {0};
    return vsprintf(simulate,fmt,va);
  }
#endif

int Yo_Detect_Required_Buffer_Size(char *fmt,va_list va)
#ifdef _YO_CORE_BUILTIN
  {
  #ifdef __windoze
    return _vscprintf(fmt,va)+1;
  #else
    va_list qva;
    va_copy(qva,va);
    return vsnprintf(0,0,fmt,qva)+1;
  #endif
  }
#endif
  ;

char *Yo_Format_(char *fmt,va_list va)
#ifdef _YO_CORE_BUILTIN
  {
    int rq_len = Yo_Detect_Required_Buffer_Size(fmt,va)+1;
    char *b = Yo_Malloc_Npl(rq_len);
  #ifdef __windoze
    vsprintf(b,fmt,va);
  #else
    vsnprintf(b,rq_len,fmt,va);
  #endif
    return b;
  }
#endif
  ;

char *Yo_Format_Npl(char *fmt,...)
  _YO_CORE_BUILTIN_CODE({va_list va;char *t; va_start(va,fmt); t = Yo_Format_(fmt,va);va_end(va); return t;});

char *Yo_Format(char *fmt,...)
  _YO_CORE_BUILTIN_CODE({va_list va;char *t; va_start(va,fmt); t = Yo_Pool(Yo_Format_(fmt,va));va_end(va); return t;});

void Yo_Print_FILE(FILE *st, char *text, unsigned flags)
#ifdef _YO_CORE_BUILTIN
  {
    __Xchg_Interlock
      {
        fputs(text,st);
        if ( flags & YO_PRINT_NEWLINE ) fputc('\n',st);
        if ( flags & YO_PRINT_FLUSH ) fflush(st);
      }
  }
#endif
  ;

#define StdOut_Print(Text) Yo_Print_FILE(stdout,Text,YO_PRINT_FLUSH)
#define StdOut_Print_Nl(Text) Yo_Print_FILE(stdout,Text,YO_PRINT_FLUSH|YO_PRINT_NEWLINE)
#define StdErr_Print(Text) Yo_Print_FILE(stderr,Text,YO_PRINT_FLUSH)
#define StdErr_Print_Nl(Text) Yo_Print_FILE(stderr,Text,YO_PRINT_FLUSH|YO_PRINT_NEWLINE)

typedef struct _YO_FUNCTABLE
  {
    char *name;
    void *func;
  } YO_FUNCTABLE;

typedef struct _YO_CORE_DYNAMIC
  {
    longptr_t contsig;
    longptr_t typeid;
    YO_FUNCTABLE funcs[1];
  }
  YO_DYNAMIC;

typedef struct _YO_CORE_OBJECT
  {
    uint_t signature; /* YO_OBJECT_SIGNATURE */
    uint_t rc;
    YO_DYNAMIC *dynamic;
  }
  YO_OBJECT;

#define YO_BASE(Ptr)          ((YO_OBJECT*)(Ptr) - 1)
#define YO_RC(Ptr)            (YO_BASE(Ptr)->rc)
#define YO_SIGNAT(Ptr)        (YO_BASE(Ptr)->signature)
#define YO_SIGNAT_IS_OK(Ptr)  ((YO_BASE(Ptr)->signature&0x00ffffff) == YO_OBJECT_SIGNATURE_PFX)

void *Yo_Unrefe(void *p);

#ifdef _YO_CORE_BUILTIN
uint_t Yo_Typeid_Counter = 0;
#endif

enum { YO_DYNCO_NYD = 0x4e5944/*'NYD'*/, YO_DYNCO_ATS = 0x415453/*'ATS'*/ };

void *Yo_Clone_Dynamic( YO_DYNAMIC *dynco, int extra )
#ifdef _YO_CORE_BUILTIN
  {
    int count = dynco->contsig&0x0ff;
    int fc = count?count-1:0;
    int fcc = (count+extra)?count+extra-1:0;
    YO_DYNAMIC *d = Yo_Malloc_Npl(sizeof(YO_DYNAMIC)+sizeof(YO_FUNCTABLE)*fcc);
    *d = *dynco;
    if ( fc )
      memcpy(d->funcs+1,dynco->funcs+1,sizeof(YO_FUNCTABLE)*fc);
    d->contsig = (YO_DYNCO_NYD<<8)|count;
    return d;
  }
#endif
  ;

void *Yo_Extend_Dynamic( YO_DYNAMIC *dynco, int extra )
#ifdef _YO_CORE_BUILTIN
  {
    int count = dynco->contsig&0x0ff;
    int fcc = (count+extra)?count+extra-1:0;
    YO_DYNAMIC *d = Yo_Realloc_Npl(dynco,sizeof(YO_DYNAMIC)+sizeof(YO_FUNCTABLE)*fcc);
    return d;
  }
#endif
  ;

void *Yo_Object_Extend( void *o, char *func_name, void *func )
#ifdef _YO_CORE_BUILTIN
  {
    YO_OBJECT *T = YO_BASE(o);
    YO_FUNCTABLE *f;
    if ( !T )
      Yo_Raise(YO_ERROR_NULL_PTR,__yoTa("failed to extend nullptr",0),__Yo_FILE__,__LINE__);

    if ( T->dynamic )
      {
        if ( (T->dynamic->contsig >> 8) == YO_DYNCO_ATS )
          T->dynamic = Yo_Clone_Dynamic(T->dynamic,1);
        else
          T->dynamic = Yo_Extend_Dynamic(T->dynamic,1);
      }
    else
      {
        T->dynamic = Yo_Malloc_Npl(sizeof(YO_DYNAMIC));
        T->dynamic->contsig = YO_DYNCO_NYD<<8;
      }

    T->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
    f = T->dynamic->funcs+(T->dynamic->contsig&0x0ff);
    ++T->dynamic->contsig;
    f->name = func_name;
    f->func = func;

    return o;
  }
#endif
  ;

enum 
  { 
    YO_OBJECT_SIGNATURE_PFX  =  0x00594f59, /*'YOY'*/  
    YO_OBJECT_SIGNATURE_HEAP =  0x4f594f59, /*'YOYO'*/  
    YO_MEMPOOL_PIECE_MAXSIZE = 1*KILOBYTE,
    YO_MEMPOOL_PIECE_ON_BLOCK= 16,
    YO_MEMPOOL_PIECE_STEP    = 64,
    YO_MEMPOOL_SLOTS_COUNT   = YO_MEMPOOL_PIECE_MAXSIZE/YO_MEMPOOL_PIECE_STEP,
  };

__Static_Assert(YO_MEMPOOL_SLOTS_COUNT <= 'O');

#ifdef _YO_CORE_BUILTIN
void *Yo_Mempool_Slots[YO_MEMPOOL_SLOTS_COUNT] = {0,};
int Yo_Mempool_Counts[YO_MEMPOOL_SLOTS_COUNT] = {0,};
#endif

void Yo_Mempool_Free(void *p,int plidx)
#ifdef _YO_CORE_BUILTIN
  {
    void **Q = p;
    STRICT_REQUIRE(plidx >= 0 && plidx <YO_MEMPOOL_SLOTS_COUNT); 
    for (;;)
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        *Q = *S;
        if ( Yo_Atomic_CmpXchg_Ptr(S,Q,*Q) ) break;
      }
  }
#endif
  ;
  
void Yo_Mempool_Extend(int plidx)
#ifdef _YO_CORE_BUILTIN
  {
    __Xchg_Interlock
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        if ( !*S )
          {
            int i,piece = (plidx+1)*YO_MEMPOOL_PIECE_STEP; 
            void **Q = Yo_Malloc_Npl(piece*YO_MEMPOOL_PIECE_ON_BLOCK);
            Yo_Mempool_Counts[plidx] += YO_MEMPOOL_PIECE_ON_BLOCK;
            for ( i=0; i < YO_MEMPOOL_PIECE_ON_BLOCK; ++i, Q = (void**)((byte_t*)Q + piece) )
              for (;;)
                {
                  *Q = *S;
                  if ( Yo_Atomic_CmpXchg_Ptr(S,Q,*Q) ) break;
                }
          }
      }
  }
#endif
  ;
  
void *Yo_Mempool_Zalloc(int plidx)
#ifdef _YO_CORE_BUILTIN
  {
    void **Q;
    STRICT_REQUIRE(plidx >= 0 && plidx <YO_MEMPOOL_SLOTS_COUNT); 
    for (;;)
      {
        void * volatile *S = Yo_Mempool_Slots+plidx;
        Q = *S;
        if ( !Q ) 
          Yo_Mempool_Extend(plidx);
        else
          if ( Yo_Atomic_CmpXchg_Ptr(S,*Q,Q) ) break;
      }
    memset(Q,0,(plidx+1)*YO_MEMPOOL_PIECE_STEP);
    return Q;              
  }
#endif
  ;

YO_OBJECT *Yo_Object_Alloc(int size)
#ifdef _YO_CORE_BUILTIN
  {
    YO_OBJECT *o;
    if ( size + sizeof(YO_OBJECT) > YO_MEMPOOL_PIECE_MAXSIZE )
      {
        o = Yo_Zero_Malloc_Npl(sizeof(YO_OBJECT)+size);
        o->signature = YO_OBJECT_SIGNATURE_HEAP;
      }
    else
      {
        int plidx = (sizeof(YO_OBJECT)+size-1)/YO_MEMPOOL_PIECE_STEP;
        o = Yo_Mempool_Zalloc(plidx);
        o->signature = YO_OBJECT_SIGNATURE_PFX + (plidx<<24);
      }
    return o;
  }
#endif
  ;

void Yo_Object_Free(YO_OBJECT *o)
#ifdef _YO_CORE_BUILTIN
  {
    int plidx = o->signature >> 24;
    if ( plidx >= YO_MEMPOOL_SLOTS_COUNT ) 
      free(o);
    else
      Yo_Mempool_Free(o,plidx);
  }
#endif
  ;

void *Yo_Object_Clone(int size, void *orign)
#ifdef _YO_CORE_BUILTIN
  {
    YO_OBJECT *o;
    YO_OBJECT *T = YO_BASE(orign);
    if ( !T )
      Yo_Raise(YO_ERROR_NULL_PTR,__yoTa("failed to clone nullptr",0),__Yo_FILE__,__LINE__);

    o = Yo_Object_Alloc(size);
    o->rc = 1;
    memcpy(o+1,orign,size);

    if ( T->dynamic )
      {
        if ( (T->dynamic->contsig>>8) == YO_DYNCO_ATS )
          o->dynamic = T->dynamic;
        else
          {
            STRICT_REQUIRE( (T->dynamic->contsig>>8) == YO_DYNCO_NYD );
            o->dynamic = Yo_Clone_Dynamic(T->dynamic,0);
          }
      }
    else
      o->dynamic = 0;

    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

void *Yo_Object(int size,YO_FUNCTABLE *tbl)
#ifdef _YO_CORE_BUILTIN
  {
    YO_OBJECT *o = Yo_Object_Alloc(size);
    o->rc = 1;
    o->dynamic = (YO_DYNAMIC*)tbl;

    if ( tbl )
      {__Xchg_Interlock
        {
          YO_DYNAMIC *dynco = (YO_DYNAMIC*)tbl;
          if ( !dynco->contsig )
            {
              int count;
              for ( count = 0; tbl[count+1].name; ) { ++count; }
              dynco->contsig = (YO_DYNCO_ATS<<8)|count;
              dynco->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
            }
        }}

    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

ulong_t Yo_Align(ulong_t val)
#ifdef _YO_CORE_BUILTIN
  {
    return (val + 7)&~7;
  }
#endif
  ;

void *Yo_Object_Dtor(int size,void *dtor)
#ifdef _YO_CORE_BUILTIN
  {
    int Sz = Yo_Align(sizeof(YO_OBJECT)+size);
    YO_OBJECT *o = Yo_Object_Alloc(Sz+sizeof(YO_DYNAMIC));
    o->rc = 1;
    o->dynamic = (YO_DYNAMIC*)((char*)o + Sz);
    o->dynamic->contsig = (YO_DYNCO_ATS<<8)|1;
    o->dynamic->funcs[0].name = Oj_Destruct_OjMID;
    o->dynamic->funcs[0].func = dtor;
    o->dynamic->typeid = Yo_Atomic_Increment(&Yo_Typeid_Counter);
    return Yo_Pool_Ptr(o+1,Yo_Unrefe);
  }
#endif
  ;

void Yo_Object_Destruct(void *ptr)
#ifdef _YO_CORE_BUILTIN
  {
    if ( ptr )
      {
        YO_OBJECT *o = (YO_OBJECT *)ptr - 1;
        if ( o->dynamic && (o->dynamic->contsig>>8) == YO_DYNCO_NYD )
          free(o->dynamic);
        o->dynamic = 0;
        Yo_Object_Free(o);
      }
  }
#endif
  ;

void *Yo_Find_Method_In_Table(char *name,YO_FUNCTABLE *tbl,int count,int flags)
#ifdef _YO_CORE_BUILTIN
  {
    int i;
    for ( i = 0; i < count; ++i )
      if ( strcmp(tbl[i].name,name) == 0 )
        return tbl[i].func;
    return 0;
  }
#endif
  ;

void *Yo_Find_Method_Of(void **self,char *name,unsigned flags)
#ifdef _YO_CORE_BUILTIN
  {
    void *o = *self;
    if ( o && STRICT_CHECK(YO_SIGNAT_IS_OK(o)) )
      {
        YO_DYNAMIC *dynco = YO_BASE(o)->dynamic;
        if ( dynco )
          {
            if ( 1 && STRICT_CHECK((dynco->contsig>>8) == YO_DYNCO_ATS || (dynco->contsig>>8) == YO_DYNCO_NYD) )
              {
                void *f = Yo_Find_Method_In_Table(name,dynco->funcs,(dynco->contsig&0x0ff),flags);
                if ( !f && (flags & YO_RAISE_ERROR) )
                  Yo_Raise(YO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
                return f;
              }
            else
              Yo_Fatal(YO_ERROR_DYNCO_CORRUPTED,o,__Yo_FILE__,__LINE__);
          }
        else if (flags & YO_RAISE_ERROR)
          Yo_Raise(YO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
      }
    else if (flags & YO_RAISE_ERROR)
      Yo_Raise(YO_ERROR_METHOD_NOT_FOUND,name,__Yo_FILE__,__LINE__);
    return 0;
  }
#endif
  ;

void *Yo_Refe(void *p)
#ifdef _YO_CORE_BUILTIN
  {
    if ( p && STRICT_CHECK(YO_SIGNAT_IS_OK(p)) )
      Yo_Atomic_Increment(&YO_RC(p));
    return p;
  }
#endif
  ;

#ifdef _YO_CORE_BUILTIN
void *Yo_Unrefe(void *p)
  {
    if ( p && STRICT_CHECK(YO_SIGNAT_IS_OK(p))
           && !(Yo_Atomic_Decrement(&YO_RC(p))&0x7fffff) )
      {
        void (*destruct)(void *) = Yo_Find_Method_Of(&p,Oj_Destruct_OjMID,0);
        if ( !destruct )
          Yo_Object_Destruct(p);
        else
          destruct(p);
        return 0;
      }
    return p;
  }
#endif
  ;

void *Oj_Clone(void *p)
#ifdef _YO_CORE_BUILTIN
  {
    if ( p )
      {
        void *(*clone)(void *) = Yo_Find_Method_Of(&p,Oj_Clone_OjMID,YO_RAISE_ERROR);
        return clone(p);
      }
    return p;
  }
#endif
  ;

int Oj_Count(void *self)
#ifdef _YO_CORE_BUILTIN
  {
    int (*count)(void *) = Yo_Find_Method_Of(&self,Oj_Count_OjMID,YO_RAISE_ERROR);
    return count(self);
  }
#endif
  ;

1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
    if (1) /* guards exception way */ while (1) \
      if (1) /* on second while's step if executed without errors */ \
        { Epilog; Yo_Pop_JmpBuf(); break; } \
      else if (0) /* if unexpected */ \
        { Epilog; Yo_Raise_Occured(); } \
      else /* there is protected code */ \
        /* switch jumps to here */ \
        case 0: if (1) { Prolog; goto YOYO_LOCAL_ID(ap_Body); } else \
           YOYO_LOCAL_ID(ap_Body):

YOYO_ERROR_INFO *Error_Info()
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && nfo->err.code )
      return &nfo->err;
    else
      return 0;
  }
#endif
  ;

char *Error_Message(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_ERROR_INFO *info = Error_Info();
    if ( info && info->msg )
      return info->msg;
    return "";
  }
#endif
  ;

int Error_Code(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_ERROR_INFO *info = Error_Info();
    if ( info )
      return info->code;
    return 0;
  }
#endif
  ;

char *Error_File(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_ERROR_INFO *info = Error_Info();
    if ( info && info->filename )
      return info->filename;
    return __yoTa("<file>",0);
  }
#endif
  ;

int Error_Line(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_ERROR_INFO *info = Error_Info();
    if ( info )
      return info->lineno;
    return 0;
  }
#endif
  ;

char *Error_Print_N_Exit(char *prefix, int code)
#ifdef _YOYO_CORE_BUILTIN
  {
    StdErr_Print_Nl(Yo_Format(__yoTa("%s: %s",0),prefix,Error_Message()));
    exit(code);
  }
#endif
  ;

#define Yo_Pop_JmpBuf() \
   (--((YOYO_C_SUPPORT_INFO *)Yo_Tls_Get(Yo_Csup_Nfo_Tls))->jb_top)

YOYO_JMPBUF *Yo_Push_JmpBuf(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_C_Support_Nfo();
    YOYO_JMPBUF *jb;

    STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
    STRICT_REQUIRE(nfo->jb_top >= -1);

    if ( nfo->jb_top == nfo->jb_count-1 )
      nfo = Yo_Extend_Csup_JmpBuf();
    ++nfo->jb_top;

    jb = &nfo->jb[nfo->jb_top];
    memset(jb->locks,0,sizeof(jb->locks));
    jb->auto_top = nfo->auto_top+1;

    return jb;
  }
#endif
  ;

void Yo_JmpBuf_Push_Cs(void *cs,Yo_JMPBUF_Unlock unlock)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    STRICT_REQUIRE ( cs );
    if ( nfo && cs )
      {
        STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
        STRICT_REQUIRE(nfo->jb_top >= -1);
        if ( nfo->jb_top > -1 && !nfo->stats.unwinding )
          {
            int i;
            YOYO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;
            for ( i = YOYO_MAX_CS_COUNT-1; i >= 0; --i )
              if ( !locks[i].cs )
                {
                  locks[i].cs = cs;
                  locks[i].unlock = unlock;
                  return;
                }
            Yo_Fatal(YOYO_FATAL_ERROR,__yoTa("no enough lock space",0),__Yo_FILE__,__LINE__);
          }
      }
  }
#endif
  ;


void Yo_JmpBuf_Pop_Cs(void *cs)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && cs )
      {
        STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
        STRICT_REQUIRE(nfo->jb_top >= -1);
        if ( nfo->jb_top > -1 && !nfo->stats.unwinding )
          {
            int i;
            YOYO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;
            for ( i = YOYO_MAX_CS_COUNT-1; i >= 0; --i )
              if ( locks[i].cs == cs )
                {
                  memset(&locks[i],0,sizeof(locks[i]));
                  return;
                }
            Yo_Fatal(YOYO_FATAL_ERROR,__yoTa("trying to pop unexistent lock",0),__Yo_FILE__,__LINE__);
          }
      }
  }
#endif
  ;

char *Yo_Btrace(void);

#ifdef _YOYO_CORE_BUILTIN
__No_Return void _Yo_Raise(int err,char *msg,char *filename,int lineno)
  {
    YOYO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    STRICT_REQUIRE( !nfo || nfo->jb_top < nfo->jb_count );

    printf(__yoTa("err: %d, msg: %s, filename: %s, lineno: %d\n",0),err,msg,filename,lineno);
  
  #if defined _DEBUG && defined __windoze
    if ( IsDebuggerPresent() ) __debugbreak();
  #endif  
  
    if ( err == YO_RERAISE_CURRENT_ERROR && (!nfo || !nfo->err.code) )
      Yo_Fatal(YOYO_ERROR_UNEXPECTED,__yoTa("no errors occured yet",0),filename,lineno);

    if ( nfo && nfo->jb_top >= 0 && !nfo->stats.unwinding )
      {
        int i;
        char *old_msg = nfo->err.msg;
        YOYO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;

        if ( err != YO_RERAISE_CURRENT_ERROR )
          {
            nfo->err.msg = msg ? strdup(msg) : 0;
            nfo->err.code = err?err:-1;
            nfo->err.filename = filename;
            nfo->err.lineno = lineno;
            nfo->err.bt_count = backtrace(nfo->err.bt_cbk,YOYO_MAX_ERROR_BTRACE);
            free( old_msg );
          }

        for ( i = YOYO_MAX_CS_COUNT-1; i >= 0; --i )
          if (  locks[i].cs )
            locks[i].unlock(locks[i].cs);

        Yo_Unwind_Scope(0,nfo->jb[nfo->jb_top].auto_top,0);

        --nfo->jb_top;
        STRICT_REQUIRE(nfo->jb_top >= -1);







|
|

|
|

|









|

|








|

|








|

|








|

|








|








|

|
|

|
|


















|

|








|
|






|








|

|







|
|





|








|


|









|





|







|



|







1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
    if (1) /* guards exception way */ while (1) \
      if (1) /* on second while's step if executed without errors */ \
        { Epilog; Yo_Pop_JmpBuf(); break; } \
      else if (0) /* if unexpected */ \
        { Epilog; Yo_Raise_Occured(); } \
      else /* there is protected code */ \
        /* switch jumps to here */ \
        case 0: if (1) { Prolog; goto YO_LOCAL_ID(ap_Body); } else \
           YO_LOCAL_ID(ap_Body):

YO_ERROR_INFO *Error_Info()
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && nfo->err.code )
      return &nfo->err;
    else
      return 0;
  }
#endif
  ;

char *Error_Message(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_ERROR_INFO *info = Error_Info();
    if ( info && info->msg )
      return info->msg;
    return "";
  }
#endif
  ;

int Error_Code(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_ERROR_INFO *info = Error_Info();
    if ( info )
      return info->code;
    return 0;
  }
#endif
  ;

char *Error_File(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_ERROR_INFO *info = Error_Info();
    if ( info && info->filename )
      return info->filename;
    return __yoTa("<file>",0);
  }
#endif
  ;

int Error_Line(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_ERROR_INFO *info = Error_Info();
    if ( info )
      return info->lineno;
    return 0;
  }
#endif
  ;

char *Error_Print_N_Exit(char *prefix, int code)
#ifdef _YO_CORE_BUILTIN
  {
    StdErr_Print_Nl(Yo_Format(__yoTa("%s: %s",0),prefix,Error_Message()));
    exit(code);
  }
#endif
  ;

#define Yo_Pop_JmpBuf() \
   (--((YO_C_SUPPORT_INFO *)Yo_Tls_Get(Yo_Csup_Nfo_Tls))->jb_top)

YO_JMPBUF *Yo_Push_JmpBuf(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_C_Support_Nfo();
    YO_JMPBUF *jb;

    STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
    STRICT_REQUIRE(nfo->jb_top >= -1);

    if ( nfo->jb_top == nfo->jb_count-1 )
      nfo = Yo_Extend_Csup_JmpBuf();
    ++nfo->jb_top;

    jb = &nfo->jb[nfo->jb_top];
    memset(jb->locks,0,sizeof(jb->locks));
    jb->auto_top = nfo->auto_top+1;

    return jb;
  }
#endif
  ;

void Yo_JmpBuf_Push_Cs(void *cs,Yo_JMPBUF_Unlock unlock)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    STRICT_REQUIRE ( cs );
    if ( nfo && cs )
      {
        STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
        STRICT_REQUIRE(nfo->jb_top >= -1);
        if ( nfo->jb_top > -1 && !nfo->stats.unwinding )
          {
            int i;
            YO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;
            for ( i = YO_MAX_CS_COUNT-1; i >= 0; --i )
              if ( !locks[i].cs )
                {
                  locks[i].cs = cs;
                  locks[i].unlock = unlock;
                  return;
                }
            Yo_Fatal(YO_FATAL_ERROR,__yoTa("no enough lock space",0),__Yo_FILE__,__LINE__);
          }
      }
  }
#endif
  ;


void Yo_JmpBuf_Pop_Cs(void *cs)
#ifdef _YO_CORE_BUILTIN
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    if ( nfo && cs )
      {
        STRICT_REQUIRE(nfo->jb_top < nfo->jb_count);
        STRICT_REQUIRE(nfo->jb_top >= -1);
        if ( nfo->jb_top > -1 && !nfo->stats.unwinding )
          {
            int i;
            YO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;
            for ( i = YO_MAX_CS_COUNT-1; i >= 0; --i )
              if ( locks[i].cs == cs )
                {
                  memset(&locks[i],0,sizeof(locks[i]));
                  return;
                }
            Yo_Fatal(YO_FATAL_ERROR,__yoTa("trying to pop unexistent lock",0),__Yo_FILE__,__LINE__);
          }
      }
  }
#endif
  ;

char *Yo_Btrace(void);

#ifdef _YO_CORE_BUILTIN
__No_Return void _Yo_Raise(int err,char *msg,char *filename,int lineno)
  {
    YO_C_SUPPORT_INFO *nfo = Yo_Tls_Get(Yo_Csup_Nfo_Tls);
    STRICT_REQUIRE( !nfo || nfo->jb_top < nfo->jb_count );

    printf(__yoTa("err: %d, msg: %s, filename: %s, lineno: %d\n",0),err,msg,filename,lineno);
  
  #if defined _DEBUG && defined __windoze
    if ( IsDebuggerPresent() ) __debugbreak();
  #endif  
  
    if ( err == YO_RERAISE_CURRENT_ERROR && (!nfo || !nfo->err.code) )
      Yo_Fatal(YO_ERROR_UNEXPECTED,__yoTa("no errors occured yet",0),filename,lineno);

    if ( nfo && nfo->jb_top >= 0 && !nfo->stats.unwinding )
      {
        int i;
        char *old_msg = nfo->err.msg;
        YO_JMPBUF_LOCK *locks = nfo->jb[nfo->jb_top].locks;

        if ( err != YO_RERAISE_CURRENT_ERROR )
          {
            nfo->err.msg = msg ? strdup(msg) : 0;
            nfo->err.code = err?err:-1;
            nfo->err.filename = filename;
            nfo->err.lineno = lineno;
            nfo->err.bt_count = backtrace(nfo->err.bt_cbk,YO_MAX_ERROR_BTRACE);
            free( old_msg );
          }

        for ( i = YO_MAX_CS_COUNT-1; i >= 0; --i )
          if (  locks[i].cs )
            locks[i].unlock(locks[i].cs);

        Yo_Unwind_Scope(0,nfo->jb[nfo->jb_top].auto_top,0);

        --nfo->jb_top;
        STRICT_REQUIRE(nfo->jb_top >= -1);
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
      }
  }
#endif

#define Yo_Raise_Occured() _Yo_Raise(YO_RERAISE_CURRENT_ERROR,0,0,0)

__No_Return void Yo_Abort(char *msg)
#ifdef _YOYO_CORE_BUILTIN
  {
    StdErr_Print_Nl(msg);
    abort();
  }
#endif
  ;

char *Yo__basename(char *S)
#ifdef _YOYO_CORE_BUILTIN
  {
    if ( S )
      {
        char *a = strrchr(S,'/');
        char *b = strrchr(S,'\\');
        if ( b > a ) a = b;
        return a ? a+1 : S;
      }
    return 0;
  }
#endif
  ;

char *Yo_Btrace_Format(int frames, void **cbk)
#ifdef _YOYO_CORE_BUILTIN
  {
    int  max_bt = 4096;
    char *bt = Yo_Malloc(max_bt);
    char *bt_p = bt;
    int i;

    i = snprintf(bt_p,max_bt,__yoTa("--backtrace--",0));







|








|














|







1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
      }
  }
#endif

#define Yo_Raise_Occured() _Yo_Raise(YO_RERAISE_CURRENT_ERROR,0,0,0)

__No_Return void Yo_Abort(char *msg)
#ifdef _YO_CORE_BUILTIN
  {
    StdErr_Print_Nl(msg);
    abort();
  }
#endif
  ;

char *Yo__basename(char *S)
#ifdef _YO_CORE_BUILTIN
  {
    if ( S )
      {
        char *a = strrchr(S,'/');
        char *b = strrchr(S,'\\');
        if ( b > a ) a = b;
        return a ? a+1 : S;
      }
    return 0;
  }
#endif
  ;

char *Yo_Btrace_Format(int frames, void **cbk)
#ifdef _YO_CORE_BUILTIN
  {
    int  max_bt = 4096;
    char *bt = Yo_Malloc(max_bt);
    char *bt_p = bt;
    int i;

    i = snprintf(bt_p,max_bt,__yoTa("--backtrace--",0));
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056

    return bt;
  }
#endif
  ;

char *Yo_Btrace(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *cbk[128] = {0};
    int frames = backtrace(cbk,127);
    return Yo_Btrace_Format(frames,cbk);
  }
#endif
  ;

#if defined __windoze  && defined _YOYO_CORE_BUILTIN

int backtrace( void **cbk, int count )
  {
    return 0;
  }

#elif defined __GNUC__ && defined _YOYO_CORE_BUILTIN \
    && !(defined __APPLE__ || defined __linux__)

typedef struct _YOYO_BACKTRACE
  {
    void **cbk;
    int count;
  } YOYO_BACKTRACE;

_Unwind_Reason_Code backtrace_Helper(struct _Unwind_Context* ctx, YOYO_BACKTRACE *bt)
  {
    if ( bt->count )
      {
        void *eip = (void*)_Unwind_GetIP(ctx);
        if ( eip )
          {
            *bt->cbk++ = eip;
            --bt->count;
            return _URC_NO_REASON;
          }
      }
    return _URC_NORMAL_STOP;
  }

int backtrace( void **cbk, int count )
  {
    YOYO_BACKTRACE T = { cbk, count };
    _Unwind_Backtrace((_Unwind_Trace_Fn)&backtrace_Helper, &T);
    return count-T.count;
  }

#endif /* __GNUC__  && _YOYO_CORE_BUILTIN */

char *Yo_Error_Format_Btrace(void)
#ifdef _YOYO_CORE_BUILTIN
  {
    YOYO_ERROR_INFO *info = Error_Info();
    if ( info && info->bt_count )
      {
        return Yo_Btrace_Format(info->bt_count,info->bt_cbk);
      }
    return __yoTa("--backtrace--\n   unavailable",0);
  }
#endif
  ;

__No_Return void Yo_Btrace_N_Abort(char *prefix, char *msg, char *filename, int lineno)
#ifdef _YOYO_CORE_BUILTIN
  {
    char *at = filename?Yo_Format_Npl(__yoTa(" [%s(%d)]",0),Yo__basename(filename),lineno):"";
    char *pfx = prefix?Yo_Format_Npl(__yoTa("%s: ",0),prefix):"";
    StdErr_Print_Nl(Yo_Btrace());
    Yo_Abort(Yo_Format_Npl(__yoTa("%s%s%s",0),pfx,msg,at));
  }
#endif
  ;

#ifdef _YOYO_CORE_BUILTIN
__No_Return void _Yo_Fatal(int err,void *ctx,char *filename,int lineno)
  {
    switch (err)
      {
        case YOYO_ERROR_OUT_OF_MEMORY:
          Yo_Abort(__yoTa("out of memory",0));
        case YOYO_ERROR_REQUIRE_FAILED:
          Yo_Btrace_N_Abort(__yoTa("require",0),ctx,filename,lineno);
        case YOYO_FATAL_ERROR:
          Yo_Btrace_N_Abort(__yoTa("fatal",0),ctx,filename,lineno);
        case YOYO_ERROR_DYNCO_CORRUPTED:
          Yo_Btrace_N_Abort(__yoTa("fatal",0),
            Yo_Format_Npl(__yoTa("corrupted dynco (%p)",0),ctx),filename,lineno);
        default:
          {
            char err_pfx[60];
            sprintf(err_pfx,__yoTa("unexpected(%08x)",0),err);
            Yo_Btrace_N_Abort(err_pfx,ctx,filename,lineno);
          }
      }
  }
#endif
  ;

__No_Return void Error_Abort()
#ifdef _YOYO_CORE_BUILTIN
  {
    Yo_Btrace_N_Abort(
      Yo_Format_Npl(__yoTa("\ncaught(0x%08x)",0),Error_Code()),
      Error_Message(),Error_File(),Error_Line());
  }
#endif
  ;

char *Yo_Error_Format()
#ifdef _YOYO_CORE_BUILTIN
  {
    int code = Error_Code();
    char *msg = Error_Message();

    if ( YOYO_ERROR_IS_USER_ERROR(code) )
      return Yo_Format(__yoTa("error(%d): %s",0),code,msg);
    else
      return Yo_Format(__yoTa("error(%08x): %s",0),code,msg);
  }
#endif
  ;

__No_Return void Error_Exit(char *pfx)
#ifdef _YOYO_CORE_BUILTIN
  {
    int code = Error_Code();
    char *msg = Error_Message();

  #ifndef _BACKTRACE
    if ( (code & YOYO_TRACED_ERROR_GROUP) || !Error_Info()->msg )
  #endif
      StdErr_Print_Nl(Yo_Error_Format_Btrace());

    if ( code == YOYO_ERROR_USER )
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s: %s",0),(pfx?pfx:__yoTa("error",0)),msg));
    else if ( YOYO_ERROR_IS_USER_ERROR(code) )
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s(%d): %s",0),(pfx?pfx:__yoTa("error",0)),code,msg));
    else
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s(%08x): %s",0),(pfx?pfx:__yoTa("error",0)),code,msg));
    if ( code & YOYO_FATAL_ERROR_GROUP )
      abort();
    Yo_Unwind_Scope(0,-1,0);
    exit(code);
  }
#endif
  ;

char *Yo_Format_System_Error()
#ifdef _YOYO_CORE_BUILTIN
  {
  #ifdef __windoze
    int err = GetLastError();
    char *msg = Yo_Malloc(1024);
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
                  FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),







|








|






|


|



|

|
















|




|


|

|










|









|




|

|

|

|














|









|




|








|





|



|

|



|








|







1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058

    return bt;
  }
#endif
  ;

char *Yo_Btrace(void)
#ifdef _YO_CORE_BUILTIN
  {
    void *cbk[128] = {0};
    int frames = backtrace(cbk,127);
    return Yo_Btrace_Format(frames,cbk);
  }
#endif
  ;

#if defined __windoze  && defined _YO_CORE_BUILTIN

int backtrace( void **cbk, int count )
  {
    return 0;
  }

#elif defined __GNUC__ && defined _YO_CORE_BUILTIN \
    && !(defined __APPLE__ || defined __linux__)

typedef struct _YO_BACKTRACE
  {
    void **cbk;
    int count;
  } YO_BACKTRACE;

_Unwind_Reason_Code backtrace_Helper(struct _Unwind_Context* ctx, YO_BACKTRACE *bt)
  {
    if ( bt->count )
      {
        void *eip = (void*)_Unwind_GetIP(ctx);
        if ( eip )
          {
            *bt->cbk++ = eip;
            --bt->count;
            return _URC_NO_REASON;
          }
      }
    return _URC_NORMAL_STOP;
  }

int backtrace( void **cbk, int count )
  {
    YO_BACKTRACE T = { cbk, count };
    _Unwind_Backtrace((_Unwind_Trace_Fn)&backtrace_Helper, &T);
    return count-T.count;
  }

#endif /* __GNUC__  && _YO_CORE_BUILTIN */

char *Yo_Error_Format_Btrace(void)
#ifdef _YO_CORE_BUILTIN
  {
    YO_ERROR_INFO *info = Error_Info();
    if ( info && info->bt_count )
      {
        return Yo_Btrace_Format(info->bt_count,info->bt_cbk);
      }
    return __yoTa("--backtrace--\n   unavailable",0);
  }
#endif
  ;

__No_Return void Yo_Btrace_N_Abort(char *prefix, char *msg, char *filename, int lineno)
#ifdef _YO_CORE_BUILTIN
  {
    char *at = filename?Yo_Format_Npl(__yoTa(" [%s(%d)]",0),Yo__basename(filename),lineno):"";
    char *pfx = prefix?Yo_Format_Npl(__yoTa("%s: ",0),prefix):"";
    StdErr_Print_Nl(Yo_Btrace());
    Yo_Abort(Yo_Format_Npl(__yoTa("%s%s%s",0),pfx,msg,at));
  }
#endif
  ;

#ifdef _YO_CORE_BUILTIN
__No_Return void _Yo_Fatal(int err,void *ctx,char *filename,int lineno)
  {
    switch (err)
      {
        case YO_ERROR_OUT_OF_MEMORY:
          Yo_Abort(__yoTa("out of memory",0));
        case YO_ERROR_REQUIRE_FAILED:
          Yo_Btrace_N_Abort(__yoTa("require",0),ctx,filename,lineno);
        case YO_FATAL_ERROR:
          Yo_Btrace_N_Abort(__yoTa("fatal",0),ctx,filename,lineno);
        case YO_ERROR_DYNCO_CORRUPTED:
          Yo_Btrace_N_Abort(__yoTa("fatal",0),
            Yo_Format_Npl(__yoTa("corrupted dynco (%p)",0),ctx),filename,lineno);
        default:
          {
            char err_pfx[60];
            sprintf(err_pfx,__yoTa("unexpected(%08x)",0),err);
            Yo_Btrace_N_Abort(err_pfx,ctx,filename,lineno);
          }
      }
  }
#endif
  ;

__No_Return void Error_Abort()
#ifdef _YO_CORE_BUILTIN
  {
    Yo_Btrace_N_Abort(
      Yo_Format_Npl(__yoTa("\ncaught(0x%08x)",0),Error_Code()),
      Error_Message(),Error_File(),Error_Line());
  }
#endif
  ;

char *Yo_Error_Format()
#ifdef _YO_CORE_BUILTIN
  {
    int code = Error_Code();
    char *msg = Error_Message();

    if ( YO_ERROR_IS_USER_ERROR(code) )
      return Yo_Format(__yoTa("error(%d): %s",0),code,msg);
    else
      return Yo_Format(__yoTa("error(%08x): %s",0),code,msg);
  }
#endif
  ;

__No_Return void Error_Exit(char *pfx)
#ifdef _YO_CORE_BUILTIN
  {
    int code = Error_Code();
    char *msg = Error_Message();

  #ifndef _BACKTRACE
    if ( (code & YO_TRACED_ERROR_GROUP) || !Error_Info()->msg )
  #endif
      StdErr_Print_Nl(Yo_Error_Format_Btrace());

    if ( code == YO_ERROR_USER )
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s: %s",0),(pfx?pfx:__yoTa("error",0)),msg));
    else if ( YO_ERROR_IS_USER_ERROR(code) )
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s(%d): %s",0),(pfx?pfx:__yoTa("error",0)),code,msg));
    else
      StdErr_Print_Nl(Yo_Format(__yoTa("\n%s(%08x): %s",0),(pfx?pfx:__yoTa("error",0)),code,msg));
    if ( code & YO_FATAL_ERROR_GROUP )
      abort();
    Yo_Unwind_Scope(0,-1,0);
    exit(code);
  }
#endif
  ;

char *Yo_Format_System_Error()
#ifdef _YO_CORE_BUILTIN
  {
  #ifdef __windoze
    int err = GetLastError();
    char *msg = Yo_Malloc(1024);
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
                  FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err,
                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
  ;

#define __Pool(Ptr)                     Yo_Pool_Ptr(Ptr,0)
#define __Pool_Ptr(Ptr,Free)            Yo_Pool_Ptr(Ptr,Free)
#define __Pool_RefPtr(Ptr)              Yo_Pool_Ptr(Ptr,Yo_Unrefe)
#define __Release(Pooled)               Yo_Release(Pooled)
#define __Retain(Pooled)                Yo_Retain(Pooled)
#define __Purge(TholdPtr)               Yo_Pool_Purge(TholdPtr,YOYO_DEFAULT_PURGE_CAP)
#define __Refe(Ptr)                     Yo_Refe(Ptr)
#define __Unrefe(Ptr)                   Yo_Unrefe(Ptr)
#define __Raise(Err,Msg)                Yo_Raise(Err,Msg,__Yo_FILE__,__LINE__)
#define __Raise_User_Error(Msg_)        Yo_Raise(YOYO_ERROR_USER,Msg_,__Yo_FILE__,__LINE__)
#define __Raise_Format(Err,Fmt)         Yo_Raise(Err,(Yo_Format Fmt),__Yo_FILE__,__LINE__)
#define __Raise_Occured()               Yo_Raise_Occured()
#define __Raise_System_Error()          Yo_Raise(YOYO_ERROR_SYSTEM,Yo_Format_System_Error(),__Yo_FILE__,__LINE__)
#define __Fatal(Ctx)                    Yo_Fatal(YOYO_FATAL_ERROR,Ctx,__Yo_FILE__,__LINE__)
#define __Fatal_Format(x)               Yo_Fatal(YOYO_FATAL_ERROR,Yo_Format_Npl x,__Yo_FILE__,__LINE__)
#define __Format                        Yo_Format
#define __Format_Npl                    Yo_Format_Npl
#define __Format_Error()                Yo_Error_Format()
#define __Format_Btrace()               Yo_Btrace()
#define __Format_Error_Btrace()         Yo_Error_Format_Btrace()
#define __Format_System_Error()         Yo_Format_System_Error()








|



|


|
|
|







2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  ;

#define __Pool(Ptr)                     Yo_Pool_Ptr(Ptr,0)
#define __Pool_Ptr(Ptr,Free)            Yo_Pool_Ptr(Ptr,Free)
#define __Pool_RefPtr(Ptr)              Yo_Pool_Ptr(Ptr,Yo_Unrefe)
#define __Release(Pooled)               Yo_Release(Pooled)
#define __Retain(Pooled)                Yo_Retain(Pooled)
#define __Purge(TholdPtr)               Yo_Pool_Purge(TholdPtr,YO_DEFAULT_PURGE_CAP)
#define __Refe(Ptr)                     Yo_Refe(Ptr)
#define __Unrefe(Ptr)                   Yo_Unrefe(Ptr)
#define __Raise(Err,Msg)                Yo_Raise(Err,Msg,__Yo_FILE__,__LINE__)
#define __Raise_User_Error(Msg_)        Yo_Raise(YO_ERROR_USER,Msg_,__Yo_FILE__,__LINE__)
#define __Raise_Format(Err,Fmt)         Yo_Raise(Err,(Yo_Format Fmt),__Yo_FILE__,__LINE__)
#define __Raise_Occured()               Yo_Raise_Occured()
#define __Raise_System_Error()          Yo_Raise(YO_ERROR_SYSTEM,Yo_Format_System_Error(),__Yo_FILE__,__LINE__)
#define __Fatal(Ctx)                    Yo_Fatal(YO_FATAL_ERROR,Ctx,__Yo_FILE__,__LINE__)
#define __Fatal_Format(x)               Yo_Fatal(YO_FATAL_ERROR,Yo_Format_Npl x,__Yo_FILE__,__LINE__)
#define __Format                        Yo_Format
#define __Format_Npl                    Yo_Format_Npl
#define __Format_Error()                Yo_Error_Format()
#define __Format_Btrace()               Yo_Btrace()
#define __Format_Error_Btrace()         Yo_Error_Format_Btrace()
#define __Format_System_Error()         Yo_Format_System_Error()

2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
#define __Auto_Release \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        Yo_Unwind_Scope(0,0,0); \
        break; \
      case 0: Yo_Push_Scope(); \
        goto YOYO_LOCAL_ID(ar_Body);\
      } \
    else \
      YOYO_LOCAL_ID(ar_Body):

#define __Auto_Ptr(Ptr) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        Yo_Unwind_Scope(Ptr,0,0); \
        break; \
      case 0: Yo_Push_Scope(); \
        goto YOYO_LOCAL_ID(ap_Body);\
      } \
    else \
      YOYO_LOCAL_ID(ap_Body):

#else

#define __Auto_Release \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        int YOYO_LOCAL_ID(ar_Mark); \
        Yo_Unwind_Scope(0,0,&YOYO_LOCAL_ID(ar_Mark)); \
        break; \
      case 0: Yo_Pool_Ptr(&YOYO_LOCAL_ID(ar_Mark),Yo_Pool_Marker_Tag); \
        goto YOYO_LOCAL_ID(ar_Body);\
      } \
    else \
      YOYO_LOCAL_ID(ar_Body):

#define __Auto_Ptr(Ptr) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        int YOYO_LOCAL_ID(ap_Mark); \
        Yo_Unwind_Scope(Ptr,0,&YOYO_LOCAL_ID(ap_Mark)); \
        break; \
      case 0: Yo_Pool_Ptr(&YOYO_LOCAL_ID(ap_Mark),Yo_Pool_Marker_Tag); \
        goto YOYO_LOCAL_ID(ap_Body);\
      } \
    else \
      YOYO_LOCAL_ID(ap_Body):

#endif /* _STRONGPOOL */

#define __Interlock_Opt(Decl,Lx,Lock,Unlock,Unlock_Proc) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      goto YOYO_LOCAL_ID(Do_Unlock); \
    else if ( 1 ) \
      case 0: \
        { \
          Decl;\
          Lock(Lx); \
          Yo_JmpBuf_Push_Cs(Lx,(Yo_JMPBUF_Unlock)Unlock_Proc); \
          goto YOYO_LOCAL_ID(Do_Code); \
        YOYO_LOCAL_ID(Do_Unlock): \
          Yo_JmpBuf_Pop_Cs(Lx); \
          Unlock(Lx); \
          break; \
        } \
    else \
      YOYO_LOCAL_ID(Do_Code):

#define __Gogo \
  if ( 1 ) goto YOYO_LOCAL_ID(__gogo); \
  else YOYO_LOCAL_ID(__gogo):

#define __Elm_Resize_Npl(MemPptr,L,Width,CpsPtr) Yo_Elm_Resize_Npl((void**)MemPptr,L,Width,CpsPtr)
void Yo_Elm_Resize_Npl(void **inout, int L, int type_width, int *capacity_ptr)
#ifdef _YOYO_CORE_BUILTIN
  {
    int requires = 0;
    int capacity = capacity_ptr?*capacity_ptr:0;

    if ( L )
      {
        requires = (L+1)*type_width;







|


|








|


|







|
|

|
|


|





|
|

|
|


|






|






|
|





|


|
|



|







2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
#define __Auto_Release \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        Yo_Unwind_Scope(0,0,0); \
        break; \
      case 0: Yo_Push_Scope(); \
        goto YO_LOCAL_ID(ar_Body);\
      } \
    else \
      YO_LOCAL_ID(ar_Body):

#define __Auto_Ptr(Ptr) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        Yo_Unwind_Scope(Ptr,0,0); \
        break; \
      case 0: Yo_Push_Scope(); \
        goto YO_LOCAL_ID(ap_Body);\
      } \
    else \
      YO_LOCAL_ID(ap_Body):

#else

#define __Auto_Release \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        int YO_LOCAL_ID(ar_Mark); \
        Yo_Unwind_Scope(0,0,&YO_LOCAL_ID(ar_Mark)); \
        break; \
      case 0: Yo_Pool_Ptr(&YO_LOCAL_ID(ar_Mark),Yo_Pool_Marker_Tag); \
        goto YO_LOCAL_ID(ar_Body);\
      } \
    else \
      YO_LOCAL_ID(ar_Body):

#define __Auto_Ptr(Ptr) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      { \
        int YO_LOCAL_ID(ap_Mark); \
        Yo_Unwind_Scope(Ptr,0,&YO_LOCAL_ID(ap_Mark)); \
        break; \
      case 0: Yo_Pool_Ptr(&YO_LOCAL_ID(ap_Mark),Yo_Pool_Marker_Tag); \
        goto YO_LOCAL_ID(ap_Body);\
      } \
    else \
      YO_LOCAL_ID(ap_Body):

#endif /* _STRONGPOOL */

#define __Interlock_Opt(Decl,Lx,Lock,Unlock,Unlock_Proc) \
  switch ( 0 ) while ( 1 ) \
    if ( 1 ) \
      goto YO_LOCAL_ID(Do_Unlock); \
    else if ( 1 ) \
      case 0: \
        { \
          Decl;\
          Lock(Lx); \
          Yo_JmpBuf_Push_Cs(Lx,(Yo_JMPBUF_Unlock)Unlock_Proc); \
          goto YO_LOCAL_ID(Do_Code); \
        YO_LOCAL_ID(Do_Unlock): \
          Yo_JmpBuf_Pop_Cs(Lx); \
          Unlock(Lx); \
          break; \
        } \
    else \
      YO_LOCAL_ID(Do_Code):

#define __Gogo \
  if ( 1 ) goto YO_LOCAL_ID(__gogo); \
  else YO_LOCAL_ID(__gogo):

#define __Elm_Resize_Npl(MemPptr,L,Width,CpsPtr) Yo_Elm_Resize_Npl((void**)MemPptr,L,Width,CpsPtr)
void Yo_Elm_Resize_Npl(void **inout, int L, int type_width, int *capacity_ptr)
#ifdef _YO_CORE_BUILTIN
  {
    int requires = 0;
    int capacity = capacity_ptr?*capacity_ptr:0;

    if ( L )
      {
        requires = (L+1)*type_width;
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
    if ( capacity_ptr ) *capacity_ptr = capacity;
  }
#endif
  ;

#define __Elm_Insert_Npl(MemPptr,Pos,Count,S,L,Width,CpsPtr) Yo_Elm_Insert_Npl((void**)MemPptr,Pos,Count,S,L,Width,CpsPtr)
int Yo_Elm_Insert_Npl(void **inout, int pos, int count, void *S, int L, int type_width, int *capacity_ptr)
#ifdef _YOYO_CORE_BUILTIN
  {
    STRICT_REQUIRE(pos <= count);

    if ( L < 0 ) /* inserting Z-string */
      switch ( type_width )
        {
          case sizeof(wchar_t): L = wcslen(S); break;







|







2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
    if ( capacity_ptr ) *capacity_ptr = capacity;
  }
#endif
  ;

#define __Elm_Insert_Npl(MemPptr,Pos,Count,S,L,Width,CpsPtr) Yo_Elm_Insert_Npl((void**)MemPptr,Pos,Count,S,L,Width,CpsPtr)
int Yo_Elm_Insert_Npl(void **inout, int pos, int count, void *S, int L, int type_width, int *capacity_ptr)
#ifdef _YO_CORE_BUILTIN
  {
    STRICT_REQUIRE(pos <= count);

    if ( L < 0 ) /* inserting Z-string */
      switch ( type_width )
        {
          case sizeof(wchar_t): L = wcslen(S); break;
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
    return L;
  }
#endif
  ;

#define __Elm_Insert(MemPptr,Pos,Count,S,L,Width,CpsPtr) Yo_Elm_Insert((void**)MemPptr,Pos,Count,S,L,Width,CpsPtr)
int Yo_Elm_Insert(void **inout, int pos, int count, void *S, int L, int type_width, int *capacity_ptr)
#ifdef _YOYO_CORE_BUILTIN
  {
    void *old = *inout;
    int r = Yo_Elm_Insert_Npl(inout,pos,count,S,L,type_width,capacity_ptr);
    if ( *inout != old )
      {
        if ( old )
          Yo_Refresh_Ptr(old,*inout,0);







|







2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
    return L;
  }
#endif
  ;

#define __Elm_Insert(MemPptr,Pos,Count,S,L,Width,CpsPtr) Yo_Elm_Insert((void**)MemPptr,Pos,Count,S,L,Width,CpsPtr)
int Yo_Elm_Insert(void **inout, int pos, int count, void *S, int L, int type_width, int *capacity_ptr)
#ifdef _YO_CORE_BUILTIN
  {
    void *old = *inout;
    int r = Yo_Elm_Insert_Npl(inout,pos,count,S,L,type_width,capacity_ptr);
    if ( *inout != old )
      {
        if ( old )
          Yo_Refresh_Ptr(old,*inout,0);