text:
#!/usr/bin/env python3

# This file is part of the Soletta Project
#
# Copyright (C) 2015 Intel Corporation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#   * Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in
#     the documentation and/or other materials provided with the
#     distribution.
#   * Neither the name of Intel Corporation nor the names of its
#     contributors may be used to endorse or promote products derived
#     from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import os
import json
import sys
import traceback
from collections import OrderedDict

def merge_schema(directory, definitions, to_merge):
    for schema in to_merge:
        if not '$ref' in schema:
            raise ValueError("no $ref in allOf")

        path, link = schema['$ref'].split('#')
        ref = load_json_schema(directory, path)
        defnref = link.split('/')[-1]
        definitions.update(ref[defnref])

def load_json_schema(directory, path, schemas={}):
    if path in schemas:
        return schemas[path]

    data = json.load(open(os.path.join(directory, path), "r", encoding='UTF-8'))
    if not data['$schema'].startswith("http://json-schema.org/schema"):
        raise ValueError("not a JSON schema")

    definitions = data.get("definitions", {})
    if not definitions:
        raise ValueError("empty definition block")

    if not 'title' in data:
        raise ValueError("JSON schema without title")

    required = set(data.get('required', []))

    for rt, descr in definitions.items():
        if 'allOf' in descr:
            merge_schema(directory, descr, descr['allOf'])
            del descr['allOf']
        if 'properties' in descr:
            for field, props in descr['properties'].items():
                doc = props.get('description', '')
                props['read_only'] = doc.startswith('ReadOnly,')
                props['required'] = field in required

                if props['read_only']:
                    props['description'] = props['description'][len('ReadOnly,'):].strip()

        descr['title'] = data['title']

    schemas[path] = definitions
    return definitions

JSON_TO_C = {
    "string": "char *",
    "integer": "int32_t",
    "boolean": "bool",
    "number": "double"
}

JSON_TO_C_TMP = {}
JSON_TO_C_TMP.update(JSON_TO_C)
JSON_TO_C_TMP['string'] = "const char *"
JSON_TO_C_TMP['number'] = "double"

JSON_TO_FLOW_GET_PKT = {
    "string": "sol_flow_packet_get_string",
    "integer": "sol_flow_packet_get_irange_value",
    "boolean": "sol_flow_packet_get_boolean",
    "number": "sol_flow_packet_get_drange_value"
}

JSON_TO_FLOW_SEND_PKT = {
    "string": "sol_flow_send_string_packet",
    "integer": "sol_flow_send_irange_value_packet",
    "boolean": "sol_flow_send_boolean_packet",
    "number": "sol_flow_send_drange_value_packet"
}

JSON_TO_INIT = {
    "string": "NULL",
    "integer": "0",
    "boolean": "false",
    "number": "0.0f"
}

JSON_TO_SOL_JSON = {
    "string": "string",
    "integer": "int",
    "boolean": "boolean",
    "number": "double"
}

def props_are_equivalent(p1, p2):
    # This disconsiders comments
    p1 = {k: get_type_from_property(v) for k, v in p1.items()}
    p2 = {k: get_type_from_property(v) for k, v in p2.items()}
    return p1 == p2

def object_fields_common_c(state_struct_name, name, props):
    fields = []
    for prop_name, descr in props.items():
        doc = '/* %s */' % descr.get('description', '???')
        if 'enum' in descr:
            var_type = 'enum %s_%s' % (state_struct_name, prop_name)
        else:
            var_type = JSON_TO_C[descr['type']]

        fields.append("%s %s; %s" % (var_type, prop_name, doc))

    return '\n'.join(fields)

def generate_object_to_repr_vec_fn_common_c(state_struct_name, name, props, client):
    fields = []
    for prop_name, prop_descr in props.items():
        if client and prop_descr['read_only']:
            continue

        if 'enum' in prop_descr:
            tbl = '%s_%s_tbl' % (state_struct_name, prop_name)
            val = '%s[state->state.%s]' % (tbl, prop_name)
            vallen = 'strlen(%s)' % val

            ftype = 'SOL_OIC_REPR_TEXT_STRING'
            fargs = (val, vallen)
        elif prop_descr['type'] == 'boolean':
            val = 'state->state.%s' % prop_name

            ftype = 'SOL_OIC_REPR_BOOLEAN'
            fargs = (val, )
        elif prop_descr['type'] == 'string':
            val = 'state->state.%s' % prop_name
            vallen = '%s ? strlen(%s) : 0' % (val, val)

            ftype = 'SOL_OIC_REPR_TEXT_STRING'
            fargs = (val, vallen)
        elif prop_descr['type'] == 'integer':
            val = 'state->state.%s' % prop_name

            ftype = 'SOL_OIC_REPR_INT'
            fargs = (val, )
        elif prop_descr['type'] == 'number':
            val = 'state->state.%s' % prop_name

            ftype = 'SOL_OIC_REPR_DOUBLE'
            fargs = (val, )
        else:
            raise ValueError('unknown field type: %s' % prop['type'])

        vars = {
            'ftype': ftype,
            'key': prop_name,
            'fargs': ', '.join(fargs)
        }
        fields.append('''f = sol_vector_append(repr);
SOL_NULL_CHECK(f, false);
*f = %(ftype)s("%(key)s", %(fargs)s);
''' % vars)

    if not fields:
        return ''

    return '''static bool
%(struct_name)s_to_repr_vec(const struct %(type)s_resource *resource, struct sol_vector *repr)
{
    struct %(struct_name)s *state = (struct %(struct_name)s *)resource;
    struct sol_oic_repr_field *f;

    %(fields)s

    return true;
}
''' % {
    'type': 'client' if client else 'server',
    'struct_name': name,
    'fields': '\n'.join(fields)
    }

def get_type_from_property(prop):
    if 'type' in prop:
        return prop['type']
    if 'enum' in prop:
        return 'enum:%s' % ','.join(prop['enum'])
    raise ValueError('Unknown type for property')

def object_to_repr_vec_fn_common_c(state_struct_name, name, props, client, equivalent={}):
    for item_name, item_props in equivalent.items():
        if item_props[0] == client and props_are_equivalent(props, item_props[1]):
            return '''static bool
%(struct_name)s_to_repr_vec(const struct %(type)s_resource *resource, struct sol_vector *repr)
{
    return %(item_name)s_to_repr_vec(resource, repr); /* %(item_name)s is equivalent to %(struct_name)s */
}
''' % {
        'item_name': item_name,
        'struct_name': name,
        'type': 'client' if client else 'server'
    }

    equivalent[name] = (client, props)
    return generate_object_to_repr_vec_fn_common_c(state_struct_name, name, props, client)

def object_to_repr_vec_fn_client_c(state_struct_name, name, props):
    return object_to_repr_vec_fn_common_c(state_struct_name, name, props, True)

def object_to_repr_vec_fn_server_c(state_struct_name, name, props):
    return object_to_repr_vec_fn_common_c(state_struct_name, name, props, False)

def get_field_integer_client_c(id, name, prop):
    return '''if (decode_mask & (1<<%(id)d) && streq(field->key, "%(field_name)s")) {
    if (field->type == SOL_OIC_REPR_TYPE_UINT)
        fields.%(field_name)s = field->v_uint;
    else if (field->type == SOL_OIC_REPR_TYPE_INT)
        fields.%(field_name)s = field->v_int;
    else if (field->type == SOL_OIC_REPR_TYPE_SIMPLE)
        fields.%(field_name)s = field->v_simple;
    else
        RETURN_ERROR(-EINVAL);
    decode_mask &= ~(1<<%(id)d);
    continue;
}
''' % {
        'field_name': name,
        'field_name_len': len(name),
        'id': id
    }

def get_field_number_client_c(id, name, prop):
    return '''if (decode_mask & (1<<%(id)d) && streq(field->key, "%(field_name)s")) {
    if (field->type == SOL_OIC_REPR_TYPE_DOUBLE)
        fields.%(field_name)s = field->v_double;
    else if (field->type == SOL_OIC_REPR_TYPE_FLOAT)
        fields.%(field_name)s = field->v_float;
    else
        RETURN_ERROR(-EINVAL);
    decode_mask &= ~(1<<%(id)d);
    continue;
}
''' % {
        'field_name': name,
        'field_name_len': len(name),
        'id': id
    }

def get_field_string_client_c(id, name, prop):
    return '''if (decode_mask & (1<<%(id)d) && streq(field->key, "%(field_name)s")) {
    if (field->type != SOL_OIC_REPR_TYPE_TEXT_STRING)
        RETURN_ERROR(-EINVAL);
    free(fields.%(field_name)s);
    fields.%(field_name)s = strndup(field->v_slice.data, field->v_slice.len);
    if (!fields.%(field_name)s)
        RETURN_ERROR(-EINVAL);
    decode_mask &= ~(1<<%(id)d);
    continue;
}
''' % {
        'field_name': name,
        'field_name_len': len(name),
        'id': id
    }

def get_field_boolean_client_c(id, name, prop):
    return '''if (decode_mask & (1<<%(id)d) && streq(field->key, "%(field_name)s")) {
    if (field->type != SOL_OIC_REPR_TYPE_BOOLEAN)
        RETURN_ERROR(-EINVAL);
    fields.%(field_name)s = field->v_boolean;
    decode_mask &= ~(1<<%(id)d);
    continue;
}
''' % {
        'field_name': name,
        'field_name_len': len(name),
        'id': id
    }

def get_field_enum_client_c(id, struct_name, name, prop):
    return '''if (decode_mask & (1<<%(id)d) && streq(field->key, "%(field_name)s")) {
    int val;

    if (field->type != SOL_OIC_REPR_TYPE_TEXT_STRING)
        RETURN_ERROR(-EINVAL);

    val = sol_str_table_lookup_fallback(%(struct_name)s_%(field_name)s_tbl,
        field->v_slice, -1);
    if (val < 0)
        RETURN_ERROR(-EINVAL);
    fields.%(field_name)s = (enum %(struct_name)s_%(field_name)s)val;
    decode_mask &= ~(1<<%(id)d);
    continue;
}
''' % {
        'struct_name': struct_name,
        'field_name': name,
        'field_name_len': len(name),
        'id': id
    }

def object_fields_from_repr_vec(name, props):
    id = 0
    fields = []
    for prop_name, prop in props.items():
        if 'enum' in prop:
            fields.append(get_field_enum_client_c(id, name, prop_name, prop))
        elif prop['type'] == 'string':
            fields.append(get_field_string_client_c(id, prop_name, prop))
        elif prop['type'] == 'integer':
            fields.append(get_field_integer_client_c(id, prop_name, prop))
        elif prop['type'] == 'number':
            fields.append(get_field_number_client_c(id, prop_name, prop))
        elif prop['type'] == 'boolean':
            fields.append(get_field_boolean_client_c(id, prop_name, prop))
        else:
            raise ValueError('unknown field type: %s' % prop['type'])
        id += 1
    return '\n'.join(fields)

