Unnamed Fossil Project

Check-in [fb3d7efd70]
Login

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
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
Hide Diffs Unified Diffs 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
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
...
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
...
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
...
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
...
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
...
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
...
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

*/

#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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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+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;

................................................................................
      }

    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++;
................................................................................
    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++;
................................................................................
        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++;
................................................................................
        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);







|







|




|

|
|






|

|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|












|
|










|










|
|
|
|
|










|
|
|
|
|












|
|
|
|
|






|
|
|
|







 







|
|



|







 







|
|
|
|







 







|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|


|
|







 







|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|













|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|


|
|







 







|
|
|
|


|
|
|
|


|
|
|
|


|
|
|
|












|

|





|






|










|

|





|






|









|


|













|


|







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
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
...
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
...
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
...
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
...
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
...
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
...
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
...
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

*/

#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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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,
................................................................................
      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+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;

................................................................................
      }

    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++;
................................................................................
    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++;
................................................................................
        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++;
................................................................................
        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
...
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
...
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
...
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
...
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
...
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
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
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
...
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
...
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

*/

#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;
................................................................................
      
    *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;
      }
................................................................................
          }
        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;
................................................................................
    
    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 ;
................................................................................
        
        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)) )
          {
................................................................................
              {
                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] ) 
................................................................................
    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]);
................................................................................
    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_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_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 */








|




|
|
|

|
|


|
|
|
|
|
|
|
|
|


|








|








|








|








|








|








|








|








|








|







 







|




|

|
|








|












|
|





|












|
|













|
|











|
|







|











|
|





|







 







|
|








|










|
|







 







|








|
|







 







|











|
|








|











|
|







 







|





|
|

|







|
|






|
|






|
|






|
|






|
|






|
|






|
|








|
|








|
|








|
|





|







|
|







 







|
|







 







|

|











|






|

|







 







|






|

|










|

|







 







|






|

|







 







|





|




|

|







 







|





|
|











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
...
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
...
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
...
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
...
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
...
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
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
...
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
...
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
...
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

*/

#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;
................................................................................
      
    *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;
      }
................................................................................
          }
        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;
................................................................................
    
    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 ;
................................................................................
        
        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)) )
          {
................................................................................
              {
                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] ) 
................................................................................
    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]);
................................................................................
    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_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_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
...
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
...
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
...
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
...
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
...
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
...
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
...
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
...
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
....
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
....
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
....
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
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
....
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
....
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

*/

#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); 
................................................................................
      }
      
    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 )
................................................................................
      }

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

    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);
        
................................................................................
        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);
................................................................................
        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(;;) 
      {
................................................................................
      }
    
    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;

................................................................................
      }
    
    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;
................................................................................
      }
      
    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;
          }
................................................................................
      }
    
    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];
................................................................................
      }
      
    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);
................................................................................
                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);
................................................................................
    *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;
................................................................................
    
    __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 */









|







|





|



|
|
|
|
|
|
|


|

|
|
|

|




|
|


|
|


|

|
|




|





|
|






|





|
|












|
|











|
|

|












|


|









|






|
|









|












|
|












|
|






|
|





|
|













|
|







 







|
|








|

|
|




|










|
|





|






|





|










|
|









|







|







 







|
|





|












|


|
|

|
|


|






|
|
|







|
|







 







|





|










|
|








|





|










|
|








|







|
|


|






|




|





|



|











|
|


|






|



|







 







|
|





|












|







|







 







|
|





|












|






|




|











|
|









|
|










|
|

|










|







 







|
|





|










|
|

|







|










|
|

|










|










|
|

|








|











|
|







 







|
|




|
|







 







|
|













|
|

|











|

|
|



|

|
|











|
|



|







 







|
|

|











|

|
|



|

|
|







 







|
|

|
|
|







 







|
|

|



|
|
|




|
|
|







 







|



|






|



|




|


|
|
|
|




|

|





|
|





|
|
|

|
|







 







|
|


|
|

|







 







|






|
|
|
|



|
|
|
|
|
|







 







|
|

|
|
|


|









|
|




|

|

|

|













