1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16
17 /* DataSource procedures */
18
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gsdsrc.h"
22 #include "gserrors.h"
23 #include "stream.h"
24
25 /* GC descriptor */
26 public_st_data_source();
27 static
ENUM_PTRS_WITH(data_source_enum_ptrs,gs_data_source_t * psrc)28 ENUM_PTRS_WITH(data_source_enum_ptrs, gs_data_source_t *psrc)
29 {
30 if (psrc->type == data_source_type_string)
31 ENUM_RETURN_CONST_STRING_PTR(gs_data_source_t, data.str);
32 else if (psrc->type == data_source_type_stream)
33 ENUM_RETURN_PTR(gs_data_source_t, data.strm);
34 else /* bytes or floats */
35 ENUM_RETURN_PTR(gs_data_source_t, data.str.data);
36 }
37 ENUM_PTRS_END
RELOC_PTRS_WITH(data_source_reloc_ptrs,gs_data_source_t * psrc)38 static RELOC_PTRS_WITH(data_source_reloc_ptrs, gs_data_source_t *psrc)
39 {
40 if (psrc->type == data_source_type_string)
41 RELOC_CONST_STRING_PTR(gs_data_source_t, data.str);
42 else if (psrc->type == data_source_type_stream)
43 RELOC_PTR(gs_data_source_t, data.strm);
44 else /* bytes or floats */
45 RELOC_PTR(gs_data_source_t, data.str.data);
46 }
47 RELOC_PTRS_END
48
49 /* Access data from a string or a byte object. */
50 /* Does check bounds, and returns 0 data oob. Spec calls for rangecheck,
51 but CPSI implementation silently gives (bogus) data. */
52 int
data_source_access_string(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)53 data_source_access_string(const gs_data_source_t * psrc, ulong start,
54 uint length, byte * buf, const byte ** ptr)
55 {
56 const byte *p = psrc->data.str.data + start;
57
58 if (start + length <= psrc->data.str.size) {
59 if (ptr)
60 *ptr = p;
61 else
62 memcpy(buf, p, length);
63 } else {
64 if (start < psrc->data.str.size) {
65 uint oklen = psrc->data.str.size - start;
66 memcpy(buf, p, oklen);
67 memset(buf + oklen, 0, length - oklen);
68 } else {
69 memset(buf, 0, length);
70 }
71 *ptr = buf;
72 }
73 return 0;
74 }
75 /* access_bytes is identical to access_string, but has a different */
76 /* GC procedure. */
77 int
data_source_access_bytes(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)78 data_source_access_bytes(const gs_data_source_t * psrc, ulong start,
79 uint length, byte * buf, const byte ** ptr)
80 {
81 const byte *p = psrc->data.str.data + start;
82
83 if (ptr)
84 *ptr = p;
85 else
86 memcpy(buf, p, length);
87 return 0;
88 }
89
90 /* Access data from a stream. */
91 /* Returns gs_error_rangecheck if out of bounds. */
92 int
data_source_access_stream(const gs_data_source_t * psrc,ulong start,uint length,byte * buf,const byte ** ptr)93 data_source_access_stream(const gs_data_source_t * psrc, ulong start,
94 uint length, byte * buf, const byte ** ptr)
95 {
96 stream *s = psrc->data.strm;
97 const byte *p;
98
99 if (start >= s->position &&
100 (p = start - s->position + s->cbuf) + length <=
101 s->cursor.r.limit + 1
102 ) {
103 if (ptr)
104 *ptr = p;
105 else
106 memcpy(buf, p, length);
107 } else {
108 uint nread;
109 int code = sseek(s, start);
110
111 if (code < 0)
112 return_error(gs_error_rangecheck);
113 code = sgets(s, buf, length, &nread);
114 if (code < 0)
115 return_error(gs_error_rangecheck);
116 if (nread != length)
117 return_error(gs_error_rangecheck);
118 if (ptr)
119 *ptr = buf;
120 }
121 return 0;
122 }
123