Fossil SCM

minor cleanups and doc additions to the json/artifact handling.

stephan 2011-10-02 11:43 UTC json-multitag-test
Commit 6d0667831a0aa39f1bbf248f1869769b35463eea
2 files changed +41 -35 +20 -6
+41 -35
--- src/json.c
+++ src/json.c
@@ -751,42 +751,49 @@
751751
752752
/*
753753
** Splits zStr (which must not be NULL) into tokens separated by the
754754
** given separator character. If doDeHttp is true then each element
755755
** will be passed through dehttpize(), otherwise they are used
756
-** as-is. Each new element is appended to the given target array
757
-** object, which must not be NULL and ownership of it is not changed
758
-** by this call.
759
-**
760
-** On success, returns the number of items appended to target. On
761
-** error a NEGATIVE number is returned - its absolute value is the
762
-** number of items inserted before the error occurred. There is a
763
-** corner case here if we fail on the 1st element, which will cause 0
764
-** to be returned, which the client cannot immediately distinguish as
765
-** success or error.
766
-**
767
-** Achtung: leading whitespace of elements is NOT elided. We should
768
-** add an option to do that, but don't have one yet.
769
-**
770
-** Achtung: empty elements will be skipped, meaning consecutive
771
-** empty elements are collapsed.
756
+** as-is. Note that tokenization happens before dehttpize(),
757
+** which is significant if the ENcoded tokens might contain the
758
+** separator character.
759
+**
760
+** Each new element is appended to the given target array object,
761
+** which must not be NULL and ownership of it is not changed by this
762
+** call.
763
+**
764
+** On success, returns the number of tokens _encountered_. On error a
765
+** NEGATIVE number is returned - its absolute value is the number of
766
+** tokens encountered (i.e. it reveals which token in zStr was
767
+** problematic).
768
+**
769
+** Achtung: leading and trailing whitespace of elements are elided.
770
+**
771
+** Achtung: empty elements will be skipped, meaning consecutive empty
772
+** elements are collapsed.
772773
*/
773774
int json_string_split( char const * zStr,
774775
char separator,
775776
char doDeHttp,
776777
cson_array * target ){
777778
char const * p = zStr /* current byte */;
778
- char const * head = p /* current start-of-token */;
779
+ char const * head /* current start-of-token */;
779780
unsigned int len = 0 /* current token's length */;
780781
int rc = 0 /* return code (number of added elements)*/;
782
+ char skipWs = fossil_isspace(separator) ? 0 : 1;
781783
assert( zStr && target );
784
+ while( fossil_isspace(*p) ){
785
+ ++p;
786
+ }
787
+ head = p;
782788
for( ; ; ++p){
783789
if( !*p || (separator == *p) ){
784790
if( len ){/* append head..(head+len) as next array
785791
element. */
786792
cson_value * part = NULL;
787793
char * zPart = NULL;
794
+ ++rc;
788795
assert( head != p );
789796
zPart = (char*)malloc(len+1);
790797
assert( (zPart != NULL) && "malloc failure" );
791798
memcpy(zPart, head, len);
792799
zPart[len] = 0;
@@ -793,15 +800,13 @@
793800
if(doDeHttp){
794801
dehttpize(zPart);
795802
}
796803
if( *zPart ){ /* should only fail if someone manages to url-encoded a NUL byte */
797804
part = cson_value_new_string(zPart, strlen(zPart));
798
- if( 0 == cson_array_append( target, part ) ){
799
- ++rc;
800
- }else{
805
+ if( 0 != cson_array_append( target, part ) ){
801806
cson_value_free(part);
802
- rc = rc ? -rc : 0;
807
+ rc = -rc;
803808
break;
804809
}
805810
}else{
806811
assert(0 && "i didn't think this was possible!");
807812
fprintf(stderr,"%s:%d: My God! It's full of stars!\n",
@@ -818,10 +823,17 @@
818823
}
819824
if( !*p ){
820825
break;
821826
}
822827
head = p+1;
828
+ while( *head && fossil_isspace(*head) ){
829
+ ++head;
830
+ ++p;
831
+ }
832
+ if(!*head){
833
+ break;
834
+ }
823835
continue;
824836
}
825837
++len;
826838
}
827839
return rc;
@@ -1328,29 +1340,23 @@
13281340
13291341
/*
13301342
** If the given rid has any tags associated with it, this function
13311343
** returns a JSON Array containing the tag names, else it returns
13321344
** NULL.
1345
+**
1346
+** See info_tags_of_checkin() for more details (this is simply a JSON
1347
+** wrapper for that function).
13331348
*/
1334
-cson_value * json_tags_for_rid(int rid){
1349
+cson_value * json_tags_for_rid(int rid, char propagatingOnly){
13351350
cson_value * v = NULL;
1336
- Stmt q;
1337
- assert((rid>0) && "rid is invalid");
1338
- db_prepare(&q,"SELECT group_concat(substr(tagname,5), ',')"
1339
- " FROM tag t, tagxref x "
1340
- " WHERE x.rid=%d "
1341
- " AND tagname GLOB 'sym-*' "
1342
- " AND t.tagid=x.tagid AND x.tagtype>0",
1343
- rid);
1344
- if( (SQLITE_ROW==db_step(&q)) ){
1345
- char const * tags;
1346
- tags = db_column_text(&q,0);
1347
- if(tags && *tags){
1351
+ char * tags = info_tags_of_checkin(rid, propagatingOnly);
1352
+ if(tags){
1353
+ if(*tags){
13481354
v = json_string_split2(tags,',',0);
13491355
}
1356
+ free(tags);
13501357
}
1351
- db_finalize(&q);
13521358
return v;
13531359
}
13541360
13551361
13561362
/*
13571363
--- src/json.c
+++ src/json.c
@@ -751,42 +751,49 @@
751
752 /*
753 ** Splits zStr (which must not be NULL) into tokens separated by the
754 ** given separator character. If doDeHttp is true then each element
755 ** will be passed through dehttpize(), otherwise they are used
756 ** as-is. Each new element is appended to the given target array
757 ** object, which must not be NULL and ownership of it is not changed
758 ** by this call.
759 **
760 ** On success, returns the number of items appended to target. On
761 ** error a NEGATIVE number is returned - its absolute value is the
762 ** number of items inserted before the error occurred. There is a
763 ** corner case here if we fail on the 1st element, which will cause 0
764 ** to be returned, which the client cannot immediately distinguish as
765 ** success or error.
766 **
767 ** Achtung: leading whitespace of elements is NOT elided. We should
768 ** add an option to do that, but don't have one yet.
769 **
770 ** Achtung: empty elements will be skipped, meaning consecutive
771 ** empty elements are collapsed.
 
772 */
773 int json_string_split( char const * zStr,
774 char separator,
775 char doDeHttp,
776 cson_array * target ){
777 char const * p = zStr /* current byte */;
778 char const * head = p /* current start-of-token */;
779 unsigned int len = 0 /* current token's length */;
780 int rc = 0 /* return code (number of added elements)*/;
 
781 assert( zStr && target );
 
 
 
 
782 for( ; ; ++p){
783 if( !*p || (separator == *p) ){
784 if( len ){/* append head..(head+len) as next array
785 element. */
786 cson_value * part = NULL;
787 char * zPart = NULL;
 
788 assert( head != p );
789 zPart = (char*)malloc(len+1);
790 assert( (zPart != NULL) && "malloc failure" );
791 memcpy(zPart, head, len);
792 zPart[len] = 0;
@@ -793,15 +800,13 @@
793 if(doDeHttp){
794 dehttpize(zPart);
795 }
796 if( *zPart ){ /* should only fail if someone manages to url-encoded a NUL byte */
797 part = cson_value_new_string(zPart, strlen(zPart));
798 if( 0 == cson_array_append( target, part ) ){
799 ++rc;
800 }else{
801 cson_value_free(part);
802 rc = rc ? -rc : 0;
803 break;
804 }
805 }else{
806 assert(0 && "i didn't think this was possible!");
807 fprintf(stderr,"%s:%d: My God! It's full of stars!\n",
@@ -818,10 +823,17 @@
818 }
819 if( !*p ){
820 break;
821 }
822 head = p+1;
 
 
 
 
 
 
 
823 continue;
824 }
825 ++len;
826 }
827 return rc;
@@ -1328,29 +1340,23 @@
1328
1329 /*
1330 ** If the given rid has any tags associated with it, this function
1331 ** returns a JSON Array containing the tag names, else it returns
1332 ** NULL.
 
 
 
1333 */
1334 cson_value * json_tags_for_rid(int rid){
1335 cson_value * v = NULL;
1336 Stmt q;
1337 assert((rid>0) && "rid is invalid");
1338 db_prepare(&q,"SELECT group_concat(substr(tagname,5), ',')"
1339 " FROM tag t, tagxref x "
1340 " WHERE x.rid=%d "
1341 " AND tagname GLOB 'sym-*' "
1342 " AND t.tagid=x.tagid AND x.tagtype>0",
1343 rid);
1344 if( (SQLITE_ROW==db_step(&q)) ){
1345 char const * tags;
1346 tags = db_column_text(&q,0);
1347 if(tags && *tags){
1348 v = json_string_split2(tags,',',0);
1349 }
 
1350 }
1351 db_finalize(&q);
1352 return v;
1353 }
1354
1355
1356 /*
1357
--- src/json.c
+++ src/json.c
@@ -751,42 +751,49 @@
751
752 /*
753 ** Splits zStr (which must not be NULL) into tokens separated by the
754 ** given separator character. If doDeHttp is true then each element
755 ** will be passed through dehttpize(), otherwise they are used
756 ** as-is. Note that tokenization happens before dehttpize(),
757 ** which is significant if the ENcoded tokens might contain the
758 ** separator character.
759 **
760 ** Each new element is appended to the given target array object,
761 ** which must not be NULL and ownership of it is not changed by this
762 ** call.
763 **
764 ** On success, returns the number of tokens _encountered_. On error a
765 ** NEGATIVE number is returned - its absolute value is the number of
766 ** tokens encountered (i.e. it reveals which token in zStr was
767 ** problematic).
768 **
769 ** Achtung: leading and trailing whitespace of elements are elided.
770 **
771 ** Achtung: empty elements will be skipped, meaning consecutive empty
772 ** elements are collapsed.
773 */
774 int json_string_split( char const * zStr,
775 char separator,
776 char doDeHttp,
777 cson_array * target ){
778 char const * p = zStr /* current byte */;
779 char const * head /* current start-of-token */;
780 unsigned int len = 0 /* current token's length */;
781 int rc = 0 /* return code (number of added elements)*/;
782 char skipWs = fossil_isspace(separator) ? 0 : 1;
783 assert( zStr && target );
784 while( fossil_isspace(*p) ){
785 ++p;
786 }
787 head = p;
788 for( ; ; ++p){
789 if( !*p || (separator == *p) ){
790 if( len ){/* append head..(head+len) as next array
791 element. */
792 cson_value * part = NULL;
793 char * zPart = NULL;
794 ++rc;
795 assert( head != p );
796 zPart = (char*)malloc(len+1);
797 assert( (zPart != NULL) && "malloc failure" );
798 memcpy(zPart, head, len);
799 zPart[len] = 0;
@@ -793,15 +800,13 @@
800 if(doDeHttp){
801 dehttpize(zPart);
802 }
803 if( *zPart ){ /* should only fail if someone manages to url-encoded a NUL byte */
804 part = cson_value_new_string(zPart, strlen(zPart));
805 if( 0 != cson_array_append( target, part ) ){
 
 
806 cson_value_free(part);
807 rc = -rc;
808 break;
809 }
810 }else{
811 assert(0 && "i didn't think this was possible!");
812 fprintf(stderr,"%s:%d: My God! It's full of stars!\n",
@@ -818,10 +823,17 @@
823 }
824 if( !*p ){
825 break;
826 }
827 head = p+1;
828 while( *head && fossil_isspace(*head) ){
829 ++head;
830 ++p;
831 }
832 if(!*head){
833 break;
834 }
835 continue;
836 }
837 ++len;
838 }
839 return rc;
@@ -1328,29 +1340,23 @@
1340
1341 /*
1342 ** If the given rid has any tags associated with it, this function
1343 ** returns a JSON Array containing the tag names, else it returns
1344 ** NULL.
1345 **
1346 ** See info_tags_of_checkin() for more details (this is simply a JSON
1347 ** wrapper for that function).
1348 */
1349 cson_value * json_tags_for_rid(int rid, char propagatingOnly){
1350 cson_value * v = NULL;
1351 char * tags = info_tags_of_checkin(rid, propagatingOnly);
1352 if(tags){
1353 if(*tags){
 
 
 
 
 
 
 
 
 
1354 v = json_string_split2(tags,',',0);
1355 }
1356 free(tags);
1357 }
 
1358 return v;
1359 }
1360
1361
1362 /*
1363
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -24,27 +24,38 @@
2424
2525
/*
2626
** Internal callback for /json/artifact handlers. rid refers to
2727
** the rid of a given type of artifact, and each callback is
2828
** specialized to return a JSON form of one type of artifact.
29
+**
30
+** Implementations may assert() that rid refers to requested artifact
31
+** type, since mismatches in the artifact types come from
32
+** json_page_artifact() as opposed to client data.
2933
*/
3034
typedef cson_value * (*artifact_f)( int rid );
3135
36
+/*
37
+** Internal per-artifact-type dispatching helper.
38
+*/
3239
typedef struct ArtifactDispatchEntry {
3340
/**
34
- Artifact type name, e.g. "checkin".
41
+ Artifact type name, e.g. "checkin", "ticket", "wiki".
3542
*/
3643
char const * name;
44
+
3745
/**
38
- JSON construction callback.
39
- */
46
+ JSON construction callback. Creates the contents for the
47
+ payload.artifact property of /json/artifact responses.
48
+ */
4049
artifact_f func;
50
+
4151
/**
4252
Must return true if g.perm has the proper permissions to fetch
4353
this info, else false. If it returns false, func() is skipped
44
- (producing no extra payload output).
45
- */
54
+ (producing no extra payload output) and an access error is
55
+ generated.
56
+ */
4657
char (*permCheck)();
4758
} ArtifactDispatchEntry;
4859
4960
5061
/*
@@ -131,11 +142,11 @@
131142
132143
if(zParent){
133144
SET("parentUuid", json_new_string(zParent));
134145
}
135146
136
- tmpV = json_tags_for_rid(rid);
147
+ tmpV = json_tags_for_rid(rid,0);
137148
if(tmpV){
138149
SET("tags",tmpV);
139150
}
140151
141152
if( showFiles ){
@@ -157,10 +168,13 @@
157168
*/
158169
static cson_value * json_artifact_ci( int rid ){
159170
return json_artifact_for_ci(rid, 1);
160171
}
161172
173
+/*
174
+** Permissions callback func for ArtifactDispatchEntry.
175
+*/
162176
static char perms_can_read(){
163177
return g.perm.Read ? 1 : 0;
164178
}
165179
166180
static ArtifactDispatchEntry ArtifactDispatchList[] = {
167181
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -24,27 +24,38 @@
24
25 /*
26 ** Internal callback for /json/artifact handlers. rid refers to
27 ** the rid of a given type of artifact, and each callback is
28 ** specialized to return a JSON form of one type of artifact.
 
 
 
 
29 */
30 typedef cson_value * (*artifact_f)( int rid );
31
 
 
 
32 typedef struct ArtifactDispatchEntry {
33 /**
34 Artifact type name, e.g. "checkin".
35 */
36 char const * name;
 
37 /**
38 JSON construction callback.
39 */
 
40 artifact_f func;
 
41 /**
42 Must return true if g.perm has the proper permissions to fetch
43 this info, else false. If it returns false, func() is skipped
44 (producing no extra payload output).
45 */
 
46 char (*permCheck)();
47 } ArtifactDispatchEntry;
48
49
50 /*
@@ -131,11 +142,11 @@
131
132 if(zParent){
133 SET("parentUuid", json_new_string(zParent));
134 }
135
136 tmpV = json_tags_for_rid(rid);
137 if(tmpV){
138 SET("tags",tmpV);
139 }
140
141 if( showFiles ){
@@ -157,10 +168,13 @@
157 */
158 static cson_value * json_artifact_ci( int rid ){
159 return json_artifact_for_ci(rid, 1);
160 }
161
 
 
 
162 static char perms_can_read(){
163 return g.perm.Read ? 1 : 0;
164 }
165
166 static ArtifactDispatchEntry ArtifactDispatchList[] = {
167
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -24,27 +24,38 @@
24
25 /*
26 ** Internal callback for /json/artifact handlers. rid refers to
27 ** the rid of a given type of artifact, and each callback is
28 ** specialized to return a JSON form of one type of artifact.
29 **
30 ** Implementations may assert() that rid refers to requested artifact
31 ** type, since mismatches in the artifact types come from
32 ** json_page_artifact() as opposed to client data.
33 */
34 typedef cson_value * (*artifact_f)( int rid );
35
36 /*
37 ** Internal per-artifact-type dispatching helper.
38 */
39 typedef struct ArtifactDispatchEntry {
40 /**
41 Artifact type name, e.g. "checkin", "ticket", "wiki".
42 */
43 char const * name;
44
45 /**
46 JSON construction callback. Creates the contents for the
47 payload.artifact property of /json/artifact responses.
48 */
49 artifact_f func;
50
51 /**
52 Must return true if g.perm has the proper permissions to fetch
53 this info, else false. If it returns false, func() is skipped
54 (producing no extra payload output) and an access error is
55 generated.
56 */
57 char (*permCheck)();
58 } ArtifactDispatchEntry;
59
60
61 /*
@@ -131,11 +142,11 @@
142
143 if(zParent){
144 SET("parentUuid", json_new_string(zParent));
145 }
146
147 tmpV = json_tags_for_rid(rid,0);
148 if(tmpV){
149 SET("tags",tmpV);
150 }
151
152 if( showFiles ){
@@ -157,10 +168,13 @@
168 */
169 static cson_value * json_artifact_ci( int rid ){
170 return json_artifact_for_ci(rid, 1);
171 }
172
173 /*
174 ** Permissions callback func for ArtifactDispatchEntry.
175 */
176 static char perms_can_read(){
177 return g.perm.Read ? 1 : 0;
178 }
179
180 static ArtifactDispatchEntry ArtifactDispatchList[] = {
181

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button