sq_fossil.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #include "squirrel.h"
  2. #include "sqstdblobimpl.h"
  3. #define MixInteger SQInteger
  4. #include "sqlite3.h"
  5. #define USE_MG_MD5
  6. #include "mongoose.h"
  7. #include "fossil-delta.h"
  8. static SQRESULT sq_fossil_delta_create(HSQUIRRELVM v) {
  9. SQ_FUNC_VARS_NO_TOP(v);
  10. SQ_GET_STRING(v, 2, str_from);
  11. SQ_GET_STRING(v, 3, str_to);
  12. SQChar *delta = sq_getscratchpad(v, str_to_size + DELTA_OVERFLOW);
  13. int delta_size = delta_create(str_from, str_from_size, str_to, str_to_size, delta);
  14. sq_pushstring(v, delta, delta_size);
  15. return 1;
  16. }
  17. static SQRESULT sq_fossil_delta_apply(HSQUIRRELVM v) {
  18. SQ_FUNC_VARS_NO_TOP(v);
  19. SQ_GET_STRING(v, 2, str_from);
  20. SQ_GET_STRING(v, 3, str_delta);
  21. int str_to_size = delta_output_size(str_delta, str_delta_size);
  22. if(str_to_size < 0) return sq_throwerror(v, _SC("invalid delta string"));
  23. SQChar *str_to = sq_getscratchpad(v, str_to_size);
  24. str_to_size = delta_apply(str_from, str_from_size, str_delta, str_delta_size, str_to);
  25. if(str_to_size < 0) return sq_throwerror(v, _SC("error applying delta"));
  26. sq_pushstring(v, str_to, str_to_size);
  27. return 1;
  28. }
  29. static SQRESULT sq_fossil_delta_output_size(HSQUIRRELVM v) {
  30. SQ_FUNC_VARS_NO_TOP(v);
  31. SQ_GET_STRING(v, 2, str_delta);
  32. int str_to_size = delta_output_size(str_delta, str_delta_size);
  33. sq_pushinteger(v, str_to_size);
  34. return 1;
  35. }
  36. static SQRESULT sq_fossil_delta_analyze(HSQUIRRELVM v) {
  37. SQ_FUNC_VARS_NO_TOP(v);
  38. SQ_GET_STRING(v, 2, str_delta);
  39. int pnCopy, pnInsert;
  40. int rc = delta_analyze(str_delta, str_delta_size, &pnCopy, &pnInsert);
  41. if(rc < 0) return sq_throwerror(v, _SC("invalid delta string"));
  42. sq_newarray(v, 2);
  43. sq_pushinteger(v, pnCopy);
  44. sq_arrayset(v, -2, 0);
  45. sq_pushinteger(v, pnInsert);
  46. sq_arrayset(v, -2, 1);
  47. return 1;
  48. }
  49. extern "C" {
  50. typedef sqlite3_uint64 u64;
  51. /*
  52. ** State structure for a SHA3 hash in progress
  53. */
  54. typedef struct SHA3Context SHA3Context;
  55. struct SHA3Context {
  56. union {
  57. u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
  58. unsigned char x[1600]; /* ... or 1600 bytes */
  59. } u;
  60. unsigned nRate; /* Bytes of input accepted per Keccak iteration */
  61. unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
  62. unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
  63. };
  64. void xsqlite3_SHA3Init(SHA3Context*, int);
  65. void xsqlite3_SHA3Update(SHA3Context*, const unsigned char*, unsigned);
  66. const unsigned char* xsqlite3_SHA3Final(SHA3Context*);
  67. #define SHA3Init xsqlite3_SHA3Init
  68. #define SHA3Update xsqlite3_SHA3Update
  69. #define SHA3Final xsqlite3_SHA3Final
  70. /* Context for the SHA1 hash */
  71. typedef struct SHA1Context SHA1Context;
  72. struct SHA1Context {
  73. unsigned int state[5];
  74. unsigned int count[2];
  75. unsigned char buffer[64];
  76. };
  77. void xsqlite3_SHA1Init(SHA1Context*);
  78. void xsqlite3_SHA1Update(SHA1Context*, const unsigned char*, unsigned);
  79. void xsqlite3_SHA1Final(SHA1Context*, char*);
  80. #define SHA1Init xsqlite3_SHA1Init
  81. #define SHA1Update xsqlite3_SHA1Update
  82. #define SHA1Final xsqlite3_SHA1Final
  83. }
  84. /*
  85. ** Convert a digest into base-16. digest should be declared as
  86. ** "unsigned char digest[20]" in the calling function. The SHA3
  87. ** digest is stored in the first 20 bytes. zBuf should
  88. ** be "char zBuf[41]".
  89. */
  90. static void DigestToBase16(const unsigned char *digest, char *zBuf, int nByte){
  91. static const char zEncode[] = "0123456789abcdef";
  92. int ix;
  93. for(ix=0; ix<nByte; ix++){
  94. *zBuf++ = zEncode[(*digest>>4)&0xf];
  95. *zBuf++ = zEncode[*digest++ & 0xf];
  96. }
  97. *zBuf = '\0';
  98. }
  99. static SQRESULT sq_fossil_sha3sum(HSQUIRRELVM v) {
  100. SQ_FUNC_VARS(v);
  101. SQ_GET_INTEGER(v, 2, iSize);
  102. switch(iSize)
  103. {
  104. case 0:
  105. iSize = 256;
  106. case 224:
  107. case 256:
  108. case 384:
  109. case 512:
  110. break;
  111. default:
  112. return sq_throwerror(v, _SC("invalid hash size expected one of [0, 224, 256, 384, 512]"));
  113. }
  114. SHA3Context ctx;
  115. SHA3Init(&ctx, iSize);
  116. for (int i = 3; i <= _top_; ++i) {
  117. SQ_GET_STRING(v, i, p);
  118. SHA3Update(&ctx, (const unsigned char *) p, p_size);
  119. }
  120. SQInteger buf_size = iSize/4;
  121. SQChar *buf = sq_getscratchpad(v, buf_size);
  122. DigestToBase16(SHA3Final(&ctx), buf, buf_size/2);
  123. sq_pushstring(v, buf, buf_size);
  124. return 1;
  125. }
  126. static SQRESULT sq_fossil_sha1sum(HSQUIRRELVM v) {
  127. SQ_FUNC_VARS(v);
  128. const int hash_size = 20;
  129. const int buf_size = hash_size*2;
  130. char buf[buf_size+1];
  131. SHA1Context ctx;
  132. SHA1Init(&ctx);
  133. for (int i = 2; i <= _top_; ++i) {
  134. SQ_GET_STRING(v, i, p);
  135. SHA1Update(&ctx, (const unsigned char *) p, p_size);
  136. }
  137. SHA1Final(&ctx, buf);
  138. sq_pushstring(v, buf, buf_size);
  139. return 1;
  140. }
  141. static SQRESULT sq_fossil_md5sum(HSQUIRRELVM v) {
  142. SQ_FUNC_VARS(v);
  143. const int hash_size = 16;
  144. const int buf_size = hash_size*2;
  145. char buf[buf_size+1];
  146. unsigned char hash[hash_size];
  147. MD5_CTX ctx;
  148. MD5Init(&ctx);
  149. for (int i = 2; i <= _top_; ++i) {
  150. SQ_GET_STRING(v, i, p);
  151. MD5Update(&ctx, (const unsigned char *) p, p_size);
  152. }
  153. MD5Final(hash, &ctx);
  154. DigestToBase16(hash, buf, hash_size);
  155. sq_pushstring(v, buf, buf_size);
  156. return 1;
  157. }
  158. #define _DECL_FUNC(name,nparams,pmask) {_SC(#name), sq_fossil_##name,nparams,pmask}
  159. static SQRegFunction fossil_obj_funcs[]={
  160. _DECL_FUNC(delta_create,3, _SC(".ss")),
  161. _DECL_FUNC(delta_apply,3, _SC(".ss")),
  162. _DECL_FUNC(delta_output_size,2, _SC(".s")),
  163. _DECL_FUNC(delta_analyze,2, _SC(".s")),
  164. _DECL_FUNC(sha3sum,-3, _SC(".is")),
  165. _DECL_FUNC(sha1sum,-2, _SC(".s")),
  166. _DECL_FUNC(md5sum,-2, _SC(".s")),
  167. {0,0}
  168. };
  169. #undef _DECL_FUNC
  170. #ifdef __cplusplus
  171. extern "C" {
  172. #endif
  173. /* This defines a function that opens up your library. */
  174. SQRESULT sqext_register_fossil (HSQUIRRELVM sqvm) {
  175. //add a namespace sqmix
  176. sq_pushstring(sqvm,_SC("sqfossil"),-1);
  177. sq_newclass(sqvm,SQFalse);
  178. sq_insert_reg_funcs(sqvm, fossil_obj_funcs);
  179. sq_newslot(sqvm,-3,SQTrue); //add sq_fossil table to the root table
  180. return SQ_OK;
  181. }
  182. #ifdef __cplusplus
  183. }
  184. #endif