def generate_object_from_repr_vec_fn_common_c(name, props):
    fields_init = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            fields_init.append('.%s = state->%s,' % (field_name, field_name))
        elif field_props['type'] == 'string':
            fields_init.append('.%s = state->%s ? strdup(state->%s) : NULL,' % (field_name, field_name, field_name))
        else:
            fields_init.append('.%s = state->%s,' % (field_name, field_name))

    fields_free = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            continue
        if field_props.get('type') == 'string':
            fields_free.append('free(fields.%s);' % (field_name))

    update_state = []
    for field_name, field_props in props.items():
        if not 'enum' in field_props and field_props.get('type') == 'string':
            update_state.append('free(state->%s);' % field_name)
        update_state.append('state->%s = fields.%s;' % (field_name, field_name))

    return '''static bool
%(struct_name)s_from_repr_vec(struct %(struct_name)s *state,
    const struct sol_vector *repr, uint32_t decode_mask)
{
    struct sol_oic_repr_field *field;
    uint16_t idx;
    struct %(struct_name)s fields = {
        %(fields_init)s
    };

    SOL_VECTOR_FOREACH_IDX (repr, field, idx) {
        %(fields)s
    }

    %(update_state)s

    return true;

out:
    %(free_fields)s
    return false;
}
''' % {
        'struct_name': name,
        'fields_init': '\n'.join(fields_init),
        'fields': object_fields_from_repr_vec(name, props),
        'free_fields': '\n'.join(fields_free),
        'update_state': '\n'.join(update_state)
    }

def object_from_repr_vec_fn_common_c(name, props, equivalent={}):
    for item_name, item_props in equivalent.items():
        if props_are_equivalent(props, item_props):
            return '''static bool
%(struct_name)s_from_repr_vec(struct %(struct_name)s *state,
    const sol_vector *repr, uint32_t decode_mask)
{
    /* %(item_name)s is equivalent to %(struct_name)s */
    return %(item_name)s_from_repr_vec((struct %(item_name)s *)state, repr, decode_mask);
}
''' % {
        'item_name': item_name,
        'struct_name': name
    }

    equivalent[name] = props
    return generate_object_from_repr_vec_fn_common_c(name, props)

def object_from_repr_vec_fn_client_c(state_struct_name, name, props):
    return '''static bool
%(struct_name)s_from_repr_vec(struct client_resource *resource, const struct sol_vector *repr)
{
    struct %(struct_name)s *res = (struct %(struct_name)s *)resource;
    return %(state_struct_name)s_from_repr_vec(&res->state, repr, ~0);
}
''' % {
        'struct_name': name,
        'state_struct_name': state_struct_name
    }

def object_from_repr_vec_fn_server_c(state_struct_name, name, props):
    decode_mask = 0
    id = 0
    for field_name, field_props in props.items():
        if not field_props['read_only']:
            decode_mask |= 1<<id
        id += 1

    if not decode_mask:
        return ''

    return '''static bool
%(struct_name)s_from_repr_vec(struct server_resource *resource, const struct sol_vector *repr)
{
    struct %(struct_name)s *res = (struct %(struct_name)s *)resource;
    return %(state_struct_name)s_from_repr_vec(&res->state, repr, 0x%(decode_mask)x);
}
''' % {
        'struct_name': name,
        'state_struct_name': state_struct_name,
        'decode_mask': decode_mask
    }

def object_inform_flow_fn_common_c(state_struct_name, name, props, client):
    send_flow_pkts = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            fn = 'sol_flow_send_string_packet'
            val = '%(struct_name)s_%(field_name)s_tbl[state->state.%(field_name)s].key' % {
                'struct_name': state_struct_name,
                'field_name': field_name
            }
        else:
            fn = JSON_TO_FLOW_SEND_PKT[field_props['type']]
            val = 'state->state.%(field_name)s' % {
                'field_name': field_name
            }

        send_flow_pkts.append('''%(flow_send_fn)s(resource->node, SOL_FLOW_NODE_TYPE_%(STRUCT_NAME)s__OUT__OUT_%(FIELD_NAME)s, %(val)s);''' % {
            'flow_send_fn': fn,
            'STRUCT_NAME': name.upper(),
            'FIELD_NAME': field_name.upper(),
            'val': val
        })

    return '''static void %(struct_name)s_inform_flow(struct %(type)s_resource *resource)
{
    struct %(struct_name)s *state = (struct %(struct_name)s *)resource;
    %(send_flow_pkts)s
}
''' % {
        'type': 'client' if client else 'server',
        'struct_name': name,
        'send_flow_pkts': '\n'.join(send_flow_pkts)
    }

def object_inform_flow_fn_client_c(state_struct_name, name, props):
    return object_inform_flow_fn_common_c(state_struct_name, name, props, True)

def object_inform_flow_fn_server_c(state_struct_name, name, props):
    read_only = all(field_props['read_only'] for field_name, field_props in props.items())
    return '' if read_only else object_inform_flow_fn_common_c(state_struct_name, name, props, False)

def object_open_fn_client_c(state_struct_name, resource_type, name, props):
    field_init = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            init = '(enum %s_%s)0' % (state_struct_name, field_name)
        else:
            init = JSON_TO_INIT[field_props.get('type', 'integer')]
        field_init.append('''resource->state.%(field_name)s = %(init)s;''' % {
            'field_name': field_name,
            'init': init
        })

    no_inputs = all(field_props['read_only'] for field_name, field_props in props.items())
    if no_inputs:
        to_repr_vec_fn = 'NULL'
    else:
        to_repr_vec_fn = '%s_to_repr_vec' % name

    return '''static int
%(struct_name)s_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    const struct sol_flow_node_type_%(struct_name)s_options *node_opts =
        (const struct sol_flow_node_type_%(struct_name)s_options *)options;
    static const struct client_resource_funcs funcs = {
        .to_repr_vec = %(to_repr_vec_fn)s,
        .from_repr_vec = %(struct_name)s_from_repr_vec,
        .inform_flow = %(struct_name)s_inform_flow,
        .found_port = SOL_FLOW_NODE_TYPE_%(STRUCT_NAME)s__OUT__FOUND
    };
    struct %(struct_name)s *resource = data;
    int r;

    r = client_resource_init(node, &resource->base, "%(resource_type)s", node_opts->device_id, &funcs);
    if (!r) {
        %(field_init)s
    }

    return 0;
}
''' % {
        'struct_name': name,
        'STRUCT_NAME': name.upper(),
        'resource_type': resource_type,
        'field_init': '\n'.join(field_init),
        'to_repr_vec_fn': to_repr_vec_fn
    }

def object_open_fn_server_c(state_struct_name, resource_type, name, props, definitions={'id':0}):
    def_id = definitions['id']
    definitions['id'] += 1

    no_inputs = all(field_props['read_only'] for field_name, field_props in props.items())
    if no_inputs:
        from_repr_vec_fn_name = 'NULL'
        inform_flow_fn_name = 'NULL'
    else:
        from_repr_vec_fn_name = '%s_from_repr_vec' % name
        inform_flow_fn_name = '%s_inform_flow' % name

    field_init = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            init = '(enum %s_%s)0' % (state_struct_name, field_name)
        else:
            init = JSON_TO_INIT[field_props.get('type', 'integer')]
        field_init.append('''resource->state.%(field_name)s = %(init)s;''' % {
            'field_name': field_name,
            'init': init
        })

    return '''static int
%(struct_name)s_open(struct sol_flow_node *node, void *data, const struct sol_flow_node_options *options)
{
    static const struct sol_str_slice rt_slice = SOL_STR_SLICE_LITERAL("%(resource_type)s");
    static const struct server_resource_funcs funcs = {
        .to_repr_vec = %(struct_name)s_to_repr_vec,
        .from_repr_vec = %(from_repr_vec_fn_name)s,
        .inform_flow = %(inform_flow_fn_name)s
    };
    struct %(struct_name)s *resource = data;
    int r;

    r = server_resource_init(&resource->base, node, rt_slice, &funcs);
    if (!r) {
        %(field_init)s
    }

    return r;
}
''' % {
        'struct_name': name,
        'resource_type': resource_type,
        'def_id': def_id,
        'from_repr_vec_fn_name': from_repr_vec_fn_name,
        'inform_flow_fn_name': inform_flow_fn_name,
        'field_init': '\n'.join(field_init)
    }

def object_close_fn_client_c(name, props):
    destroy_fields = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            continue
        if field_props.get('type') == 'string':
            destroy_fields.append('free(resource->state.%s);' % field_name)

    return '''static void %(struct_name)s_close(struct sol_flow_node *node, void *data)
{
    struct %(struct_name)s *resource = data;
    %(destroy_fields)s
    client_resource_close(&resource->base);
}
''' % {
        'struct_name': name,
        'destroy_fields': '\n'.join(destroy_fields)
    }

def object_close_fn_server_c(name, props):
    destroy_fields = []
    for field_name, field_props in props.items():
        if 'enum' in field_props:
            continue
        if field_props.get('type') == 'string':
            destroy_fields.append('free(resource->state.%s);' % field_name)

    return '''static void %(struct_name)s_close(struct sol_flow_node *node, void *data)
{
    struct %(struct_name)s *resource = data;
    %(destroy_fields)s
    server_resource_close(&resource->base);
}
''' % {
        'struct_name': name,
        'destroy_fields': '\n'.join(destroy_fields)
    }

def object_setters_fn_common_c(state_struct_name, name, props, client):
    fields = []
    for field, descr in props.items():
        if client and descr['read_only']:
            continue

        if 'enum' in descr:
            fields.append('''static int
%(struct_name)s_set_%(field_name)s(struct sol_flow_node *node, void *data, uint16_t port,
    uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct %(struct_name)s *resource = data;
    const char *var;

    if (!sol_flow_packet_get_string(packet, &var)) {
        int16_t val = sol_str_table_lookup_fallback(%(state_struct_name)s_%(field_name)s_tbl,
            sol_str_slice_from_str(var), -1);
        if (val >= 0) {
            resource->state.%(field_name)s = (enum %(state_struct_name)s_%(field_name)s)val;
            %(type)s_resource_schedule_update(&resource->base);
            return 0;
        }
        return -ENOENT;
    }
    return -EINVAL;
}
''' % {
        'field_name': field,
        'FIELD_NAME': field.upper(),
        'state_struct_name': state_struct_name,
        'STATE_STRUCT_NAME': state_struct_name.upper(),
        'struct_name': name,
        'type': 'client' if client else 'server'
    })

        else:
            fields.append('''static int
%(struct_name)s_set_%(field_name)s(struct sol_flow_node *node, void *data, uint16_t port,
    uint16_t conn_id, const struct sol_flow_packet *packet)
{
    struct %(struct_name)s *resource = data;
    %(c_type_tmp)s var;
    int r;

    r = %(c_getter)s(packet, &var);
    if (!r) {
        resource->state.%(field_name)s = (%(c_type)s) var;
        %(type)s_resource_schedule_update(&resource->base);
    }
    return r;
}
''' % {
        'struct_name': name,
        'field_name': field,
        'c_type': JSON_TO_C[descr['type']],
        'c_type_tmp': JSON_TO_C_TMP[descr['type']],
        'c_getter': JSON_TO_FLOW_GET_PKT[descr['type']],
        'type': 'client' if client else 'server'
    })

    return '\n'.join(fields)

def object_setters_fn_client_c(state_struct_name, name, props):
    return object_setters_fn_common_c(state_struct_name, name, props, True)

def object_setters_fn_server_c(state_struct_name, name, props):
    return object_setters_fn_common_c(state_struct_name, name, props, False)