|
|
|

|



|







 







|
|







 







|
|






|












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
...
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
...
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
...
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
...
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
...
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
...
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
...
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
...
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
....
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
....
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
....
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
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
....
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
....
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

*/

#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); 
................................................................................
      }
      
    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 )
................................................................................
      }

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

    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);
        
................................................................................
        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);
................................................................................
        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(;;) 
      {
................................................................................
      }
    
    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;

................................................................................
      }
    
    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;
................................................................................
      }
      
    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;
          }
................................................................................
      }
    
    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];
................................................................................
      }
      
    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);
................................................................................
                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);
................................................................................
    *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;
................................................................................
    
    __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
...
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
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

*/

#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 )
          {
................................................................................
      }
       
    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));

................................................................................
      }
    
    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 )
................................................................................
      }
    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; )
      {
................................................................................
          {
            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; )
      {
................................................................................
          {
            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 */







|




|
|
|


|


|
|

|

|



|

|
|

|

|


|
|







|
|

|

|




|
|







|
|


|
|








|
|




|
|







 







|
|







|




|
|


|
|







 







|
|


|







 







|
|







 







|






|
|







 







|






|
|







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
...
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
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302

*/

#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 )
          {
................................................................................
      }
       
    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));

................................................................................
      }
    
    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 )
................................................................................
      }
    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; )
      {
................................................................................
          {
            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; )
      {
................................................................................
          {
            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
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
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
...
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
...
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

*/

#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,
................................................................................
      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) 
................................................................................

    *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) 
................................................................................

    *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);

................................................................................
      
    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 */








|






|



|

|







 







|






|
|







 







|
|










|
|







 







|
|










|



|
|






|
|







 







|

|






|







|












|


|











|


|












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
...
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
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
...
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
...
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

*/

#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,
................................................................................
      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) 
................................................................................

    *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) 
................................................................................

    *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);

................................................................................
      
    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
...
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
...
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
...
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
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
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

*/

#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);
................................................................................
      }
      
    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);
................................................................................
        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
................................................................................
    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;
................................................................................
        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;
................................................................................
          
        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;
................................................................................
          
        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 */








|







|




|

|
|










|
|


|







 







|
|


|







 







|
|








|
|







|
|







 







|
|







 







|
|






|
|







|
|







|
|







 







|
|









|
|







 







|
|







 







|
|







 







|
|






|













|
|










|
|












|
|
|


|
|








|
|







|
|








|
|








|
|









|

|








|

|










|

|








|

|









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
...
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
...
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
...
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
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
...
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

*/

#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);
................................................................................
      }
      
    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);
................................................................................
        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
................................................................................
    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;
................................................................................
        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;
................................................................................
          
        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;
................................................................................
          
        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
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
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
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
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

*/

#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 )
      {
................................................................................
        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 )
      {
................................................................................
        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 )
................................................................................
    
    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 )
................................................................................
    
    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
................................................................................
        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
................................................................................
        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 */








|






|
|
|

|
|


|
|
|
|

|



|



|



|




|


|


|





|


|


|





|







 







|







 







|








|






|








|






|







 







|







 







|







 







|







|







 







|







|







|







|







|








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
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
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
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
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

*/

#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 )
      {
................................................................................
        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 )
      {
................................................................................
        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 )
................................................................................
    
    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 )
................................................................................
    
    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
................................................................................
        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
................................................................................
        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
..
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
...
391
392
393
394
395
396
397
398
399
400
401

*/

#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);
................................................................................
#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)
................................................................................

#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 */








|




|
|
|

|
|


|
|







 







|








|








|








|








|








|








|








|








|







|







 







|



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
..
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
...
391
392
393
394
395
396
397
398
399
400
401

*/

#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);
................................................................................
#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)
................................................................................

#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
..
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
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
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
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
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
#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'),
................................................................................
      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 
................................................................................
        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 )
................................................................................
        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;
      }
................................................................................
#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:  
................................................................................
      {
      }
    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);







|







 







|




|

|








|
|
|

|
|











|
|







 







|
|







 







|
|










|
|







 







|
|











|
|







