File: atom.c

package info (click to toggle)
taningia 0.2.2-2
  • links: PTS
  • area: main
  • in suites: bookworm, bullseye, buster, stretch
  • size: 1,944 kB
  • ctags: 687
  • sloc: sh: 10,949; ansic: 5,443; makefile: 44
file content (239 lines) | stat: -rw-r--r-- 8,760 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * Copyright (C) 2009  Lincoln de Sousa <lincoln@minaslivre.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <taningia/atom.h>
#include <taningia/iri.h>

/* This example shows how our atom implementation works.
 *
 * == Basic usage of the API ==
 *
 * It is actually quite simple, the only thing we do is to provide an
 * `object' for each piece of an atom document. For example, an atom
 * person can be represented with a name, an email address and an uri,
 * so to abstract this idea, the AtomPerson class was created and can
 * be used like this:
 *
 *   >>> ta_atom_person_t *person;
 *   >>> person = ta_atom_person_new ("lincoln", NULL, NULL);
 *
 * The only required argument in the above constructor is the
 * `name'. Email and uri fields can be nullable.
 *
 * And now, to retrieve the value of these attributes you need to do:
 *
 *   >>> const char *name;
 *   >>> name = ta_atom_person_get_name (person);
 *   >>> printf ("%s\n", name);
 *   lincoln
 *
 * To free the person object and all its attributes, use the
 * destructor. That is a function named with the class full name,
 * separated by underscores and with the `_free' sufix.
 *
 *   >>> ta_object_unref (person);
 *
 * So, that's easy, all the rest of the API follows these
 * standards. All of the available objects has a constructor with the
 * `_new' sufix, getters and setters with the full class name, the
 * attribute name and the `_get' or the `_set' sufix.
 *
 * The only current exception is in the list getters, that uses out
 * parameters, like in `ta_atom_person_get_see' that returns a list of
 * all simple extension elements. This is its prototype:
 *
 *   >>> void
 *   >>> ta_atom_person_get_see (ta_atom_person_t *person,
 *   ...                        TAtomSimpleExtElement ***elements,
 *   ...                        int *len);
 *
 * Soon we'll implement a List type in our library and we'll change it
 * to the above cited standard.
 *
 * == Uri/Iri consideratinos ==
 *
 * All fields that were designed to store uris, like Person.uri,
 * Link.href, Content.src and others, are actually using iri's. This
 * was done to follow recommendations in the RFC4287. So, to fill
 * these attributes You'll need to use our iri implementation, like
 * this:
 *
 *   >>> TAtomLink *link;
 *   >>> iri_t *href;
 *   >>> href = iri_new ("http://gnu.org");
 *   >>> link = t_link_new (href);
 *
 * Remembering that when passing href parameter to the link
 * constructor, you should not free href, since link is using the
 * reference you just created. The `href' var will be freed by the
 * `ta_atom_link_free' destructor. All setters of this lib follows this
 * standard. Maybe in the future we should use reference count
 * strategy. =P
 *
 */