def generate_enums_common_c(name, props):
    output = []
    for field, descr in props.items():
        if 'enum' in descr:
            if 'description' in descr:
                output.append('''/* %s */''' % descr['description'])
            output.append('''enum %(struct_name)s_%(field_name)s { %(items)s };''' % {
                'struct_name': name,
                'field_name': field,
                'items': ', '.join(('%s_%s_%s' % (name, field, item)).upper() for item in descr['enum'])
            })

            output.append('''static const struct sol_str_table %(struct_name)s_%(field_name)s_tbl[] = {
    %(items)s,
    { }
};''' % {
                'struct_name': name,
                'field_name': field,
                'items': ',\n'.join('SOL_STR_TABLE_ITEM(\"%s\", %s_%s_%s)' % (
                    item, name.upper(), field.upper(), item.upper()) for item in descr['enum'])
            })

    return '\n'.join(output)

def generate_object_client_c(resource_type, state_struct_name, name, props):
    return """struct %(struct_name)s {
    struct client_resource base;
    struct %(state_struct_name)s state;
};

%(to_repr_vec_fn)s
%(from_repr_vec_fn)s
%(inform_flow_fn)s
%(open_fn)s
%(close_fn)s
%(setters_fn)s
""" % {
    'state_struct_name': state_struct_name,
    'struct_name': name,
    'to_repr_vec_fn': object_to_repr_vec_fn_client_c(state_struct_name, name, props),
    'from_repr_vec_fn': object_from_repr_vec_fn_client_c(state_struct_name, name, props),
    'inform_flow_fn': object_inform_flow_fn_client_c(state_struct_name, name, props),
    'open_fn': object_open_fn_client_c(state_struct_name, resource_type, name, props),
    'close_fn': object_close_fn_client_c(name, props),
    'setters_fn': object_setters_fn_client_c(state_struct_name, name, props)
    }

def generate_object_server_c(resource_type, state_struct_name, name, props):
    return """struct %(struct_name)s {
    struct server_resource base;
    struct %(state_struct_name)s state;
};

%(to_repr_vec_fn)s
%(from_repr_vec_fn)s
%(inform_flow_fn)s
%(open_fn)s
%(close_fn)s
%(setters_fn)s
""" % {
    'struct_name': name,
    'state_struct_name': state_struct_name,
    'to_repr_vec_fn': object_to_repr_vec_fn_server_c(state_struct_name, name, props),
    'from_repr_vec_fn': object_from_repr_vec_fn_server_c(state_struct_name, name, props),
    'inform_flow_fn': object_inform_flow_fn_server_c(state_struct_name, name, props),
    'open_fn': object_open_fn_server_c(state_struct_name, resource_type, name, props),
    'close_fn': object_close_fn_server_c(name, props),
    'setters_fn': object_setters_fn_server_c(state_struct_name, name, props)
    }

def generate_object_common_c(name, props):
    return """%(enums)s
struct %(struct_name)s {
    %(struct_fields)s
};
%(from_repr_vec_fn)s
""" % {
        'enums': generate_enums_common_c(name, props),
        'struct_name': name,
        'struct_fields': object_fields_common_c(name, name, props),
        'from_repr_vec_fn': object_from_repr_vec_fn_common_c(name, props),
    }

def generate_object_json(resource_type, struct_name, node_name, title, props, server):
    in_ports = []
    for prop_name, prop_descr in props.items():
        if not server and prop_descr['read_only']:
            continue

        in_ports.append({
            'data_type': JSON_TO_SOL_JSON[prop_descr.get('type', 'string')],
            'description': prop_descr.get('description', '???'),
            'methods': {
                'process': '%s_set_%s' % (struct_name, prop_name)
            },
            'name': 'IN_%s' % prop_name.upper()
        })

    if server:
        out_ports = []
    else:
        out_ports = [{
            'data_type': 'boolean',
            'description': 'Outputs true if resource was found, false if not, or if unreachable',
            'name': 'FOUND'
        }]
    for prop_name, prop_descr in props.items():
        out_ports.append({
            'data_type': JSON_TO_SOL_JSON[prop_descr.get('type', 'string')],
            'description': prop_descr.get('description', '???'),
            'name': 'OUT_%s' % prop_name.upper()
        })

    output = {
        'methods': {
            'open': '%s_open' % struct_name,
            'close': '%s_close' % struct_name
        },
        'private_data_type': struct_name,
        'name': node_name,
        'url': 'http://solettaproject.org/doc/latest/components/%s.html' % node_name.replace('/', '-')
    }
    if server:
        output.update({
            'category': 'iot/server',
            'description': 'OIC Server (%s)' % title
        })
    else:
        output.update({
            'category': 'iot/client',
            'description': 'OIC Client (%s)' % title,
            'options': {
                'version': 1,
                'members': [
                    {
                        'data_type': 'string',
                        'description': 'Unique device ID (UUID, MAC address, etc)',
                        'name': 'device_id'
                    }
                ]
            }
        })

    if in_ports:
        output['in_ports'] = in_ports
    if out_ports:
        output['out_ports'] = out_ports

    return output

def generate_object(rt, title, props, json_name):
    def type_value(item):
        return '%s %s' % (get_type_from_property(item[1]), item[0])

    resource_type = rt

    if rt.startswith('oic.r.'):
        rt = rt[len('oic.r.'):]
    elif rt.startswith('core.'):
        rt = rt[len('core.'):]

    c_identifier = rt.replace(".", "_").replace("-", "_").lower()
    c_json_name = json_name.replace(".", "_").replace("-", "_").lower()
    flow_identifier = rt.replace(".", "-").replace("_", "-").lower()
    flow_json_name = json_name.replace(".", "-").replace("_", "-").lower()

    client_node_name = "%s/client-%s" % (flow_json_name, flow_identifier)
    client_struct_name = "%s_client_%s" % (c_json_name, c_identifier)
    server_node_name = "%s/server-%s" % (flow_json_name, flow_identifier)
    server_struct_name = "%s_server_%s" % (c_json_name, c_identifier)
    state_struct_name = "%s_state_%s" % (c_json_name, c_identifier)

    new_props = OrderedDict()
    for k, v in sorted(props.items(), key=type_value):
        new_props[k] = v
    props = new_props

    retval = {
        'c_common': generate_object_common_c(state_struct_name, props),
        'c_client': generate_object_client_c(resource_type, state_struct_name, client_struct_name, props),
        'c_server': generate_object_server_c(resource_type, state_struct_name, server_struct_name, props),
        'json_client': generate_object_json(resource_type, client_struct_name, client_node_name, title, props, False),
        'json_server': generate_object_json(resource_type, server_struct_name, server_node_name, title, props, True)
    }
    return retval

def generate_for_schema(directory, path, json_name):
    j = load_json_schema(directory, path)

    for rt, defn in j.items():
        if not (rt.startswith("oic.r.") or rt.startswith("core.")):
            raise ValueError("not an OIC resource definition")

        if defn.get('type') == 'object':
            yield generate_object(rt, defn['title'], defn['properties'],
                    json_name)

def master_json_as_string(generated, json_name):
    master_json = {
        '$schema': 'http://solettaproject.github.io/soletta/schemas/node-type-genspec.schema',
        'name': json_name,
        'meta': {
            'author': 'Intel Corporation',
            'license': 'BSD-3-Clause',
            'version': '1'
        },
        'types': [t['json_server'] for t in generated] + [t['json_client'] for t in generated]
    }
    return json.dumps(master_json, indent=4)

