Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Pulled in another round of memory optimizations in cson/sqlite3. Added a few minor error reporting cleanups in JSON mode. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | json-multitag-test | json |
| Files: | files | file ages | folders |
| SHA1: |
09e5fcd795ce5fe6e7157e5982283ee7 |
| User & Date: | stephan 2011-10-07 10:59:45.960 |
Context
|
2011-10-07
| ||
| 12:02 | Added a very, very prototypic/pre-alphalpha demo fossil shell. Requires rhino JS. check-in: 7ab5d85487 user: stephan tags: json-multitag-test, json | |
| 10:59 | Pulled in another round of memory optimizations in cson/sqlite3. Added a few minor error reporting cleanups in JSON mode. check-in: 09e5fcd795 user: stephan tags: json-multitag-test, json | |
| 10:20 | Another round of cson memory optimizations. Object keys can now be cson_strings, which can be refcounted/shared. check-in: 3d252e8754 user: stephan tags: json-multitag-test, json | |
Changes
Changes to src/cson_amalgamation.c.
| ︙ | ︙ | |||
2678 2679 2680 2681 2682 2683 2684 |
cson_double_t cson_value_get_double( cson_value const * val )
{
cson_double_t i = 0.0;
cson_value_fetch_double( val, &i );
return i;
}
| | | | | | 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 |
cson_double_t cson_value_get_double( cson_value const * val )
{
cson_double_t i = 0.0;
cson_value_fetch_double( val, &i );
return i;
}
int cson_value_fetch_string( cson_value const * val, cson_string ** dest )
{
if( ! val || ! dest ) return cson_rc.ArgError;
else if( ! cson_value_is_string(val) ) return cson_rc.TypeError;
else
{
if( dest ) *dest = CSON_STR(val);
return 0;
}
}
cson_string * cson_value_get_string( cson_value const * val )
{
cson_string * rc = NULL;
cson_value_fetch_string( val, &rc );
return rc;
}
char const * cson_value_get_cstr( cson_value const * val )
{
return cson_string_cstr( cson_value_get_string(val) );
|
| ︙ | ︙ | |||
5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 |
else
{
cson_value_free(aryV);
return NULL;
}
}
cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st )
{
cson_value * rootV = NULL;
cson_object * root = NULL;
char const * colName = NULL;
int i = 0;
int rc = 0;
cson_value * currentValue = NULL;
int const colCount = sqlite3_column_count(st);
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 |
else
{
cson_value_free(aryV);
return NULL;
}
}
cson_value * cson_sqlite3_row_to_object2( sqlite3_stmt * st,
cson_array * colNames )
{
cson_value * rootV = NULL;
cson_object * root = NULL;
cson_string * colName = NULL;
int i = 0;
int rc = 0;
cson_value * currentValue = NULL;
int const colCount = sqlite3_column_count(st);
if( !colCount || (colCount>cson_array_length_get(colNames)) ) {
return NULL;
}
rootV = cson_value_new_object();
if(!rootV) return NULL;
root = cson_value_get_object(rootV);
for( i = 0; i < colCount; ++i )
{
colName = cson_value_get_string( cson_array_get( colNames, i ) );
if( ! colName ) goto error;
currentValue = cson_sqlite3_column_to_value(st,i);
if( ! currentValue ) currentValue = cson_value_null();
rc = cson_object_set_s( root, colName, currentValue );
if( 0 != rc )
{
cson_value_free( currentValue );
goto error;
}
}
goto end;
error:
cson_value_free( rootV );
rootV = NULL;
end:
return rootV;
}
cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st )
{
#if 0
cson_value * arV = cson_sqlite3_column_names(st);
cson_array * ar = NULL;
cson_value * rc = NULL;
if(!arV) return NULL;
ar = cson_value_get_array(arV);
assert( NULL != ar );
rc = cson_sqlite3_row_to_object2(st, ar);
cson_value_free(arV);
return rc;
#else
cson_value * rootV = NULL;
cson_object * root = NULL;
char const * colName = NULL;
int i = 0;
int rc = 0;
cson_value * currentValue = NULL;
int const colCount = sqlite3_column_count(st);
|
| ︙ | ︙ | |||
5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 |
}
goto end;
error:
cson_value_free( rootV );
rootV = NULL;
end:
return rootV;
}
cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st )
{
cson_value * aryV = NULL;
cson_array * ary = NULL;
int i = 0;
| > | 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 |
}
goto end;
error:
cson_value_free( rootV );
rootV = NULL;
end:
return rootV;
#endif
}
cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st )
{
cson_value * aryV = NULL;
cson_array * ary = NULL;
int i = 0;
|
| ︙ | ︙ | |||
5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 |
#define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; }
if( ! tgt || !st ) return cson_rc.ArgError;
else
{
cson_value * rootV = NULL;
cson_object * root = NULL;
cson_value * colsV = NULL;
cson_value * rowsV = NULL;
cson_array * rows = NULL;
cson_value * objV = NULL;
int rc = 0;
int const colCount = sqlite3_column_count(st);
if( colCount <= 0 ) return cson_rc.ArgError;
rootV = cson_value_new_object();
if( ! rootV ) return cson_rc.AllocError;
colsV = cson_sqlite3_column_names(st);
if( ! colsV )
{
cson_value_free( rootV );
RETURN(cson_rc.AllocError);
}
root = cson_value_get_object(rootV);
rc = cson_object_set( root, "columns", colsV );
if( rc )
{
cson_value_free( colsV );
RETURN(rc);
}
| > > > < | | 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 |
#define RETURN(RC) { if(rootV) cson_value_free(rootV); return RC; }
if( ! tgt || !st ) return cson_rc.ArgError;
else
{
cson_value * rootV = NULL;
cson_object * root = NULL;
cson_value * colsV = NULL;
cson_array * cols = NULL;
cson_value * rowsV = NULL;
cson_array * rows = NULL;
cson_value * objV = NULL;
int rc = 0;
int const colCount = sqlite3_column_count(st);
if( colCount <= 0 ) return cson_rc.ArgError;
rootV = cson_value_new_object();
if( ! rootV ) return cson_rc.AllocError;
colsV = cson_sqlite3_column_names(st);
if( ! colsV )
{
cson_value_free( rootV );
RETURN(cson_rc.AllocError);
}
cols = cson_value_get_array(colsV);
assert(NULL != cols);
root = cson_value_get_object(rootV);
rc = cson_object_set( root, "columns", colsV );
if( rc )
{
cson_value_free( colsV );
RETURN(rc);
}
rowsV = cson_value_new_array();
if( ! rowsV ) RETURN(cson_rc.AllocError);
rc = cson_object_set( root, "rows", rowsV );
if( rc )
{
cson_value_free( rowsV );
RETURN(rc);
}
rows = cson_value_get_array(rowsV);
assert(rows);
while( SQLITE_ROW == sqlite3_step(st) )
{
objV = cson_sqlite3_row_to_object2(st, cols);
if( ! objV ) RETURN(cson_rc.UnknownError);
rc = cson_array_append( rows, objV );
if( rc )
{
cson_value_free( objV );
RETURN(rc);
}
|
| ︙ | ︙ |
Changes to src/cson_amalgamation.h.
| ︙ | ︙ | |||
861 862 863 864 865 866 867 | And thus the bytes should be consumed before any further operations on val or any container which holds it. Note that this routine does not convert non-String values to their string representations. (Adding that ability would add more overhead to every cson_value instance.) */ | | | 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | And thus the bytes should be consumed before any further operations on val or any container which holds it. Note that this routine does not convert non-String values to their string representations. (Adding that ability would add more overhead to every cson_value instance.) */ int cson_value_fetch_string( cson_value const * val, cson_string ** str ); /** If cson_value_is_object(val) then this function assigns *obj to the underlying object value and returns 0, otherwise non-0 is returned and *obj is not modified. obj may be NULL, in which case this function works like cson_value_is_object() but with inverse return value semantics (0==success) (and it's a few |
| ︙ | ︙ | |||
918 919 920 921 922 923 924 | */ cson_double_t cson_value_get_double( cson_value const * val ); /** Simplified form of cson_value_fetch_string(). Returns NULL if val is-not-a string value. */ | | | 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 | */ cson_double_t cson_value_get_double( cson_value const * val ); /** Simplified form of cson_value_fetch_string(). Returns NULL if val is-not-a string value. */ cson_string * cson_value_get_string( cson_value const * val ); /** Returns a pointer to the NULL-terminated string bytes of str. The bytes are owned by string and will be invalided when it is cleaned up. If str is NULL then NULL is returned. |
| ︙ | ︙ | |||
2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 | caller. On error NULL is returned. cson_sqlite3_column_to_value() is used to convert each column to a JSON value, and the column names are taken from sqlite3_column_name(). */ cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st ); /** Similar to cson_sqlite3_row_to_object(), but creates an Array value which contains the JSON-form values of the given result set row. */ cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st ); | > > > > > > > > > > > > > > > > > > > > | 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 |
caller. On error NULL is returned.
cson_sqlite3_column_to_value() is used to convert each column to a
JSON value, and the column names are taken from
sqlite3_column_name().
*/
cson_value * cson_sqlite3_row_to_object( sqlite3_stmt * st );
/**
Functionally almost identical to cson_sqlite3_row_to_object(), the
only difference being how the result objects gets its column names.
st must be a freshly-step()'d handle holding a result row.
colNames must be an Array with at least the same number of columns
as st. If it has fewer, NULL is returned and this function has
no side-effects.
For each column in the result set, the colNames entry at the same
index is used for the column key. If a given entry is-not-a String
then conversion will fail and NULL will be returned.
The one reason to prefer this over cson_sqlite3_row_to_object() is
that this one can share the keys across multiple rows (or even
other JSON containers), whereas the former makes fresh copies of
the column names for each row.
*/
cson_value * cson_sqlite3_row_to_object2( sqlite3_stmt * st,
cson_array * colNames );
/**
Similar to cson_sqlite3_row_to_object(), but creates an Array
value which contains the JSON-form values of the given result
set row.
*/
cson_value * cson_sqlite3_row_to_array( sqlite3_stmt * st );
|
| ︙ | ︙ |
Changes to src/db.c.
| ︙ | ︙ | |||
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 |
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
if( file_access(zDbName, 0) ){
fossil_panic("repository does not exist or"
" is in an unreadable directory: %s", zDbName);
}else if( file_access(zDbName, R_OK) ){
fossil_panic("read permission denied for repository %s", zDbName);
}else{
fossil_panic("not a valid repository: %s", zDbName);
}
}
db_open_or_attach(zDbName, "repository");
g.repositoryOpen = 1;
g.zRepositoryName = mprintf("%s", zDbName);
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
| > > > | 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 |
}
if( zDbName==0 ){
db_err("unable to find the name of a repository database");
}
}
if( file_access(zDbName, R_OK) || file_size(zDbName)<1024 ){
if( file_access(zDbName, 0) ){
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
fossil_panic("repository does not exist or"
" is in an unreadable directory: %s", zDbName);
}else if( file_access(zDbName, R_OK) ){
g.json.resultCode = FSL_JSON_E_DENIED;
fossil_panic("read permission denied for repository %s", zDbName);
}else{
g.json.resultCode = FSL_JSON_E_DB_NOT_VALID;
fossil_panic("not a valid repository: %s", zDbName);
}
}
db_open_or_attach(zDbName, "repository");
g.repositoryOpen = 1;
g.zRepositoryName = mprintf("%s", zDbName);
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
|
| ︙ | ︙ | |||
917 918 919 920 921 922 923 |
if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
zRep = g.argv[nArgUsed];
}
if( zRep==0 ){
if( db_open_local()==0 ){
goto rep_not_found;
}
| | > | 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 |
if( zRep==0 && nArgUsed && g.argc==nArgUsed+1 ){
zRep = g.argv[nArgUsed];
}
if( zRep==0 ){
if( db_open_local()==0 ){
goto rep_not_found;
}
zRep = db_lget("repository", 0)/*leak here*/;
if( zRep==0 ){
goto rep_not_found;
}
}
db_open_repository(zRep);
if( g.repositoryOpen ){
if( (bFlags & OPEN_ANY_SCHEMA)==0 ) db_verify_schema();
return;
}
rep_not_found:
if( (bFlags & OPEN_OK_NOT_FOUND)==0 ){
g.json.resultCode = FSL_JSON_E_DB_NOT_FOUND;
fossil_fatal("use --repository or -R to specify the repository database");
}
}
/*
** Return the name of the database "localdb", "configdb", or "repository".
*/
|
| ︙ | ︙ |
Changes to src/json.c.
| ︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
C(DB,"Database error");
C(STMT_PREP,"Statement preparation failed");
C(STMT_BIND,"Statement parameter binding failed");
C(STMT_EXEC,"Statement execution/stepping failed");
C(DB_LOCKED,"Database is locked");
C(DB_NEEDS_REBUILD,"Fossil repository needs to be rebuilt");
#undef C
default:
return "Unknown Error";
}
}
/*
| > > | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
C(DB,"Database error");
C(STMT_PREP,"Statement preparation failed");
C(STMT_BIND,"Statement parameter binding failed");
C(STMT_EXEC,"Statement execution/stepping failed");
C(DB_LOCKED,"Database is locked");
C(DB_NEEDS_REBUILD,"Fossil repository needs to be rebuilt");
C(DB_NOT_FOUND,"Fossil repository db file could not be found.");
C(DB_NOT_VALID, "Fossil repository db file is not valid.");
#undef C
default:
return "Unknown Error";
}
}
/*
|
| ︙ | ︙ | |||
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 |
**
*/
cson_value * json_page_resultCodes(){
cson_value * listV = cson_value_new_array();
cson_array * list = cson_value_get_array(listV);
cson_value * objV = NULL;
cson_object * obj = NULL;
int rc = cson_array_reserve( list, 35 );
if(rc){
assert( 0 && "Allocation error.");
exit(1);
}
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
| > > > > > > > > | | | | | 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 |
**
*/
cson_value * json_page_resultCodes(){
cson_value * listV = cson_value_new_array();
cson_array * list = cson_value_get_array(listV);
cson_value * objV = NULL;
cson_object * obj = NULL;
cson_string * kRC;
cson_string * kSymbol;
cson_string * kNumber;
cson_string * kDesc;
int rc = cson_array_reserve( list, 35 );
if(rc){
assert( 0 && "Allocation error.");
exit(1);
}
kRC = cson_new_string("resultCode",10);
kSymbol = cson_new_string("cSymbol",7);
kNumber = cson_new_string("number",6);
kDesc = cson_new_string("description",11);
#define C(K) objV = cson_value_new_object(); obj = cson_value_get_object(objV); \
cson_object_set_s(obj, kRC, json_new_string(json_rc_cstr(FSL_JSON_E_##K)) ); \
cson_object_set_s(obj, kSymbol, json_new_string("FSL_JSON_E_"#K) ); \
cson_object_set_s(obj, kNumber, cson_value_new_integer(FSL_JSON_E_##K) ); \
cson_object_set_s(obj, kDesc, json_new_string(json_err_cstr(FSL_JSON_E_##K))); \
cson_array_append( list, objV ); obj = NULL; objV = NULL
C(GENERIC);
C(INVALID_REQUEST);
C(UNKNOWN_COMMAND);
C(UNKNOWN);
C(TIMEOUT);
|
| ︙ | ︙ | |||
1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 |
C(DB);
C(STMT_PREP);
C(STMT_BIND);
C(STMT_EXEC);
C(DB_LOCKED);
C(DB_NEEDS_REBUILD);
#undef C
return listV;
}
/*
** /json/version implementation.
| > > | 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 |
C(DB);
C(STMT_PREP);
C(STMT_BIND);
C(STMT_EXEC);
C(DB_LOCKED);
C(DB_NEEDS_REBUILD);
C(DB_NOT_FOUND);
C(DB_NOT_VALID);
#undef C
return listV;
}
/*
** /json/version implementation.
|
| ︙ | ︙ |
Changes to src/json_detail.h.
| ︙ | ︙ | |||
80 81 82 83 84 85 86 | FSL_JSON_E_DB = 4000, FSL_JSON_E_STMT_PREP /*+1*/, FSL_JSON_E_STMT_BIND /*+2*/, FSL_JSON_E_STMT_EXEC /*+3*/, FSL_JSON_E_DB_LOCKED /*+4*/, | | > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | FSL_JSON_E_DB = 4000, FSL_JSON_E_STMT_PREP /*+1*/, FSL_JSON_E_STMT_BIND /*+2*/, FSL_JSON_E_STMT_EXEC /*+3*/, FSL_JSON_E_DB_LOCKED /*+4*/, FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101, FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102, FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103 }; /* ** Signature for JSON page/command callbacks. Each callback is ** responsible for handling one JSON request/command and/or |
| ︙ | ︙ |