streaming.con commit convert: CRLF_INPUT is a no-op in the output codepath (b0d9c69)
   1/*
   2 * Copyright (c) 2011, Google Inc.
   3 */
   4#include "cache.h"
   5#include "streaming.h"
   6
   7enum input_source {
   8        stream_error = -1,
   9        incore = 0,
  10        loose = 1,
  11        pack_non_delta = 2
  12};
  13
  14typedef int (*open_istream_fn)(struct git_istream *,
  15                               struct object_info *,
  16                               const unsigned char *,
  17                               enum object_type *);
  18typedef int (*close_istream_fn)(struct git_istream *);
  19typedef ssize_t (*read_istream_fn)(struct git_istream *, char *, size_t);
  20
  21struct stream_vtbl {
  22        close_istream_fn close;
  23        read_istream_fn read;
  24};
  25
  26#define open_method_decl(name) \
  27        int open_istream_ ##name \
  28        (struct git_istream *st, struct object_info *oi, \
  29         const unsigned char *sha1, \
  30         enum object_type *type)
  31
  32#define close_method_decl(name) \
  33        int close_istream_ ##name \
  34        (struct git_istream *st)
  35
  36#define read_method_decl(name) \
  37        ssize_t read_istream_ ##name \
  38        (struct git_istream *st, char *buf, size_t sz)
  39
  40/* forward declaration */
  41static open_method_decl(incore);
  42static open_method_decl(loose);
  43static open_method_decl(pack_non_delta);
  44
  45static open_istream_fn open_istream_tbl[] = {
  46        open_istream_incore,
  47        open_istream_loose,
  48        open_istream_pack_non_delta,
  49};
  50
  51struct git_istream {
  52        const struct stream_vtbl *vtbl;
  53        unsigned long size; /* inflated size of full object */
  54
  55        union {
  56                struct {
  57                        char *buf; /* from read_object() */
  58                        unsigned long read_ptr;
  59                } incore;
  60
  61                struct {
  62                        int fd; /* open for reading */
  63                        /* NEEDSWORK: what else? */
  64                } loose;
  65
  66                struct {
  67                        int fd; /* open for reading */
  68                        /* NEEDSWORK: what else? */
  69                } in_pack;
  70        } u;
  71};
  72
  73int close_istream(struct git_istream *st)
  74{
  75        return st->vtbl->close(st);
  76}
  77
  78ssize_t read_istream(struct git_istream *st, char *buf, size_t sz)
  79{
  80        return st->vtbl->read(st, buf, sz);
  81}
  82
  83static enum input_source istream_source(const unsigned char *sha1,
  84                                        enum object_type *type,
  85                                        struct object_info *oi)
  86{
  87        unsigned long size;
  88        int status;
  89
  90        oi->sizep = &size;
  91        status = sha1_object_info_extended(sha1, oi);
  92        if (status < 0)
  93                return stream_error;
  94        *type = status;
  95
  96        switch (oi->whence) {
  97        case OI_LOOSE:
  98                return loose;
  99        case OI_PACKED:
 100                if (!oi->u.packed.is_delta && big_file_threshold <= size)
 101                        return pack_non_delta;
 102                /* fallthru */
 103        default:
 104                return incore;
 105        }
 106}
 107
 108struct git_istream *open_istream(const unsigned char *sha1,
 109                                 enum object_type *type,
 110                                 unsigned long *size)
 111{
 112        struct git_istream *st;
 113        struct object_info oi;
 114        const unsigned char *real = lookup_replace_object(sha1);
 115        enum input_source src = istream_source(real, type, &oi);
 116
 117        if (src < 0)
 118                return NULL;
 119
 120        st = xmalloc(sizeof(*st));
 121        if (open_istream_tbl[src](st, &oi, real, type)) {
 122                if (open_istream_incore(st, &oi, real, type)) {
 123                        free(st);
 124                        return NULL;
 125                }
 126        }
 127        *size = st->size;
 128        return st;
 129}
 130
 131/*****************************************************************
 132 *
 133 * Loose object stream
 134 *
 135 *****************************************************************/
 136
 137static open_method_decl(loose)
 138{
 139        return -1; /* for now */
 140}
 141
 142
 143/*****************************************************************
 144 *
 145 * Non-delta packed object stream
 146 *
 147 *****************************************************************/
 148
 149static open_method_decl(pack_non_delta)
 150{
 151        return -1; /* for now */
 152}
 153
 154
 155/*****************************************************************
 156 *
 157 * In-core stream
 158 *
 159 *****************************************************************/
 160
 161static close_method_decl(incore)
 162{
 163        free(st->u.incore.buf);
 164        return 0;
 165}
 166
 167static read_method_decl(incore)
 168{
 169        size_t read_size = sz;
 170        size_t remainder = st->size - st->u.incore.read_ptr;
 171
 172        if (remainder <= read_size)
 173                read_size = remainder;
 174        if (read_size) {
 175                memcpy(buf, st->u.incore.buf + st->u.incore.read_ptr, read_size);
 176                st->u.incore.read_ptr += read_size;
 177        }
 178        return read_size;
 179}
 180
 181static struct stream_vtbl incore_vtbl = {
 182        close_istream_incore,
 183        read_istream_incore,
 184};
 185
 186static open_method_decl(incore)
 187{
 188        st->u.incore.buf = read_sha1_file_extended(sha1, type, &st->size, 0);
 189        st->u.incore.read_ptr = 0;
 190        st->vtbl = &incore_vtbl;
 191
 192        return st->u.incore.buf ? 0 : -1;
 193}