def master_c_as_string(generated, oic_gen_c, oic_gen_h):
    generated = list(generated)
    code = '''#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>

#include "%(oic_gen_h)s"

#include "sol-coap.h"
#include "sol-mainloop.h"
#include "sol-oic-common.h"
#include "sol-oic-client.h"
#include "sol-oic-server.h"
#include "sol-str-slice.h"
#include "sol-str-table.h"

#define DEFAULT_UDP_PORT 5683
#define MULTICAST_ADDRESS_IPv4 "224.0.1.187"
#define MULTICAST_ADDRESS_IPv6_LOCAL "ff02::fd"
#define MULTICAST_ADDRESS_IPv6_SITE "ff05::fd"
#define FIND_PERIOD_MS 5000
#define UPDATE_TIMEOUT_MS 50

#define streq(a, b) (strcmp((a), (b)) == 0)
#define likely(x)   __builtin_expect(!!(x), 1)

struct client_resource;
struct server_resource;

struct client_resource_funcs {
    bool (*to_repr_vec)(const struct client_resource *resource, struct sol_vector *repr_vec);
    bool (*from_repr_vec)(struct client_resource *resource, const struct sol_vector *repr);
    void (*inform_flow)(struct client_resource *resource);
    int found_port;
};

struct server_resource_funcs {
    bool (*to_repr_vec)(const struct server_resource *resource, struct sol_vector *repr_vec);
    bool (*from_repr_vec)(struct server_resource *resource, const struct sol_vector *repr);
    void (*inform_flow)(struct server_resource *resource);
};

struct client_resource {
    struct sol_flow_node *node;
    const struct client_resource_funcs *funcs;

    struct sol_oic_resource *resource;

    struct sol_timeout *find_timeout;
    struct sol_timeout *update_schedule_timeout;

    struct sol_oic_client client;

    const char *rt;
    char *device_id;
};

struct server_resource {
    struct sol_flow_node *node;
    const struct server_resource_funcs *funcs;

    struct sol_oic_server_resource *resource;
    struct sol_timeout *update_schedule_timeout;

    struct sol_oic_resource_type type;
};

static struct sol_network_link_addr multicast_ipv4, multicast_ipv6_local, multicast_ipv6_site;

static bool
initialize_multicast_addresses_once(void)
{
    static bool multicast_addresses_initialized = false;

    if (multicast_addresses_initialized)
        return true;

    multicast_ipv4 = (struct sol_network_link_addr) { .family = AF_INET, .port = DEFAULT_UDP_PORT };
    if (!sol_network_addr_from_str(&multicast_ipv4, MULTICAST_ADDRESS_IPv4)) {
        SOL_WRN("Could not parse multicast IP address");
        return false;
    }
    multicast_ipv6_local = (struct sol_network_link_addr) { .family = AF_INET6, .port = DEFAULT_UDP_PORT };
    if (!sol_network_addr_from_str(&multicast_ipv6_local, MULTICAST_ADDRESS_IPv6_LOCAL)) {
        SOL_WRN("Could not parse multicast IP address");
        return false;
    }
    multicast_ipv6_site = (struct sol_network_link_addr) { .family = AF_INET6, .port = DEFAULT_UDP_PORT };
    if (!sol_network_addr_from_str(&multicast_ipv6_site, MULTICAST_ADDRESS_IPv6_SITE)) {
        SOL_WRN("Could not parse multicast IP address");
        return false;
    }

    multicast_addresses_initialized = true;
    return true;
}

static bool
client_resource_implements_type(struct sol_oic_resource *oic_res, const char *resource_type)
{
    struct sol_str_slice rt = SOL_STR_SLICE_STR(resource_type, strlen(resource_type));
    struct sol_str_slice *type;
    uint16_t idx;

    SOL_VECTOR_FOREACH_IDX(&oic_res->types, type, idx) {
        if (sol_str_slice_eq(*type, rt))
            return true;
    }

    return false;
}

static void
state_changed(struct sol_oic_client *oic_cli, const struct sol_network_link_addr *cliaddr,
    const struct sol_str_slice *href, const struct sol_vector *reprs, void *data)
{
    struct client_resource *resource = data;

    if (!sol_str_slice_eq(*href, resource->resource->href)) {
        SOL_WRN("Received response to href=`%%.*s`, but resource href is `%%.*s`",
            SOL_STR_SLICE_PRINT(*href),
            SOL_STR_SLICE_PRINT(resource->resource->href));
        return;
    }

    if (!sol_network_link_addr_eq(cliaddr, &resource->resource->addr)) {
        char resaddr[SOL_INET_ADDR_STRLEN] = {0};
        char respaddr[SOL_INET_ADDR_STRLEN] = {0};

        if (!sol_network_addr_to_str(&resource->resource->addr, resaddr, sizeof(resaddr))) {
            SOL_WRN("Could not convert network address to string");
            return;
        }
        if (!sol_network_addr_to_str(cliaddr, respaddr, sizeof(respaddr))) {
            SOL_WRN("Could not convert network address to string");
            return;
        }

        SOL_WRN("Expecting response from %%s, got from %%s, ignoring", resaddr, respaddr);
        return;
    }

    if (resource->funcs->from_repr_vec(resource, reprs))
        resource->funcs->inform_flow(resource);
}

static void
found_resource(struct sol_oic_client *oic_cli, struct sol_oic_resource *oic_res, void *data)
{
    struct client_resource *resource = data;
    int r;

    /* Some OIC device sent this node a discovery response packet but node's already set up. */
    if (resource->resource) {
        SOL_DBG("Received discovery packet when resource already set up, ignoring");
        return;
    }

    if (memcmp(oic_res->device_id.data, resource->device_id, 16) != 0) {
        /* Not the droid we're looking for. */
        SOL_DBG("Received resource with an unknown device_id, ignoring");
        return;
    }

    /* FIXME: Should this check move to sol-oic-client? Does it actually make sense? */
    if (resource->rt && !client_resource_implements_type(oic_res, resource->rt)) {
        SOL_DBG("Received resource that does not implement rt=%%s, ignoring", resource->rt);
        return;
    }

    if (resource->find_timeout) {
        sol_timeout_del(resource->find_timeout);
        resource->find_timeout = NULL;
    }

    SOL_INF("Found resource matching device_id");
    resource->resource = sol_oic_resource_ref(oic_res);

    if (!sol_oic_client_resource_set_observable(oic_cli, resource->resource,
        state_changed, resource, true)) {
        SOL_WRN("Could not observe resource as requested, will try again");
    }

    r = sol_flow_send_boolean_packet(resource->node,
        resource->funcs->found_port, true);
    if (r < 0)
        SOL_WRN("Could not send flow packet, will try again");
}

static void
send_discovery_packets(struct client_resource *resource)
{
    if (resource->resource)
        return;

    sol_flow_send_boolean_packet(resource->node, resource->funcs->found_port, false);

    sol_oic_client_find_resource(&resource->client, &multicast_ipv4, resource->rt,
        found_resource, resource);
    sol_oic_client_find_resource(&resource->client, &multicast_ipv6_local, resource->rt,
        found_resource, resource);
    sol_oic_client_find_resource(&resource->client, &multicast_ipv6_site, resource->rt,
        found_resource, resource);
}

static bool
find_timer(void *data)
{
    struct client_resource *resource = data;

    if (resource->resource) {
        SOL_INF("Timer expired when node already configured; disabling");
        resource->find_timeout = NULL;
        return false;
    }

    send_discovery_packets(resource);
    return true;
}

static bool
server_resource_perform_update(void *data)
{
    struct server_resource *resource = data;
    struct sol_vector repr = SOL_VECTOR_INIT(struct sol_oic_repr_field);

    SOL_NULL_CHECK(resource->funcs->to_repr_vec, false);
    if (!resource->funcs->to_repr_vec(resource, &repr)) {
        SOL_WRN("Error while serializing update message");
    } else {
        resource->funcs->inform_flow(resource);
        sol_oic_notify_observers(resource->resource, &repr);
    }

    sol_vector_clear(&repr);

    resource->update_schedule_timeout = NULL;
    return false;
}

static void
server_resource_schedule_update(struct server_resource *resource)
{
    if (resource->update_schedule_timeout)
        return;

    resource->update_schedule_timeout = sol_timeout_add(UPDATE_TIMEOUT_MS,
        server_resource_perform_update, resource);
}

static sol_coap_responsecode_t
server_handle_put(const struct sol_network_link_addr *cliaddr, const void *data,
    const struct sol_vector *input, struct sol_vector *output)
{
    struct server_resource *resource = (struct server_resource *)data;

    if (!resource->funcs->from_repr_vec)
        return SOL_COAP_RSPCODE_NOT_IMPLEMENTED;

    if (resource->funcs->from_repr_vec(resource, input)) {
        server_resource_schedule_update(resource);
        return SOL_COAP_RSPCODE_CHANGED;
    }

    return SOL_COAP_RSPCODE_PRECONDITION_FAILED;
}

static sol_coap_responsecode_t
server_handle_get(const struct sol_network_link_addr *cliaddr, const void *data,
    const struct sol_vector *input, struct sol_vector *output)
{
    const struct server_resource *resource = data;

    if (!resource->funcs->to_repr_vec)
        return SOL_COAP_RSPCODE_NOT_IMPLEMENTED;

    if (!resource->funcs->to_repr_vec(resource, output))
        return SOL_COAP_RSPCODE_INTERNAL_ERROR;

    return SOL_COAP_RSPCODE_CONTENT;
}

// log_init() implementation happens within oic-gen.c
static void log_init(void);

static int
server_resource_init(struct server_resource *resource, struct sol_flow_node *node,
    struct sol_str_slice resource_type, const struct server_resource_funcs *funcs)
{
    log_init();

    if (sol_oic_server_init(DEFAULT_UDP_PORT) != 0) {
        SOL_WRN("Could not create %%.*s server", SOL_STR_SLICE_PRINT(resource_type));
        return -ENOTCONN;
    }

    resource->node = node;
    resource->update_schedule_timeout = NULL;
    resource->funcs = funcs;

    resource->type = (struct sol_oic_resource_type) {
        .api_version = SOL_OIC_RESOURCE_TYPE_API_VERSION,
        .resource_type = resource_type,
        .interface = SOL_STR_SLICE_LITERAL("oc.mi.def"),
        .get = { .handle = server_handle_get },
        .put = { .handle = server_handle_put },
    };

    resource->resource = sol_oic_server_add_resource(&resource->type,
        resource, SOL_OIC_FLAG_DISCOVERABLE | SOL_OIC_FLAG_OBSERVABLE | SOL_OIC_FLAG_ACTIVE);
    if (resource->resource)
        return 0;

    sol_oic_server_release();
    return -EINVAL;
}

static void
server_resource_close(struct server_resource *resource)
{
    if (resource->update_schedule_timeout)
        sol_timeout_del(resource->update_schedule_timeout);
    sol_oic_server_del_resource(resource->resource);
    sol_oic_server_release();
}

static unsigned int
as_nibble(const char c)
{
    if (c >= '0' && c <= '9')
        return c - '0';
    if (c >= 'a' && c <= 'f')
        return c - 'a' + 10;
    if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;

    SOL_WRN("Invalid hex character: %%d", c);
    return 0;
}

static char *
hex_ascii_to_binary(const char *ascii)
{
    char *binary = malloc(16);

    if (likely(binary)) {
        const char *p;
        size_t i;

        for (p = ascii, i = 0; i < 16; i++, p += 2)
            binary[i] = as_nibble(*p) << 4 | as_nibble(*(p + 1));
    }

    return binary;
}

static int
client_resource_init(struct sol_flow_node *node, struct client_resource *resource, const char *resource_type,
    const char *device_id, const struct client_resource_funcs *funcs)
{
    log_init();

    if (!initialize_multicast_addresses_once()) {
        SOL_ERR("Could not initialize multicast addresses");
        return -ENOTCONN;
    }

    assert(resource_type);

    if (!device_id || strlen(device_id) != 32)
        return -EINVAL;

    resource->client.api_version = SOL_OIC_CLIENT_API_VERSION;
    resource->client.server = sol_coap_server_new(0);
    SOL_NULL_CHECK(resource->client.server, -ENOMEM);

    resource->device_id = hex_ascii_to_binary(device_id);
    SOL_NULL_CHECK_GOTO(resource->device_id, nomem);

    resource->node = node;
    resource->find_timeout = NULL;
    resource->update_schedule_timeout = NULL;
    resource->resource = NULL;
    resource->funcs = funcs;
    resource->rt = resource_type;

    SOL_INF("Sending multicast packets to find resource with device_id %%s (rt=%%s)",
        device_id, resource->rt);
    resource->find_timeout = sol_timeout_add(FIND_PERIOD_MS, find_timer, resource);
    if (resource->find_timeout) {
        /* Perform a find now instead of waiting FIND_PERIOD_MS the first time.  If the
         * resource is found in the mean time, the timeout will be automatically disabled. */
        send_discovery_packets(resource);
        return 0;
    }

    SOL_ERR("Could not create timeout to find resource");
    free(resource->device_id);

nomem:
    sol_coap_server_unref(resource->client.server);
    return -ENOMEM;
}

static void
client_resource_close(struct client_resource *resource)
{
    free(resource->device_id);

    if (resource->find_timeout)
        sol_timeout_del(resource->find_timeout);
    if (resource->update_schedule_timeout)
        sol_timeout_del(resource->update_schedule_timeout);

    if (resource->resource) {
        bool r = sol_oic_client_resource_set_observable(&resource->client, resource->resource,
            NULL, NULL, false);
        if (!r)
            SOL_WRN("Could not unobserve resource");

        sol_oic_resource_unref(resource->resource);
    }

    sol_coap_server_unref(resource->client.server);
}

static bool
client_resource_perform_update(void *data)
{
    struct client_resource *resource = data;
    struct sol_vector repr = SOL_VECTOR_INIT(struct sol_oic_repr_field);

    SOL_NULL_CHECK_GOTO(resource->resource, disable_timeout);
    SOL_NULL_CHECK_GOTO(resource->funcs->to_repr_vec, disable_timeout);

    if (!resource->funcs->to_repr_vec(resource, &repr)) {
        SOL_WRN("Error while serializing update message");
    } else {
        int r = sol_oic_client_resource_request(&resource->client, resource->resource,
            SOL_COAP_METHOD_PUT, &repr, NULL, NULL);
        if (r < 0) {
            SOL_WRN("Could not send update request to resource, will try again");
            return true;
        }
    }

    sol_vector_clear(&repr);

disable_timeout:
    resource->update_schedule_timeout = NULL;
    return false;
}

static void
client_resource_schedule_update(struct client_resource *resource)
{
    if (resource->update_schedule_timeout)
        return;

    resource->update_schedule_timeout = sol_timeout_add(UPDATE_TIMEOUT_MS,
        client_resource_perform_update, resource);
}

#define RETURN_ERROR(errcode) do { goto out; } while(0)

%(generated_c_common)s
%(generated_c_client)s
%(generated_c_server)s

#undef RETURN_ERROR

#include "%(oic_gen_c)s"
''' % {
        'generated_c_common': '\n'.join(t['c_common'] for t in generated),
        'generated_c_client': '\n'.join(t['c_client'] for t in generated),
        'generated_c_server': '\n'.join(t['c_server'] for t in generated),
        'oic_gen_c': oic_gen_c,
        'oic_gen_h': oic_gen_h,
    }

    return code.replace('\n\n\n', '\n')

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("--schema-dir",
                        help="Directory where JSON schemas are located. "
                        "Names must start with 'oic.r.' or 'core.' and use "
                        "extension '.json'",
                        required=True)
    parser.add_argument("--node-type-json",
                        help="Path to store the master JSON with node type information",
                        required=True)
    parser.add_argument("--node-type-impl",
                        help="Path to store the node type implementation",
                        required=True)
    parser.add_argument("--node-type-gen-c",
                        help="Relative path to source generated with "
                        "sol-flow-node-type-gen for inclusion purposes.",
                        required=True)
    parser.add_argument("--node-type-gen-h",
                        help="Relative path to header generated with "
                        "sol-flow-node-type-gen for inclusion purposes.",
                        required=True)
    args = parser.parse_args()

    def seems_schema(path):
        return path.endswith('.json') and (path.startswith('oic.r.') or path.startswith('core.'))

    json_name = os.path.basename(args.node_type_json)
    if json_name.endswith(".json"):
        json_name = json_name[:-5]

    generated = []
    print('Generating code for schemas: ', end='')
    for path in (f for f in os.listdir(args.schema_dir) if seems_schema(f)):
        print(path, end=', ')

        try:
            for code in generate_for_schema(args.schema_dir, path, json_name):
                generated.append(code)
        except KeyError as e:
            if e.args[0] == 'array':
                print("(arrays unsupported)", end=' ')
            else:
                raise e
        except Exception as e:
            print('Ignoring due to exception in generator. Traceback follows:')
            traceback.print_exc(e, file=sys.stderr)
            continue

    print('\nWriting master JSON: %s' % args.node_type_json)
    open(args.node_type_json, 'w+', encoding='UTF-8').write(
            master_json_as_string(generated, json_name))

    print('Writing C: %s' % args.node_type_impl)
    open(args.node_type_impl, 'w+', encoding='UTF-8').write(
            master_c_as_string(generated, args.node_type_gen_c,
            args.node_type_gen_h))
    if os.path.exists('/usr/bin/indent'):
        print('Indenting generated C.')
        os.system("/usr/bin/indent -kr -l120 '%s'" % args.node_type_impl)

    print('Done.')