|
|







|
|










|
|







 







|
|







 







|
|

|






|







|
|













|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
..
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
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
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
...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
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
#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'),
................................................................................
      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 
................................................................................
        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 )
................................................................................
        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;
      }
................................................................................
#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:  
................................................................................
      {
      }
    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
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
..
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
...
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
...
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_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);
................................................................................
    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_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);
................................................................................
    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
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
..
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
...
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
...
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_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);
................................................................................
    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_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);
................................................................................
    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
...
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
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
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
...
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

*/

#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*));
      }
................................................................................
      }
    
    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;
          }
................................................................................
      }
    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 );
................................................................................
          }
      }
  }
#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;
            }
................................................................................
          {
            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); 







|







|

|



|

|

|


|



|

|

|



|
|

|







 







|
|


|









|
|




|








|
|




|








|
|












|
|




|


|







 







|
|




|


|







 







|
|




|


|













|
|













|
|









|







 







|
|





|







 







|







 







|
|








|

|




|






|

|




|






|

|





|
|


|







 







|
|






|
|

|






|
|






|
|

|






|

|
|


|
|







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
...
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
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
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
...
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

*/

#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*));
      }
................................................................................
      }
    
    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;
          }
................................................................................
      }
    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 );
................................................................................
          }
      }
  }
#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;
            }
................................................................................
          {
            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
..
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
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
150
151
152
153
154
155
156






















157
158
159
160
161
162
163
164
165
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
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
...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
...
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
...
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
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
...
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
...
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
...
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
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
...
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
...
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
....
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
....
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
....
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
....
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
....
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
....
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
....
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
....
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
....
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
....
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
....
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

*/

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

................................................................................

#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) ) 
................................................................................
    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,'\\');
................................................................................
      }
    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,'\\');
................................................................................
          }
      }
    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));
................................................................................
      }
    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);
................................................................................
          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 )
      {
................................................................................
    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};
................................................................................
    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 )
................................................................................
    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;
................................................................................
      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;
................................................................................
      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)
................................................................................
      }
  #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_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);
................................................................................
    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);
................................................................................
        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
................................................................................
#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);
          }
................................................................................
          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);
................................................................................
  #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
................................................................................
        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);
................................................................................
        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 ; )
................................................................................
            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;
................................................................................
        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(;;)
          {
................................................................................
      }
    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 ; )
          {
................................................................................
        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);
................................................................................
        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);
................................................................................
          }
        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);
................................................................................
        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 = 
................................................................................
        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_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; */
................................................................................
    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);
    
................................................................................
        
    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 )
        {
................................................................................
        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 )
................................................................................
#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   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);
................................................................................
      {
        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));
................................................................................
        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 )
      {
................................................................................
        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 */








|







 







|

|
|
|

|
|



|

|



|







 







|







|







 







|







 







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

|







 







|







 







|







 







|





|







 







|







 







|







 







|







 







|







 







|







 







|



|

|










|


|
|

|







 







|
|

|







 







|







|
|





|








|

|

|

|

|

|

|

|

|


|

|







 







|

|







 







|







 







|










|






|
|







 







|

|










|







 







|







 







|




|

|
|


|







|
|



|
|











|
|







 







|
|



|
|










|
|








|
|








|
|



|







 







|
|




|
|











|
|




|
|







 







|







 







|
|




|
|







 







|
|




|
|







 







|
|



|
|













|
|




|
|







 







|
|




|
|



|







|
|




|
|



|







|
|
|













|







 







|
|



|


|







 







|
|




|
|







 







|
|

|







 







|








|
|

|










|








|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|



|

|


|




|
|
|
|


|
|





|





|
|

|
|
|
|
|
|
|
|
|










|







 







|







 







|







 







|







 







|










|



|

|

|

|


|







 







|









|




|





|












|













|

|





|












|












|












|











|






|












|











|










|












|








|







 







|

|

|

|
|







|
|






|
|



|








|
|










|
|






|
|








|
|








|
|











|






|
|







|





|
|

|

|











|






|
|







|
|


|








|

|

|












|
|








|









|







 







|







 







|

|




|









|
|




|








43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
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
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
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
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
...
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
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
...
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
...
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
...
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
...
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
...
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
...
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
...
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
...
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
...
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
....
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
....
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
....
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
....
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
....
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
....
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
....
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
....
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
....
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
....
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
....
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

*/

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

................................................................................

#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) ) 
................................................................................
    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,'\\');
