static readstat_error_t dta_emit_fmtlist(readstat_writer_t *writer, dta_ctx_t *ctx) {
    int i;
    for (i=0; i<ctx->nvar; i++) {
        readstat_variable_t *r_variable = readstat_get_variable(writer, i);

        if (r_variable->format[0]) {
            strncpy(&ctx->fmtlist[ctx->fmtlist_entry_len*i],
                    r_variable->format, ctx->fmtlist_entry_len);
        } else {
            char *format = "%9s";
            if (r_variable->type == READSTAT_TYPE_CHAR) {
                format = DTA_DEFAULT_FORMAT_BYTE;
            } else if (r_variable->type == READSTAT_TYPE_INT16) {
                format = DTA_DEFAULT_FORMAT_INT16;
            } else if (r_variable->type == READSTAT_TYPE_INT32) {
                format = DTA_DEFAULT_FORMAT_INT32;
            } else if (r_variable->type == READSTAT_TYPE_FLOAT) {
                format = DTA_DEFAULT_FORMAT_FLOAT;
            } else if (r_variable->type == READSTAT_TYPE_DOUBLE) {
                format = DTA_DEFAULT_FORMAT_DOUBLE;
            }
            strncpy(&ctx->fmtlist[ctx->fmtlist_entry_len*i],
                    format, ctx->fmtlist_entry_len);
        }
    }
    return readstat_write_bytes(writer, ctx->fmtlist, ctx->fmtlist_len);
}
static readstat_error_t dta_emit_variable_labels(readstat_writer_t *writer, dta_ctx_t *ctx) {
    int i;
    for (i=0; i<ctx->nvar; i++) {
        readstat_variable_t *r_variable = readstat_get_variable(writer, i);

        strncpy(&ctx->variable_labels[ctx->variable_labels_entry_len*i], 
                r_variable->label, ctx->variable_labels_entry_len);
    }
    return readstat_write_bytes(writer, ctx->variable_labels, ctx->variable_labels_len);
}
static readstat_error_t dta_emit_varlist(readstat_writer_t *writer, dta_ctx_t *ctx) {
    int i;
    for (i=0; i<ctx->nvar; i++) {
        readstat_variable_t *r_variable = readstat_get_variable(writer, i);

        strncpy(&ctx->varlist[ctx->variable_name_len*i], 
                r_variable->name, ctx->variable_name_len);
    }
    return readstat_write_bytes(writer, ctx->varlist, ctx->varlist_len);
}
static readstat_error_t dta_emit_lbllist(readstat_writer_t *writer, dta_ctx_t *ctx) {
    int i;
    for (i=0; i<ctx->nvar; i++) {
        readstat_variable_t *r_variable = readstat_get_variable(writer, i);

        if (r_variable->label_set) {
            strncpy(&ctx->lbllist[ctx->lbllist_entry_len*i], 
                    r_variable->label_set->name, ctx->lbllist_entry_len);
        } else {
            memset(&ctx->lbllist[ctx->lbllist_entry_len*i], '\0', ctx->lbllist_entry_len);
        }
    }
    return readstat_write_bytes(writer, ctx->lbllist, ctx->lbllist_len);
}
static readstat_error_t dta_emit_typlist(readstat_writer_t *writer, dta_ctx_t *ctx) {
    readstat_error_t error = READSTAT_OK;
    int i;

    for (i=0; i<ctx->nvar; i++) {
        readstat_variable_t *r_variable = readstat_get_variable(writer, i);
        unsigned char type = 0x00;
        readstat_types_t user_type = r_variable->type;
        if (user_type == READSTAT_TYPE_CHAR) {
            type = DTA_111_TYPE_CODE_CHAR;
        } else if (user_type == READSTAT_TYPE_INT16) {
            type = DTA_111_TYPE_CODE_INT16;
        } else if (user_type == READSTAT_TYPE_INT32) {
            type = DTA_111_TYPE_CODE_INT32;
        } else if (user_type == READSTAT_TYPE_FLOAT) {
            type = DTA_111_TYPE_CODE_FLOAT;
        } else if (user_type == READSTAT_TYPE_DOUBLE) {
            type = DTA_111_TYPE_CODE_DOUBLE;
        } else if (user_type == READSTAT_TYPE_STRING) {
            size_t max_len = r_variable->width;
            if (max_len > 244)
                max_len = 244;
            
            type = max_len;
        }
        ctx->typlist[i] = type;
    }

    for (i=0; i<ctx->nvar; i++) {
        unsigned char byte = ctx->typlist[i];
        error = readstat_write_bytes(writer, &byte, 1);
        if (error != READSTAT_OK)
            goto cleanup;
    }
cleanup:
    return error;
}
Exemple #6
0
static int handle_fweight(int var_index, void *ctx) {
    rs_ctx_t *rs_ctx = (rs_ctx_t *)ctx;
    readstat_writer_t *writer = rs_ctx->writer;
    readstat_writer_set_fweight_variable(writer, readstat_get_variable(writer, var_index));
    return 0;
}
Exemple #7
0
static int handle_value(int obs_index, int var_index, readstat_value_t value, void *ctx) {
    rs_ctx_t *rs_ctx = (rs_ctx_t *)ctx;
    readstat_writer_t *writer = rs_ctx->writer;

    readstat_variable_t *variable = readstat_get_variable(writer, var_index);
    readstat_types_t type = readstat_value_type(value);
    readstat_error_t error = READSTAT_OK;

    if (var_index == 0) {
        if (obs_index == 0) {
            if (rs_ctx->out_format == RS_FORMAT_SAV) {
                error = readstat_begin_writing_sav(writer, rs_ctx, rs_ctx->row_count);
            } else if (rs_ctx->out_format == RS_FORMAT_DTA) {
                error = readstat_begin_writing_dta(writer, rs_ctx, rs_ctx->row_count);
            }
            if (error != READSTAT_OK)
                goto cleanup;
        }
        if (var_index == 0) {
            error = readstat_begin_row(writer);
            if (error != READSTAT_OK)
                goto cleanup;
        }
    }

    if (readstat_value_is_system_missing(value)) {
        error = readstat_insert_missing_value(writer, variable);
    } else if (type == READSTAT_TYPE_STRING || type == READSTAT_TYPE_LONG_STRING) {
        error = readstat_insert_string_value(writer, variable, readstat_string_value(value));
    } else if (type == READSTAT_TYPE_CHAR) {
        error = readstat_insert_char_value(writer, variable, readstat_char_value(value));
    } else if (type == READSTAT_TYPE_INT16) {
        error = readstat_insert_int16_value(writer, variable, readstat_int16_value(value));
    } else if (type == READSTAT_TYPE_INT32) {
        error = readstat_insert_int32_value(writer, variable, readstat_int32_value(value));
    } else if (type == READSTAT_TYPE_FLOAT) {
        error = readstat_insert_float_value(writer, variable, readstat_float_value(value));
    } else if (type == READSTAT_TYPE_DOUBLE) {
        error = readstat_insert_double_value(writer, variable, readstat_double_value(value));
    }
    if (error != READSTAT_OK)
        goto cleanup;

    if (var_index == rs_ctx->var_count - 1) {
        error = readstat_end_row(writer);
        if (error != READSTAT_OK)
            goto cleanup;

        if (obs_index == rs_ctx->row_count - 1) {
            error = readstat_end_writing(writer);
            if (error != READSTAT_OK)
                goto cleanup;
        }
    }

cleanup:
    if (error != READSTAT_OK)
        return 1;

    return 0;
}
static readstat_error_t xport_write_variables(readstat_writer_t *writer) {
    readstat_error_t retval = READSTAT_OK;
    int i;
    long offset = 0;
    int num_long_labels = 0;
    int any_has_long_format = 0;
    for (i=0; i<writer->variables_count; i++) {
        int needs_long_record = 0;
        readstat_variable_t *variable = readstat_get_variable(writer, i);
        size_t width = xport_variable_width(variable->type, variable->user_width);
        xport_namestr_t namestr = { 
            .nvar0 = i,
            .nlng = width,
            .npos = offset
        };
        if (readstat_variable_get_type_class(variable) == READSTAT_TYPE_CLASS_STRING) {
            namestr.ntype = SAS_COLUMN_TYPE_CHR;
        } else {
            namestr.ntype = SAS_COLUMN_TYPE_NUM;
        }

        copypad(namestr.nname, sizeof(namestr.nname), variable->name);
        copypad(namestr.nlabel, sizeof(namestr.nlabel), variable->label);

        if (variable->format[0]) {
            int decimals = 0;
            int width = 0;
            char name[24];

            sscanf(variable->format, "%s%d.%d", name, &width, &decimals);

            copypad(namestr.nform, sizeof(namestr.nform), name);
            namestr.nfl = width;
            namestr.nfd = decimals;

            copypad(namestr.niform, sizeof(namestr.niform), name);
            namestr.nifl = width;
            namestr.nifd = decimals;

            if (strlen(name) > 8) {
                any_has_long_format = 1;
                needs_long_record = 1;
            }
        }

        namestr.nfj = (variable->alignment == READSTAT_ALIGNMENT_RIGHT);

        if (writer->version == 8) {
            copypad(namestr.longname, sizeof(namestr.longname), variable->name);

            size_t label_len = strlen(variable->label);
            if (label_len > 40) {
                needs_long_record = 1;
            }
            namestr.labeln = label_len;
        }

        if (needs_long_record) {
            num_long_labels++;
        }

        offset += width;

        xport_namestr_bswap(&namestr);

        retval = xport_write_bytes(writer, &namestr, sizeof(xport_namestr_t));
        if (retval != READSTAT_OK)
            goto cleanup;
    }

    retval = xport_finish_record(writer);
    if (retval != READSTAT_OK)
        goto cleanup;

    if (writer->version == 8 && num_long_labels) {
        xport_header_record_t header = { 
            .name = "LABELV8",
            .num1 = num_long_labels };
        if (any_has_long_format) {
            strcpy(header.name, "LABELV9");
        }
        retval = xport_write_header_record_v8(writer, &header);
        if (retval != READSTAT_OK)
            goto cleanup;

        for (i=0; i<writer->variables_count; i++) {
            readstat_variable_t *variable = readstat_get_variable(writer, i);
            size_t label_len = strlen(variable->label);
            size_t name_len = strlen(variable->name);
            int has_long_label = 0;
            int has_long_format = 0;
            int format_len = 0;
            char format_name[24];
            memset(format_name, 0, sizeof(format_name));

            has_long_label = (label_len > 40);

            if (variable->format[0]) {
                int decimals = 2;
                int width = 8;

                int matches = sscanf(variable->format, "%s%d.%d", format_name, &width, &decimals);
                if (matches < 1) {
                    retval = READSTAT_ERROR_BAD_FORMAT_STRING;
                    goto cleanup;
                }
                format_len = strlen(format_name);
                if (format_len > 8) {
                    has_long_format = 1;
                }
            }

            if (has_long_format) {
                uint16_t labeldef[5] = { i, name_len, format_len, format_len, label_len };

                if (machine_is_little_endian()) {
                    labeldef[0] = byteswap2(labeldef[0]);
                    labeldef[1] = byteswap2(labeldef[1]);
                    labeldef[2] = byteswap2(labeldef[2]);
                    labeldef[3] = byteswap2(labeldef[3]);
                    labeldef[4] = byteswap2(labeldef[4]);
                }

                retval = readstat_write_bytes(writer, labeldef, sizeof(labeldef));
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, variable->name);
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, format_name);
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, format_name);
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, variable->label);
                if (retval != READSTAT_OK)
                    goto cleanup;

            } else if (has_long_label) {
                uint16_t labeldef[3] = { i, name_len, label_len };

                if (machine_is_little_endian()) {
                    labeldef[0] = byteswap2(labeldef[0]);
                    labeldef[1] = byteswap2(labeldef[1]);
                    labeldef[2] = byteswap2(labeldef[2]);
                }

                retval = readstat_write_bytes(writer, labeldef, sizeof(labeldef));
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, variable->name);
                if (retval != READSTAT_OK)
                    goto cleanup;

                retval = readstat_write_string(writer, variable->label);
                if (retval != READSTAT_OK)
                    goto cleanup;
            }
        }

        retval = xport_finish_record(writer);
        if (retval != READSTAT_OK)
            goto cleanup;
    }

cleanup:

    return retval;
}