text:
<!DOCTYPE html>

		<meta charset="utf-8" />
		<link rel="stylesheet" type="text/css" href="css/examples.css">

		<title>item</title>

		<button id="xray">X-Ray</button>

			<button contenteditable="true">
				Some action

						Hey!

			</button>

redpajama_set_name: RedPajamaGithub


text:
from oslo_config import cfg
from stevedore import named
import threading

from barbican.common import config
from barbican.common import utils
from barbican import i18n as u
from barbican.plugin.crypto import base
from barbican.plugin.util import multiple_backends
from barbican.plugin.util import utils as plugin_utils

_PLUGIN_MANAGER = None
_PLUGIN_MANAGER_LOCK = threading.RLock()

CONF = config.new_config()

DEFAULT_PLUGIN_NAMESPACE = 'barbican.crypto.plugin'
DEFAULT_PLUGINS = ['simple_crypto']

crypto_opt_group = cfg.OptGroup(name='crypto',
                                title='Crypto Plugin Options')
crypto_opts = [
    cfg.StrOpt('namespace',
               default=DEFAULT_PLUGIN_NAMESPACE,
               help=u._('Extension namespace to search for plugins.')
               ),
    cfg.MultiStrOpt('enabled_crypto_plugins',
                    default=DEFAULT_PLUGINS,
                    help=u._('List of crypto plugins to load.')
                    )
]
CONF.register_group(crypto_opt_group)
CONF.register_opts(crypto_opts, group=crypto_opt_group)
config.parse_args(CONF)

config.set_module_config("crypto", CONF)

def list_opts():
    yield crypto_opt_group, crypto_opts

class _CryptoPluginManager(named.NamedExtensionManager):
    def __init__(self, conf=CONF, invoke_args=(), invoke_kwargs={}):
        """Crypto Plugin Manager

        Each time this class is initialized it will load a new instance
        of each enabled crypto plugin. This is undesirable, so rather than
        initializing a new instance of this class use the PLUGIN_MANAGER
        at the module level.
        """
        crypto_conf = config.get_module_config('crypto')
        plugin_names = self._get_internal_plugin_names(crypto_conf)

        super(_CryptoPluginManager, self).__init__(
            crypto_conf.crypto.namespace,
            plugin_names,
            invoke_on_load=False,  # Defer creating plugins to utility below.
            invoke_args=invoke_args,
            invoke_kwds=invoke_kwargs,
            name_order=True  # extensions sorted as per order of plugin names
        )

        plugin_utils.instantiate_plugins(
            self, invoke_args, invoke_kwargs)

    def get_plugin_store_generate(self, type_needed, algorithm=None,
                                  bit_length=None, mode=None, project_id=None):
        """Gets a secret store or generate plugin that supports provided type.

        :param type_needed: PluginSupportTypes that contains details on the
        type of plugin required
        :returns: CryptoPluginBase plugin implementation
        """
        active_plugins = multiple_backends.get_applicable_crypto_plugins(
            self, project_id=project_id, existing_plugin_name=None)

        if not active_plugins:
            raise base.CryptoPluginNotFound()

        for generating_plugin in active_plugins:
            if generating_plugin.supports(
                    type_needed, algorithm, bit_length, mode):
                break
        else:
            operation = (u._("store or generate a secret of type {secret_type}"
                             " with algorithm {algorithm}, bit length "
                             "{bit_length}, and mode {mode}")
                         .format(secret_type=type_needed,
                                 algorithm=algorithm,
                                 bit_length=bit_length,
                                 mode=mode))
            raise base.CryptoPluginUnsupportedOperation(operation=operation)

        return generating_plugin

    def get_plugin_retrieve(self, plugin_name_for_store):
        """Gets a secret retrieve plugin that supports the provided type.

        :param type_needed: PluginSupportTypes that contains details on the
        type of plugin required
        :returns: CryptoPluginBase plugin implementation
        """
        active_plugins = plugin_utils.get_active_plugins(self)

        if not active_plugins:
            raise base.CryptoPluginNotFound()

        for decrypting_plugin in active_plugins:
            plugin_name = utils.generate_fullname_for(decrypting_plugin)
            if plugin_name == plugin_name_for_store:
                break
        else:
            operation = (u._("retrieve a secret from plugin: {plugin}")
                         .format(plugin=plugin_name_for_store))
            raise base.CryptoPluginUnsupportedOperation(operation=operation)

        return decrypting_plugin

    def _get_internal_plugin_names(self, crypto_conf):
        """Gets plugin names used for loading via stevedore.

        When multiple secret store support is enabled, then crypto plugin names
        are read via updated configuration structure. If not enabled, then it
        reads MultiStr property in 'crypto' config section.
        """
        # to cache default global secret store value on first use
        self.global_default_store_dict = None
        if utils.is_multiple_backends_enabled():
            parsed_stores = multiple_backends.read_multiple_backends_config()
            plugin_names = [store.crypto_plugin for store in parsed_stores
                            if store.crypto_plugin]
        else:
            plugin_names = crypto_conf.crypto.enabled_crypto_plugins
        return plugin_names

def get_manager():
    """Return a singleton crypto plugin manager."""
    global _PLUGIN_MANAGER
    global _PLUGIN_MANAGER_LOCK
    if not _PLUGIN_MANAGER:
        with _PLUGIN_MANAGER_LOCK:
            if not _PLUGIN_MANAGER:
                _PLUGIN_MANAGER = _CryptoPluginManager()
    return _PLUGIN_MANAGER


text:
package es.rogermartinez.ratingsystem.impl;

import org.junit.Assert;
import org.junit.Test;

import java.util.List;

import es.rogermartinez.ratingsystem.Team;

/**
 * Created by roger on 10/6/16.
 */
public class ELORatingSystemTest {

    ELORatingSystem eloRatingSystem = new ELORatingSystem();

    @Test
    public void should_when_blah() {
        Team team1 = createTeamWith1000Score();
        Team team2 = createTeamWith1000Score();

        double score = eloRatingSystem.calculateEstimateRating(team1, team2);

        Assert.assertEquals(score, 0.5d, 0);
    }

    private Team createTeamWith1000Score() {
        Team team = new Team() {
            @Override
            public List<Player> getPlayers() {
                return null;
            }

            @Override
            public float getScore() {
                return 1000;
            }
        };
        return team;
    }
}


text:
namespace tracked_objects {
class Location;
}  // namespace tracked_objects

namespace syncer {

class SyncChange;

typedef std::vector<SyncChange> SyncChangeList;

// An interface for services that handle receiving SyncChanges.
class SYNC_EXPORT SyncChangeProcessor {
 public:
  // Whether a context change should force a datatype refresh or not.
  enum ContextRefreshStatus { NO_REFRESH, REFRESH_NEEDED };
  typedef base::Callback<void(const SyncData&)> GetSyncDataCallback;

  SyncChangeProcessor();
  virtual ~SyncChangeProcessor();

  // Process a list of SyncChanges.
  // Returns: A default SyncError (IsSet() == false) if no errors were
  //          encountered, and a filled SyncError (IsSet() == true)
  //          otherwise.
  // Inputs:
  //   |from_here|: allows tracking of where sync changes originate.
  //   |change_list|: is the list of sync changes in need of processing.
  virtual SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const SyncChangeList& change_list) = 0;

  // Fills a list of SyncData. This should create an up to date representation
  // of all the data known to the ChangeProcessor for |datatype|, and
  // should match/be a subset of the server's view of that datatype.
  //
  // WARNING: This can be a potentially slow & memory intensive operation and
  // should only be used when absolutely necessary / sparingly.
  virtual SyncDataList GetAllSyncData(ModelType type) const = 0;

  // Retrieves the SyncData identified by |type| and |sync_tag| and invokes
  // |callback| asynchronously. If no such SyncData exists locally, IsValid on
  // the SyncData passed to |callback| will return false.
  //
  // This is an asynchronous local operation that may result in disk IO.
  //
  // Refer to sync_data.h for a description of |sync_tag|.
  //
  // TODO(maniscalco): N.B. this method should really be pure virtual. An
  // implentation is provided here just to verify that everything compiles.
  // Update this method to be pure virtual (bug 353300).
  virtual void GetSyncData(const ModelType& type,
                           const std::string& sync_tag,
                           const GetSyncDataCallback& callback) const {}

  // Updates the context for |type|, triggering an optional context refresh.
  // Default implementation does nothing. A type's context is a per-client blob
  // that can affect all SyncData sent to/from the server, much like a cookie.
  // TODO(zea): consider pulling the refresh logic into a separate method
  // unrelated to datatype implementations.
  virtual syncer::SyncError UpdateDataTypeContext(
      ModelType type,
      ContextRefreshStatus refresh_status,
      const std::string& context);
};

}  // namespace syncer

#endif  // COMPONENTS_SYNC_API_SYNC_CHANGE_PROCESSOR_H_


text:
/*
 * (C) Copyright 2017 Kyle F. Downey.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cloudwall.exchange.coinbase;

import cloudwall.order.Side;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;

/**
 * A snapshot of the full GDAX level 3 order book as of a particular sequence number.
 *
 * @author Kyle F. Downey
 */
@SuppressWarnings("WeakerAccess")
class OrderBookSnapshot {
    private static final Logger log = LogManager.getLogger(OrderBookSnapshot.class);

    private long sequence;
    private final Collection<PostedOrder> bids = new ArrayList<>();
    private final Collection<PostedOrder> asks = new ArrayList<>();

    long getSequence() {
        return sequence;
    }

    void apply(OrderBook orderBook) {
        bids.forEach(bid -> orderBook.open(bid.orderId, Side.BUY, bid.price, bid.size));
        asks.forEach(ask -> orderBook.open(ask.orderId, Side.SELL, ask.price, ask.size));
    }

