📄 blob.mx
字号:
@' The contents of this file are subject to the MonetDB Public License@' Version 1.1 (the "License"); you may not use this file except in@' compliance with the License. You may obtain a copy of the License at@' http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html@'@' Software distributed under the License is distributed on an "AS IS"@' basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the@' License for the specific language governing rights and limitations@' under the License.@'@' The Original Code is the MonetDB Database System.@'@' The Initial Developer of the Original Code is CWI.@' Portions created by CWI are Copyright (C) 1997-2007 CWI.@' All Rights Reserved.@f blob@v 1.0@a Wilko Quak, Peter Boncz, M. Kersten, N. Nes@+ The blob data typeThe datatype 'blob' introduced here illustrates the powerin the hands of a programmer to extend the functionality of theMonet GDK library. It consists of an interface specification forthe necessary operators, a startup routine to register thetype in thekernel, and some additional operators used outsidethe kernel itself.The 'blob' data type is used in many database engines tostore a variable sized atomary value. Its definition forms a generic base to store arbitrary structuresin the database, without knowing its internal coding, layout,or interpretation. The blob memory layout consists of first 4 bytes containing the bytes-size of the blob (excluding the integer), and then just binary data.@+ Module Definition@malmodule blob;atom blob;command tostr() address BLOBtostr;command fromstr() address BLOBfromstr;command nequal() address BLOBnequal;command hash() address BLOBhash;command null() address BLOBnull;command read() address BLOBread;command write() address BLOBwrite;command convert() address BLOBconvert;command put() address BLOBput;command del() address BLOBdel;command length() address BLOBlength;command heap() address BLOBheap;command blob(s:blob):blobaddress BLOBblob_blobcomment "Noop routine.";command blob(s:str):blobaddress BLOBblob_fromstr;@+ string functionsManipulation functions to extract strings from blobs and vice versa.Not to be confused with blob parsing and printing.@malcommand tostring(v:blob) :str address BLOBfromblobcomment "get the bytes from blob as a string, till the first 0 byte or the end of the blob";command tostring(v:blob, index:int ) :str address BLOBfromidxcomment "get the bytes from blob as a string, starting at byte 'index' till the first 0 byte or the end of the blob.";command toblob(v:str) :blob address BLOBtoblobcomment "store a string as a blob.";command nitems(b:blob):int address BLOBnitemscomment " get the number of bytes in this blob.";atom sqlblob:blob;command tostr() address SQLBLOBtostr;command fromstr() address SQLBLOBfromstr;command sqlblob(s:sqlblob):sqlblobaddress BLOBblob_blobcomment "Noop routine.";command sqlblob(s:str):sqlblobaddress BLOBsqlblob_fromstr;module blob;command prelude() :voidaddress BLOBprelude;blob.prelude();module calc;command blob(b:blob):blob address BLOBblob_blob;command blob(s:str):blob address BLOBblob_fromstr;command sqlblob(b:sqlblob):sqlblob address BLOBblob_blob;command sqlblob(s:str):sqlblob address BLOBsqlblob_fromstr;@{@* Example MAL ScriptThe following test should be moved to the test section.@mil#import blob;#v1 := setoid(oid(20000000));bl := "(5:11 FC E2 A0 0A)":blob;err:= print(bl);b2 := blob.toblob("Hello World");err:= print(b2);v1 := blob.tostring(b2);err:= print(v1);@* Implementation Code@h#ifndef __BLOB_H__#define __BLOB_H__#include "mal.h"#include "mal_exception.h"typedef struct blob { size_t nitems; /*unsigned */ char data[1];} blob;#define sqlblob blob#ifdef WIN32#ifndef LIBBLOB#define blob_export extern __declspec(dllimport)#else#define blob_export extern __declspec(dllexport)#endif#else#define blob_export extern#endifblob_export int TYPE_blob;blob_export int TYPE_sqlblob;blob_export size_t blobsize(size_t nitems);blob_export int sqlblob_tostr(str *tostr, int *l, blob *p);blob_export int sqlblob_fromstr(char *instr, int *l, blob **val);#endif /* __BLOB_H__ */@c#include "mal_config.h"#include "blob.h"int TYPE_blob;int TYPE_sqlblob;blob_export str BLOBprelude(void);blob_export int BLOBtostr(str *tostr, int *l, blob *pin);blob_export int BLOBfromstr(char *instr, int *l, blob **val);blob_export int BLOBnequal(blob *l, blob *r);blob_export hash_t BLOBhash(blob *b);blob_export blob * BLOBnull(void);blob_export void BLOBconvert(blob *b, int direction);blob_export var_t BLOBput(Heap *h, var_t *bun, blob *val);blob_export void BLOBdel(Heap *h, var_t *index);blob_export int BLOBlength(blob *p);blob_export void BLOBheap(Heap *heap, size_t capacity);blob_export int SQLBLOBfromstr(char *instr, int *l, blob **val);blob_export int SQLBLOBtostr(str *tostr, int *l, blob *pin);blob_export str BLOBtoblob(blob **retval, str *s);blob_export str BLOBfromblob(str *retval, blob **b);blob_export str BLOBfromidx(str *retval, blob **binp, int *index);blob_export str BLOBeoln(char *src, char *end);blob_export int BLOBnitems(int *ret, blob *b);blob_export int BLOBget(Heap *h, int *bun, int *l, blob **val);blob_export blob * BLOBread(blob *a, stream *s, size_t cnt);blob_export void BLOBwrite(blob *a, stream *s, size_t cnt);blob_export str BLOBblob_blob(blob **d, blob *s);blob_export str BLOBblob_fromstr(blob **b, str *d);blob_export str BLOBsqlblob_fromstr(sqlblob **b, str *d);str BLOBprelude(void){ TYPE_blob = ATOMindex("blob"); TYPE_sqlblob = ATOMindex("sqlblob"); return MAL_SUCCEED;}size_tblobsize(size_t nitems){ if (nitems == ~(size_t) 0) nitems = 0; return (sizeof(size_t) + nitems);}var_tblob_put(Heap *h, var_t *bun, blob *val){ char *base; *bun = HEAP_malloc(h, blobsize(val->nitems)); base = h->base; if (*bun) memcpy(&base[*bun], (char *) val, blobsize(val->nitems)); return *bun;}#if 0intblob_get(Heap *h, int *bun, int *l, blob **val){ blob *from = HEAP_index(h, *bun, blob); size_t size = blobsize(from->nitems); if (*val == NULL) { *val = (blob *) GDKmalloc(size); *l = size; } else if (*l < size) { GDKfree(*val); *val = (blob *) GDKmalloc(size); *l = size; } memcpy(*val, from, size); return (size);}#endifintblob_nequal(blob *l, blob *r){ size_t len = l->nitems; if (len != r->nitems) return (1); if (len == ~(size_t) 0) return (0); return memcmp(l->data, r->data, len) != 0;}voidblob_del(Heap *h, var_t *index){ HEAP_free(h, *index);}hash_tblob_hash(blob *b){ return (hash_t) b->nitems;}blob *blob_null(void){ static blob nullval; nullval.nitems = ~(size_t) 0; return (&nullval);}blob *blob_read(blob *a, stream *s, size_t cnt){ int len; (void) cnt; assert(cnt == 1); if (!stream_readInt(s, &len)) return NULL; if ((a = GDKmalloc(len)) == NULL) return NULL; if (stream_read(s, (char *) a, len, 1) != 1) { GDKfree(a); return NULL; } return a;}voidblob_write(blob *a, stream *s, size_t cnt){ size_t len = blobsize(a->nitems); (void) cnt; assert(cnt == 1); if (stream_writeInt(s, (int) len)) /* 64bit: check for overflow */ stream_write(s, (char *) a, len, 1);}voidblob_convert(blob *b, int direction){ (void) direction; b->nitems = normal_vart_SWAP(b->nitems);}intblob_length(blob *p){ return blobsize(p->nitems); /* 64bit: check for overflow */}voidblob_heap(Heap *heap, size_t capacity){ HEAP_initialize(heap, capacity, 0, (int) sizeof(var_t));}#ifndef OLDSTYLEstatic char hexit[] = "0123456789ABCDEF";intblob_tostr(str *tostr, int *l, blob *p){ char *s; size_t i; size_t expectedlen; if (p->nitems == ~(size_t) 0) expectedlen = 4; else expectedlen = 24 + (p->nitems * 3); if (*l < 0 || (size_t) * l < expectedlen) { if (*tostr != NULL) GDKfree(*tostr); *tostr = (str) GDKmalloc(expectedlen); *l = (int) expectedlen; } if (p->nitems == ~(size_t) 0) { strcpy(*tostr, "nil"); return 3; } sprintf(*tostr, "(" SZFMT ":", p->nitems); s = *tostr + strlen(*tostr); for (i = 0; i < p->nitems; i++) { int val = (p->data[i] >> 4) & 15; *s++ = ' '; *s++ = hexit[val]; val = p->data[i] & 15; *s++ = hexit[val]; } *s++ = ')'; *s = '\0'; return (int) (s - *tostr); /* 64bit: check for overflow */}/* SQL 99 compatible BLOB output string * differs from the MonetDB BLOB output in that it does not start with a size * no brackets and no spaces in between the hexits */intsqlblob_tostr(str *tostr, int *l, blob *p){ char *s; size_t i; size_t expectedlen; if (p->nitems == ~(size_t) 0) expectedlen = 4; else expectedlen = 24 + (p->nitems * 3); if (*l < 0 || (size_t) * l < expectedlen) { if (*tostr != NULL) GDKfree(*tostr); *tostr = (str) GDKmalloc(expectedlen); *l = (int) expectedlen; } if (p->nitems == ~(size_t) 0) { strcpy(*tostr, "nil"); return 3; } strcpy(*tostr, "\0"); s = *tostr; for (i = 0; i < p->nitems; i++) { int val = (p->data[i] >> 4) & 15; *s++ = hexit[val]; val = p->data[i] & 15; *s++ = hexit[val]; } *s = '\0'; return (int) (s - *tostr); /* 64bit: check for overflow */}intblob_fromstr(char *instr, int *l, blob **val){ size_t i; size_t nitems; size_t nbytes; blob *result; char *s = instr; s = strchr(s, '('); if (s == NULL) { GDKwarning("Missing ( in blob\n"); *val = (blob *) NULL; return (0); } nitems = (size_t) strtoul(s + 1, &s, 10); if (s == NULL) { GDKwarning("Missing nitems in blob\n"); *val = (blob *) NULL; return (0); }#if SIZEOF_SIZE_T > SIZEOF_INT if (nitems > 0x7fffffff) { GDKwarning("Blob too large\n"); *val = (blob *) NULL; return (0); }#endif nbytes = blobsize(nitems); s = strchr(s, ':'); if (s == NULL) { GDKwarning("Missing ':' in blob\n"); *val = (blob *) NULL; return (0); } ++s; if (*val == (blob *) NULL) { *val = (blob *) GDKmalloc(nbytes); *l = (int) nbytes; } else if (*l < 0 || (size_t) * l < nbytes) { GDKfree(*val); *val = (blob *) GDKmalloc(nbytes); *l = (int) nbytes; } result = *val; result->nitems = nitems; /* // Read the values of the blob. */ for (i = 0; i < nitems; ++i) { char res = 0; if (*s == ' ') s++; if (*s >= '0' && *s <= '9') { res = *s - '0'; } else if (*s >= 'A' && *s <= 'F') { res = 10 + *s - 'A'; } else if (*s >= 'a' && *s <= 'f') { res = 10 + *s - 'a'; } else { break; } s++; res <<= 4; if (*s >= '0' && *s <= '9') { res += *s - '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -