Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

blobtoxy.c

Go to the documentation of this file.
00001 
00186 #ifdef STANDALONE
00187 #include <sqlite3.h>
00188 #else
00189 #include <sqlite3ext.h>
00190 static SQLITE_EXTENSION_INIT1
00191 #endif
00192 
00193 #include <stdlib.h>
00194 #include <string.h>
00195 #include <stdarg.h>
00196 #include <stdio.h>
00197 
00198 #ifdef _WIN32
00199 #define strcasecmp  _stricmp
00200 #define strncasecmp _strnicmp
00201 #define vsnprintf   _vsnprintf
00202 #endif
00203 
00204 #define TYPE_CODE(num, type) (((num) << 8) | (sizeof (type)))
00205 #define TYPE_SIZE(code)      ((code) & 0xFF)
00206 
00207 #define TYPE_CHAR      TYPE_CODE( 0, char)
00208 #define TYPE_UCHAR     TYPE_CODE( 1, char)
00209 #define TYPE_SHORT_LE  TYPE_CODE( 2, short)
00210 #define TYPE_USHORT_LE TYPE_CODE( 3, short)
00211 #define TYPE_SHORT_BE  TYPE_CODE( 4, short)
00212 #define TYPE_USHORT_BE TYPE_CODE( 5, short)
00213 #define TYPE_INT_LE    TYPE_CODE( 6, int)
00214 #define TYPE_UINT_LE   TYPE_CODE( 7, int)
00215 #define TYPE_INT_BE    TYPE_CODE( 8, int)
00216 #define TYPE_UINT_BE   TYPE_CODE( 9, int)
00217 #define TYPE_BIGINT_LE TYPE_CODE(10, sqlite_int64)
00218 #define TYPE_BIGINT_BE TYPE_CODE(11, sqlite_int64)
00219 #define TYPE_FLOAT     TYPE_CODE(12, float)
00220 #define TYPE_DOUBLE    TYPE_CODE(13, double)
00221 
00228 typedef struct b2xy_table {
00229     sqlite3_vtab base;          
00230     sqlite3 *db;                
00231     char *master_table;         
00232     char *fq_master_table;      
00233     char *key_column;           
00234     char *blob_column;          
00235     char *x_scale_column;       
00236     char *x_offset_column;      
00237     char *y_scale_column;       
00238     char *y_offset_column;      
00239     char *other_columns;        
00240     int type;                   
00241     int do_x_sl;                
00242     int x_start, x_length;      
00243     int argc;                   
00244     char **argv;                
00245 } b2xy_table;
00246 
00253 typedef struct b2xy_cursor {
00254     sqlite3_vtab_cursor base;   
00255     b2xy_table *table;          
00256     sqlite3_stmt *select;       
00257     sqlite3_value *key;         
00258     int fix_cols;               
00259     int num_cols;               
00260     char *val;                  
00261     int val_len;                
00262     int x_scale_col;            
00263     int x_offset_col;           
00264     double x_scale, x_offset;   
00265     int y_scale_col;            
00266     int y_offset_col;           
00267     double y_scale, y_offset;   
00268     int do_x_scale;             
00269     int do_y_scale;             
00270     int do_x_sl;                
00271     int x_start, x_length;      
00272     int type;                   
00273     int index;                  
00274     int rowid_from_key;         
00275     sqlite_int64 rowid;         
00276 } b2xy_cursor;
00277 
00284 static int
00285 string_to_type(const char *str)
00286 {
00287     if (strcasecmp(str, "char") == 0) {
00288         return TYPE_CHAR;
00289     }
00290     if (strcasecmp(str, "uchar") == 0) {
00291         return TYPE_UCHAR;
00292     }
00293     if (strcasecmp(str, "short_le") == 0) {
00294         return TYPE_SHORT_LE;
00295     }
00296     if (strcasecmp(str, "ushort_le") == 0) {
00297         return TYPE_USHORT_LE;
00298     }
00299     if (strcasecmp(str, "short_be") == 0) {
00300         return TYPE_SHORT_BE;
00301     }
00302     if (strcasecmp(str, "ushort_be") == 0) {
00303         return TYPE_USHORT_BE;
00304     }
00305     if (strcasecmp(str, "int_le") == 0) {
00306         return TYPE_INT_LE;
00307     }
00308     if (strcasecmp(str, "uint_le") == 0) {
00309         return TYPE_UINT_LE;
00310     }
00311     if (strcasecmp(str, "int_be") == 0) {
00312         return TYPE_INT_BE;
00313     }
00314     if (strcasecmp(str, "uint_be") == 0) {
00315         return TYPE_UINT_BE;
00316     }
00317     if (strcasecmp(str, "bigint_le") == 0) {
00318         return TYPE_BIGINT_LE;
00319     }
00320     if (strcasecmp(str, "bigint_be") == 0) {
00321         return TYPE_BIGINT_BE;
00322     }
00323     if (strcasecmp(str, "float") == 0) {
00324         return TYPE_FLOAT;
00325     }
00326     if (strcasecmp(str, "double") == 0) {
00327         return TYPE_DOUBLE;
00328     }
00329     return 0;
00330 }
00331 
00338 static int
00339 b2xy_destroy(sqlite3_vtab *vtab)
00340 {
00341     b2xy_table *bt = (b2xy_table *) vtab;
00342 
00343     sqlite3_free(bt);
00344     return SQLITE_OK;
00345 }
00346 
00375 static int
00376 b2xy_create(sqlite3 *db, void *userdata, int argc,
00377             const char * const *argv, sqlite3_vtab **vtabret, char **errp)
00378 {
00379     int rc = SQLITE_NOMEM;
00380     b2xy_table *bt;
00381     int i, size, type = TYPE_CHAR;
00382     int x_start = -1, x_length = 0;
00383 
00384     if (argc < 6) {
00385         *errp = sqlite3_mprintf("need at least 3 arguments");
00386         return SQLITE_ERROR;
00387     }
00388     if (argc > 6) {
00389         type = string_to_type(argv[6]);
00390         if (!type) {
00391             *errp = sqlite3_mprintf("unsupported type %Q", argv[6]);
00392             return SQLITE_ERROR;
00393         }
00394     }
00395     if (argc > 11) {
00396         if ((argv[11][0] != '"') && (argv[11][0] != '\'')) {
00397             *errp = sqlite3_mprintf("other columns must be quoted");
00398             return SQLITE_ERROR;
00399         }
00400     }
00401     if (argc > 12) {
00402         char *endp = 0;
00403 
00404         x_start = strtol(argv[12], &endp, 10);
00405         if ((endp == argv[12]) || (endp && (endp[0] != '\0'))) {
00406             *errp = sqlite3_mprintf("X start index must be integer");
00407             return SQLITE_ERROR;
00408         }
00409         if (x_start < 0) {
00410             *errp = sqlite3_mprintf("X start index must be >= 0");
00411             return SQLITE_ERROR;
00412         }
00413     }
00414     if (argc > 13) {
00415         char *endp = 0;
00416 
00417         x_length = strtol(argv[13], &endp, 10);
00418         if ((endp == argv[13]) || (endp && (endp[0] != '\0'))) {
00419             *errp = sqlite3_mprintf("X length must be integer");
00420             return SQLITE_ERROR;
00421         }
00422         if (x_length <= 0) {
00423             *errp = sqlite3_mprintf("X length must be > 0");
00424             return SQLITE_ERROR;
00425         }
00426     }
00427     size = sizeof (char *) * argc;
00428     for (i = 0; i < argc; i++) {
00429         size += argv[i] ? (strlen(argv[i]) + 1) : 0;
00430     }
00431     /* additional space for '"' + argv[1] '"."' + argv[3] + '"' */
00432     size += argv[1] ? (strlen(argv[1]) + 3) : 3;
00433     size += argv[3] ? (strlen(argv[3]) + 3) : 0;
00434     bt = sqlite3_malloc(sizeof (b2xy_table) + size);
00435     if (bt) {
00436         char *p, *key_type = 0, *x_type, *y_type, *other_types = 0;
00437 
00438         memset(bt, 0, sizeof (b2xy_table) + size);
00439         bt->db = db;
00440         bt->type = type;
00441         bt->x_start = x_start;
00442         bt->x_length = x_length;
00443         bt->do_x_sl = (x_start >= 0) || (x_length > 0);
00444         if (bt->x_start < 0) {
00445             bt->x_start = 0;
00446         }
00447         bt->argc = argc;
00448         bt->argv = (char **) (bt + 1);
00449         p = (char *) (bt->argv + argc);
00450         for (i = 0; i < argc; i++) {
00451             if (argv[i]) {
00452                 bt->argv[i] = p;
00453                 strcpy(p, argv[i]);
00454                 p += strlen(p) + 1;
00455             }
00456         }
00457         bt->master_table = bt->argv[3];
00458         bt->fq_master_table = p;
00459         p[0] = '\0';
00460         if (bt->argv[1]) {
00461             strcat(p, "\"");
00462             strcat(p, bt->argv[1]);
00463             strcat(p, "\".");
00464         }
00465         if (bt->argv[3]) {
00466             strcat(p, "\"");
00467             strcat(p, bt->argv[3]);
00468             strcat(p, "\"");
00469         }
00470         bt->key_column = bt->argv[4];
00471         bt->blob_column = bt->argv[5];
00472         if ((bt->argc > 7) && bt->argv[7][0]) {
00473             bt->x_scale_column = bt->argv[7];
00474             if (strcasecmp(bt->x_scale_column, "null") == 0) {
00475                 bt->x_scale_column = 0;
00476             }
00477         }
00478         if ((bt->argc > 8) && bt->argv[8][0]) {
00479             bt->x_offset_column = bt->argv[8];
00480             if (strcasecmp(bt->x_offset_column, "null") == 0) {
00481                 bt->x_offset_column = 0;
00482             }
00483         }
00484         if ((bt->argc > 9) && bt->argv[9][0]) {
00485             bt->y_scale_column = bt->argv[9];
00486             if (strcasecmp(bt->y_scale_column, "null") == 0) {
00487                 bt->y_scale_column = 0;
00488             }
00489         }
00490         if ((bt->argc > 10) && bt->argv[10][0]) {
00491             bt->y_offset_column = bt->argv[10];
00492             if (strcasecmp(bt->y_offset_column, "null") == 0) {
00493                 bt->y_offset_column = 0;
00494             }
00495         }
00496         if (bt->argc > 11) {
00497             p = bt->argv[11];
00498             p[0] = ',';
00499             bt->other_columns = p;
00500             p += strlen(p) - 1;
00501             if ((*p == '"') || (*p == '\'')) {
00502                 *p = '\0';
00503             }
00504         } else {
00505             bt->other_columns = "";
00506         }
00507         /* find out types of key and x/y columns */
00508         if (bt->x_scale_column || bt->x_offset_column ||
00509             (bt->type == TYPE_FLOAT) || (bt->type == TYPE_DOUBLE)) {
00510             x_type = " DOUBLE";
00511         } else {
00512             x_type = " INTEGER";
00513         }
00514         if (bt->y_scale_column || bt->y_offset_column ||
00515             (bt->type == TYPE_FLOAT) || (bt->type == TYPE_DOUBLE)) {
00516             y_type = " DOUBLE";
00517         } else {
00518             y_type = " INTEGER";
00519         }
00520         p = sqlite3_mprintf("PRAGMA %Q.table_info(%Q)",
00521                             bt->argv[1] ? bt->argv[1] : "MAIN",
00522                             bt->master_table);
00523         if (p) {
00524             int nrows = 0, ncols = 0;
00525             char **rows = 0;
00526 
00527             rc = sqlite3_get_table(db, p, &rows, &nrows, &ncols, 0);
00528             sqlite3_free(p);
00529             if (rc == SQLITE_OK) {
00530                 for (i = 1; (ncols >= 3) && (i <= nrows); i++) {
00531                     p = rows[i * ncols + 1];
00532                     if (p && (strcasecmp(bt->key_column, p) == 0)) {
00533                         key_type = sqlite3_mprintf(" %s", rows[i * ncols + 2]);
00534                         break;
00535                     }
00536                 }
00537             }
00538             if (rows) {
00539                 sqlite3_free_table(rows);
00540             }
00541         }
00542         /* find out types of other columns */
00543         p = 0;
00544         if (bt->other_columns[0]) {
00545             p = sqlite3_mprintf("SELECT %s FROM %s WHERE 0",
00546                                 bt->other_columns + 1, bt->fq_master_table);
00547         }
00548         if (p) {
00549             sqlite3_stmt *stmt = 0;
00550 
00551 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
00552             rc = sqlite3_prepare_v2(db, p, -1, &stmt, 0);
00553 #else
00554             rc = sqlite3_prepare(db, p, -1, &stmt, 0);
00555 #endif
00556             sqlite3_free(p);
00557             if ((rc == SQLITE_OK) && stmt) {
00558                 sqlite3_step(stmt);
00559                 for (i = 0; i < sqlite3_column_count(stmt); i++) {
00560                     p = sqlite3_mprintf("%s%s\"%s\" %s",
00561                                         other_types ? other_types : "",
00562                                         other_types ? "," : "",
00563                                         sqlite3_column_name(stmt, i),
00564                                         sqlite3_column_decltype(stmt, i));
00565                     sqlite3_free(other_types);
00566                     other_types = 0;
00567                     if (p) {
00568                         other_types = p;
00569                     } else {
00570                         break;
00571                     }
00572                 }
00573                 sqlite3_finalize(stmt);
00574                 if (other_types) {
00575                     p = sqlite3_mprintf(",%s", other_types);
00576                     sqlite3_free(other_types);
00577                     other_types = p;
00578                 }
00579             }
00580         }
00581         p = sqlite3_mprintf("CREATE TABLE \"%s\"(key%s CONSTRAINT fk "
00582                             "REFERENCES \"%s\"(\"%s\"),x%s,y%s%s)",
00583                             argv[2], key_type ? key_type : "",
00584                             bt->master_table, bt->key_column,
00585                             x_type, y_type,
00586                             other_types ? other_types : bt->other_columns);
00587         if (key_type) {
00588             sqlite3_free(key_type);
00589         }
00590         if (other_types) {
00591             sqlite3_free(other_types);
00592         }
00593         if (p) {
00594             rc = sqlite3_declare_vtab(db, p);
00595             sqlite3_free(p);
00596         }
00597         if (rc != SQLITE_OK) {
00598             b2xy_destroy((sqlite3_vtab *) bt);
00599             bt = 0;
00600         }
00601     }
00602     *vtabret = (sqlite3_vtab *) bt;
00603     return rc;
00604 }
00605 
00613 static int
00614 b2xy_open(sqlite3_vtab *vtab, sqlite3_vtab_cursor **curret)
00615 {
00616     int rc = SQLITE_NOMEM;
00617     b2xy_table *bt = (b2xy_table *) vtab;
00618     b2xy_cursor *bc;
00619 
00620     bc = sqlite3_malloc(sizeof (b2xy_cursor));
00621     if (bc) {
00622         memset(bc, 0, sizeof(b2xy_cursor));
00623         bc->table = bt;
00624         bc->type = bt->type;
00625         bc->do_x_sl = bt->do_x_sl;
00626         bc->x_start = bt->x_start;
00627         bc->x_length = bt->x_length;
00628         *curret = (sqlite3_vtab_cursor *) bc;
00629         rc = SQLITE_OK;
00630     }
00631     return rc;
00632 }
00633 
00640 static int
00641 b2xy_close(sqlite3_vtab_cursor *cur)
00642 {
00643     b2xy_cursor *bc = (b2xy_cursor *) cur;
00644 
00645     sqlite3_finalize(bc->select);
00646     sqlite3_free(bc);
00647     return SQLITE_OK;
00648 }
00649 
00658 static int
00659 b2xy_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
00660 {
00661     b2xy_cursor *bc = (b2xy_cursor *) cur;
00662     char *p;
00663     double v;
00664 
00665     switch (i) {
00666     case 0:
00667         sqlite3_result_value(ctx, bc->key);
00668         break;
00669     case 1:
00670         if (bc->do_x_scale) {
00671             v = bc->index * bc->x_scale + bc->x_offset;
00672             sqlite3_result_double(ctx, v);
00673         } else {
00674             sqlite3_result_int(ctx, bc->index);
00675         }
00676         break;
00677     case 2:
00678         if (!bc->val ||
00679             ((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len)) {
00680             goto put_null;
00681         }
00682         p = bc->val + bc->index * TYPE_SIZE(bc->type);
00683         switch (bc->type) {
00684         case TYPE_CHAR:
00685             if (bc->do_y_scale) {
00686                 v = p[0];
00687                 goto scale_it;
00688             }
00689             sqlite3_result_int(ctx, p[0]);
00690             break;
00691         case TYPE_UCHAR:
00692             if (bc->do_y_scale) {
00693                 v = p[0] & 0xFF;
00694                 goto scale_it;
00695             }
00696             sqlite3_result_int(ctx, p[0] & 0xFF);
00697             break;
00698         case TYPE_SHORT_LE:
00699             if (bc->do_y_scale) {
00700                 v = (p[0] & 0xFF) | (p[1] << 8);
00701                 goto scale_it;
00702             }
00703             sqlite3_result_int(ctx, (p[0] & 0xFF) | (p[1] << 8));
00704             break;
00705         case TYPE_USHORT_LE:
00706             if (bc->do_y_scale) {
00707                 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8);
00708                 goto scale_it;
00709             }
00710             sqlite3_result_int(ctx, (p[0] & 0xFF) | ((p[1] & 0xFF) << 8));
00711             break;
00712         case TYPE_SHORT_BE:
00713             if (bc->do_y_scale) {
00714                 v = (p[1] & 0xFF) | (p[0] << 8);
00715                 goto scale_it;
00716             }
00717             sqlite3_result_int(ctx, (p[1] & 0xFF) | (p[0] << 8));
00718             break;
00719         case TYPE_USHORT_BE:
00720             if (bc->do_y_scale) {
00721                 v = (p[1] & 0xFF) | ((p[0] & 0xFF) << 8);
00722                 goto scale_it;
00723             }
00724             sqlite3_result_int(ctx, (p[1] & 0xFF) | ((p[0] & 0xFF) << 8));
00725             break;
00726         case TYPE_INT_LE:
00727             if (bc->do_y_scale) {
00728                 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
00729                     ((p[2] & 0xFF) << 16) | (p[3] << 24);
00730                 goto scale_it;
00731             }
00732             sqlite3_result_int64(ctx,  (p[0] & 0xFF) |
00733                                  ((p[1] & 0xFF) << 8) |
00734                                  ((p[2] & 0xFF) << 16) |
00735                                  (p[3] << 24));
00736             break;
00737         case TYPE_UINT_LE:
00738             if (bc->do_y_scale) {
00739                 v = (p[0] & 0xFF) | ((p[1] & 0xFF) << 8) |
00740                     ((p[2] & 0xFF) << 16) | ((p[3] & 0xFF) << 24);
00741                 goto scale_it;
00742             }
00743             sqlite3_result_int64(ctx,  (p[0] & 0xFF) |
00744                                  ((p[1] & 0xFF) << 8) |
00745                                  ((p[2] & 0xFF) << 16) |
00746                                  ((p[3] & 0xFF) << 24));
00747             break;
00748         case TYPE_INT_BE:
00749             if (bc->do_y_scale) {
00750                 v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
00751                     ((p[1] & 0xFF) << 16) | (p[0] << 24);
00752                 goto scale_it;
00753             }
00754             sqlite3_result_int64(ctx,  (p[3] & 0xFF) |
00755                                  ((p[2] & 0xFF) << 8) |
00756                                  ((p[1] & 0xFF) << 16) |
00757                                  (p[0] << 24));
00758             break;
00759         case TYPE_UINT_BE:
00760             if (bc->do_y_scale) {
00761                 v = (p[3] & 0xFF) | ((p[2] & 0xFF) << 8) |
00762                     ((p[1] & 0xFF) << 16) | ((p[0] & 0xFF) << 24);
00763                 goto scale_it;
00764             }
00765             sqlite3_result_int64(ctx,  (p[3] & 0xFF) |
00766                                  ((p[2] & 0xFF) << 8) |
00767                                  ((p[1] & 0xFF) << 16) |
00768                                  ((p[0] & 0xFF) << 24));
00769             break;
00770         case TYPE_BIGINT_LE:
00771             if (bc->do_y_scale) {
00772                 v = (p[0] & 0xFFLL) | ((p[1] & 0xFFLL) << 8) |
00773                     ((p[2] & 0xFFLL) << 16) | ((p[3] & 0xFFLL) << 24) |
00774                     ((p[4] & 0xFFLL) << 32) | ((p[5] & 0xFFLL) << 40) |
00775                     ((p[6] & 0xFFLL) << 48) | ((p[6] & 0xFFLL) << 56);
00776                 goto scale_it;
00777             }
00778             sqlite3_result_int64(ctx,  (p[0] & 0xFFLL) |
00779                                  ((p[1] & 0xFFLL) << 8) |
00780                                  ((p[2] & 0xFFLL) << 16) |
00781                                  ((p[3] & 0xFFLL) << 24) |
00782                                  ((p[4] & 0xFFLL) << 32) |
00783                                  ((p[5] & 0xFFLL) << 40) |
00784                                  ((p[6] & 0xFFLL) << 48) |
00785                                  ((p[7] & 0xFFLL) << 56));
00786             break;
00787         case TYPE_BIGINT_BE:
00788             if (bc->do_y_scale) {
00789                 v = (p[7] & 0xFFLL) | ((p[6] & 0xFFLL) << 8) |
00790                     ((p[5] & 0xFFLL) << 16) | ((p[4] & 0xFFLL) << 24) |
00791                     ((p[3] & 0xFFLL) << 32) | ((p[2] & 0xFFLL) << 40) |
00792                     ((p[1] & 0xFFLL) << 48) | ((p[0] & 0xFFLL) << 56);
00793                 goto scale_it;
00794             }
00795             sqlite3_result_int64(ctx,  (p[7] & 0xFFLL) |
00796                                  ((p[6] & 0xFFLL) << 8) |
00797                                  ((p[5] & 0xFFLL) << 16) |
00798                                  ((p[4] & 0xFFLL) << 24) |
00799                                  ((p[3] & 0xFFLL) << 32) |
00800                                  ((p[2] & 0xFFLL) << 40) |
00801                                  ((p[1] & 0xFFLL) << 48) |
00802                                  ((p[0] & 0xFFLL) << 56));
00803             break;
00804         case TYPE_FLOAT:
00805             v = ((float *) p)[0];
00806             goto scale_it;
00807         case TYPE_DOUBLE:
00808             v = ((double *) p)[0];
00809             if (bc->do_y_scale) {
00810         scale_it:
00811                 v = v * bc->y_scale + bc->y_offset;
00812             }
00813             sqlite3_result_double(ctx, v);
00814             break;
00815         default:
00816         put_null:
00817             sqlite3_result_null(ctx);
00818             break;
00819         }
00820         break;
00821     default:
00822         i += bc->fix_cols - 3;
00823         if ((i < 0) || (i >= bc->num_cols)) {
00824             sqlite3_result_null(ctx);
00825         } else {
00826             sqlite3_result_value(ctx, sqlite3_column_value(bc->select, i));
00827         }
00828         break;
00829     }
00830     return SQLITE_OK;
00831 }
00832 
00840 static int
00841 b2xy_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *rowidp)
00842 {
00843     b2xy_cursor *bc = (b2xy_cursor *) cur;
00844 
00845     *rowidp = bc->rowid;
00846     return SQLITE_OK;
00847 }
00848 
00855 static int
00856 b2xy_eof(sqlite3_vtab_cursor *cur)
00857 {
00858     b2xy_cursor *bc = (b2xy_cursor *) cur;
00859 
00860     return bc->select ? 0 : 1;
00861 }
00862 
00869 static int
00870 b2xy_next(sqlite3_vtab_cursor *cur)
00871 {
00872     b2xy_cursor *bc = (b2xy_cursor *) cur;
00873     b2xy_table *bt = bc->table;
00874     int rc, dofetch = 0;
00875 
00876     if (!bc->select) {
00877         return SQLITE_OK;
00878     }
00879     if (bc->val) {
00880         bc->index += 1;
00881     }
00882     if (!bc->val) {
00883         dofetch = 1;
00884     } else if (bc->do_x_sl && bc->x_length) {
00885         if (bc->index >= bc->x_start + bc->x_length) {
00886             dofetch = 1;
00887         }
00888     } else if ((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len) {
00889         dofetch = 1;
00890     }
00891     if (dofetch) {
00892 refetch:
00893         rc = sqlite3_step(bc->select);
00894 
00895         if (rc == SQLITE_SCHEMA) {
00896             rc = sqlite3_step(bc->select);
00897         }
00898         if (rc != SQLITE_ROW) {
00899             sqlite3_finalize(bc->select);
00900             bc->select = 0;
00901             return SQLITE_OK;
00902         }
00903         bc->rowid_from_key = 0;
00904         bc->index = bc->x_start;
00905         bc->val = (char *) sqlite3_column_blob(bc->select, 1);
00906         bc->val_len = sqlite3_column_bytes(bc->select, 1);
00907         if (!bc->val) {
00908             if (bc->do_x_sl && bc->x_length) {
00909                 bc->val = (char *) sqlite3_column_text(bc->select, 1);
00910                 if (!bc->val) {
00911                     goto refetch;
00912                 }
00913             } else {
00914                 goto refetch;
00915             }
00916         }
00917         if (!(bc->do_x_sl && bc->x_length) &&
00918             (((bc->index + 1) * TYPE_SIZE(bc->type) > bc->val_len))) {
00919             goto refetch;
00920         }
00921         bc->key = sqlite3_column_value(bc->select, 0);
00922         if (sqlite3_column_type(bc->select, 0) == SQLITE_INTEGER) {
00923             bc->rowid_from_key = 1;
00924             bc->rowid = sqlite3_column_int64(bc->select, 0);
00925         }
00926         bc->do_x_scale = 0;
00927         bc->x_scale = 1.0;
00928         bc->x_offset = 0.0;
00929         if (bt->x_scale_column) {
00930             bc->x_scale = sqlite3_column_double(bc->select, bc->x_scale_col);
00931             bc->do_x_scale++;
00932         }
00933         if (bt->x_offset_column) {
00934             bc->x_offset = sqlite3_column_double(bc->select, bc->x_offset_col);
00935             bc->do_x_scale++;
00936         }
00937         bc->do_y_scale = 0;
00938         bc->y_scale = 1.0;
00939         bc->y_offset = 0.0;
00940         if (bt->y_scale_column) {
00941             bc->y_scale = sqlite3_column_double(bc->select, bc->y_scale_col);
00942             bc->do_y_scale++;
00943         }
00944         if (bt->y_offset_column) {
00945             bc->y_offset = sqlite3_column_double(bc->select, bc->y_offset_col);
00946             bc->do_y_scale++;
00947         }
00948     }
00949     if (!bc->rowid_from_key) {
00950         bc->rowid++;
00951     }
00952     return SQLITE_OK;
00953 }
00954 
00965 static int
00966 b2xy_filter(sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr,
00967             int argc, sqlite3_value **argv)
00968 {
00969     b2xy_cursor *bc = (b2xy_cursor *) cur;
00970     b2xy_table *bt = bc->table;
00971     char *query, *tmp, *op = 0;
00972     int rc;
00973 
00974     bc->rowid_from_key = 0;
00975     bc->rowid = 0;
00976     if (bc->select) {
00977         sqlite3_finalize(bc->select);
00978         bc->select = 0;
00979     }
00980     bc->fix_cols = 2;
00981     query = sqlite3_mprintf("select \"%s\",\"%s\"", bt->key_column,
00982                             bt->blob_column);
00983     if (!query) {
00984         return SQLITE_NOMEM;
00985     }
00986     if (bt->x_scale_column) {
00987         tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->x_scale_column);
00988         sqlite3_free(query);
00989         if (!tmp) {
00990             return SQLITE_NOMEM;
00991         }
00992         query = tmp;
00993         bc->x_scale_col = bc->fix_cols;
00994         bc->fix_cols++;
00995     }
00996     if (bt->x_offset_column) {
00997         tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->x_offset_column);
00998         sqlite3_free(query);
00999         if (!tmp) {
01000             return SQLITE_NOMEM;
01001         }
01002         query = tmp;
01003         bc->x_offset_col = bc->fix_cols;
01004         bc->fix_cols++;
01005     }
01006     if (bt->y_scale_column) {
01007         tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->y_scale_column);
01008         sqlite3_free(query);
01009         if (!tmp) {
01010             return SQLITE_NOMEM;
01011         }
01012         query = tmp;
01013         bc->y_scale_col = bc->fix_cols;
01014         bc->fix_cols++;
01015     }
01016     if (bt->y_offset_column) {
01017         tmp = sqlite3_mprintf("%s,\"%s\"", query, bt->y_offset_column);
01018         sqlite3_free(query);
01019         if (!tmp) {
01020             return SQLITE_NOMEM;
01021         }
01022         query = tmp;
01023         bc->y_offset_col = bc->fix_cols;
01024         bc->fix_cols++;
01025     }
01026     tmp = sqlite3_mprintf("%s%s from %s", query, bt->other_columns,
01027                           bt->fq_master_table);
01028     sqlite3_free(query);
01029     if (!tmp) {
01030         return SQLITE_NOMEM;
01031     }
01032     query = tmp;
01033     if (idxNum && (argc > 0)) {
01034         switch (idxNum) {
01035         case SQLITE_INDEX_CONSTRAINT_EQ:
01036             op = "=";
01037             break;
01038         case SQLITE_INDEX_CONSTRAINT_GT:
01039             op = ">";
01040             break;
01041         case SQLITE_INDEX_CONSTRAINT_LE:
01042             op = "<=";
01043             break;
01044         case SQLITE_INDEX_CONSTRAINT_LT:
01045             op = "<";
01046             break;
01047         case SQLITE_INDEX_CONSTRAINT_GE:
01048             op = ">=";
01049             break;
01050         case SQLITE_INDEX_CONSTRAINT_MATCH:
01051             op = "like";
01052             break;
01053         }
01054         if (op) {
01055             tmp = sqlite3_mprintf("%s where \"%s\" %s ?",
01056                                   query, bt->key_column, op);
01057             sqlite3_free(query);
01058             if (!tmp) {
01059                 return SQLITE_NOMEM;
01060             }
01061             query = tmp;
01062         }
01063     }
01064     if (idxStr) {
01065         tmp = sqlite3_mprintf("%s %s", query, idxStr);
01066         sqlite3_free(query);
01067         if (!tmp) {
01068             return SQLITE_NOMEM;
01069         }
01070         query = tmp;
01071     }
01072     bc->num_cols = bc->fix_cols;
01073 #if defined(HAVE_SQLITE3PREPAREV2) && HAVE_SQLITE3PREPAREV2
01074     rc = sqlite3_prepare_v2(bt->db, query, -1, &bc->select, 0);
01075 #else
01076     rc = sqlite3_prepare(bt->db, query, -1, &bc->select, 0);
01077     if (rc == SQLITE_SCHEMA) {
01078         rc = sqlite3_prepare(bt->db, query, -1, &bc->select, 0);
01079     }
01080 #endif
01081     sqlite3_free(query);
01082     if (rc == SQLITE_OK) {
01083         bc->num_cols = sqlite3_column_count(bc->select);
01084         if (op) {
01085             sqlite3_bind_value(bc->select, 1, argv[0]);
01086         }
01087     }
01088     return (rc == SQLITE_OK) ? b2xy_next(cur) : rc;
01089 }
01090 
01099 static int
01100 b2xy_bestindex(sqlite3_vtab *tab, sqlite3_index_info *info)
01101 {
01102     b2xy_table *bt = (b2xy_table *) tab;
01103     int i, key_order = 0, consumed = 0;
01104 
01105     /* preset to not using index */
01106     info->idxNum = 0;
01107 
01108     /*
01109      * Only when the key column of the master table
01110      * (0th column in virtual table) is used in a
01111      * constraint, a WHERE condition in the xFilter
01112      * function can be coded. This is indicated by
01113      * setting "idxNum" to the "op" value of that
01114      * constraint.
01115      */
01116     for (i = 0; i < info->nConstraint; ++i) {
01117         if (info->aConstraint[i].usable) {
01118             if ((info->aConstraint[i].iColumn == 0) &&
01119                 (info->aConstraint[i].op != 0)) {
01120                 info->idxNum = info->aConstraint[i].op;
01121                 info->aConstraintUsage[i].argvIndex = 1;
01122                 info->aConstraintUsage[i].omit = 1;
01123                 info->estimatedCost = 1.0;
01124                 break;
01125             }
01126         }
01127     }
01128 
01129     /*
01130      * ORDER BY can be optimized, when our X column
01131      * is not present or to be sorted ascending.
01132      * Additionally when the key column is to be sorted
01133      * an ORDER BY is sent to the xFilter function.
01134      */
01135     for (i = 0; i < info->nOrderBy; i++) {
01136         if (info->aOrderBy[i].iColumn == 0) {
01137             key_order = info->aOrderBy[i].desc ? -1 : 1;
01138             consumed++;
01139         } else if ((info->aOrderBy[i].iColumn == 1) &&
01140                    !info->aOrderBy[i].desc) {
01141             consumed++;
01142         }
01143     }
01144     if (consumed) {
01145         /* check for other ORDER BY columns */
01146         for (i = 0; i < info->nOrderBy; i++) {
01147             if ((info->aOrderBy[i].iColumn == 1) &&
01148                 info->aOrderBy[i].desc) {
01149                 consumed = 0;
01150             } else if (info->aOrderBy[i].iColumn > 1) {
01151                 consumed = 0;
01152             }
01153         }
01154     }
01155     if (consumed && key_order) {
01156         info->idxStr = sqlite3_mprintf("ORDER BY \"%s\" %s",
01157                                        bt->key_column,
01158                                        (key_order < 0) ? "DESC" : "ASC");
01159         info->needToFreeIdxStr = 1;
01160     }
01161     info->orderByConsumed = consumed;
01162     return SQLITE_OK;
01163 }
01164 
01165 #if (SQLITE_VERSION_NUMBER > 3004000)
01166 
01173 static int
01174 b2xy_rename(sqlite3_vtab *tab, const char *newname)
01175 {
01176     return SQLITE_OK;
01177 }
01178 
01179 #endif
01180 
01181 static const sqlite3_module b2xy_module = {
01182     1,              /* iVersion */
01183     b2xy_create,    /* xCreate */
01184     b2xy_create,    /* xConnect */
01185     b2xy_bestindex, /* xBestIndex */
01186     b2xy_destroy,   /* xDisconnect */
01187     b2xy_destroy,   /* xDestroy */
01188     b2xy_open,      /* xOpen */
01189     b2xy_close,     /* xClose */
01190     b2xy_filter,    /* xFilter */
01191     b2xy_next,      /* xNext */
01192     b2xy_eof,       /* xEof */
01193     b2xy_column,    /* xColumn */
01194     b2xy_rowid,     /* xRowid */
01195     0,              /* xUpdate */
01196     0,              /* xBegin */
01197     0,              /* xSync */
01198     0,              /* xCommit */
01199     0,              /* xRollback */
01200     0,              /* xFindFunction */
01201 #if (SQLITE_VERSION_NUMBER > 3004000)
01202     b2xy_rename,    /* xRename */
01203 #endif
01204 };
01205 
01212 typedef struct {
01213     int max;            
01214     int idx;            
01215     char *str;          
01216 } strbuf;
01217 
01224 static int
01225 init_strbuf(strbuf *sb)
01226 {
01227     int n = 1024;
01228 
01229     if ((sb->max <= 0) || !sb->str) {
01230         sb->str = sqlite3_malloc(n);
01231         if (!sb->str) {
01232             return SQLITE_NOMEM;
01233         }
01234         sb->max = n;
01235     }
01236     sb->idx = 0;
01237     return SQLITE_OK;
01238 }
01239 
01246 static int
01247 expand_strbuf(strbuf *sb)
01248 {
01249     int n;
01250     char *str;
01251 
01252     if ((sb->max <= 0) || !sb->str) {
01253         return init_strbuf(sb);
01254     }
01255     n = sb->max * 2;
01256     str = sqlite3_realloc(sb->str, n);
01257     if (!str) {
01258         return SQLITE_NOMEM;
01259     }
01260     sb->max = n;
01261     sb->str = str;
01262     return SQLITE_OK;
01263 }
01264 
01270 static void
01271 drop_strbuf(strbuf *sb)
01272 {
01273     if (sb->str) {
01274         sqlite3_free(sb->str);
01275         sb->str = 0;
01276     }
01277     sb->max = 0;
01278 }
01279 
01287 static int
01288 print_strbuf(strbuf *sb, const char *fmt, ...)
01289 {
01290     int i, n, rc;
01291     va_list ap;
01292 
01293     va_start(ap, fmt);
01294     for (i = 0; i < 2; i++) {
01295         if (sb->max - (sb->idx + 1) < 256) {
01296             rc = expand_strbuf(sb);
01297             if (rc != SQLITE_OK) {
01298                 goto done;
01299             }
01300         }
01301         rc = SQLITE_NOMEM;
01302         n = vsnprintf(sb->str + sb->idx, sb->max - sb->idx, fmt, ap);
01303         if ((n >= 0) && ((sb->idx + n) < (sb->max - 1))) {
01304             sb->idx += n;
01305             rc = SQLITE_OK;
01306             break;
01307         }
01308     }
01309 done:
01310     va_end(ap);
01311     return rc;
01312 }
01313 
01314 #define PATH_MODE_TK    ((void *) 0)
01315 #define PATH_MODE_SVG   ((void *) 1)
01316 #define PATH_MODE_BLT_X ((void *) 2)
01317 #define PATH_MODE_BLT_Y ((void *) 3)
01318 #define PATH_MODE_BLT   ((void *) 4)
01319 #define PATH_MODE_TK3D  ((void *) 5)
01320 
01340 static void
01341 common_path_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
01342 {
01343     void *mode = sqlite3_user_data(ctx);
01344     char *data;
01345     int i, linebreak, size, type = TYPE_CHAR;
01346     int do_x_scale = 0, do_y_scale = 0, do_z_scale = 0;
01347     double x_scale, x_offset, y_scale, y_offset, z0, z_scale, z_offset;
01348     strbuf sb;
01349 
01350     if (nargs < 1) {
01351         sqlite3_result_error(ctx, "need at least 1 argument", -1);
01352         return;
01353     }
01354     if (nargs > 1) {
01355         type = string_to_type((const char *) sqlite3_value_text(args[1]));
01356         if (!type) {
01357             sqlite3_result_error(ctx, "bad type name", -1);
01358             return;
01359         }
01360     }
01361     data = (char *) sqlite3_value_blob(args[0]);
01362     size = sqlite3_value_bytes(args[0]) / TYPE_SIZE(type);
01363     if (!data ||
01364         ((mode != PATH_MODE_BLT_X) && (mode != PATH_MODE_BLT_Y) &&
01365          (size < 2)) || (size < 1)) {
01366         goto nullorempty;
01367     }
01368     x_scale = 1;
01369     x_offset = 0;
01370     if (nargs > 2) {
01371         x_scale = sqlite3_value_double(args[2]);
01372         do_x_scale++;
01373     }
01374     if (nargs > 3) {
01375         x_offset = sqlite3_value_double(args[3]);
01376         do_x_scale++;
01377     }
01378     y_scale = 1;
01379     y_offset = 0;
01380     if (nargs > 4) {
01381         y_scale = sqlite3_value_double(args[4]);
01382         do_y_scale++;
01383     }
01384     if (nargs > 5) {
01385         y_offset = sqlite3_value_double(args[5]);
01386         do_y_scale++;
01387     }
01388     z0 = 0;
01389     z_scale = 1;
01390     z_offset = 0;
01391     if ((mode == PATH_MODE_TK3D) && (nargs > 6)) {
01392         z0 = sqlite3_value_double(args[6]);
01393     }
01394     if ((mode == PATH_MODE_TK3D) && (nargs > 7)) {
01395         z_scale = sqlite3_value_double(args[7]);
01396         do_z_scale++;
01397     }
01398     if ((mode == PATH_MODE_TK3D) && (nargs > 8)) {
01399         z_offset = sqlite3_value_double(args[8]);
01400         do_z_scale++;
01401     }
01402     memset(&sb, 0, sizeof (sb));
01403     if (init_strbuf(&sb) != SQLITE_OK) {
01404         goto nullorempty;
01405     }
01406     linebreak = 100;
01407     for (i = 0; i < size; i++, data += TYPE_SIZE(type)) {
01408         double x, y = 0, z = z0;
01409         char *fmt;
01410 
01411         if (do_z_scale) {
01412             z = z0 * z_scale + z_offset;
01413         }
01414         if (do_x_scale) {
01415             x = i * x_scale + x_offset;
01416         } else {
01417             x = i;
01418         }
01419         switch (type) {
01420         case TYPE_CHAR:
01421             y = data[0];
01422             break;
01423         case TYPE_UCHAR:
01424             y = data[0] & 0xFF;
01425             break;
01426         case TYPE_SHORT_LE:
01427             y = (data[0] & 0xFF) | (data[1] << 8);
01428             break;
01429         case TYPE_USHORT_LE:
01430             y = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8);
01431             break;
01432         case TYPE_SHORT_BE:
01433             y = (data[1] & 0xFF) | (data[0] << 8);
01434             break;
01435         case TYPE_USHORT_BE:
01436             y = (data[1] & 0xFF) | ((data[0] & 0xFF) << 8);
01437             break;
01438         case TYPE_INT_LE:
01439             y =  (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
01440                 ((data[2] & 0xFF) << 16) | (data[3] << 24);
01441             break;
01442         case TYPE_UINT_LE:
01443             y =  (data[0] & 0xFF) | ((data[1] & 0xFF) << 8) |
01444                 ((data[2] & 0xFF) << 16) | ((data[3] & 0xFF) << 24);
01445             break;
01446         case TYPE_INT_BE:
01447             y =  (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
01448                 ((data[1] & 0xFF) << 16) | (data[0] << 24);
01449             break;
01450         case TYPE_UINT_BE:
01451             y =  (data[3] & 0xFF) | ((data[2] & 0xFF) << 8) |
01452                 ((data[1] & 0xFF) << 16) | ((data[0] & 0xFF) << 24);
01453             break;
01454         case TYPE_FLOAT:
01455             y = ((float *) data)[0];
01456             break;
01457         case TYPE_DOUBLE:
01458             y = ((double *) data)[0];
01459             break;
01460         }
01461         if (do_y_scale) {
01462             y = y * y_scale + y_offset;
01463         }
01464         if ((mode == PATH_MODE_BLT_X) || (mode == PATH_MODE_BLT_Y)) {
01465             double v = (mode == PATH_MODE_BLT_X) ? x : y;
01466 
01467             if (print_strbuf(&sb, (i == 0) ? "%g" : " %g", v) != SQLITE_OK) {
01468                 drop_strbuf(&sb);
01469                 break;
01470             }
01471             continue;
01472         }
01473         if ((mode == PATH_MODE_SVG) && (i == 0)) {
01474             fmt = "M %g %g";
01475         } else if ((mode == PATH_MODE_SVG) && (i == 1)) {
01476             fmt = " L %g %g";
01477         } else if ((mode == PATH_MODE_SVG) && (sb.idx >= linebreak)) {
01478             fmt = "\nL %g %g";
01479             linebreak = sb.idx + 100;
01480         } else if (i == 0) {
01481             fmt = (mode == PATH_MODE_TK3D) ? "%g %g %g" : "%g %g";
01482         } else {
01483             fmt = (mode == PATH_MODE_TK3D) ? " %g %g %g" : " %g %g";
01484         }
01485         if (print_strbuf(&sb, fmt, x, y, z) != SQLITE_OK) {
01486             drop_strbuf(&sb);
01487             break;
01488         }
01489     }
01490     if (sb.str) {
01491         sqlite3_result_text(ctx, sb.str, sb.idx, sqlite3_free);
01492         sb.str = 0;
01493         return;
01494     }
01495 nullorempty:
01496     if ((mode == PATH_MODE_BLT_X) || (mode == PATH_MODE_BLT_Y)) {
01497         sqlite3_result_text(ctx, "", 0, SQLITE_STATIC);
01498     } else {
01499         sqlite3_result_null(ctx);
01500     }
01501 }
01502 
01509 typedef struct {
01510     int init;           
01511     int count;          
01512     int linebreak;      
01513     void *mode;         
01514     strbuf sb;          
01515 } path_aggctx;
01516 
01537 static void
01538 common_path_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
01539 {
01540     path_aggctx *pag;
01541     int type;
01542     char *fmt;
01543     double x, y, z = 0;
01544     double x_scale, y_scale, x_offset, y_offset, z_scale, z_offset;
01545 
01546     if (nargs < 2) {
01547         return;
01548     }
01549     pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
01550     if (!pag->init) {
01551         if (init_strbuf(&pag->sb) != SQLITE_OK) {
01552             return;
01553         }
01554         pag->linebreak = 100;
01555         pag->count = 0;
01556         pag->mode = sqlite3_user_data(ctx);
01557         pag->init = 1;
01558     }
01559     type = sqlite3_value_type(args[0]);
01560     if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
01561         return;
01562     }
01563     type = sqlite3_value_type(args[1]);
01564     if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
01565         return;
01566     }
01567     x = sqlite3_value_double(args[0]);
01568     y = sqlite3_value_double(args[1]);
01569     x_scale = 1;
01570     x_offset = 0;
01571     if (nargs > 2) {
01572         type = sqlite3_value_type(args[2]);
01573         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01574             x_scale = sqlite3_value_double(args[2]);
01575         }
01576     }
01577     if (nargs > 3) {
01578         type = sqlite3_value_type(args[3]);
01579         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01580             x_offset = sqlite3_value_double(args[3]);
01581         }
01582     }
01583     y_scale = 1;
01584     y_offset = 0;
01585     if (nargs > 4) {
01586         type = sqlite3_value_type(args[4]);
01587         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01588             y_scale = sqlite3_value_double(args[4]);
01589         }
01590     }
01591     if (nargs > 5) {
01592         type = sqlite3_value_type(args[5]);
01593         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01594             y_offset = sqlite3_value_double(args[5]);
01595         }
01596     }
01597     z_scale = 1;
01598     z_offset = 0;
01599     if ((pag->mode == PATH_MODE_TK3D) && (nargs > 6)) {
01600         z = sqlite3_value_double(args[6]);
01601         if (nargs > 7) {
01602             type = sqlite3_value_type(args[7]);
01603             if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01604                 z_scale = sqlite3_value_double(args[7]);
01605             }
01606         }
01607         if (nargs > 8) {
01608             type = sqlite3_value_type(args[8]);
01609             if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01610                 z_offset = sqlite3_value_double(args[8]);
01611             }
01612         }
01613         z = z * z_scale + z_offset;
01614     }
01615     x = x * x_scale + x_offset;
01616     y = y * y_scale + y_offset;
01617     if ((pag->mode == PATH_MODE_SVG) && (pag->count == 0)) {
01618         fmt = "M %g %g";
01619     } else if ((pag->mode == PATH_MODE_SVG) && (pag->count == 1)) {
01620         fmt = " L %g %g";
01621     } else if ((pag->mode == PATH_MODE_SVG) &&
01622                (pag->sb.idx >= pag->linebreak)) {
01623         fmt = "\nL %g %g";
01624         pag->linebreak = pag->sb.idx + 100;
01625     } else if (pag->count == 0) {
01626         fmt = (pag->mode == PATH_MODE_TK3D) ? "%g %g %g" : "%g %g";
01627     } else {
01628         fmt = (pag->mode == PATH_MODE_TK3D) ? " %g %g %g" : " %g %g";
01629     }
01630     if (print_strbuf(&pag->sb, fmt, x, y, z) != SQLITE_OK) {
01631         drop_strbuf(&pag->sb);
01632         pag->init = 0;
01633     } else {
01634         pag->count++;
01635     }
01636 }
01637 
01643 static void
01644 common_path_finalize(sqlite3_context *ctx)
01645 {
01646     path_aggctx *pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
01647 
01648     if (pag->init) {
01649         if ((pag->count > 1) || (pag->mode == PATH_MODE_BLT)) {
01650             sqlite3_result_text(ctx, pag->sb.str, pag->sb.idx, sqlite3_free);
01651             pag->sb.str = 0;
01652             pag->init = 0;
01653             return;
01654         }
01655         drop_strbuf(&pag->sb);
01656     }
01657     if (pag->mode == PATH_MODE_BLT) {
01658         sqlite3_result_text(ctx, "", 0, SQLITE_STATIC);
01659     } else {
01660         sqlite3_result_null(ctx);
01661     }
01662 }
01663 
01677 static void
01678 blt_vec_step(sqlite3_context *ctx, int nargs, sqlite3_value **args)
01679 {
01680     path_aggctx *pag;
01681     int type;
01682     double v, scale, offset;
01683 
01684     if (nargs < 1) {
01685         return;
01686     }
01687     pag = sqlite3_aggregate_context(ctx, sizeof (*pag));
01688     if (!pag->init) {
01689         if (init_strbuf(&pag->sb) != SQLITE_OK) {
01690             return;
01691         }
01692         pag->count = 0;
01693         pag->mode = PATH_MODE_BLT;
01694         pag->init = 1;
01695     }
01696     type = sqlite3_value_type(args[0]);
01697     if ((type != SQLITE_INTEGER) && (type != SQLITE_FLOAT)) {
01698         return;
01699     }
01700     v = sqlite3_value_double(args[0]);
01701     scale = 1;
01702     offset = 0;
01703     if (nargs > 1) {
01704         type = sqlite3_value_type(args[1]);
01705         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01706             scale = sqlite3_value_double(args[2]);
01707         }
01708     }
01709     if (nargs > 2) {
01710         type = sqlite3_value_type(args[2]);
01711         if ((type == SQLITE_INTEGER) || (type == SQLITE_FLOAT)) {
01712             offset = sqlite3_value_double(args[3]);
01713         }
01714     }
01715     v = v * scale + offset;
01716     if (print_strbuf(&pag->sb, (pag->count == 0) ? "%g" : " %g", v)
01717         != SQLITE_OK) {
01718         drop_strbuf(&pag->sb);
01719         pag->init = 0;
01720     } else {
01721         pag->count++;
01722     }
01723 }
01724 
01732 static void
01733 subblob_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
01734 {
01735     int insize, outsize, start, itemsize = 1, itemskip = 0;
01736     int i, k, n;
01737     char *indata, *outdata;
01738 
01739     if (nargs < 3) {
01740         sqlite3_result_error(ctx, "need at least 1 argument", -1);
01741         return;
01742     }
01743     indata = (char *) sqlite3_value_blob(args[0]);
01744     insize = sqlite3_value_bytes(args[0]);
01745     if (!indata || (insize <= 0)) {
01746 isnull:
01747         sqlite3_result_null(ctx);
01748         return;
01749     }
01750     start = sqlite3_value_int(args[1]);
01751     if (start < 0) {
01752         start = insize - start;
01753         if (start < 0) {
01754             start = 0;
01755         }
01756     } else if (start > 0) {
01757         start--;
01758     }
01759     if (start >= insize) {
01760         goto isnull;
01761     }
01762     outsize = sqlite3_value_int(args[2]);
01763     if (outsize > insize - start) {
01764         outsize = insize - start;
01765     }
01766     if (outsize <= 0) {
01767         goto isnull;
01768     }
01769     if (nargs > 3) {
01770         itemsize = sqlite3_value_int(args[3]);
01771         if ((itemsize <= 0) || (itemsize > outsize)) {
01772             goto isnull;
01773         }
01774     }
01775     if (nargs > 4) {
01776         itemskip = sqlite3_value_int(args[4]);
01777         if (itemskip < 0) {
01778             goto isnull;
01779         }
01780     }
01781     outdata = sqlite3_malloc(outsize);
01782     if (!outdata) {
01783         sqlite3_result_error(ctx, "out of memory", -1);
01784         return;
01785     }
01786     for (i = n = 0; i < outsize; i++) {
01787         for (k = 0; k < itemsize; k++) {
01788             outdata[i + k] = indata[start];
01789             n++;
01790             start++;
01791             if (start >= insize) {
01792                 break;
01793             }
01794         }
01795         start += itemskip;
01796         if (start >= insize) {
01797             break;
01798         }
01799     }
01800     if (n > 0) {
01801         sqlite3_result_blob(ctx, outdata, n, sqlite3_free);
01802         return;
01803     }
01804     sqlite3_result_null(ctx);
01805     sqlite3_free(outdata);
01806 }
01807 
01814 typedef struct {
01815     sqlite3_context *ctx;       
01816     sqlite3_value *value;       
01817     sqlite_int64 count;         
01818 } rownumber_ctx;
01819 
01827 static void
01828 rownumber_func(sqlite3_context *ctx, int nargs, sqlite3_value **args)
01829 {
01830     rownumber_ctx *rn = sqlite3_get_auxdata(ctx, 0);
01831 
01832     if (!rn || (rn->ctx != ctx) || (rn->value != args[0])) {
01833         rn = sqlite3_malloc(sizeof (*rn));
01834         if (rn) {
01835             rn->ctx = ctx;
01836             rn->value = args[0];
01837             rn->count = 0;
01838         }
01839         sqlite3_set_auxdata(ctx, 0, rn, sqlite3_free);
01840     } else {
01841         rn->count++;
01842     }
01843     sqlite3_result_int64(ctx, rn ? rn->count : 0);
01844 }
01845 
01853 #ifndef STANDALONE
01854 static
01855 #endif
01856 int
01857 b2xy_init(sqlite3 *db)
01858 {
01859     sqlite3_create_function(db, "subblob", -1, SQLITE_ANY, (void *) 0,
01860                             subblob_func, 0, 0);
01861     sqlite3_create_function(db, "tk_path_from_blob", -1, SQLITE_UTF8,
01862                             PATH_MODE_TK, common_path_func, 0, 0);
01863     sqlite3_create_function(db, "svg_path_from_blob", -1, SQLITE_UTF8,
01864                             PATH_MODE_SVG, common_path_func, 0, 0);
01865     sqlite3_create_function(db, "blt_vec_x", -1, SQLITE_UTF8,
01866                             PATH_MODE_BLT_X, common_path_func, 0, 0);
01867     sqlite3_create_function(db, "blt_vec_y", -1, SQLITE_UTF8,
01868                             PATH_MODE_BLT_Y, common_path_func, 0, 0);
01869     sqlite3_create_function(db, "tk3d_path_from_blob", -1, SQLITE_UTF8,
01870                             PATH_MODE_TK3D, common_path_func, 0, 0);
01871     sqlite3_create_function(db, "tk_path", -1, SQLITE_ANY, PATH_MODE_TK,
01872                             0, common_path_step, common_path_finalize);
01873     sqlite3_create_function(db, "svg_path", -1, SQLITE_ANY, PATH_MODE_SVG,
01874                             0, common_path_step, common_path_finalize);
01875     sqlite3_create_function(db, "blt_vec", -1, SQLITE_ANY, PATH_MODE_BLT,
01876                             0, blt_vec_step, common_path_finalize);
01877     sqlite3_create_function(db, "tk3d_path", -1, SQLITE_ANY, PATH_MODE_TK3D,
01878                             0, common_path_step, common_path_finalize);
01879     sqlite3_create_function(db, "rownumber", 1, SQLITE_ANY, 0,
01880                             rownumber_func, 0, 0);
01881     return sqlite3_create_module(db, "blobtoxy", &b2xy_module, 0);
01882 }
01883 
01884 #ifndef STANDALONE
01885 
01894 int
01895 sqlite3_extension_init(sqlite3 *db, char **errmsg,
01896                        const sqlite3_api_routines *api)
01897 {
01898     SQLITE_EXTENSION_INIT2(api);
01899     return b2xy_init(db);
01900 }
01901 
01902 #endif
01903 
01904 /*
01905  * Local Variables:
01906  * mode: c
01907  * c-basic-offset: 4
01908  * fill-column: 78
01909  * tab-width: 8
01910  * End:
01911  */

Generated on 23 Oct 2023 by doxygen.
Contact: chw@ch-werner.de