................................................................................
      }
    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,'\\');
................................................................................
          }
      }
    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));
................................................................................
      }
    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);
................................................................................
          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 )
      {
................................................................................
    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};
................................................................................
    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 )
................................................................................
    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;
................................................................................
      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;
................................................................................
      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)
................................................................................
      }
  #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_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);
................................................................................
    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);
................................................................................
        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
................................................................................
#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);
          }
................................................................................
          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);
................................................................................
  #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
................................................................................
        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);
................................................................................
        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 ; )
................................................................................
            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;
................................................................................
        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(;;)
          {
................................................................................
      }
    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 ; )
          {
................................................................................
        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);
................................................................................
        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);
................................................................................
          }
        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);
................................................................................
        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 = 
................................................................................
        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_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; */
................................................................................
    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);
    
................................................................................
        
    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 )
        {
................................................................................
        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 )
................................................................................
#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   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);
................................................................................
      {
        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));
................................................................................
        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 )
      {
................................................................................
        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
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
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
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
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
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
...
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
#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 = &(*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);
................................................................................
    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";
................................................................................
      }
      
    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->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 )
................................................................................
      }
      
    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";
................................................................................
        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);
      }
................................................................................
            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;
      }
................................................................................
  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;
................................................................................
    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;
      }
................................................................................
      {
        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;
................................................................................
    
    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 (;;)
      {
................................................................................
          }
        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;
      }
................................................................................
              }
          }
      }
  }
#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 */








|


|
|
|

|



|


|

|

|





|







 







|
|




|
|


|

|
|

|
|

|
|







 







|
|







 







|







 







|
|

|







 







|
|







 







|
|








|







 







|
|


|







 







|
|


|







 







|
|

|






|
|

|







 







|
|

|







 







|
|







 







|
|







 







|
|


|







 







|
|








|











|
|










|
|






|
|










|
|

|









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
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
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
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
...
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
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
...
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
...
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
#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 = &(*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);
................................................................................
    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";
................................................................................
      }
      
    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->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 )
................................................................................
      }
      
    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";
................................................................................
        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);
      }
................................................................................
            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;
      }
................................................................................
  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;
................................................................................
    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;
      }
................................................................................
      {
        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;
................................................................................
    
    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 (;;)
      {
................................................................................
          }
        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;
      }
................................................................................
              }
          }
      }
  }
#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
...
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
...
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
...
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
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
...
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
...
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
...
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
...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
...
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
#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);
................................................................................
    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);
  }
................................................................................
      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 )
................................................................................
        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 ) )
................................................................................
        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; } 
................................................................................
      }
      
    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 (;;)
................................................................................
          }
        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;
      }
      
................................................................................

    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;
      }
................................................................................

    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);
................................................................................
    
    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);
................................................................................
    
    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;
      }
................................................................................
    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
................................................................................
                           (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
................................................................................
    
    /// 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
................................................................................
          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;
................................................................................
    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 )
      {
................................................................................
      }

    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 ) 
          {
................................................................................
        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 ) 
          {
................................................................................
        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 ) 
................................................................................
        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 */








|

|


|
|











|

|
|













|

|







 







|








|








|







 







|








|







 







|













|


|







 







|









|







 







|


|







 







|







 







|



|







 







|


|







 







|


|







 







|







 







|


|







 







|







 







|







 







|







 







|







 







|


|










|







 







|












|







 







|







 







|







 







|








|




|













|











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
...
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
...
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
...
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
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
...
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
...
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
...
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
...
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
...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
...
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
#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);
................................................................................
    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);
  }
................................................................................
      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 )
................................................................................
        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 ) )
................................................................................
        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; } 
................................................................................
      }
      
    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 (;;)
................................................................................
          }
        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;
      }
      
