Back to index

lightning-sunbird  0.9+nobinonly
query.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 
00040 
00041 #include "rdf-int.h"
00042 
00043 #define SEP '|'
00044 
00045 typedef struct _QuerySegmentStruct {
00046     RDF_Resource s;
00047     int          num;
00048     int          inversep;
00049 } QuerySegmentStruct;
00050 
00051 typedef QuerySegmentStruct* QuerySegment;
00052 
00053 QuerySegment*
00054 parseQuery (char* query, RDF_Resource *root, int *numSegments) {
00055     int len = strlen(query);
00056     int count ;
00057     char* rootURL = getMem(100);
00058     QuerySegment* ans;
00059        *numSegments = 0;
00060     for (count = 0; count < len; count++) {
00061        if (query[count] != SEP) {
00062            if (!*numSegments) rootURL[count] = query[count];
00063        } else 
00064            (*numSegments)++;
00065     }
00066     *root = getResource(rootURL, 1);
00067     freeMem(rootURL);
00068     ans =  (QuerySegment*)getMem(*numSegments * (sizeof(QuerySegment)));
00069     query = strchr(query, SEP)+1;
00070     for (count = 0; count < *numSegments; count++) {
00071       char *surl = getMem(100);
00072       int num = -1; 
00073       char* nquery = strchr(query, SEP) ;
00074       QuerySegment nq = (QuerySegment)getMem(sizeof(QuerySegmentStruct));
00075       if (query[0] == '!') {
00076               memcpy(surl, query+1, (nquery ? nquery-query-1 : strlen(query)-1));
00077            nq->inversep = 1;
00078       } else {
00079            memcpy(surl, query, (nquery ? nquery-query : strlen(query)));
00080       }
00081       if (strchr(surl, '[') && strchr(surl, ']')) {
00082                 int n = strchr(surl, '[') - surl;
00083                 surl[n] = '\0';
00084                 sscanf(&surl[n+1], "%i]", &num);
00085                 if (num == -1) num = 4096;
00086           nq->s = getResource(surl, 1);
00087           nq->num = num;
00088       } else {
00089         nq->s = getResource(surl, 1);
00090         nq->num = 4096;
00091       } 
00092       freeMem(surl);
00093       ans[count] = nq;
00094       if (nquery) {
00095         query = nquery+1;
00096       } else break;
00097     }
00098     return ans;
00099 }
00100 
00101 char**
00102 processRDFQuery (char* query) {
00103     RDF_Resource root;
00104     int          numSegments;
00105     int count = 0;
00106     char** ans = NULL;
00107     QuerySegment* querySegments = parseQuery(query, &root, &numSegments);
00108     int          n = 0;
00109     QuerySegment current = NULL;
00110     QuerySegment prev    = NULL;
00111     char** currentValArray = (char**)getMem(sizeof(RDF_Resource)*2);
00112     char** newValArray     = (char**)getMem(4096 * sizeof(RDF_Resource));
00113     currentValArray[0] = (char*) root;
00114     for (n = 0; n < numSegments; n++) {
00115       QuerySegment q = querySegments[n];     
00116       int nc = 0;
00117       int ansType = ((n == numSegments-1) ? RDF_STRING_TYPE : RDF_RESOURCE_TYPE);
00118          count = 0;
00119       for (nc = 0; currentValArray[nc] != NULL; nc++) {
00120            RDF_Cursor c = getSlotValues(NULL, (RDF_Resource)currentValArray[nc], q->s, 
00121                                      ansType, q->inversep, 1);
00122            RDF_Resource ans;
00123             int lc = 0;
00124            while (c  && (lc++ <= q->num) && (ans = nextValue(c))) {
00125               newValArray[count] = (char*) ans;
00126               count++;
00127            }
00128         if (c) disposeCursor(c);
00129       }
00130       freeMem(currentValArray);
00131       currentValArray = newValArray;
00132       newValArray = (char**) getMem(4096 * sizeof(RDF_Resource));
00133     }
00134     freeMem(newValArray);
00135     if (count > 0) {
00136       ans = (char**)getMem((count+1) * sizeof(char*));
00137       memcpy(ans, currentValArray, (count * sizeof(char*)));
00138     }
00139     freeMem(currentValArray);
00140     for (n = 0; n < numSegments; n++) freeMem(querySegments[n]);     
00141     return ans;
00142 }
00143     
00144