コード例 #1
0
void traverse(const value&                                           tree,
              const std::function<void (const path&, const value&)>& func,
              const path&                                            base_path,
              bool                                                   leafs_only
             )
{
    if (!leafs_only || tree.empty() || (tree.kind() != kind::array && tree.kind() != kind::object))
        func(base_path, tree);
    
    if (tree.kind() == kind::object)
    {
        for (const auto& field : tree.as_object())
        {
            traverse(field.second,
                     func,
                     base_path + field.first,
                     leafs_only
                    );
        }
    }
    else if (tree.kind() == kind::array)
    {
        for (value::size_type idx = 0; idx < tree.size(); ++idx)
            traverse(tree[idx],
                     func,
                     base_path + idx,
                     leafs_only
                    );
    }
}
コード例 #2
0
static void GenStat(Stat& stat, const value& v) {
    switch (v.kind()) {
    case kind::array:
        {
            for (value::const_array_iterator itr = v.begin_array(); itr != v.end_array(); ++itr)
                GenStat(stat, *itr);
            stat.arrayCount++;
            stat.elementCount += v.size();
        }
        break;

    case kind::object:
        {
            for (value::const_object_iterator itr = v.begin_object(); itr != v.end_object(); ++itr) {
                GenStat(stat, itr->second);
                stat.stringLength += itr->first.size();
            }
            stat.objectCount++;
            stat.memberCount += v.size();
            stat.stringCount += v.size();
        }
        break;

    case kind::string: 
        stat.stringCount++;
        stat.stringLength += v.size();
        break;

    case kind::integer:
    case kind::decimal:
        stat.numberCount++;
        break;

    case kind::boolean:
        if (v.as_boolean())
            stat.trueCount++;
        else
            stat.falseCount++;
        break;

    case kind::null:
        stat.nullCount++;
        break;
    }
}
コード例 #3
0
    std::pair<bool, value> delta( const object& a, const object& b, std::size_t max_size )
    {
        array result;

        const std::vector<string> akeys = a.keys();
        const std::vector<string> bkeys = b.keys();

        std::vector<string>::const_iterator pa = akeys.begin(), pb = bkeys.begin();

        for ( ; (pa != akeys.end() || pb != bkeys.end()) && result.size() < max_size; ) 
        {
            if ( pb == bkeys.end() || pa != akeys.end() && *pa < *pb )
            {
                result.add( delete_at_operation() )
                      .add( *pa );

                ++pa;
            }
            else if ( pa == akeys.end() || pb != bkeys.end() && *pb < *pa )
            {
                result.add( insert_at_operation() )
                      .add( *pb )
                      .add( b.at( *pb ) );

                ++pb;
            }
            else
            {
                assert( *pa == *pb );
                const value b_element = b.at( *pb );

                std::pair<bool, value> edit_op = delta(a.at(*pa), b_element, max_size - result.size());

                // use edit, if possible and shorter
                if ( edit_op.first && edit_op.second.size() < b_element.size() )
                {
                    result.add( edit_at_operation() )
                          .add( *pa )
                          .add( edit_op.second );

                }
                else
                {
                    result.add( update_at_operation() )
                          .add( *pa)
                          .add( b_element );
                }

                ++pa;
                ++pb;
            }
        }

        return result.size() <= max_size
            ? std::make_pair(true, value(result))
            : std::make_pair(false, value(b));
    }
コード例 #4
0
 virtual TContainer create(const extraction_context& context, const value& from) const override
 {
     using std::end;
     
     TContainer out;
     from.as_array(); // get nice error if input is not an array
     for (value::size_type idx = 0U; idx < from.size(); ++idx)
         out.insert(end(out), context.extract_sub<element_type>(from, idx));
     return out;
 }
コード例 #5
0
diff_result diff(value left, value right)
{
    diff_result result;
    if (left == right)
    {
        result.same = std::move(left);
    }
    else if (left.kind() != right.kind())
    {
        result.left  = std::move(left);
        result.right = std::move(right);
    }
    else switch (left.kind())
    {
    case kind::boolean:
    case kind::decimal:
    case kind::integer:
    case kind::null:
    case kind::string:
        result.left = std::move(left);
        result.right = std::move(right);
        break;
    case kind::array:
        result.same = array();
        result.left = array();
        result.right = array();
        for (value::size_type idx = 0; idx < std::min(left.size(), right.size()); ++idx)
        {
            diff_result subresult = diff(std::move(left.at(idx)), std::move(right.at(idx)));
            result.same.push_back(std::move(subresult.same));
            result.left.push_back(std::move(subresult.left));
            result.right.push_back(std::move(subresult.right));
        }

        if (left.size() > right.size())
            result.left.insert(result.left.end_array(),
                               std::make_move_iterator(left.begin_array() + right.size()),
                               std::make_move_iterator(left.end_array())
                              );
        else if (left.size() < right.size())
            result.right.insert(result.right.end_array(),
                                std::make_move_iterator(right.begin_array() + left.size()),
                                std::make_move_iterator(right.end_array())
                               );
        break;
    case kind::object:
        result.same = object();
        result.left = object();
        result.right = object();
        for (value::object_iterator liter = left.begin_object();
             liter != left.end_object();
             liter = left.erase(liter)
            )
        {
            auto riter = right.find(liter->first);
            if (riter == right.end_object())
            {
                result.left.insert({ liter->first, std::move(liter->second) });
            }
            else if (liter->second == riter->second)
            {
                result.same[liter->first] = std::move(liter->second);
                right.erase(riter);
            }
            else
            {
                diff_result subresult = diff(std::move(liter->second), std::move(riter->second));
                result.left[liter->first] = std::move(subresult.left);
                result.right[liter->first] = std::move(subresult.right);
                right.erase(riter);
            }
        }

        for (value::object_iterator riter = right.begin_object();
             riter != right.end_object();
             riter = right.erase(riter)
            )
        {
            result.right.insert({ riter->first, std::move(riter->second) });
        }
        break;
    }
    return result;
}