................................................................................

    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;
      }
................................................................................

    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);
................................................................................
    
    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);
................................................................................
    
    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;
      }
................................................................................
    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
................................................................................
                           (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
................................................................................
    
    /// 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
................................................................................
          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;
................................................................................
    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 )
      {
................................................................................
      }

    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 ) 
          {
................................................................................
        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 ) 
          {
................................................................................
        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 ) 
................................................................................
        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
280

*/

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

*/

#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
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
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
...
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

*/

#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;
................................................................................
    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);

................................................................................
        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);

................................................................................

    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;
................................................................................
    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);
................................................................................
    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 */








|





|










|







 







|







 







|







 







|







 







|












|







 







|











|
|












|




|
|



|













|







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
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
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
...
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

*/

#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;
................................................................................
    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);

................................................................................
        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);

................................................................................

    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;
................................................................................
    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);
................................................................................
    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
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
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
...
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

*/

#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) 
      {
................................................................................
  #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,
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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 */








|





|





|

|

|
|

|




|
|











|
|


|

|





|





|


|

|







|


|










|







 







|







 







|







 







|







 







|

|

|


|

|
|

|




|
|







 







|
|






|
|







|
|













|

|








|

|





|







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
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
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
...
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

*/

#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) 
      {
................................................................................
  #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,
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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
..
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
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
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

*/

#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,
................................................................................
    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];
................................................................................
    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];
................................................................................
    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 */








|






|







 







|


|

|
|






|
|







 







|
|







 







|
|








|

|





|





|













49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
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
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
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

*/

#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,
................................................................................
    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];
................................................................................
    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];
................................................................................
    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
...
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
...
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
...
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
...
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
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
...
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
...
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
...
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

*/

#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.
................................................................................
#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 )
................................................................................
      
    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;
................................................................................
      
    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;
................................................................................
    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);
................................................................................
    
    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
................................................................................
          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;
................................................................................
    
    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 )
      {
................................................................................
      
    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 */









|







 







|







|


|





|







|







|












|










|







 







|










|










|











|










|







 







|







|







|










|







 







|







 







|








|







|







 







|







 







|







 







|






|
|


|







 







|







 







|



|


|



|

|






|







|









43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
...
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
...
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
...
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
...
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
...
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
...
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
...
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
...
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
...
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

*/

#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.
................................................................................
#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 )
................................................................................
      
    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;
................................................................................
      
    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;
................................................................................
    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);
................................................................................
    
    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
................................................................................
          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;
................................................................................
    
    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 )
      {
................................................................................
      
    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
...
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,
................................................................................
      }
      
    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
...
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,
................................................................................
      }
      
    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
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
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

*/

#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;
................................................................................

            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 )
................................................................................
              }
            //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 */








|




|







 







|
|
|

|













|







 







|







|







 







|








|
|
|

|


|









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
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
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

*/

#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;
................................................................................

            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 )
................................................................................
              }
            //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
...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
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]];
................................................................................
      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.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
...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
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]];
................................................................................
      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.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
...
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
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
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
...
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
#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 )
................................................................................
        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)) );
................................................................................
        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;
................................................................................
      }      
    
    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
  ;
  







|


|
|

|





|


|
|
|


|



|




|

|
|







 







|
|




|
|




|
|






|






|
|







 







|
|







|
|



|







 







|
|







 







|
|

|







|


|







 







|
|













|
|











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
...
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
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
...
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
...
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
#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 )
................................................................................
        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)) );
................................................................................
        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;
................................................................................
      }      
    
    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
...
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
...
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
...
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
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
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

*/

#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;
................................................................................
      
    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)) )
................................................................................
                        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);
................................................................................
          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;
................................................................................
    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 */








|








|






|





|




|

|



|
|

|
|









|

|





|



|



|







|







 







|











|
|







 







|





|







|







 







|













|







 







|
|

|







 







|





|










|







|







|









|








|

|






|

|








|

|








|

|








|









|

|








|









|







|








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
...
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
...
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
...
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
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
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

*/

#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;
................................................................................
      
    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)) )