int
gen_feed (void)
{
  ta_atom_feed_t *feed;
  ta_atom_entry_t *entry;
  ta_atom_content_t *content;
  ta_atom_person_t *author;
  ta_error_t *error;
  ta_iri_t *feed_id, *entry_id;
  char *feed_string;

  /* This usually is the first step, create a feed instance: */
  feed = ta_atom_feed_new ("My cool atom feed");

  /* Creating a random id and setting it to our feed object */
  feed_id = ta_iri_new ();
  ta_iri_set_from_string (feed_id, "urn:uuid:981db243-7aca-4467-8e38-9641429eba37");

  /* Since this iri is hardcoded we're sure that it will be parsed
   * successfuly, but in a real example, you should validate it, like
   * this: */
  if ((error = ta_iri_get_error (feed_id)) != NULL)
    {
      /* This frees the already set attributes and the feed object
       * itself. */
      ta_object_unref (feed);

      /* Giving some feedback to the user. */
      fprintf (stderr, "Invalid uri: %s: %s\n", ta_error_get_name (error),
               ta_error_get_message (error));

      /* We had no time to set the iri in the feed object, so, we
       * should free it manually. But only do it when done with the
       * error object it will be freed here too. */
      ta_object_unref (feed_id);
      return 1;
    }
  ta_atom_feed_set_id (feed, feed_id);

  /* Adding an author to the feed object. This can be done multiple
   * times. */
  author = ta_atom_person_new ("Lincoln", "lincoln@minaslivre.org", NULL);
  ta_atom_feed_add_author (feed, author);

  /* Now is the time to create an entry and set a random id to it */
  entry = ta_atom_entry_new ("Blah!");
  entry_id = ta_iri_new ();
  ta_iri_set_from_string (entry_id, "urn:uuid:0a5866b1-1c53-4323-9370-1f7c6a0c3f66");
  ta_atom_entry_set_id (entry, entry_id);

  /* Setting the rights attribute of the entry */
  ta_atom_entry_set_rights (entry, "GNU FDL... bleh bleh bleh...");

  /* Adding a content to our entry, without it, it will not work. */
  content = ta_atom_content_new ("text/plain");
  ta_atom_content_set_content (content, "This is the entry content!", 26);
  ta_atom_entry_set_content (entry, content);

  /* Finally adding the entry to our feed object. */
  ta_atom_feed_add_entry (feed, entry);

  /* Generating the xml string of our feed object. Here you can use
   * the `ta_atom_feed_to_file' to save it to a file instead of
   * printing it. Or use the `ta_atom_feed_to_iks' to generate an iks
   * instance and, maybe, send the entry in a pubsub message. */
  feed_string = ta_atom_feed_to_string (feed);
  printf ("%s\n", feed_string);

  /* The only object that should be freed is the toplevel one. Don't
   * worry about freeing iri's entries or content. */
  ta_object_unref (feed);
  free (feed_string);
  return 0;
}

/* Simple extension of some atom objects.
 *
 * As said in the atom spec, it was designed to be extended easily
 * when needed. There are three objects that accepts simple extension
 * elements, they are: Person, Entry and Feed. And our library
 * provides an API to do it. There are two kinds of extension
 * elements: The simple and the structured elements. At this moment,
 * our library only provides the first way.
 *
 * A `SimpleExtensionElement' is just a key/value structure that is
 * added to an internal array of objects that suports this kind of
 * extension. Its representation in an xml file is very simple, like
 * this:
 *
 *   >>> TAtomSimpleExtElement *ext_element;
 *   >>> ext_element = ta_atom_simple_ext_element_new ("key", "value");
 *   >>> printf ("%s\n", ta_atom_simple_ext_element_to_string (ext_element));
 *   <key>value</key>
 *
 * To use it in an object that supports it, you should use the
 * `_add_see', `_del_see' and `_get_see' methods. Take a look at the
 * function `simple_extension_example'. This example uses an atom
 * person to demonstrate the extension, but you can do it with an atom
 * entry or an atom feed too.
 */

void
simple_extension_example (void)
{
  ta_atom_person_t *person;
  ta_atom_simple_element_t *state, *city;
  ta_iri_t *uri;
  char *person_string;

  /* Here we're creating a new person instance with name, email and
   * uri fields filled. These are the only fields specified by the
   * atom rfc. */
  uri = ta_iri_new ();
  ta_iri_set_from_string (uri, "http://lincoln.comum.org");
  person = ta_atom_person_new ("Lincoln", "lincoln@minaslivre.org", uri);

  /* Now, we're going to add simple extension objects to the person
   * instance. */
  state = ta_atom_simple_element_new ("state", "MG");
  ta_atom_person_add_see (person, state);
  city = ta_atom_simple_element_new ("city", "Belo Horizonte");
  ta_atom_person_add_see (person, city);

  /* When executing this example, you'll see all required fields
   * (name, email and uri), but both the state and city fields were
   * added too. */
  person_string = ta_atom_person_to_string (person, "person");
  printf ("%s\n", person_string);
  free (person_string);

  /* like in other places, freeing an instance that holds references
   * for other objects is enough. You should not try to free state,
   * city or uri vars */
  ta_object_unref (person);
}

int
main (int argc, char **argv)
{
  printf ("Generating an atom feed:\n");
  gen_feed ();
  printf ("\n");

  printf ("Extending an atom element:\n");
  simple_extension_example ();
  return 0;
}