1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2005-2007 Emmanuel Pacaud <emmanuel.pacaud@free.fr>
5 * Copyright © 2009 Chris Wilson
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is Red Hat, Inc.
35 * Kristian Høgsberg <krh@redhat.com>
36 * Chris Wilson <chris@chris-wilson.co.uk>
40 #include "cairo-error-private.h"
41 #include "cairo-output-stream-private.h"
43 typedef struct _cairo_base64_stream
{
44 cairo_output_stream_t base
;
45 cairo_output_stream_t
*output
;
47 unsigned int trailing
;
49 } cairo_base64_stream_t
;
51 static char const base64_table
[64] =
52 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
55 _cairo_base64_stream_write (cairo_output_stream_t
*base
,
56 const unsigned char *data
,
59 cairo_base64_stream_t
* stream
= (cairo_base64_stream_t
*) base
;
60 unsigned char *src
= stream
->src
;
63 if (stream
->in_mem
+ length
< 3) {
64 for (i
= 0; i
< length
; i
++) {
65 src
[i
+ stream
->in_mem
] = *data
++;
67 stream
->in_mem
+= length
;
68 return CAIRO_STATUS_SUCCESS
;
74 for (i
= stream
->in_mem
; i
< 3; i
++) {
80 dst
[0] = base64_table
[src
[0] >> 2];
81 dst
[1] = base64_table
[(src
[0] & 0x03) << 4 | src
[1] >> 4];
82 dst
[2] = base64_table
[(src
[1] & 0x0f) << 2 | src
[2] >> 6];
83 dst
[3] = base64_table
[src
[2] & 0xfc >> 2];
84 /* Special case for the last missing bits */
85 switch (stream
->trailing
) {
93 _cairo_output_stream_write (stream
->output
, dst
, 4);
94 } while (length
>= 3);
96 for (i
= 0; i
< length
; i
++) {
99 stream
->in_mem
= length
;
101 return _cairo_output_stream_get_status (stream
->output
);
104 static cairo_status_t
105 _cairo_base64_stream_close (cairo_output_stream_t
*base
)
107 cairo_base64_stream_t
*stream
= (cairo_base64_stream_t
*) base
;
108 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
110 if (stream
->in_mem
> 0) {
111 memset (stream
->src
+ stream
->in_mem
, 0, 3 - stream
->in_mem
);
112 stream
->trailing
= 3 - stream
->in_mem
;
114 status
= _cairo_base64_stream_write (base
, NULL
, 0);
120 cairo_output_stream_t
*
121 _cairo_base64_stream_create (cairo_output_stream_t
*output
)
123 cairo_base64_stream_t
*stream
;
126 return _cairo_output_stream_create_in_error (output
->status
);
128 stream
= malloc (sizeof (cairo_base64_stream_t
));
129 if (unlikely (stream
== NULL
)) {
130 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
131 return (cairo_output_stream_t
*) &_cairo_output_stream_nil
;
134 _cairo_output_stream_init (&stream
->base
,
135 _cairo_base64_stream_write
,
137 _cairo_base64_stream_close
);
139 stream
->output
= output
;
141 stream
->trailing
= 0;
143 return &stream
->base
;