................................................................................
                        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);
................................................................................
          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;
................................................................................
    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
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
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
...
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
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

*/

#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
      {
................................................................................
          }
      }
  }
#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 )
              {
................................................................................
                    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;
      }
................................................................................
  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 );
    
................................................................................
    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;
................................................................................
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++) 
................................................................................
    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 */








|













|

|
|
|

|
|



|







 







|




|







 







|
|







 







|







 







|













|







 







|
|
|
|
|


|





|

|
|





|


|
|


|







|
|



|







|
|




|
|




|
|




|
|







|
|







|
|









|
|

|













|
|







 







|
|

|





|







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
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
...
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
...
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
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387

*/

#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
      {
................................................................................
          }
      }
  }
#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 )
              {
................................................................................
                    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;
      }
................................................................................
  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 );
    
................................................................................
    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;
................................................................................
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++) 
................................................................................
    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
..
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
...
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

#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 );
................................................................................
      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);
................................................................................
    {\
      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()\







|


|




|

|
|







 







|
|







 







|
|







 







|
|







 







|



|



|




|



|



|



|



|









|






|




|



|







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

#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 );
................................................................................
      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);
................................................................................
    {\
      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
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
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
...
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

*/

#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) 
        {
................................................................................
  #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]  );
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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 */








|





|





|

|

|
|

|




|
|












|
|


|

|





|






|

|







|


|










|







 







|







 







|







 







|







 







|

|

|


|

|
|

|




|
|







 







|
|






|
|












|
|








|

|








|

|





|







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
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
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
...
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

*/

#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) 
        {
................................................................................
  #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]  );
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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
..
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
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
...
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
...
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

*/

#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[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) 
        {
................................................................................
  #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], 
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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 */








|





|





|

|
|

|




|
|







 







|
|


|

|





|





|





|

|







|


|










|







 







|







 







|







 







|







 







|

|

|


|

|
|

|




|
|







 







|
|






|
|












|
|








|

|








|

|





|







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
..
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
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
...
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
...
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

*/

#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[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) 
        {
................................................................................
  #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], 
................................................................................
  #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);
................................................................................
          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
................................................................................
          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);
................................................................................
    
    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
...
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
...
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
...
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
...
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
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
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
...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
...
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
...
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
...
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
...
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
....
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
....
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
....
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
....
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
....
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
....
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
....
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
....
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
....
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
....
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
....
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
....
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
....
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
....
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
....
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
....
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
....
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
....
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
....
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
....
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
....
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
#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;
      }
................................................................................
  }
#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;
................................................................................
        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;

................................................................................
    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];
................................................................................
        *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,
................................................................................
    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 ,
................................................................................
#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);
................................................................................
    
    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;
................................................................................
    *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);
................................................................................
            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;
................................................................................
    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;
................................................................................
    
    return 0;
  }
#endif
  ;

int Str_Urldecode_Char(char **S)
#ifdef _YOYO_STRING_BUILTIN
  {
    int r = 0;
    if ( *S ) 
      {
        if ( **S == '+' ) 
          {
            r = ' ';
................................................................................
      }
    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,
................................................................................
    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
................................................................................
      }
    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; 
................................................................................
    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; }
................................................................................
      }
    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); }
      }
................................................................................
    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 )
................................................................................
  }
#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;
................................................................................
  }
#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
................................................................................
  #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 )
................................................................................
    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 )
................................................................................
      }
    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
................................................................................
      }
    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;
................................................................................
#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;
................................................................................
#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 )
................................................................................
    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
................................................................................
      }
    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;
................................................................................
#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;
................................................................................
#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;
................................................................................
    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;
................................................................................
      }
    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
      {
................................................................................
    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;
    
................................................................................
    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' ) )
................................................................................
  }
#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;
................................................................................
  }
#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;
................................................................................
  }
#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;
................................................................................
  ;

#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;
................................................................................
  ;

#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
          {
................................................................................
      }
      
    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;
................................................................................
        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);
................................................................................
    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]);
................................................................................

#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]);
................................................................................