    public void decodeFrame(JsonParser parser) throws IOException {
        log.info("decoding OrderBookSnapshot");
        JsonToken token;
        while ((token = parser.nextToken()) != JsonToken.END_OBJECT) {
            switch (token) {
                case FIELD_NAME:
                    String fieldName = parser.getCurrentName();
                    switch (fieldName) {
                        case "sequence":
                            token = parser.nextToken();
                            assert token == JsonToken.VALUE_NUMBER_INT;
                            sequence = parser.getLongValue();
                            break;
                        case "bids":
                        case "asks":
                            token = parser.nextToken();
                            assert token == JsonToken.START_ARRAY;
                            while ((token = parser.nextToken()) != JsonToken.END_ARRAY) {
                                assert token == JsonToken.START_ARRAY;
                                token = parser.nextToken();
                                assert token == JsonToken.VALUE_STRING;
                                BigDecimal price = new BigDecimal(parser.getValueAsString());

                                token = parser.nextToken();
                                assert token == JsonToken.VALUE_STRING;
                                BigDecimal qty = new BigDecimal(parser.getValueAsString());

                                token = parser.nextToken();
                                assert token == JsonToken.VALUE_STRING;
                                String orderId = parser.getValueAsString();

                                if (fieldName.equals("bids")) {
                                    addBid(orderId, price, qty);
                                } else {
                                    addAsk(orderId, price, qty);
                                }
                                token = parser.nextToken();
                                assert token == JsonToken.END_ARRAY;
                            }
                            break;
                    }

            }
        }
    }

    void setSequence(long sequence) {
        this.sequence = sequence;
    }

    Collection<PostedOrder> getBids() {
        return bids;
    }

    void addBid(String orderId, BigDecimal price, BigDecimal size) {
        bids.add(new PostedOrder(orderId, price, size));
    }

    Collection<PostedOrder> getAsks() {
        return asks;
    }

    void addAsk(String orderId, BigDecimal price, BigDecimal size) {
        asks.add(new PostedOrder(orderId, price, size));
    }

    class PostedOrder {
        String orderId;
        BigDecimal price;
        BigDecimal size;

        private PostedOrder(String orderId, BigDecimal price, BigDecimal size) {
            this.orderId = orderId;
            this.price = price;
            this.size = size;
        }
    }
}


text:
#include "gm.h"
#include "SkArithmeticMode.h"
#include "SkOffsetImageFilter.h"
#include "SkXfermodeImageFilter.h"
#include "SkBitmapSource.h"

#define WIDTH 600
#define HEIGHT 600
#define MARGIN 12

namespace skiagm {

class XfermodeImageFilterGM : public GM {
public:
    XfermodeImageFilterGM(){
        this->setBGColor(0xFF000000);
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("xfermodeimagefilter");
    }

    void make_bitmap() {
        fBitmap.allocN32Pixels(80, 80);
        SkCanvas canvas(fBitmap);
        canvas.clear(0x00000000);
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(0xD000D000);
        paint.setTextSize(SkIntToScalar(96));
        const char* str = "e";
        canvas.drawText(str, strlen(str), SkIntToScalar(15), SkIntToScalar(65), paint);
    }

    void make_checkerboard() {
        fCheckerboard.allocN32Pixels(80, 80);
        SkCanvas canvas(fCheckerboard);
        canvas.clear(0x00000000);
        SkPaint darkPaint;
        darkPaint.setColor(0xFF404040);
        SkPaint lightPaint;
        lightPaint.setColor(0xFFA0A0A0);
        for (int y = 0; y < 80; y += 16) {
          for (int x = 0; x < 80; x += 16) {
            canvas.save();
            canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
            canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
            canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
            canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
            canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
            canvas.restore();
          }
        }
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(WIDTH, HEIGHT);
    }

    static void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint,
                           int x, int y) {
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        canvas->clipRect(SkRect::MakeWH(
            SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
        canvas->drawBitmap(bitmap, 0, 0, &paint);
        canvas->restore();
    }

    static void drawClippedPaint(SkCanvas* canvas, const SkRect& rect, const SkPaint& paint,
                          int x, int y) {
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        canvas->clipRect(rect);
        canvas->drawPaint(paint);
        canvas->restore();
    }

    virtual void onOnceBeforeDraw() SK_OVERRIDE {
        make_bitmap();
        make_checkerboard();
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        canvas->clear(0x00000000);
        SkPaint paint;

        const struct {
            SkXfermode::Mode  fMode;
            const char*         fLabel;
        } gModes[] = {
            { SkXfermode::kClear_Mode,    "Clear"     },
            { SkXfermode::kSrc_Mode,      "Src"       },
            { SkXfermode::kDst_Mode,      "Dst"       },
            { SkXfermode::kSrcOver_Mode,  "SrcOver"   },
            { SkXfermode::kDstOver_Mode,  "DstOver"   },
            { SkXfermode::kSrcIn_Mode,    "SrcIn"     },
            { SkXfermode::kDstIn_Mode,    "DstIn"     },
            { SkXfermode::kSrcOut_Mode,   "SrcOut"    },
            { SkXfermode::kDstOut_Mode,   "DstOut"    },
            { SkXfermode::kSrcATop_Mode,  "SrcATop"   },
            { SkXfermode::kDstATop_Mode,  "DstATop"   },
            { SkXfermode::kXor_Mode,      "Xor"       },

            { SkXfermode::kPlus_Mode,         "Plus"          },
            { SkXfermode::kModulate_Mode,     "Modulate"      },
            { SkXfermode::kScreen_Mode,       "Screen"        },
            { SkXfermode::kOverlay_Mode,      "Overlay"       },
            { SkXfermode::kDarken_Mode,       "Darken"        },
            { SkXfermode::kLighten_Mode,      "Lighten"       },
            { SkXfermode::kColorDodge_Mode,   "ColorDodge"    },
            { SkXfermode::kColorBurn_Mode,    "ColorBurn"     },
            { SkXfermode::kHardLight_Mode,    "HardLight"     },
            { SkXfermode::kSoftLight_Mode,    "SoftLight"     },
            { SkXfermode::kDifference_Mode,   "Difference"    },
            { SkXfermode::kExclusion_Mode,    "Exclusion"     },
            { SkXfermode::kMultiply_Mode,     "Multiply"      },
            { SkXfermode::kHue_Mode,          "Hue"           },
            { SkXfermode::kSaturation_Mode,   "Saturation"    },
            { SkXfermode::kColor_Mode,        "Color"         },
            { SkXfermode::kLuminosity_Mode,   "Luminosity"    },
        };

        int x = 0, y = 0;
        SkAutoTUnref<SkImageFilter> background(SkBitmapSource::Create(fCheckerboard));
        for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(gModes[i].fMode));
            SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
            paint.setImageFilter(filter);
            drawClippedBitmap(canvas, fBitmap, paint, x, y);
            x += fBitmap.width() + MARGIN;
            if (x + fBitmap.width() > WIDTH) {
                x = 0;
                y += fBitmap.height() + MARGIN;
            }
        }
        // Test arithmetic mode as image filter
        SkAutoTUnref<SkXfermode> mode(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
        SkAutoTUnref<SkImageFilter> filter(SkXfermodeImageFilter::Create(mode, background));
        paint.setImageFilter(filter);
        drawClippedBitmap(canvas, fBitmap, paint, x, y);
        x += fBitmap.width() + MARGIN;
        if (x + fBitmap.width() > WIDTH) {
            x = 0;
            y += fBitmap.height() + MARGIN;
        }
        // Test NULL mode
        filter.reset(SkXfermodeImageFilter::Create(NULL, background));
        paint.setImageFilter(filter);
        drawClippedBitmap(canvas, fBitmap, paint, x, y);
        x += fBitmap.width() + MARGIN;
        if (x + fBitmap.width() > WIDTH) {
            x = 0;
            y += fBitmap.height() + MARGIN;
        }
        SkRect clipRect = SkRect::MakeWH(SkIntToScalar(fBitmap.width() + 4),
                                         SkIntToScalar(fBitmap.height() + 4));
        // Test offsets on SrcMode (uses fixed-function blend)
        SkAutoTUnref<SkImageFilter> foreground(SkBitmapSource::Create(fBitmap));
        SkAutoTUnref<SkImageFilter> offsetForeground(SkOffsetImageFilter::Create(
            SkIntToScalar(4), SkIntToScalar(-4), foreground));
        SkAutoTUnref<SkImageFilter> offsetBackground(SkOffsetImageFilter::Create(
            SkIntToScalar(4), SkIntToScalar(4), background));
        mode.reset(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
        filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
        paint.setImageFilter(filter);
        drawClippedPaint(canvas, clipRect, paint, x, y);
        x += fBitmap.width() + MARGIN;
        if (x + fBitmap.width() > WIDTH) {
            x = 0;
            y += fBitmap.height() + MARGIN;
        }
        // Test offsets on Darken (uses shader blend)
        mode.reset(SkXfermode::Create(SkXfermode::kDarken_Mode));
        filter.reset(SkXfermodeImageFilter::Create(mode, offsetBackground, offsetForeground));
        paint.setImageFilter(filter);
        drawClippedPaint(canvas, clipRect, paint, x, y);
        x += fBitmap.width() + MARGIN;
        if (x + fBitmap.width() > WIDTH) {
            x = 0;
            y += fBitmap.height() + MARGIN;
        }
        // Test cropping
        static const size_t nbSamples = 3;
        SkXfermode::Mode sampledModes[nbSamples] = {SkXfermode::kOverlay_Mode,
                                                    SkXfermode::kSrcOver_Mode,
                                                    SkXfermode::kPlus_Mode};
        int offsets[nbSamples][4] = {{ 10,  10, -16, -16},
                                     { 10,  10,  10,  10},
                                     {-10, -10,  -6,  -6}};
        for (size_t i = 0; i < nbSamples; ++i) {
            SkIRect cropRect = SkIRect::MakeXYWH(offsets[i][0],
                                                 offsets[i][1],
                                                 fBitmap.width()  + offsets[i][2],
                                                 fBitmap.height() + offsets[i][3]);
            SkImageFilter::CropRect rect(SkRect::Make(cropRect));
            mode.reset(SkXfermode::Create(sampledModes[i]));
            filter.reset(SkXfermodeImageFilter::Create(
                                    mode, offsetBackground, offsetForeground, &rect));
            paint.setImageFilter(filter);
            drawClippedPaint(canvas, clipRect, paint, x, y);
            x += fBitmap.width() + MARGIN;
            if (x + fBitmap.width() > WIDTH) {
                x = 0;
                y += fBitmap.height() + MARGIN;
            }
        }
    }
private:
    SkBitmap fBitmap, fCheckerboard;
    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM( return new XfermodeImageFilterGM; );

}


text:
//
//  SSCollectionViewController.m
//  新特性界面
//
//  Created by YFL on 15/9/5.
//  Copyright (c) 2015年 text. All rights reserved.
//

#import "SSCollectionViewController.h"
#import "SSCollectionViewCell.h"

@interface SSCollectionViewController ()

@property(nonatomic,strong)UIPageControl *pageControl;

@end

@implementation SSCollectionViewController
- (UIPageControl *)pageControl
{
    if (_pageControl == nil) {
        //分页控件
        _pageControl = [[UIPageControl alloc] init];
        //总页数
        _pageControl.numberOfPages = 4;
        //控件尺寸会更具页书自动算出
        CGSize size = [_pageControl sizeForNumberOfPages:5];

        _pageControl.bounds = CGRectMake(0, 0 , size.width, size.height);
        //使用最大y貌似就能自动放最下面
        _pageControl.center = CGPointMake(self.view.center.x, CGRectGetMaxY(self.collectionView.bounds)-size.height/2);
        //设置按钮颜色
        _pageControl.pageIndicatorTintColor = [UIColor whiteColor];//备选按钮颜色
        _pageControl.currentPageIndicatorTintColor = [UIColor blackColor];//选中按钮颜色
        //    _pageControl.backgroundColor = [UIColor blackColor];

        //设置下默认初始第一页是0
        _pageControl.currentPage = 0;
        //监听一下,在oc中绝大多数控件都可以监听数值变化
        [_pageControl addTarget:self action:@selector(pageChanged) forControlEvents:UIControlEventValueChanged];

    }
    return _pageControl;
}

- (void)pageChanged
{
    CGFloat X = self.pageControl.currentPage * self.collectionView.bounds.size.width;
    [self.collectionView setContentOffset:CGPointMake(X, 0) animated:YES];

}

- (instancetype)init
{
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.itemSize = [UIScreen mainScreen].bounds.size;
    //设置行的边距
    layout.minimumLineSpacing = 0;
    //设置列的边距
    layout.minimumInteritemSpacing = 0;
    //设置离上下左右的间距
    layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);

    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    return [super initWithCollectionViewLayout:layout];
}

static NSString * const reuseIdentifier = @"Cell";

- (void)viewDidLoad {
    [super viewDidLoad];

    // Register cell classes
    [self.collectionView registerClass:[SSCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];

    //取消弹簧效果
    self.collectionView.bounces = NO;

    //不现实水平移动条
    self.collectionView.showsHorizontalScrollIndicator = NO;

    //自动滑到整页
    self.collectionView.pagingEnabled = YES;

    self.collectionView.backgroundColor = [UIColor greenColor];
    // Do any additional setup after loading the view.

    //添加分页符
    [self.view addSubview:self.pageControl];

}

#pragma mark <UICollectionViewDataSource>

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return 4;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    SSCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];

