1/*
2 * libid3tag - ID3 tag manipulation library
3 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 *
19 * $Id: render.c,v 1.11 2004/01/23 09:41:32 rob Exp $
20 */
21
22# ifdef HAVE_CONFIG_H
23#  include "config.h"
24# endif
25
26# include "global.h"
27
28# include <string.h>
29# include <stdlib.h>
30
31# ifdef HAVE_ASSERT_H
32#  include <assert.h>
33# endif
34
35# include "id3tag.h"
36# include "render.h"
37# include "ucs4.h"
38# include "latin1.h"
39# include "utf16.h"
40# include "utf8.h"
41
42id3_length_t id3_render_immediate(id3_byte_t **ptr,
43				  char const *value, unsigned int bytes)
44{
45  assert(value);
46  assert(bytes == 8 || bytes == 4 || bytes == 3);
47
48  if (ptr) {
49    switch (bytes) {
50    case 8: *(*ptr)++ = *value++;
51            *(*ptr)++ = *value++;
52	    *(*ptr)++ = *value++;
53	    *(*ptr)++ = *value++;
54    case 4: *(*ptr)++ = *value++;
55    case 3: *(*ptr)++ = *value++;
56            *(*ptr)++ = *value++;
57	    *(*ptr)++ = *value++;
58    }
59  }
60
61  return bytes;
62}
63
64id3_length_t id3_render_syncsafe(id3_byte_t **ptr,
65				 unsigned long num, unsigned int bytes)
66{
67  assert(bytes == 4 || bytes == 5);
68
69  if (ptr) {
70    switch (bytes) {
71    case 5: *(*ptr)++ = (num >> 28) & 0x0f;
72    case 4: *(*ptr)++ = (num >> 21) & 0x7f;
73            *(*ptr)++ = (num >> 14) & 0x7f;
74	    *(*ptr)++ = (num >>  7) & 0x7f;
75	    *(*ptr)++ = (num >>  0) & 0x7f;
76    }
77  }
78
79  return bytes;
80}
81
82id3_length_t id3_render_int(id3_byte_t **ptr,
83			    signed long num, unsigned int bytes)
84{
85  assert(bytes >= 1 && bytes <= 4);
86
87  if (ptr) {
88    switch (bytes) {
89    case 4: *(*ptr)++ = num >> 24;
90    case 3: *(*ptr)++ = num >> 16;
91    case 2: *(*ptr)++ = num >>  8;
92    case 1: *(*ptr)++ = num >>  0;
93    }
94  }
95
96  return bytes;
97}
98
99id3_length_t id3_render_binary(id3_byte_t **ptr,
100			       id3_byte_t const *data, id3_length_t length)
101{
102  if (data == 0)
103    return 0;
104
105  if (ptr) {
106    memcpy(*ptr, data, length);
107    *ptr += length;
108  }
109
110  return length;
111}
112
113id3_length_t id3_render_latin1(id3_byte_t **ptr,
114			       id3_latin1_t const *latin1, int terminate)
115{
116  id3_length_t size;
117
118  if (latin1 == 0)
119    latin1 = "";
120
121  size = id3_latin1_size(latin1);
122  if (!terminate)
123    --size;
124
125  if (ptr) {
126    memcpy(*ptr, latin1, size);
127    *ptr += size;
128  }
129
130  return size;
131}
132
133id3_length_t id3_render_string(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
134			       enum id3_field_textencoding encoding,
135			       int terminate)
136{
137  enum id3_utf16_byteorder byteorder = ID3_UTF16_BYTEORDER_ANY;
138
139  if (ucs4 == 0)
140    ucs4 = id3_ucs4_empty;
141
142  switch (encoding) {
143  case ID3_FIELD_TEXTENCODING_ISO_8859_1:
144    return id3_latin1_serialize(ptr, ucs4, terminate);
145
146  case ID3_FIELD_TEXTENCODING_UTF_16BE:
147    byteorder = ID3_UTF16_BYTEORDER_BE;
148  case ID3_FIELD_TEXTENCODING_UTF_16:
149    return id3_utf16_serialize(ptr, ucs4, byteorder, terminate);
150
151  case ID3_FIELD_TEXTENCODING_UTF_8:
152    return id3_utf8_serialize(ptr, ucs4, terminate);
153  }
154
155  return 0;
156}
157
158id3_length_t id3_render_padding(id3_byte_t **ptr, id3_byte_t value,
159				id3_length_t length)
160{
161  if (ptr) {
162    memset(*ptr, value, length);
163    *ptr += length;
164  }
165
166  return length;
167}
168
169/*
170 * NAME:	render->paddedstring()
171 * DESCRIPTION:	render a space-padded string using latin1 encoding
172 */
173id3_length_t id3_render_paddedstring(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
174				     id3_length_t length)
175{
176  id3_ucs4_t padded[31], *data, *end;
177
178  /* latin1 encoding only (this is used for ID3v1 fields) */
179
180  assert(length <= 30);
181
182  data = padded;
183  end  = data + length;
184
185  if (ucs4) {
186    while (*ucs4 && end - data > 0) {
187      *data++ = *ucs4++;
188
189      if (data[-1] == '\n')
190	data[-1] = ' ';
191    }
192  }
193
194  while (end - data > 0)
195    *data++ = ' ';
196
197  *data = 0;
198
199  return id3_latin1_serialize(ptr, padded, 0);
200}
201