#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 )
      {
................................................................................
#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 )







|


|
|

|





|







 







|







 







|













|













|







|









|










|







 







|










|







 







|













|







 







|

|












|

|








|







 







|







 







|







 







|
|




|
|




|
|









|







 







|







|








|
|







 







|
|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







|







|









|









|











|











|











|












|
|







 







|







 







|













|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|













|










|












|



|






|




|





|








|







 







|




|





|








|







 







|







 







|
|
|
|



|


|

|

|
|





|












|












|













|











|










|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







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
...
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
...
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
...
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
...
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
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
...
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
...
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
...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
...
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
...
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
...
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
...
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
...
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
....
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
....
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
....
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
....
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
....
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
....
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
....
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
....
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
....
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
....
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
....
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
....
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
....
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
....
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
....
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
....
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
....
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
....
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
....
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
....
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
....
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
#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;
      }
................................................................................
  }
#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;
................................................................................
        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;

................................................................................
    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];
................................................................................
        *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,
................................................................................
    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 ,
................................................................................
#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);
................................................................................
    
    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;
................................................................................
    *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);
................................................................................
            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;
................................................................................
    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;
................................................................................
    
    return 0;
  }
#endif
  ;

int Str_Urldecode_Char(char **S)
#ifdef _YO_STRING_BUILTIN
  {
    int r = 0;
    if ( *S ) 
      {
        if ( **S == '+' ) 
          {
            r = ' ';
................................................................................
      }
    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,
................................................................................
    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
................................................................................
      }
    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; 
................................................................................
    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; }
................................................................................
      }
    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); }
      }
................................................................................
    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 )
................................................................................
  }
#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;
................................................................................
  }
#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
................................................................................
  #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 )
................................................................................
    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 )
................................................................................
      }
    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
................................................................................
      }
    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;
................................................................................
#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;
................................................................................
#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 )
................................................................................
    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
................................................................................
      }
    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;
................................................................................
#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;
................................................................................
#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;
................................................................................
    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;
................................................................................
      }
    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
      {
................................................................................
    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;
    
................................................................................
    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' ) )
................................................................................
  }
#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;
................................................................................
  }
#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;
................................................................................
  }
#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;
................................................................................
  ;

#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;
................................................................................
  ;

#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
          {
................................................................................
      }
      
    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;
................................................................................
        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);
................................................................................
    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]);
................................................................................

#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]);
................................................................................

#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 )
      {
................................................................................
#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
...
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
...
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
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#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;
................................................................................
          
        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 )
................................................................................
      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);
................................................................................
        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 
      {







|













|

|





|

|

|



|

|




|
|
|
|
|
|





|
|









|
|









|



|













|





|







 







|
|







 







|



|




|









|

|










|



|
|
|







|







 







|
|

|


|









|

|







 







|







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
...
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
...
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
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
#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;
................................................................................
          
        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 )
................................................................................
      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);
................................................................................
        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
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
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
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
...
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
...
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
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
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
...
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
...
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
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
...
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
...
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
...
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
...
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
  #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];
................................................................................
    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;
................................................................................
      }
    #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;
................................................................................
  #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);
          }
      }
................................................................................
#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);
................................................................................
#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;
................................................................................
      }
    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;
................................................................................
  }
#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;
................................................................................
        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);
................................................................................
      }
    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);
................................................................................
      }
    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
................................................................................
  }
#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();
................................................................................
    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);
          }
................................................................................
    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);
          }
................................................................................
          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);
    
................................................................................
    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 )
      {
................................................................................
      {
        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 */








|







 







|







 







|







 







|




|







 







|







|







|







 







|







 







|











|







 







|










|

|






|
|







 







|
|










|
|







|
|









|













|
|









|







 







|



|







 







|
|

|
|


|
|










|
|

|




|
|







 







|
|











|
|



|











|
|







 







|
|











|
|



|












|
|

|

|








|






|
|










|
|







 







|
|







 







|







 







|







 







|
|






|
|







 







|





|









|

|



|

|
|








|
|









|
|







|
|

|









|
|

|






|
|

|







 







|












|

|



|







 







|







 







|
|



|













69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
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
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
...
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
...
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
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
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
...
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
...
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
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
...
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
...
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
...
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
...
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
  #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];
................................................................................
    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;
................................................................................
      }
    #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;
................................................................................
  #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);
          }
      }
