Esempio n. 1
0
sav_ctx_t *sav_ctx_init(sav_file_header_record_t *header, readstat_io_t *io) {
    sav_ctx_t *ctx = NULL;
    if ((ctx = malloc(sizeof(sav_ctx_t))) == NULL) {
        return NULL;
    }
    memset(ctx, 0, sizeof(sav_ctx_t));
    
    ctx->bswap = !(header->layout_code == 2 || header->layout_code == 3);

    ctx->data_is_compressed = (header->compressed != 0);
    ctx->record_count = ctx->bswap ? byteswap4(header->ncases) : header->ncases;
    ctx->fweight_index = ctx->bswap ? byteswap4(header->weight_index) : header->weight_index;

    ctx->missing_double = SAV_MISSING_DOUBLE;
    ctx->lowest_double = SAV_LOWEST_DOUBLE;
    ctx->highest_double = SAV_HIGHEST_DOUBLE;
    
    double bias = ctx->bswap ? byteswap_double(header->bias) : header->bias;
    
    if (bias != 100.0) {
        sav_ctx_free(ctx);
        return NULL;
    }
    
    ctx->varinfo_capacity = SAV_VARINFO_INITIAL_CAPACITY;
    
    if ((ctx->varinfo = calloc(ctx->varinfo_capacity, sizeof(spss_varinfo_t))) == NULL) {
        sav_ctx_free(ctx);
        return NULL;
    }

    ctx->io = io;
    
    return ctx;
}
Esempio n. 2
0
readstat_error_t sav_parse_timestamp(sav_ctx_t *ctx, sav_file_header_record_t *header) {
    readstat_error_t retval = READSTAT_OK;
    struct tm timestamp = { .tm_isdst = -1 };

    if ((retval = sav_parse_time(header->creation_time, sizeof(header->creation_time), &timestamp, ctx)) 
            != READSTAT_OK)
        goto cleanup;

    if ((retval = sav_parse_date(header->creation_date, sizeof(header->creation_date), &timestamp, ctx)) 
            != READSTAT_OK)
        goto cleanup;

    ctx->timestamp = mktime(&timestamp);

cleanup:
    return retval;
}

readstat_error_t readstat_parse_sav(readstat_parser_t *parser, const char *path, void *user_ctx) {
    readstat_error_t retval = READSTAT_OK;
    readstat_io_t *io = parser->io;
    sav_file_header_record_t header;
    sav_ctx_t *ctx = NULL;
    size_t file_size = 0;
    
    if (io->open(path, io->io_ctx) == -1) {
        return READSTAT_ERROR_OPEN;
    }

    file_size = io->seek(0, READSTAT_SEEK_END, io->io_ctx);
    if (file_size == -1) {
        retval = READSTAT_ERROR_SEEK;
        goto cleanup;
    }

    if (io->seek(0, READSTAT_SEEK_SET, io->io_ctx) == -1) {
        retval = READSTAT_ERROR_SEEK;
        goto cleanup;
    }

    if (io->read(&header, sizeof(sav_file_header_record_t), io->io_ctx) < sizeof(sav_file_header_record_t)) {
        retval = READSTAT_ERROR_READ;
        goto cleanup;
    }

    ctx = sav_ctx_init(&header, io);
    if (ctx == NULL) {
        retval = READSTAT_ERROR_PARSE;
        goto cleanup;
    }

    ctx->progress_handler = parser->progress_handler;
    ctx->error_handler = parser->error_handler;
    ctx->note_handler = parser->note_handler;
    ctx->value_handler = parser->value_handler;
    ctx->value_label_handler = parser->value_label_handler;
    ctx->input_encoding = parser->input_encoding;
    ctx->output_encoding = parser->output_encoding;
    ctx->user_ctx = user_ctx;
    ctx->file_size = file_size;
    if (ctx->record_count == -1 ||
            (parser->row_limit > 0 && parser->row_limit < ctx->record_count)) {
        ctx->row_limit = parser->row_limit;
    } else {
        ctx->row_limit = ctx->record_count;
    }
    
    if ((retval = sav_parse_timestamp(ctx, &header)) != READSTAT_OK)
        goto cleanup;

    if ((retval = sav_parse_records_pass1(ctx)) != READSTAT_OK)
        goto cleanup;
    
    if (io->seek(sizeof(sav_file_header_record_t), READSTAT_SEEK_SET, io->io_ctx) == -1) {
        retval = READSTAT_ERROR_SEEK;
        goto cleanup;
    }

    if ((retval = sav_update_progress(ctx)) != READSTAT_OK)
        goto cleanup;

    if ((retval = sav_parse_records_pass2(ctx)) != READSTAT_OK)
        goto cleanup;
 
    sav_set_n_segments_and_var_count(ctx);

    if (parser->info_handler) {
        if (parser->info_handler(ctx->record_count == -1 ? -1 : ctx->row_limit,
                    ctx->var_count, ctx->user_ctx)) {
            retval = READSTAT_ERROR_USER_ABORT;
            goto cleanup;
        }
    }

    if (parser->metadata_handler) {
        if ((retval = readstat_convert(ctx->file_label, sizeof(ctx->file_label),
                        header.file_label, sizeof(header.file_label), ctx->converter)) != READSTAT_OK)
            goto cleanup;

        if (parser->metadata_handler(ctx->file_label, ctx->timestamp, 2, ctx->user_ctx)) {
            retval = READSTAT_ERROR_USER_ABORT;
            goto cleanup;
        }
    }

    sav_parse_variable_display_parameter_record(ctx);

    if ((retval = sav_handle_variables(parser, ctx)) != READSTAT_OK)
        goto cleanup;

    if ((retval = sav_handle_fweight(parser, ctx)) != READSTAT_OK)
        goto cleanup;

    if (ctx->value_handler) {
        retval = sav_read_data(ctx);
    }
    
cleanup:
    io->close(io->io_ctx);
    if (ctx)
        sav_ctx_free(ctx);
    
    return retval;
}