Fossil SCM

pulled in latest cson for cson_object_merge().

stephan 2011-10-16 13:29 UTC json-multitag-test
Commit d3ad893c5b8134ee503611dbdd7e35a9d845d22d
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2409,11 +2409,11 @@
24092409
kvp->value = NULL;
24102410
}
24112411
}
24122412
}
24132413
2414
-cson_string const * cson_kvp_key( cson_kvp const * kvp )
2414
+cson_string * cson_kvp_key( cson_kvp const * kvp )
24152415
{
24162416
return kvp ? cson_value_get_string(kvp->key) : NULL;
24172417
}
24182418
cson_value * cson_kvp_value( cson_kvp const * kvp )
24192419
{
@@ -3057,10 +3057,17 @@
30573057
cson_value * cson_object_get( cson_object const * obj, char const * key )
30583058
{
30593059
cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
30603060
return kvp ? kvp->value : NULL;
30613061
}
3062
+
3063
+cson_value * cson_object_get_s( cson_object const * obj, cson_string const *key )
3064
+{
3065
+ cson_kvp * kvp = cson_object_search_impl( obj, cson_string_cstr(key), NULL );
3066
+ return kvp ? kvp->value : NULL;
3067
+}
3068
+
30623069
30633070
#if CSON_OBJECT_PROPS_SORT
30643071
static void cson_object_sort_props( cson_object * obj )
30653072
{
30663073
assert( NULL != obj );
@@ -4482,10 +4489,17 @@
44824489
*inp = pos;
44834490
for( ; *pos && (*pos != separator); ++pos) { /* find next splitter */ }
44844491
*end = pos;
44854492
return (pos > *inp) ? 1 : 0;
44864493
}
4494
+
4495
+int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path )
4496
+{
4497
+ if( ! obj || !path ) return cson_rc.ArgError;
4498
+ else if( !*path || !*(1+path) ) return cson_rc.RangeError;
4499
+ else return cson_object_fetch_sub(obj, tgt, path+1, *path);
4500
+}
44874501
44884502
int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
44894503
{
44904504
if( ! obj || !path ) return cson_rc.ArgError;
44914505
else if( !*path || !sep ) return cson_rc.RangeError;
@@ -4554,10 +4568,17 @@
45544568
{
45554569
cson_value * v = NULL;
45564570
cson_object_fetch_sub( obj, &v, path, sep );
45574571
return v;
45584572
}
4573
+
4574
+cson_value * cson_object_get_sub2( cson_object const * obj, char const * path )
4575
+{
4576
+ cson_value * v = NULL;
4577
+ cson_object_fetch_sub2( obj, &v, path );
4578
+ return v;
4579
+}
45594580
45604581
static cson_value * cson_value_clone_array( cson_value const * orig )
45614582
{
45624583
unsigned int i = 0;
45634584
cson_array const * asrc = cson_value_get_array( orig );
@@ -4889,10 +4910,49 @@
48894910
48904911
}
48914912
return rc;
48924913
}
48934914
}
4915
+
4916
+int cson_object_merge( cson_object * dest, cson_object const * src, int flags ){
4917
+ cson_object_iterator iter = cson_object_iterator_empty;
4918
+ int rc;
4919
+ char const replace = (flags & CSON_MERGE_REPLACE);
4920
+ char const recurse = !(flags & CSON_MERGE_NO_RECURSE);
4921
+ cson_kvp const * kvp;
4922
+ if((!dest || !src) || (dest==src)) return cson_rc.ArgError;
4923
+ rc = cson_object_iter_init( src, &iter );
4924
+ if(rc) return rc;
4925
+ while( (kvp = cson_object_iter_next(&iter) ) )
4926
+ {
4927
+ cson_string * key = cson_kvp_key(kvp);
4928
+ cson_value * val = cson_kvp_value(kvp);
4929
+ cson_value * check = cson_object_get_s( dest, key );
4930
+ if(!check){
4931
+ cson_object_set_s( dest, key, val );
4932
+ continue;
4933
+ }
4934
+ else if(!replace && !recurse) continue;
4935
+ else if(replace && !recurse){
4936
+ cson_object_set_s( dest, key, val );
4937
+ continue;
4938
+ }
4939
+ else if( recurse ){
4940
+ if( cson_value_is_object(check) &&
4941
+ cson_value_is_object(val) ){
4942
+ rc = cson_object_merge( cson_value_get_object(check),
4943
+ cson_value_get_object(val),
4944
+ flags );
4945
+ if(rc) return rc;
4946
+ else continue;
4947
+ }
4948
+ else continue;
4949
+ }
4950
+ else continue;
4951
+ }
4952
+ return 0;
4953
+}
48944954
48954955
#if defined(__cplusplus)
48964956
} /*extern "C"*/
48974957
#endif
48984958
48994959
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2409,11 +2409,11 @@
2409 kvp->value = NULL;
2410 }
2411 }
2412 }
2413
2414 cson_string const * cson_kvp_key( cson_kvp const * kvp )
2415 {
2416 return kvp ? cson_value_get_string(kvp->key) : NULL;
2417 }
2418 cson_value * cson_kvp_value( cson_kvp const * kvp )
2419 {
@@ -3057,10 +3057,17 @@
3057 cson_value * cson_object_get( cson_object const * obj, char const * key )
3058 {
3059 cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
3060 return kvp ? kvp->value : NULL;
3061 }
 
 
 
 
 
 
 
3062
3063 #if CSON_OBJECT_PROPS_SORT
3064 static void cson_object_sort_props( cson_object * obj )
3065 {
3066 assert( NULL != obj );
@@ -4482,10 +4489,17 @@
4482 *inp = pos;
4483 for( ; *pos && (*pos != separator); ++pos) { /* find next splitter */ }
4484 *end = pos;
4485 return (pos > *inp) ? 1 : 0;
4486 }
 
 
 
 
 
 
 
4487
4488 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
4489 {
4490 if( ! obj || !path ) return cson_rc.ArgError;
4491 else if( !*path || !sep ) return cson_rc.RangeError;
@@ -4554,10 +4568,17 @@
4554 {
4555 cson_value * v = NULL;
4556 cson_object_fetch_sub( obj, &v, path, sep );
4557 return v;
4558 }
 
 
 
 
 
 
 
4559
4560 static cson_value * cson_value_clone_array( cson_value const * orig )
4561 {
4562 unsigned int i = 0;
4563 cson_array const * asrc = cson_value_get_array( orig );
@@ -4889,10 +4910,49 @@
4889
4890 }
4891 return rc;
4892 }
4893 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4894
4895 #if defined(__cplusplus)
4896 } /*extern "C"*/
4897 #endif
4898
4899
--- src/cson_amalgamation.c
+++ src/cson_amalgamation.c
@@ -2409,11 +2409,11 @@
2409 kvp->value = NULL;
2410 }
2411 }
2412 }
2413
2414 cson_string * cson_kvp_key( cson_kvp const * kvp )
2415 {
2416 return kvp ? cson_value_get_string(kvp->key) : NULL;
2417 }
2418 cson_value * cson_kvp_value( cson_kvp const * kvp )
2419 {
@@ -3057,10 +3057,17 @@
3057 cson_value * cson_object_get( cson_object const * obj, char const * key )
3058 {
3059 cson_kvp * kvp = cson_object_search_impl( obj, key, NULL );
3060 return kvp ? kvp->value : NULL;
3061 }
3062
3063 cson_value * cson_object_get_s( cson_object const * obj, cson_string const *key )
3064 {
3065 cson_kvp * kvp = cson_object_search_impl( obj, cson_string_cstr(key), NULL );
3066 return kvp ? kvp->value : NULL;
3067 }
3068
3069
3070 #if CSON_OBJECT_PROPS_SORT
3071 static void cson_object_sort_props( cson_object * obj )
3072 {
3073 assert( NULL != obj );
@@ -4482,10 +4489,17 @@
4489 *inp = pos;
4490 for( ; *pos && (*pos != separator); ++pos) { /* find next splitter */ }
4491 *end = pos;
4492 return (pos > *inp) ? 1 : 0;
4493 }
4494
4495 int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path )
4496 {
4497 if( ! obj || !path ) return cson_rc.ArgError;
4498 else if( !*path || !*(1+path) ) return cson_rc.RangeError;
4499 else return cson_object_fetch_sub(obj, tgt, path+1, *path);
4500 }
4501
4502 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char sep )
4503 {
4504 if( ! obj || !path ) return cson_rc.ArgError;
4505 else if( !*path || !sep ) return cson_rc.RangeError;
@@ -4554,10 +4568,17 @@
4568 {
4569 cson_value * v = NULL;
4570 cson_object_fetch_sub( obj, &v, path, sep );
4571 return v;
4572 }
4573
4574 cson_value * cson_object_get_sub2( cson_object const * obj, char const * path )
4575 {
4576 cson_value * v = NULL;
4577 cson_object_fetch_sub2( obj, &v, path );
4578 return v;
4579 }
4580
4581 static cson_value * cson_value_clone_array( cson_value const * orig )
4582 {
4583 unsigned int i = 0;
4584 cson_array const * asrc = cson_value_get_array( orig );
@@ -4889,10 +4910,49 @@
4910
4911 }
4912 return rc;
4913 }
4914 }
4915
4916 int cson_object_merge( cson_object * dest, cson_object const * src, int flags ){
4917 cson_object_iterator iter = cson_object_iterator_empty;
4918 int rc;
4919 char const replace = (flags & CSON_MERGE_REPLACE);
4920 char const recurse = !(flags & CSON_MERGE_NO_RECURSE);
4921 cson_kvp const * kvp;
4922 if((!dest || !src) || (dest==src)) return cson_rc.ArgError;
4923 rc = cson_object_iter_init( src, &iter );
4924 if(rc) return rc;
4925 while( (kvp = cson_object_iter_next(&iter) ) )
4926 {
4927 cson_string * key = cson_kvp_key(kvp);
4928 cson_value * val = cson_kvp_value(kvp);
4929 cson_value * check = cson_object_get_s( dest, key );
4930 if(!check){
4931 cson_object_set_s( dest, key, val );
4932 continue;
4933 }
4934 else if(!replace && !recurse) continue;
4935 else if(replace && !recurse){
4936 cson_object_set_s( dest, key, val );
4937 continue;
4938 }
4939 else if( recurse ){
4940 if( cson_value_is_object(check) &&
4941 cson_value_is_object(val) ){
4942 rc = cson_object_merge( cson_value_get_object(check),
4943 cson_value_get_object(val),
4944 flags );
4945 if(rc) return rc;
4946 else continue;
4947 }
4948 else continue;
4949 }
4950 else continue;
4951 }
4952 return 0;
4953 }
4954
4955 #if defined(__cplusplus)
4956 } /*extern "C"*/
4957 #endif
4958
4959
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1400,10 +1400,16 @@
14001400
@see cson_object_fetch_sub()
14011401
@see cson_object_get_sub()
14021402
*/
14031403
cson_value * cson_object_get( cson_object const * obj, char const * key );
14041404
1405
+/**
1406
+ Equivalent to cson_object_get() but takes a cson_string argument
1407
+ instead of a C-style string.
1408
+*/
1409
+cson_value * cson_object_get_s( cson_object const * obj, cson_string const *key );
1410
+
14051411
/**
14061412
Similar to cson_object_get(), but removes the value from the parent
14071413
object's ownership. If no item is found then NULL is returned, else
14081414
the object (now owned by the caller or possibly shared with other
14091415
containers) is returned.
@@ -1485,19 +1491,79 @@
14851491
Multiple successive separators in the list are collapsed into a
14861492
single separator for parsing purposes. e.g. the path "a...b...c"
14871493
(separator='.') is equivalent to "a.b.c".
14881494
14891495
@see cson_object_get_sub()
1496
+ @see cson_object_get_sub2()
14901497
*/
14911498
int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char separator );
14921499
1500
+/**
1501
+ Similar to cson_object_fetch_sub(), but derives the path separator
1502
+ character from the first byte of the path argument. e.g. the
1503
+ following arg equivalent:
1504
+
1505
+ @code
1506
+ cson_object_fetch_sub( obj, &tgt, "foo.bar.baz", '.' );
1507
+ cson_object_fetch_sub2( obj, &tgt, ".foo.bar.baz" );
1508
+ @endcode
1509
+*/
1510
+int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path );
1511
+
14931512
/**
14941513
Convenience form of cson_object_fetch_sub() which returns NULL if the given
14951514
item is not found.
14961515
*/
14971516
cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep );
14981517
1518
+/**
1519
+ Convenience form of cson_object_fetch_sub2() which returns NULL if the given
1520
+ item is not found.
1521
+*/
1522
+cson_value * cson_object_get_sub2( cson_object const * obj, char const * path );
1523
+
1524
+/** @enum CSON_MERGE_FLAGS
1525
+
1526
+ Flags for cson_object_merge().
1527
+*/
1528
+enum CSON_MERGE_FLAGS {
1529
+ CSON_MERGE_DEFAULT = 0,
1530
+ CSON_MERGE_REPLACE = 0x01,
1531
+ CSON_MERGE_NO_RECURSE = 0x02
1532
+};
1533
+
1534
+/**
1535
+ "Merges" the src object's properties into dest. Each property in
1536
+ src is copied (using reference counting, not cloning) into dest. If
1537
+ dest already has the given property then behaviour depends on the
1538
+ flags argument:
1539
+
1540
+ If flag has the CSON_MERGE_REPLACE bit set then this function will
1541
+ by default replace non-object properties with the src property. If
1542
+ src and dest both have the property AND it is an Object then this
1543
+ function operates recursively on those objects. If
1544
+ CSON_MERGE_NO_RECURSE is set then objects are not recursed in this
1545
+ manner, and will be completely replaced if CSON_MERGE_REPLACE is
1546
+ set.
1547
+
1548
+ Array properties in dest are NOT recursed for merging - they are
1549
+ either replaced or left as-is, depending on whether flags contains
1550
+ he CSON_MERGE_REPLACE bit.
1551
+
1552
+ Returns 0 on success. The error conditions are:
1553
+
1554
+ - dest or src are NULL or (dest==src) returns cson_rc.ArgError.
1555
+
1556
+ - dest or src contain cyclic references - this will likely cause a
1557
+ crash due to endless recursion.
1558
+
1559
+ Potential TODOs:
1560
+
1561
+ - Add a flag to copy clones, not the original values.
1562
+*/
1563
+int cson_object_merge( cson_object * dest, cson_object const * src, int flags );
1564
+
14991565
15001566
/**
15011567
An iterator type for traversing object properties.
15021568
15031569
Its values must be considered private, not to be touched by client
@@ -1590,11 +1656,11 @@
15901656
Returns the key associated with the given key/value pair,
15911657
or NULL if !kvp. The memory is owned by the object which contains
15921658
the key/value pair, and may be invalidated by any modifications
15931659
to that object.
15941660
*/
1595
-cson_string const * cson_kvp_key( cson_kvp const * kvp );
1661
+cson_string * cson_kvp_key( cson_kvp const * kvp );
15961662
15971663
/**
15981664
Returns the value associated with the given key/value pair,
15991665
or NULL if !kvp. The memory is owned by the object which contains
16001666
the key/value pair, and may be invalidated by any modifications
16011667
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1400,10 +1400,16 @@
1400 @see cson_object_fetch_sub()
1401 @see cson_object_get_sub()
1402 */
1403 cson_value * cson_object_get( cson_object const * obj, char const * key );
1404
 
 
 
 
 
 
1405 /**
1406 Similar to cson_object_get(), but removes the value from the parent
1407 object's ownership. If no item is found then NULL is returned, else
1408 the object (now owned by the caller or possibly shared with other
1409 containers) is returned.
@@ -1485,19 +1491,79 @@
1485 Multiple successive separators in the list are collapsed into a
1486 single separator for parsing purposes. e.g. the path "a...b...c"
1487 (separator='.') is equivalent to "a.b.c".
1488
1489 @see cson_object_get_sub()
 
1490 */
1491 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char separator );
1492
 
 
 
 
 
 
 
 
 
 
 
 
1493 /**
1494 Convenience form of cson_object_fetch_sub() which returns NULL if the given
1495 item is not found.
1496 */
1497 cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep );
1498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1499
1500 /**
1501 An iterator type for traversing object properties.
1502
1503 Its values must be considered private, not to be touched by client
@@ -1590,11 +1656,11 @@
1590 Returns the key associated with the given key/value pair,
1591 or NULL if !kvp. The memory is owned by the object which contains
1592 the key/value pair, and may be invalidated by any modifications
1593 to that object.
1594 */
1595 cson_string const * cson_kvp_key( cson_kvp const * kvp );
1596
1597 /**
1598 Returns the value associated with the given key/value pair,
1599 or NULL if !kvp. The memory is owned by the object which contains
1600 the key/value pair, and may be invalidated by any modifications
1601
--- src/cson_amalgamation.h
+++ src/cson_amalgamation.h
@@ -1400,10 +1400,16 @@
1400 @see cson_object_fetch_sub()
1401 @see cson_object_get_sub()
1402 */
1403 cson_value * cson_object_get( cson_object const * obj, char const * key );
1404
1405 /**
1406 Equivalent to cson_object_get() but takes a cson_string argument
1407 instead of a C-style string.
1408 */
1409 cson_value * cson_object_get_s( cson_object const * obj, cson_string const *key );
1410
1411 /**
1412 Similar to cson_object_get(), but removes the value from the parent
1413 object's ownership. If no item is found then NULL is returned, else
1414 the object (now owned by the caller or possibly shared with other
1415 containers) is returned.
@@ -1485,19 +1491,79 @@
1491 Multiple successive separators in the list are collapsed into a
1492 single separator for parsing purposes. e.g. the path "a...b...c"
1493 (separator='.') is equivalent to "a.b.c".
1494
1495 @see cson_object_get_sub()
1496 @see cson_object_get_sub2()
1497 */
1498 int cson_object_fetch_sub( cson_object const * obj, cson_value ** tgt, char const * path, char separator );
1499
1500 /**
1501 Similar to cson_object_fetch_sub(), but derives the path separator
1502 character from the first byte of the path argument. e.g. the
1503 following arg equivalent:
1504
1505 @code
1506 cson_object_fetch_sub( obj, &tgt, "foo.bar.baz", '.' );
1507 cson_object_fetch_sub2( obj, &tgt, ".foo.bar.baz" );
1508 @endcode
1509 */
1510 int cson_object_fetch_sub2( cson_object const * obj, cson_value ** tgt, char const * path );
1511
1512 /**
1513 Convenience form of cson_object_fetch_sub() which returns NULL if the given
1514 item is not found.
1515 */
1516 cson_value * cson_object_get_sub( cson_object const * obj, char const * path, char sep );
1517
1518 /**
1519 Convenience form of cson_object_fetch_sub2() which returns NULL if the given
1520 item is not found.
1521 */
1522 cson_value * cson_object_get_sub2( cson_object const * obj, char const * path );
1523
1524 /** @enum CSON_MERGE_FLAGS
1525
1526 Flags for cson_object_merge().
1527 */
1528 enum CSON_MERGE_FLAGS {
1529 CSON_MERGE_DEFAULT = 0,
1530 CSON_MERGE_REPLACE = 0x01,
1531 CSON_MERGE_NO_RECURSE = 0x02
1532 };
1533
1534 /**
1535 "Merges" the src object's properties into dest. Each property in
1536 src is copied (using reference counting, not cloning) into dest. If
1537 dest already has the given property then behaviour depends on the
1538 flags argument:
1539
1540 If flag has the CSON_MERGE_REPLACE bit set then this function will
1541 by default replace non-object properties with the src property. If
1542 src and dest both have the property AND it is an Object then this
1543 function operates recursively on those objects. If
1544 CSON_MERGE_NO_RECURSE is set then objects are not recursed in this
1545 manner, and will be completely replaced if CSON_MERGE_REPLACE is
1546 set.
1547
1548 Array properties in dest are NOT recursed for merging - they are
1549 either replaced or left as-is, depending on whether flags contains
1550 he CSON_MERGE_REPLACE bit.
1551
1552 Returns 0 on success. The error conditions are:
1553
1554 - dest or src are NULL or (dest==src) returns cson_rc.ArgError.
1555
1556 - dest or src contain cyclic references - this will likely cause a
1557 crash due to endless recursion.
1558
1559 Potential TODOs:
1560
1561 - Add a flag to copy clones, not the original values.
1562 */
1563 int cson_object_merge( cson_object * dest, cson_object const * src, int flags );
1564
1565
1566 /**
1567 An iterator type for traversing object properties.
1568
1569 Its values must be considered private, not to be touched by client
@@ -1590,11 +1656,11 @@
1656 Returns the key associated with the given key/value pair,
1657 or NULL if !kvp. The memory is owned by the object which contains
1658 the key/value pair, and may be invalidated by any modifications
1659 to that object.
1660 */
1661 cson_string * cson_kvp_key( cson_kvp const * kvp );
1662
1663 /**
1664 Returns the value associated with the given key/value pair,
1665 or NULL if !kvp. The memory is owned by the object which contains
1666 the key/value pair, and may be invalidated by any modifications
1667

Keyboard Shortcuts

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