................................................................................
#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);
................................................................................
#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;
................................................................................
      }
    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;
................................................................................
  }
#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;
................................................................................
        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);
................................................................................
      }
    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);
................................................................................
      }
    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
................................................................................
  }
#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();
................................................................................
    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);
          }
................................................................................
    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);
          }
................................................................................
          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);
    
................................................................................
    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 )
      {
................................................................................
      {
        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
...
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
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
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
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
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
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
................................................................................
      _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);
................................................................................

    return 0;    
  }
#endif
  ;
    
int Thread_Join(thread_t thr)
#ifdef _YOYO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        for(;;)
          {
            DWORD ecode;
................................................................................
      
    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
  ;
     
#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;
      }
................................................................................
        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*/







|









|
|



|
|



|

|




|










|









|

|











|








|







 







|











|







 







|







 







|










|







 







|



|

|
|







 







|













|










|
|







|
|







|
|







|
|







|
|








|
|









|
|







|
|

|




|










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
...
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
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
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
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
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
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
................................................................................
      _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);
................................................................................

    return 0;    
  }
#endif
  ;
    
int Thread_Join(thread_t thr)
#ifdef _YO_THREADS_BUILTIN
  {
    if ( thr != INVALID_THREAD_VALIUE )
      {
    #ifdef __windoze
        for(;;)
          {
            DWORD ecode;
................................................................................
      
    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
  ;
     
#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;
      }
................................................................................
        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
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

*/

#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;
................................................................................
    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;"
................................................................................
          __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;
    
................................................................................
    }
    
    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");
      }
................................................................................
      
    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";
................................................................................
    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;







|





|







 







|



|







 







|

|
|







 







|
|


|







 







|







 







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

*/

#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;
................................................................................
    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;"
................................................................................
          __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;
    
................................................................................
    }
    
    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");
      }
................................................................................
      
    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";
................................................................................
    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
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
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
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#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);
................................................................................
    __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
................................................................................
    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;
        
................................................................................
                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;
              }
................................................................................
        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);
................................................................................
          }
          
        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 )
                  {
................................................................................
      }
      
    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];
................................................................................
              }
          }
      }
  }
#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 )
................................................................................
      }
        
    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] = '?';
          }







|










|



|
|

|
|







 







|







 







|
|

|







 







|







 







|







 







|







 







|



|


|

|
|







 







|
|

|







 







|
|



|







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
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
...
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
...
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#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);
................................................................................
    __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
................................................................................
    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;
        
................................................................................
                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;
              }
................................................................................
        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);
................................................................................
          }
          
        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 )
                  {
................................................................................
      }
      
    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];
................................................................................
              }
          }
      }
  }
#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 )
................................................................................
      }
        
    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.

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
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
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
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
...
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
...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
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
...
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
...
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
...
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
...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
...
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
...
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
...
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
#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_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;
................................................................................
        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 )
          {
................................................................................
      }
  
    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;
................................................................................
   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.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) )
                        {
................................................................................
      ;
    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+");
................................................................................
        }
    __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;
................................................................................
        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);
            
................................................................................
            _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
................................................................................
            _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);
................................................................................
      _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
          {
................................................................................
      }
    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*/








|







 







|
|
|

|







 







|


|




|
|

|

|








|




|

|

|

|
|

|
|








|
|








|
|


|







 







|
|







 







|
|







 







|
|










|
|










|
|

|







 







|
|







|



|










|
|

|





|
|








|
|

|







 







|
|







 







|
|




|









|
|




|









|
|

|
|










|
|








|
|








|
|








|
|

|










|
|
|
|

|
|



|








|













|







 







|







|
|






|
|







 







|
|











|
|

|







 







|







 







|
|



|









|
|






|







 







|
|
|

|







 







|
|

|





|
|







 







|



|

|











|
|







 







|
|





|
|






|
|

|










|
|

|












2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
..
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36