    //==============================图片写这里=================
    /*

     cell.image =

     */
    CGFloat red = arc4random()%255;
    CGFloat green = arc4random()%255;
    CGFloat blue = arc4random()%255;
    cell.backgroundColor = [UIColor colorWithRed:red/255 green:green/255 blue:blue/255 alpha:1.0];

    return cell;
}

//计算页数
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //计算在第几页图片
    int page = scrollView.contentOffset.x/scrollView.bounds.size.width;
    //分页的当前按钮在的页数等于页数
    self.pageControl.currentPage = page;

}

@end


text:
let bucket = (sigmaDelta) => {
  if (sigmaDelta > 500) {
    return 4;
  }
  if (sigmaDelta > 300) {
    return 3;
  }
  if (sigmaDelta > 100) {
    return 2;
  }
  return 1;
}

let bucket_qualitative = (sigmaDeltaBucketed) => {
    if (sigmaDeltaBucketed === 4) {
        return "Rare";
    }
    if (sigmaDeltaBucketed === 3) {
        return "Unusual";
    }
    if (sigmaDeltaBucketed === 2) {
        return "Common";
    }
    if (sigmaDeltaBucketed === 1) {
        return "Very common";
    }
}

let bucket_name = (sigmaDeltaBucketed) => {
    if (sigmaDeltaBucketed === 4) {
        return "weird";
    }
    if (sigmaDeltaBucketed === 3) {
        return "odd";
    }
    if (sigmaDeltaBucketed === 2) {
        return "common";
    }
    if (sigmaDeltaBucketed === 1) {
        return "vcommon";
    }
}

module.exports = {
  bucket: bucket,
  bucket_qualitative: bucket_qualitative,
  bucket_name: bucket_name
};


text:
import sys, os, traceback, string
import neo_cgi

def log (s):
  sys.stderr.write("CGI: %s\n" % s)

def exceptionString():
  import StringIO

  ## get the traceback message
  sfp = StringIO.StringIO()
  traceback.print_exc(file=sfp)
  exception = sfp.getvalue()
  sfp.close()

  return exception

def main (argv, environ):
  # log ("starting")
  cgi = neo_cgi.CGI("")

  try:
    hdf_file = cgi.hdf.getValue("CGI.PathTranslated", "")
    if hdf_file == "":
      cgi.error ("No PATH_TRANSLATED var")
      return

    x = string.rfind (hdf_file, '/')
    if x != -1:
      cgi.hdf.setValue ("hdf.loadpaths.0", hdf_file[:x])

    cgi.hdf.readFile(hdf_file)
    content = cgi.hdf.getValue("Content", "")
    if content == "":
      cgi.error ("No Content var specified in HDF file %s" % hdf_file)
      return

    cgi.display(content)

  except neo_cgi.CGIFinished:
    return
  except Exception, Reason:
    log ("Python Exception: %s" % (str(repr(Reason))))
    s = neo_cgi.text2html("Python Exception: %s" % exceptionString())
    cgi.error (s)

if __name__ == "__main__":
  main (sys.argv, os.environ)


text:
namespace mojo {
namespace edk {

ScopedPlatformHandle DuplicatePlatformHandle(PlatformHandle platform_handle) {
  DCHECK(platform_handle.is_valid());
  // Note that |dup()| returns -1 on error (which is exactly the value we use
  // for invalid |PlatformHandle| FDs).
  return ScopedPlatformHandle(PlatformHandle(dup(platform_handle.fd)));
}

}  // namespace edk
}  // namespace mojo


text:
using System;
using System.Windows.Forms;

namespace ReadOut
{
    /// <summary>
    /// Helper class to catch WM_SIZE messages via subclassing
    /// </summary>
    sealed class SubclassedWindow : NativeWindow
    {

        public bool IsDestroyed { get; private set; }

        /// <summary>
        /// Size of subclassed window has changed
        /// </summary>
        public event EventHandler SizeChanged;

        public event EventHandler GotFocus;

        public event EventHandler Destroyed;

        public delegate void KeyMessageEvent(ref Message m);
        public event KeyMessageEvent KeyMessage;

        /// <summary>
        /// Window procedure
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            switch ((SafeNativeMethods.WindowsMessages)m.Msg)
            {
                case SafeNativeMethods.WindowsMessages.WM_SIZE:
                    OnSizeChanged();
                    break;
                case SafeNativeMethods.WindowsMessages.WM_SETFOCUS:
                    OnGotFocus();
                    break;
                case SafeNativeMethods.WindowsMessages.WM_DESTROY:
                case SafeNativeMethods.WindowsMessages.WM_CLOSE:
                    IsDestroyed = true;
                    if (Destroyed != null)
                        Destroyed(this, new EventArgs());
                    break;
                //case SafeNativeMethods.WindowsMessages.WM_NCDESTROY: case SafeNativeMethods.WindowsMessages.WM_DESTROY:
                //    break;
                                                    case SafeNativeMethods.WindowsMessages.WM_KEYDOWN:
                case SafeNativeMethods.WindowsMessages.WM_SYSKEYDOWN:
//System.IO.File.AppendAllText("e:\\el.txt", m.WParam + " " + m.LParam + "\r\n\r\n");
                    if (KeyMessage != null)
                        KeyMessage(ref m);
                    break;
            }
        }

        /// <summary>
        /// Raise SizeChanged event
        /// </summary>
        private void OnSizeChanged()
        {
            if (SizeChanged != null)
                SizeChanged(this, null);
        }

        private void OnGotFocus()
        {
            if (GotFocus != null)
                GotFocus(this, null);
        }

    }
}


text:
package com.reason.ide.reference;

import com.intellij.psi.*;
import com.reason.ide.*;

