\doxysubsection{scoop.\+c}
\label{scoop_8c_source}\index{scoop.c@{scoop.c}}
\mbox{\hyperlink{scoop_8c}{Go to the documentation of this file.}}
\begin{DoxyCode}{0}
\DoxyCodeLine{00001 \textcolor{comment}{/*= -\/*-\/ c-\/basic-\/offset: 4; indent-\/tabs-\/mode: nil; -\/*-\/}}
\DoxyCodeLine{00002 \textcolor{comment}{ *}}
\DoxyCodeLine{00003 \textcolor{comment}{ * librsync -\/-\/ the library for network deltas}}
\DoxyCodeLine{00004 \textcolor{comment}{ *}}
\DoxyCodeLine{00005 \textcolor{comment}{ * Copyright (C) 2000, 2001 by Martin Pool <mbp@sourcefrog.net>}}
\DoxyCodeLine{00006 \textcolor{comment}{ *}}
\DoxyCodeLine{00007 \textcolor{comment}{ * This program is free software; you can redistribute it and/or}}
\DoxyCodeLine{00008 \textcolor{comment}{ * modify it under the terms of the GNU Lesser General Public License}}
\DoxyCodeLine{00009 \textcolor{comment}{ * as published by the Free Software Foundation; either version 2.1 of}}
\DoxyCodeLine{00010 \textcolor{comment}{ * the License, or (at your option) any later version.}}
\DoxyCodeLine{00011 \textcolor{comment}{ *}}
\DoxyCodeLine{00012 \textcolor{comment}{ * This program is distributed in the hope that it will be useful, but}}
\DoxyCodeLine{00013 \textcolor{comment}{ * WITHOUT ANY WARRANTY; without even the implied warranty of}}
\DoxyCodeLine{00014 \textcolor{comment}{ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU}}
\DoxyCodeLine{00015 \textcolor{comment}{ * Lesser General Public License for more details.}}
\DoxyCodeLine{00016 \textcolor{comment}{ *}}
\DoxyCodeLine{00017 \textcolor{comment}{ * You should have received a copy of the GNU Lesser General Public}}
\DoxyCodeLine{00018 \textcolor{comment}{ * License along with this program; if not, write to the Free Software}}
\DoxyCodeLine{00019 \textcolor{comment}{ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.}}
\DoxyCodeLine{00020 \textcolor{comment}{ */}}
\DoxyCodeLine{00021 }
\DoxyCodeLine{00022                               \textcolor{comment}{/*=}}
\DoxyCodeLine{00023 \textcolor{comment}{                               | To walk on water you've gotta sink}}
\DoxyCodeLine{00024 \textcolor{comment}{                               | in the ice.}}
\DoxyCodeLine{00025 \textcolor{comment}{                               |   -\/-\/ Shihad, `The General Electric'.}}
\DoxyCodeLine{00026 \textcolor{comment}{                               */}}
\DoxyCodeLine{00027 \textcolor{comment}{}}
\DoxyCodeLine{00028 \textcolor{comment}{/** \(\backslash\)file scoop.c}}
\DoxyCodeLine{00029 \textcolor{comment}{ * This file deals with readahead from caller-\/supplied buffers.}}
\DoxyCodeLine{00030 \textcolor{comment}{ *}}
\DoxyCodeLine{00031 \textcolor{comment}{ * Many functions require a certain minimum amount of contiguous input data to}}
\DoxyCodeLine{00032 \textcolor{comment}{ * do their processing. For example, to calculate a strong checksum of a block}}
\DoxyCodeLine{00033 \textcolor{comment}{ * we need at least a block of input.}}
\DoxyCodeLine{00034 \textcolor{comment}{ *}}
\DoxyCodeLine{00035 \textcolor{comment}{ * Since we put the buffers completely under the control of the caller, we}}
\DoxyCodeLine{00036 \textcolor{comment}{ * can't count on ever getting this much data all in one go. We can't simply}}
\DoxyCodeLine{00037 \textcolor{comment}{ * wait, because the caller might have a smaller buffer than we require and so}}
\DoxyCodeLine{00038 \textcolor{comment}{ * we'll never get it.}}
\DoxyCodeLine{00039 \textcolor{comment}{ *}}
\DoxyCodeLine{00040 \textcolor{comment}{ * Stream input data is used directly if there is sufficient data to satisfy}}
\DoxyCodeLine{00041 \textcolor{comment}{ * the readhead requests, otherwise it is copied and accumulated into an}}
\DoxyCodeLine{00042 \textcolor{comment}{ * internal buffer until there is enough. This means for large input buffers we}}
\DoxyCodeLine{00043 \textcolor{comment}{ * can leave a "{}tail"{} of unprocessed data in the input buffer, and only consume}}
\DoxyCodeLine{00044 \textcolor{comment}{ * all the data if it was too small and start accumulating into the internal}}
\DoxyCodeLine{00045 \textcolor{comment}{ * buffer. Provided the input buffers always have enough data we avoid copying}}
\DoxyCodeLine{00046 \textcolor{comment}{ * into the internal buffer at all.}}
\DoxyCodeLine{00047 \textcolor{comment}{ *}}
\DoxyCodeLine{00048 \textcolor{comment}{ * \(\backslash\)todo We probably know a maximum amount of data that can be scooped up, so}}
\DoxyCodeLine{00049 \textcolor{comment}{ * we could just avoid dynamic allocation. However that can't be fixed at}}
\DoxyCodeLine{00050 \textcolor{comment}{ * compile time, because when generating a delta it needs to be large enough to}}
\DoxyCodeLine{00051 \textcolor{comment}{ * hold one full block. Perhaps we can set it up when the job is allocated? It}}
\DoxyCodeLine{00052 \textcolor{comment}{ * would be kind of nice to not do any memory allocation after startup, as}}
\DoxyCodeLine{00053 \textcolor{comment}{ * bzlib does this. */}}
\DoxyCodeLine{00054 }
\DoxyCodeLine{00055 \textcolor{preprocessor}{\#include "{}config.h"{}}             \textcolor{comment}{/* IWYU pragma: keep */}}
\DoxyCodeLine{00056 \textcolor{preprocessor}{\#include <assert.h>}}
\DoxyCodeLine{00057 \textcolor{preprocessor}{\#include <stdlib.h>}}
\DoxyCodeLine{00058 \textcolor{preprocessor}{\#include <string.h>}}
\DoxyCodeLine{00059 \textcolor{preprocessor}{\#include "{}librsync.h"{}}}
\DoxyCodeLine{00060 \textcolor{preprocessor}{\#include "{}job.h"{}}}
\DoxyCodeLine{00061 \textcolor{preprocessor}{\#include "{}scoop.h"{}}}
\DoxyCodeLine{00062 \textcolor{preprocessor}{\#include "{}trace.h"{}}}
\DoxyCodeLine{00063 \textcolor{preprocessor}{\#include "{}util.h"{}}}
\DoxyCodeLine{00064 \textcolor{comment}{}}
\DoxyCodeLine{00065 \textcolor{comment}{/** Try to accept a from the input buffer to get LEN bytes in the scoop. */}}
\DoxyCodeLine{00066 \textcolor{keyword}{static} \textcolor{keyword}{inline} \textcolor{keywordtype}{void} rs\_scoop\_input(rs\_job\_t *job, \textcolor{keywordtype}{size\_t} len)}
\DoxyCodeLine{00067 \{}
\DoxyCodeLine{00068     rs\_buffers\_t *stream = job-\/>stream;}
\DoxyCodeLine{00069     \textcolor{keywordtype}{size\_t} tocopy;}
\DoxyCodeLine{00070 }
\DoxyCodeLine{00071     assert(len > job-\/>scoop\_avail);}
\DoxyCodeLine{00072 }
\DoxyCodeLine{00073     \textcolor{keywordflow}{if} (job-\/>scoop\_alloc < len) \{}
\DoxyCodeLine{00074         \textcolor{comment}{/* Need to allocate a larger scoop. */}}
\DoxyCodeLine{00075         rs\_byte\_t *newbuf;}
\DoxyCodeLine{00076         \textcolor{keywordtype}{size\_t} newsize;}
\DoxyCodeLine{00077         \textcolor{keywordflow}{for} (newsize = 64; newsize < len; newsize <<= 1) ;}
\DoxyCodeLine{00078         newbuf = rs\_alloc(newsize, \textcolor{stringliteral}{"{}scoop buffer"{}});}
\DoxyCodeLine{00079         \textcolor{keywordflow}{if} (job-\/>scoop\_avail)}
\DoxyCodeLine{00080             memcpy(newbuf, job-\/>scoop\_next, job-\/>scoop\_avail);}
\DoxyCodeLine{00081         \textcolor{keywordflow}{if} (job-\/>scoop\_buf)}
\DoxyCodeLine{00082             free(job-\/>scoop\_buf);}
\DoxyCodeLine{00083         job-\/>scoop\_buf = job-\/>scoop\_next = newbuf;}
\DoxyCodeLine{00084         rs\_trace(\textcolor{stringliteral}{"{}resized scoop buffer to "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes from "{}} FMT\_SIZE \textcolor{stringliteral}{"{}"{}},}
\DoxyCodeLine{00085                  newsize, job-\/>scoop\_alloc);}
\DoxyCodeLine{00086         job-\/>scoop\_alloc = newsize;}
\DoxyCodeLine{00087     \} \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (job-\/>scoop\_buf + job-\/>scoop\_alloc < job-\/>scoop\_next + len) \{}
\DoxyCodeLine{00088         \textcolor{comment}{/* Move existing data to the front of the scoop. */}}
\DoxyCodeLine{00089         rs\_trace(\textcolor{stringliteral}{"{}moving scoop "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes to reuse "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes"{}},}
\DoxyCodeLine{00090                  job-\/>scoop\_avail, (\textcolor{keywordtype}{size\_t})(job-\/>scoop\_next -\/ job-\/>scoop\_buf));}
\DoxyCodeLine{00091         memmove(job-\/>scoop\_buf, job-\/>scoop\_next, job-\/>scoop\_avail);}
\DoxyCodeLine{00092         job-\/>scoop\_next = job-\/>scoop\_buf;}
\DoxyCodeLine{00093     \}}
\DoxyCodeLine{00094     \textcolor{comment}{/* take as much input as is available, to give up to LEN bytes in the}}
\DoxyCodeLine{00095 \textcolor{comment}{       scoop. */}}
\DoxyCodeLine{00096     tocopy = len -\/ job-\/>scoop\_avail;}
\DoxyCodeLine{00097     \textcolor{keywordflow}{if} (tocopy > stream-\/>avail\_in)}
\DoxyCodeLine{00098         tocopy = stream-\/>avail\_in;}
\DoxyCodeLine{00099     assert(job-\/>scoop\_next + tocopy + job-\/>scoop\_avail <=}
\DoxyCodeLine{00100            job-\/>scoop\_buf + job-\/>scoop\_alloc);}
\DoxyCodeLine{00101 }
\DoxyCodeLine{00102     memcpy(job-\/>scoop\_next + job-\/>scoop\_avail, stream-\/>next\_in, tocopy);}
\DoxyCodeLine{00103     rs\_trace(\textcolor{stringliteral}{"{}accepted "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes from input to scoop"{}}, tocopy);}
\DoxyCodeLine{00104     job-\/>scoop\_avail += tocopy;}
\DoxyCodeLine{00105     stream-\/>next\_in += tocopy;}
\DoxyCodeLine{00106     stream-\/>avail\_in -\/= tocopy;}
\DoxyCodeLine{00107 \}}
\DoxyCodeLine{00108 \textcolor{comment}{}}
\DoxyCodeLine{00109 \textcolor{comment}{/** Advance the input cursor forward \(\backslash\)p len bytes.}}
\DoxyCodeLine{00110 \textcolor{comment}{ *}}
\DoxyCodeLine{00111 \textcolor{comment}{ * This is used after doing readahead, when you decide you want to keep it. \(\backslash\)p}}
\DoxyCodeLine{00112 \textcolor{comment}{ * len must be no more than the amount of available data, so you can't cheat.}}
\DoxyCodeLine{00113 \textcolor{comment}{ *}}
\DoxyCodeLine{00114 \textcolor{comment}{ * So when creating a delta, we require one block of readahead. But after}}
\DoxyCodeLine{00115 \textcolor{comment}{ * examining that block, we might decide to advance over all of it (if there is}}
\DoxyCodeLine{00116 \textcolor{comment}{ * a match), or just one byte (if not). */}}
\DoxyCodeLine{00117 \textcolor{keywordtype}{void} rs\_scoop\_advance(rs\_job\_t *job, \textcolor{keywordtype}{size\_t} len)}
\DoxyCodeLine{00118 \{}
\DoxyCodeLine{00119     rs\_buffers\_t *stream = job-\/>stream;}
\DoxyCodeLine{00120 }
\DoxyCodeLine{00121     \textcolor{comment}{/* It never makes sense to advance over a mixture of bytes from the scoop}}
\DoxyCodeLine{00122 \textcolor{comment}{       and input, because you couldn't possibly have looked at them all at the}}
\DoxyCodeLine{00123 \textcolor{comment}{       same time. */}}
\DoxyCodeLine{00124     \textcolor{keywordflow}{if} (job-\/>scoop\_avail) \{}
\DoxyCodeLine{00125         \textcolor{comment}{/* reading from the scoop buffer */}}
\DoxyCodeLine{00126         rs\_trace(\textcolor{stringliteral}{"{}advance over "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes from scoop"{}}, len);}
\DoxyCodeLine{00127         assert(len <= job-\/>scoop\_avail);}
\DoxyCodeLine{00128         job-\/>scoop\_avail -\/= len;}
\DoxyCodeLine{00129         job-\/>scoop\_next += len;}
\DoxyCodeLine{00130     \} \textcolor{keywordflow}{else} \{}
\DoxyCodeLine{00131         rs\_trace(\textcolor{stringliteral}{"{}advance over "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes from input buffer"{}}, len);}
\DoxyCodeLine{00132         assert(len <= stream-\/>avail\_in);}
\DoxyCodeLine{00133         stream-\/>avail\_in -\/= len;}
\DoxyCodeLine{00134         stream-\/>next\_in += len;}
\DoxyCodeLine{00135     \}}
\DoxyCodeLine{00136 \}}
\DoxyCodeLine{00137 \textcolor{comment}{}}
\DoxyCodeLine{00138 \textcolor{comment}{/** Read from scoop without advancing.}}
\DoxyCodeLine{00139 \textcolor{comment}{ *}}
\DoxyCodeLine{00140 \textcolor{comment}{ * Ask for LEN bytes of input from the stream. If that much data is available,}}
\DoxyCodeLine{00141 \textcolor{comment}{ * then return a pointer to it in PTR, advance the stream input pointer over}}
\DoxyCodeLine{00142 \textcolor{comment}{ * the data, and return RS\_DONE. If there's not enough data, then accept}}
\DoxyCodeLine{00143 \textcolor{comment}{ * whatever is there into a buffer, advance over it, and return RS\_BLOCKED.}}
\DoxyCodeLine{00144 \textcolor{comment}{ *}}
\DoxyCodeLine{00145 \textcolor{comment}{ * The data is not actually removed from the input, so this function lets you}}
\DoxyCodeLine{00146 \textcolor{comment}{ * do readahead. If you want to keep any of the data, you should also call}}
\DoxyCodeLine{00147 \textcolor{comment}{ * rs\_scoop\_advance() to skip over it. */}}
\DoxyCodeLine{00148 rs\_result rs\_scoop\_readahead(rs\_job\_t *job, \textcolor{keywordtype}{size\_t} len, \textcolor{keywordtype}{void} **ptr)}
\DoxyCodeLine{00149 \{}
\DoxyCodeLine{00150     rs\_buffers\_t *stream = job-\/>stream;}
\DoxyCodeLine{00151     rs\_job\_check(job);}
\DoxyCodeLine{00152 }
\DoxyCodeLine{00153     \textcolor{keywordflow}{if} (!job-\/>scoop\_avail \&\& stream-\/>avail\_in >= len) \{}
\DoxyCodeLine{00154         \textcolor{comment}{/* The scoop is empty and there's enough data in the input. */}}
\DoxyCodeLine{00155         *ptr = stream-\/>next\_in;}
\DoxyCodeLine{00156         rs\_trace(\textcolor{stringliteral}{"{}got "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes direct from input"{}}, len);}
\DoxyCodeLine{00157         \textcolor{keywordflow}{return} RS\_DONE;}
\DoxyCodeLine{00158     \} \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (job-\/>scoop\_avail < len \&\& stream-\/>avail\_in) \{}
\DoxyCodeLine{00159         \textcolor{comment}{/* There is not enough data in the scoop. */}}
\DoxyCodeLine{00160         rs\_trace(\textcolor{stringliteral}{"{}scoop has less than "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes, scooping from "{}}}
\DoxyCodeLine{00161                  FMT\_SIZE \textcolor{stringliteral}{"{} input bytes"{}}, len, stream-\/>avail\_in);}
\DoxyCodeLine{00162         rs\_scoop\_input(job, len);}
\DoxyCodeLine{00163     \}}
\DoxyCodeLine{00164     \textcolor{keywordflow}{if} (job-\/>scoop\_avail >= len) \{}
\DoxyCodeLine{00165         \textcolor{comment}{/* There is enough data in the scoop now. */}}
\DoxyCodeLine{00166         rs\_trace(\textcolor{stringliteral}{"{}scoop has at least "{}} FMT\_SIZE \textcolor{stringliteral}{"{} bytes, this is enough"{}},}
\DoxyCodeLine{00167                  job-\/>scoop\_avail);}
\DoxyCodeLine{00168         *ptr = job-\/>scoop\_next;}
\DoxyCodeLine{00169         \textcolor{keywordflow}{return} RS\_DONE;}
\DoxyCodeLine{00170     \} \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (stream-\/>eof\_in) \{}
\DoxyCodeLine{00171         \textcolor{comment}{/* Not enough input data and at EOF. */}}
\DoxyCodeLine{00172         rs\_trace(\textcolor{stringliteral}{"{}reached end of input stream"{}});}
\DoxyCodeLine{00173         \textcolor{keywordflow}{return} RS\_INPUT\_ENDED;}
\DoxyCodeLine{00174     \} \textcolor{keywordflow}{else} \{}
\DoxyCodeLine{00175         \textcolor{comment}{/* Not enough input data yet. */}}
\DoxyCodeLine{00176         rs\_trace(\textcolor{stringliteral}{"{}blocked with insufficient input data"{}});}
\DoxyCodeLine{00177         \textcolor{keywordflow}{return} RS\_BLOCKED;}
\DoxyCodeLine{00178     \}}
\DoxyCodeLine{00179 \}}
\DoxyCodeLine{00180 \textcolor{comment}{}}
\DoxyCodeLine{00181 \textcolor{comment}{/** Read LEN bytes if possible, and remove them from the input scoop.}}
\DoxyCodeLine{00182 \textcolor{comment}{ *}}
\DoxyCodeLine{00183 \textcolor{comment}{ * \(\backslash\)param *job An rs\_job\_t pointer to the job instance.}}
\DoxyCodeLine{00184 \textcolor{comment}{ *}}
\DoxyCodeLine{00185 \textcolor{comment}{ * \(\backslash\)param len The length of the data in the ptr buffer.}}
\DoxyCodeLine{00186 \textcolor{comment}{ *}}
\DoxyCodeLine{00187 \textcolor{comment}{ * \(\backslash\)param **ptr will be updated to point to a read-\/only buffer holding the}}
\DoxyCodeLine{00188 \textcolor{comment}{ * data, if enough is available.}}
\DoxyCodeLine{00189 \textcolor{comment}{ *}}
\DoxyCodeLine{00190 \textcolor{comment}{ * \(\backslash\)return RS\_DONE if there was enough data, RS\_BLOCKED if there was not enough}}
\DoxyCodeLine{00191 \textcolor{comment}{ * data yet, or RS\_INPUT\_ENDED if there was not enough data and at EOF. */}}
\DoxyCodeLine{00192 rs\_result rs\_scoop\_read(rs\_job\_t *job, \textcolor{keywordtype}{size\_t} len, \textcolor{keywordtype}{void} **ptr)}
\DoxyCodeLine{00193 \{}
\DoxyCodeLine{00194     rs\_result result;}
\DoxyCodeLine{00195 }
\DoxyCodeLine{00196     result = rs\_scoop\_readahead(job, len, ptr);}
\DoxyCodeLine{00197     \textcolor{keywordflow}{if} (result == RS\_DONE)}
\DoxyCodeLine{00198         rs\_scoop\_advance(job, len);}
\DoxyCodeLine{00199     \textcolor{keywordflow}{return} result;}
\DoxyCodeLine{00200 \}}
\DoxyCodeLine{00201 \textcolor{comment}{}}
\DoxyCodeLine{00202 \textcolor{comment}{/** Read whatever data remains in the input stream.}}
\DoxyCodeLine{00203 \textcolor{comment}{ *}}
\DoxyCodeLine{00204 \textcolor{comment}{ * \(\backslash\)param *job The rs\_job\_t instance the job instance.}}
\DoxyCodeLine{00205 \textcolor{comment}{ *}}
\DoxyCodeLine{00206 \textcolor{comment}{ * \(\backslash\)param *len will be updated to the length of the available data.}}
\DoxyCodeLine{00207 \textcolor{comment}{ *}}
\DoxyCodeLine{00208 \textcolor{comment}{ * \(\backslash\)param **ptr will point at the available data.}}
\DoxyCodeLine{00209 \textcolor{comment}{ *}}
\DoxyCodeLine{00210 \textcolor{comment}{ * \(\backslash\)return RS\_DONE if there was data, RS\_INPUT\_ENDED if there was no data and}}
\DoxyCodeLine{00211 \textcolor{comment}{ * at EOF, RS\_BLOCKED if there was no data and not at EOF. */}}
\DoxyCodeLine{00212 rs\_result rs\_scoop\_read\_rest(rs\_job\_t *job, \textcolor{keywordtype}{size\_t} *len, \textcolor{keywordtype}{void} **ptr)}
\DoxyCodeLine{00213 \{}
\DoxyCodeLine{00214     *len = rs\_scoop\_avail(job);}
\DoxyCodeLine{00215     \textcolor{keywordflow}{if} (*len)}
\DoxyCodeLine{00216         \textcolor{keywordflow}{return} rs\_scoop\_read(job, *len, ptr);}
\DoxyCodeLine{00217     \textcolor{keywordflow}{else} \textcolor{keywordflow}{if} (job-\/>stream-\/>eof\_in)}
\DoxyCodeLine{00218         \textcolor{keywordflow}{return} RS\_INPUT\_ENDED;}
\DoxyCodeLine{00219     \textcolor{keywordflow}{else}}
\DoxyCodeLine{00220         \textcolor{keywordflow}{return} RS\_BLOCKED;}
\DoxyCodeLine{00221 \}}

\end{DoxyCode}