public class ResolveJsxPropertyElementRESTest extends ORBasePlatformTestCase {
    public void test_basic() {
        configureCode("X.res", "let make = (~value) => <div/>");
        configureCode("A.res", "<X value<caret> =1></X>");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_basic_multiple_props() {
        configureCode("X.res", "let make = (~propA, ~propB, ~propC) => <div/>");
        configureCode("A.res", "<X propA propB propC<caret> />");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("X.make[propC]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_basic_nested() {
        configureCode("A.res", "module X = { let make = (~value) => <div/>; }; <X value<caret> =1></X>");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("A.X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_autoclose() {
        configureCode("X.res", "let make = (~value) => <div/>");
        configureCode("A.res", "<X value<caret> =1/>");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_open() {
        configureCode("A.res", "module X = { let make = (~value) => <div/>; }");
        configureCode("B.res", "open A; <X value<caret>=1");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("A.X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_multiple() {
        configureCode("A.res", "module X = { let make = (~value) => <div/> }\n module Y = { let make = (~value) => <div/> }");
        configureCode("B.res", "open A; <X value<caret>=1");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("A.X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }

    public void test_make_make() {
        configureCode("A.res", "module X = { let make = (~value) => <div/> }\n let make = (~value) => <X value<caret> = 1>");

        PsiElement e = myFixture.getElementAtCaret();
        assertEquals("A.X.make[value]", ((PsiQualifiedNamedElement) e).getQualifiedName());
    }
}


text:
namespace rl
{
	namespace sg
	{
		class Model;
		class Shape;

		class Body
		{
		public:
			typedef ::std::vector< Shape* >::iterator Iterator;

			Body(Model* model);

			virtual ~Body();

			virtual void add(Shape* shape);

			Iterator begin();

			virtual Shape* create(SoVRMLShape* shape) = 0;

			Iterator end();

			void getBoundingBoxPoints(const ::rl::math::Transform& frame, ::std::vector< ::rl::math::Vector3 >& p) const;

			Model* getModel() const;

			virtual ::std::string getName() const;

			::std::size_t getNumShapes() const;

			void getPoints(const ::rl::math::Transform& frame, ::std::vector< ::rl::math::Vector3 >& p) const;

			Shape* getShape(const ::std::size_t& i) const;

			virtual void getFrame(::rl::math::Transform& frame) = 0;

			virtual void remove(Shape* shape);

			virtual void setFrame(const ::rl::math::Transform& frame) = 0;

			virtual void setName(const ::std::string& name);

			::rl::math::Vector3 center;

			::rl::math::Vector3 max;

			::rl::math::Vector3 min;

			::std::vector< ::rl::math::Vector3 > points;

		protected:
			Model* model;

			::std::vector< Shape* > shapes;

		private:
			::std::string name;
		};
	}
}

#endif // _RL_SG_BODY_H_


text:
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package rdpclient.clip;

import java.util.HashMap;
import java.util.Map;

import rdpclient.rdp.RdpConstants;
import streamer.BaseElement;
import streamer.ByteBuffer;
import streamer.Element;
import streamer.Link;
import streamer.Pipeline;
import streamer.PipelineImpl;
import streamer.debug.MockSink;
import streamer.debug.MockSource;

public class ServerFormatListPDU extends BaseElement {

    protected ClipboardState state;

    public ServerFormatListPDU(String id, ClipboardState state) {
        super(id);
        this.state = state;
    }

    @Override
    public void handleData(ByteBuffer buf, Link link) {
        if (verbose)
            System.out.println("[" + this + "] INFO: Data received: " + buf + ".");

        parseFormatNames(buf);
        buf.unref();

        // Automatically send request for text-based data to insert it into local
        // clipboard
        ClipboardDataFormat textFormat = ClipboardDataFormat.findBestTextFormat(state.serverClipboardDataFormats);
        if (textFormat != null) {
            // Send response: OK
            sendFormatListParseResponse(true);
            // Request data
            sendFormatDataRequest(textFormat);
        } else {
            // Send response: FAIL, we are not interested in this data
            sendFormatListParseResponse(false);
        }
    }

    /**
     * The Format Data Request PDU is sent by the recipient of the Format List
     * PDU. It is used to request the data for one of the formats that was listed
     * in the Format List PDU.
     */
    protected void sendFormatDataRequest(ClipboardDataFormat textFormat) {

        if (verbose)
            System.out.println("[" + this + "] INFO: Sending request for data in following format: " + textFormat + ".");

        // Store data format to parse server response later
        state.serverRequestedFormat = textFormat;

        ByteBuffer buf = new ByteBuffer(12, true);

        // Type
        buf.writeShortLE(ServerClipRdrChannelRouter.CB_FORMAT_DATA_REQUEST);
        // Message flags
        buf.writeShortLE(0);
        // Length
        buf.writeIntLE(4);

        // ID of chosen format
        buf.writeIntLE(textFormat.id);

        buf.trimAtCursor();

        pushDataToPad(STDOUT, buf);
    }

    /**
     * The Format List Response PDU is sent as a reply to the Format List PDU. It
     * is used to indicate whether processing of the Format List PDU was
     * successful.
     *
     * @param b
     */
    protected void sendFormatListParseResponse(boolean ok) {
        ByteBuffer buf = new ByteBuffer(8, true);

        // Type
        buf.writeShortLE(ServerClipRdrChannelRouter.CB_FORMAT_LIST_RESPONSE);
        // Message flags
        buf.writeShortLE((ok) ? ServerClipRdrChannelRouter.CB_RESPONSE_OK : ServerClipRdrChannelRouter.CB_RESPONSE_FAIL);
        // Length
        buf.writeIntLE(0);

        buf.trimAtCursor();

        pushDataToPad(STDOUT, buf);
    }

    protected void parseFormatNames(ByteBuffer buf) {

        // Set will not be modified after creation, so there is no need to make it
        // synchronous.
        Map<Object, ClipboardDataFormat> formats = new HashMap<Object, ClipboardDataFormat>();

        while (buf.cursor < buf.length) {
            int id = buf.readSignedIntLE();

            String name;
            if (state.serverUseLongFormatNames) {
                // Long format names in Unicode
                name = buf.readVariableWideString(RdpConstants.CHARSET_16);
            } else {
                Boolean asciiNames = (Boolean)buf.getMetadata(ServerClipRdrChannelRouter.ASCII_NAMES);

                if (asciiNames != null && asciiNames) {
                    // Short format names in ASCII
                    name = buf.readString(32, RdpConstants.CHARSET_8);
                } else {
                    // Short format names in Unicode
                    name = buf.readString(32, RdpConstants.CHARSET_16);
                }

            }

            // Store format in map by both ID and name (if name is not empty)
            formats.put(id, new ClipboardDataFormat(id, name));
            if (name.length() > 0)
                formats.put(name, new ClipboardDataFormat(id, name));
        }

        if (verbose)
            System.out.println("Server supports following formats for clipboard data: " + formats.values().toString() + ".");

        state.serverClipboardDataFormats = formats;
    }

    /**
     * Example.
     */
    public static void main(String[] args) {
        // System.setProperty("streamer.Link.debug", "true");
        System.setProperty("streamer.Element.debug", "true");
        // System.setProperty("streamer.Pipeline.debug", "true");

        /* @formatter:off */
        byte[] packet = new byte[] {
                0x02, 0x00,  //  CLIPRDR_HEADER::msgType = CB_FORMAT_LIST (2)
                0x00, 0x00,  //  CLIPRDR_HEADER::msgFlags = 0
                (byte) 0xe0, 0x00, 0x00, 0x00,  //  CLIPRDR_HEADER::dataLen = 0xe0 = 224 bytes

                (byte) 0x8a, (byte) 0xc0, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0xc08a = 49290
                0x52, 0x00, 0x69, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = "Rich Text Format"

                0x45, (byte) 0xc1, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0xc145 = 49477
                0x52, 0x00, 0x69, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x78, 0x00,
                0x74, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00,
                0x20, 0x00, 0x57, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x74, 0x00,
                0x20, 0x00, 0x4f, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x73, 0x00,
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = "Rich Text Format Without Objects"

                0x43, (byte) 0xc1, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0xc143 = 49475
                0x52, 0x00, 0x54, 0x00, 0x46, 0x00, 0x20, 0x00, 0x41, 0x00, 0x73, 0x00, 0x20, 0x00, 0x54, 0x00,
                0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = "RTF As Text"

                0x01, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 1
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = ""

                0x0d, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0x0d = 13
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = ""

                0x04, (byte) 0xc0, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0xc004 = 49156
                0x4e, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x00, 0x00,  //  "Native"

                0x0e, (byte) 0xc0, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 0xc00e = 49166
                0x4f, 0x00, 0x62, 0x00, 0x6a, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x44, 0x00,
                0x65, 0x00, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6f, 0x00,
                0x72, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = "Object Descriptor"

                0x03, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 3
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = ""

                0x10, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 16
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = ""

                0x07, 0x00, 0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatId = 7
                0x00, 0x00,  //  CLIPRDR_LONG_FORMAT_NAME::formatName = ""
        };
        /* @formatter:on */

        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(packet));
        Element router = new ServerClipRdrChannelRouter("router");
        ClipboardState state = new ClipboardState();
        state.serverUseLongFormatNames = true;
        Element format_list = new ServerFormatListPDU("format_list", state);

        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {
                // Format List Response PDU
                0x03, 0x00, // CLIPRDR_HEADER::msgType = CB_FORMAT_LIST_RESPONSE (3)
                0x01, 0x00, // CLIPRDR_HEADER::msgFlags = 0x0001 = CB_RESPONSE_OK
                0x00, 0x00, 0x00, 0x00, // CLIPRDR_HEADER::dataLen = 0 bytes
        }, new byte[] {
                // Format Data Request PDU
                0x04, 0x00, // CLIPRDR_HEADER::msgType = CB_FORMAT_DATA_REQUEST (4)
                0x00, 0x00, // CLIPRDR_HEADER::msgFlags = 0
                0x04, 0x00, 0x00, 0x00, // CLIPRDR_HEADER::dataLen = 4 bytes
                0x0d, 0x00, 0x00, 0x00, // CLIPRDR_FORMAT_DATA_REQUEST::requestedFormatId
                // = 0x0d
        }));

        Pipeline pipeline = new PipelineImpl("test");
        pipeline.add(source, router, format_list, sink);
        pipeline.link("source", "router >format_list", "format_list", "sink");
        pipeline.runMainLoop("source", STDOUT, false, false);

        // Check state
        if (!(state.serverClipboardDataFormats.containsKey(49475) && state.serverClipboardDataFormats.containsKey("Rich Text Format")))
            throw new RuntimeException("Server format list packet parsed incorrectly.");

    }

}


text:
Python wrappers for [GTSAM 3](https://research.cc.gatech.edu/borg/download?destination=node%2F299).

This previously lived [here](https://github.com/spillai/conda-recipes-slam/tree/master/pygtsam/pygtsam) but it made sense to move it a separate repo.

## Build Instructions
GTSAM 3.2.1 (https://research.cc.gatech.edu/borg/sites/edu.borg/files/downloads/gtsam-3.2.1.zip)
 - There is a bug with Factor removal in GTSAM 3.2.1, see: https://bitbucket.org/gtborg/gtsam/pull-requests/272/fix-recalculate-batch-step-when-variables/diff
 - replace ..../gtsam-3.2.1/gtsam/nonlinear/ISAM2.cpp with https://github.com/spillai/pygtsam/blob/dev/fixedlag/factor_removal_fix/ISAM2.cpp; this is critical to enable fixed-lag smoothing
 - replace ..../gtsam-3.2.1/gtsam/nonlinear/ISAM2.h with https://github.com/spillai/pygtsam/blob/dev/fixedlag/factor_removal_fix/ISAM2.h; this allows us to enable/disable factor ID reuse after factor removal
 - note: you may have issues with C++ Boost, especially with ver. 1.58 or greater; you may have to build ver. 1.57 from source at: https://sourceforge.net/projects/boost/files/boost/1.57.0/, using instructions at: http://www.boost.org/doc/libs/1_61_0/more/getting_started/unix-variants.html; the required Boost libraries are: python,serialization,system,filesystem,thread,program_options,date_time,regex,timer,chrono
 - build from source
   - cd gtsam-3.2.1; mkdir build; cd build
   - cmake -DCMAKE_INSTALL_PREFIX=..../gtsam-3.2.1/ -DGTSAM_WITH_EIGEN_MKL=OFF -DGTSAM_WITH_EIGEN_MKL_OPENMP=OFF -DGTSAM_BUILD_EXAMPLES_ALWAYS=OFF -DGTSAM_BUILD_TESTS=OFF ..
   - make install
 - export LIBRARY and INCLUDE paths to add include and lib directories of CMAKE_INSTALL_PREFIX

Eigen 3 (sudo apt-get install libeigen3-dev)

Boost-Python (sudo apt-get install libboost-python-dev)

SuiteSparse (sudo apt-get install libsuitesparse-dev)

Google GLOG (sudo apt-get install libgoogle-glog-dev)

pygtsam
 - git clone https://github.com/spillai/pygtsam.git
 - build from source
   - cd pygtsam; mkdir build; cd build
   - cmake -DCMAKE_INSTALL_PREFIX=..../gtsam-3.2.1 -DCMAKE_PREFIX_PATH=..../gtsam-3.2.1/lib/cmake/GTSAM ..
   - make install
 - export PYTHONPATH to add lib directory of CMAKE_INSTALL_PREFIX

## Contribute
Feel free to contribute new factors and python-based applications for GTSAM on this branch, I'm sure [Frank Dellaert](http://www.cc.gatech.edu/~dellaert/FrankDellaert/Frank_Dellaert/Frank_Dellaert.html) will be ecstatic that more people are using factor graphs.


text:
using namespace std;

static int test_HttpC(){
    cout << "Go Testing" << __FILE__ << endl;

    HttpC http;
    std::string url = "http://m.baidu.com/?from=1002296a";

    http.setWriteToFile (true, true);
    http.get (url);

    cout << "http code:" << http.getStateCode () << endl;
    cout << "http content length:" << http.getContentLength () << endl;
    if (http.getContent ())
        cout << "content:" << (char*)http.getContent () << endl;

    return 0;
}

TC_Entry( HttpC )

#endif // ENABLE_TESTCASE


text:
module OrgSync
  class Resource::ApplicationNodejs < Resource::Application
    resource_name :application_nodejs

    property :shared_dirs,
      kind_of: Hash,
      default: {log: true, node_modules: false}
    property :script,
      kind_of: String,
      default: 'src/index.js'
    property :openfile_limit,
      kind_of: Fixnum
  end

  class Provider::ApplicationNodejs < Provider::Application
    provides :application_nodejs

    action(:before_init) { include_recipe 'os-nodejs' }

    action :before_deploy do
      config_systemd_service(
        app_cookbook: 'os-application_nodejs',
        svc_vars: {
          name: new_resource.name,
          cwd: current_path(),
          limit: new_resource.openfile_limit,
          script: ::File.join(current_path(), new_resource.script)
        })
    end
  end
end