summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am11
-rw-r--r--src/vf_access.c661
-rw-r--r--src/vf_access_calendar.c528
-rw-r--r--src/vf_access_wrappers.c541
-rw-r--r--src/vf_config.h85
-rw-r--r--src/vf_create_object.c158
-rw-r--r--src/vf_delete.c327
-rw-r--r--src/vf_internals.h223
-rw-r--r--src/vf_malloc.c270
-rw-r--r--src/vf_malloc.h166
-rw-r--r--src/vf_malloc_stdlib.c392
-rw-r--r--src/vf_malloc_stdlib.h90
-rw-r--r--src/vf_modified.c159
-rw-r--r--src/vf_modified.h84
-rw-r--r--src/vf_parser.c1182
-rw-r--r--src/vf_reader.c277
-rw-r--r--src/vf_search.c457
-rw-r--r--src/vf_string_arrays.c435
-rw-r--r--src/vf_string_arrays.h177
-rw-r--r--src/vf_strings.c472
-rw-r--r--src/vf_strings.h230
-rw-r--r--src/vf_writer.c616
22 files changed, 7541 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..19b2d85
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,11 @@
+lib_LTLIBRARIES = libvformat.la
+
+libvformat_la_SOURCES = vf_access.c vf_malloc.c vf_strings.c vf_access_wrappers.c \
+ vf_parser.c vf_writer.c vf_create_object.c \
+ vf_access_calendar.c vf_reader.c vf_delete.c \
+ vf_search.c vf_malloc_stdlib.c vf_modified.c vf_string_arrays.c
+
+EXTRA_DIST = *.h
+
+libvformat_la_LDFLAGS = -version-info 0
+
diff --git a/src/vf_access.c b/src/vf_access.c
new file mode 100644
index 0000000..7504150
--- /dev/null
+++ b/src/vf_access.c
@@ -0,0 +1,661 @@
+/****************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Revision: 1.23 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Core access functions for VF_OBJECT_Ts. The library includes other access
+ functions (see vf_access_wrappers.c) which are often just alternative slightly
+ higher level versions of what's found below.
+
+ The intention is to provide a basic interface which covers all the required
+ functionality and also some quick'n'easy functions which can be used but don't
+ bloat the code (in a static library build anyway).
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_access.c,v $
+ * Revision 1.23 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.22 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.21 2002/11/02 08:56:17 tilda
+ * Start of internationalisation changes.
+ *
+ * Revision 1.20 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.19 2002/10/08 21:45:06 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.18 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.17 2002/02/24 17:10:34 tilda
+ * Add API for "is modified" functionality.
+ *
+ * Revision 1.16 2002/01/06 16:18:48 tilda
+ * Add dialog box for events / todos.
+ *
+ * Revision 1.15 2001/11/18 21:45:58 tilda
+ * Ensure parameters changed to QP are updated correctly.
+ *
+ * Revision 1.14 2001/11/17 17:40:29 tilda
+ * Image / sound dialog box now works.
+ *
+ * Revision 1.13 2001/11/05 21:07:20 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.12 2001/10/24 18:36:06 tilda
+ * BASE64 bugfixes. Split reader/writer code. Start create/modify work.
+ *
+ * Revision 1.11 2001/10/24 05:30:39 tilda
+ * Start work on object create/modify API.
+ *
+ * Revision 1.10 2001/10/16 05:50:53 tilda
+ * Debug support for lists of vobjects from single file (ie. a phonebook).
+ *
+ * Revision 1.9 2001/10/14 20:42:37 tilda
+ * Addition of group searching.
+ *
+ * Revision 1.8 2001/10/14 16:40:05 tilda
+ * Initial testing of access functions.
+ *
+ * Revision 1.7 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.6 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.5 2001/10/13 14:49:30 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ * Revision 1.4 2001/10/12 16:20:03 tilda
+ * Correctly parse compound quoted printable properties.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *****************************************************************************/
+
+#ifndef NORCSID
+static const char vf_access_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access.c,v 1.23 2002/11/03 18:43:16 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+/*===========================================================================*
+ Interface Header Files
+ *===========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*===========================================================================*
+ Local Header File
+ *===========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+#include "vf_modified.h"
+
+/*===========================================================================*
+ Public Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Defines
+ *===========================================================================*/
+
+#define MAXINCREMENT (5)
+#define MAXNUMTAGS (10)
+
+/*===========================================================================*
+ Private Data Types
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Function Prototypes
+ *===========================================================================*/
+
+static bool_t strings_valid_index(
+ VPROP_T *p_vprop, /* The property */
+ uint32_t n_string /* Index required */
+ );
+
+static bool_t ensure_value_encoding_tag(
+ VPROP_T *p_vprop, /* The property */
+ vf_encoding_t encoding /* Encoding required */
+ );
+
+static bool_t set_prop_value_string(
+ VPROP_T *p_vprop, /* The property */
+ uint32_t n_string, /* Index required */
+ const char *p_string /* String required */
+ );
+
+static bool_t set_prop_value_base64(
+ VPROP_T *p_vprop, /* The property */
+ const uint8_t *p_data, /* Pointer to the binary data */
+ uint32_t length, /* Length of the binary data */
+ bool_t copy /* Copy or keep pointer */
+ );
+
+
+
+
+/*===========================================================================*
+ Private Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Public Function Implementations
+ *===========================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_name()
+ *
+ * DESCRIPTION
+ * Build the property name string in the indicated buffer.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+void vf_get_prop_name(
+ VF_PROP_T *p_prop, /* The property */
+ char *p_buffer, /* The buffer */
+ uint32_t bufsize /* Size of the buffer */
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ uint32_t i;
+
+ if (p_vprop->p_group)
+ {
+ p_strcpy(p_buffer, p_vprop->p_group);
+ p_strcat(p_buffer, ".");
+ }
+ else
+ {
+ p_buffer[0] = '\0';
+ }
+
+ for (i = 0;i < p_vprop->name.n_strings;i++)
+ {
+ if (0 < i)
+ p_strcat(p_buffer, ";");
+
+ if (p_vprop->name.pp_strings[i])
+ {
+ p_strcat(p_buffer, p_vprop->name.pp_strings[i]);
+ }
+ }
+}
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_object_type()
+ *
+ * DESCRIPTION
+ * Return the type string identifying the indicated vformat object.
+ *
+ * RETURNS
+ * Ptr to string.
+ *---------------------------------------------------------------------------*/
+
+const char *vf_get_object_type(
+ VF_OBJECT_T *p_object
+ )
+{
+ const char *p_ret = NULL;
+
+ if (p_object)
+ {
+ p_ret = ((VOBJECT_T *)p_object)->p_type;
+ }
+
+ return p_ret;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_value()
+ *
+ * DESCRIPTION
+ * Get hold of raw fields associated with the property. These are of
+ * various types:
+ *
+ * VF_ENC_VOBJECT
+ * - *pp_value = pointer to contained VF_OBJECT_T which can be
+ * passed back to any of the object manipulation functions.
+ *
+ * VF_ENC_7BIT, VF_ENC_QUOTEDPRINTABLE
+ * - *pp_value = ptr to array of char*, *p_size = number of elts.
+ *
+ * VF_ENC_8BIT, VF_BASE64
+ * - *pp_value = ptr to bytes, *p_size = number of bytes
+ *
+ * RETURNS
+ * TRUE <=> encoding is valid, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_prop_value(
+ VF_PROP_T *p_prop, /* The property */
+ void **pp_value, /* Pointer value */
+ uint32_t *p_size, /* Integer value */
+ vf_encoding_t *p_encoding /* Type of return values */
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ bool_t ret = TRUE;
+
+ switch (p_vprop->value.encoding)
+ {
+ case VF_ENC_VOBJECT:
+ if (pp_value)
+ {
+ *pp_value = p_vprop->value.v.o.p_object;
+ }
+ break;
+
+ case VF_ENC_7BIT:
+ case VF_ENC_QUOTEDPRINTABLE:
+ if (pp_value)
+ {
+ *pp_value = p_vprop->value.v.s.pp_strings;
+ }
+ if (p_size)
+ {
+ *p_size = p_vprop->value.v.s.n_strings;
+ }
+ break;
+
+ case VF_ENC_8BIT:
+ case VF_ENC_BASE64:
+ if (pp_value)
+ {
+ *pp_value = p_vprop->value.v.b.p_buffer;
+ }
+ if (p_size)
+ {
+ *p_size = p_vprop->value.v.b.n_bufsize;
+ }
+ break;
+
+ default:
+ ret = FALSE;
+ break;
+ }
+
+ if (p_encoding)
+ {
+ *p_encoding = p_vprop->value.encoding;
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_value()
+ *
+ * DESCRIPTION
+ * Set values associated with a property.
+ *
+ * Passing a value of encoding not the same as the current property
+ * encoding will cause the property contents to be freed prior to
+ * setting the indicated value.
+ *
+ * RETURNS
+ * TRUE <=> re-allocation success & encoding correct, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_value(
+ VF_PROP_T *p_prop, /* The property */
+ void *p_value, /* Pointer to the data */
+ uint32_t n_param, /* Data size or index */
+ vf_encoding_t encoding, /* Encoding in use */
+ bool_t copy /* Copy the data? */
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ bool_t ret = TRUE;
+
+ if (!copy)
+ return FALSE;
+
+ if (encoding == p_vprop->value.encoding)
+ {
+ /* Leave it as is */
+ }
+ else
+ {
+ delete_prop_contents(p_prop, FALSE);
+
+ ensure_value_encoding_tag(p_vprop, encoding);
+ }
+
+ switch (p_vprop->value.encoding)
+ {
+ case VF_ENC_VOBJECT:
+ {
+ if (p_vprop->value.v.o.p_object != p_value)
+ {
+ mark_property_modified(p_vprop, TRUE);
+ }
+
+ p_vprop->value.v.o.p_object = p_value;
+ }
+ break;
+
+ case VF_ENC_7BIT:
+ case VF_ENC_QUOTEDPRINTABLE:
+ {
+ ret = set_prop_value_string(p_vprop, n_param, p_value);
+ }
+ break;
+
+ case VF_ENC_8BIT:
+ case VF_ENC_BASE64:
+ {
+ ret = set_prop_value_base64(p_vprop, p_value, n_param, copy);
+ }
+ break;
+
+ default:
+ ret = FALSE;
+ break;
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*===========================================================================*
+ Private Function Implementations
+ *===========================================================================*/
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * set_prop_value_string()
+ *
+ * DESCRIPTION
+ * Set the value of a property.
+ *
+ * RETURNS
+ * TRUE <=> set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t set_prop_value_string(
+ VPROP_T *p_vprop,
+ uint32_t n_string,
+ const char *p_string
+ )
+{
+ bool_t ret = FALSE;
+
+ if (strings_valid_index(p_vprop, n_string))
+ {
+ if ((p_vprop->value.v.s.pp_strings[n_string] && !p_string) ||
+ (!p_vprop->value.v.s.pp_strings[n_string] && p_string) ||
+ (p_vprop->value.v.s.pp_strings[n_string] && p_string &&
+ p_stricmp(p_vprop->value.v.s.pp_strings[n_string], p_string)))
+ {
+ mark_property_modified(p_vprop, TRUE);
+ }
+
+ ret = set_string_array_entry(&(p_vprop->value.v.s), p_string, n_string);
+ }
+
+ return ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * set_prop_value_base64()
+ *
+ * DESCRIPTION
+ * Set the value of a property.
+ *
+ * RETURNS
+ * TRUE <=> set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t set_prop_value_base64(
+ VPROP_T *p_vprop,
+ const uint8_t *p_data, /* Pointer to the binary data */
+ uint32_t length, /* Length of the binary data */
+ bool_t copy /* Copy or keep pointer */
+ )
+{
+ bool_t ret = FALSE;
+
+ if (copy)
+ {
+ p_vprop->value.v.b.p_buffer = vf_malloc(length);
+
+ if (p_vprop->value.v.b.p_buffer)
+ {
+ p_memcpy(p_vprop->value.v.b.p_buffer, p_data, length);
+ p_vprop->value.v.b.n_bufsize = length;
+
+ ret = TRUE;
+ }
+ }
+ else
+ {
+ /* TBD */
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * strings_valid_index()
+ *
+ * DESCRIPTION
+ * Check request for indicated string. If it's either in the current
+ * object or represents a reasonable exapansion the request is allowed.
+ *
+ * RETURNS
+ * TRUE <=> object can include indicated string.
+ *---------------------------------------------------------------------------*/
+
+bool_t strings_valid_index(
+ VPROP_T *p_vprop,
+ uint32_t n_string
+ )
+{
+ bool_t ret = FALSE;
+
+ if (n_string < p_vprop->value.v.s.n_strings)
+ {
+ /* String in current extent of object */
+
+ ret = TRUE;
+ }
+ else
+ if ((p_vprop->value.v.s.n_strings <= n_string) && (n_string < p_vprop->value.v.s.n_strings + MAXINCREMENT))
+ {
+ /* Set string within reasonable expansion of object */
+
+ void *p_tmp = vf_realloc(p_vprop->value.v.s.pp_strings, (1 + n_string) * sizeof(char *));
+
+ if (p_tmp)
+ {
+ uint32_t i;
+
+ p_vprop->value.v.s.pp_strings = p_tmp;
+
+ for (i = p_vprop->value.v.s.n_strings;i < (uint32_t)(1 + n_string);i++)
+ {
+ p_vprop->value.v.s.pp_strings[i] = NULL;
+ }
+
+ p_vprop->value.v.s.n_strings = (1 + n_string);
+
+ ret = TRUE;
+ }
+ }
+ else
+ {
+ /* Invalid request */
+ }
+
+ return ret;
+}
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * ensure_value_encoding_tag()
+ *
+ * DESCRIPTION
+ * Check/set encoding.
+ *
+ * RETURNS
+ * TRUE <=> encoding was set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t ensure_value_encoding_tag(
+ VPROP_T *p_vprop,
+ vf_encoding_t encoding
+ )
+{
+ int n;
+ uint32_t i;
+ bool_t ret = TRUE;
+
+ /*
+ * Locate the encoding value.
+ */
+ for (i = 0, n = (-1);n == (-1) && (i < p_vprop->name.n_strings);i++)
+ {
+ const char *p_string = p_vprop->name.pp_strings[i];
+
+ if (p_string)
+ {
+ if (p_stristr(p_string, VFP_ENCODING)
+ || p_stristr(p_string, VFP_QUOTEDPRINTABLE)
+ || p_stristr(p_string, VFP_BASE64)
+ || p_stristr(p_string, VFP_8BIT)
+ || p_stristr(p_string, VFP_7BIT))
+ {
+ n = i;
+ }
+ }
+ }
+
+ /*
+ * Remove previous encoding
+ */
+ if (0 <= n)
+ {
+ ret = set_string_array_entry(&(p_vprop->name), NULL, n);
+ }
+
+ if (ret)
+ {
+ char *p_enc_string;
+
+ switch (encoding)
+ {
+ case VF_ENC_QUOTEDPRINTABLE:
+ p_enc_string = VFP_QUOTEDPRINTABLE;
+ break;
+
+ case VF_ENC_BASE64:
+ p_enc_string = VFP_BASE64;
+ break;
+
+ default:
+ p_enc_string = NULL;
+ }
+
+ if (p_enc_string)
+ {
+ if ((-1) == n)
+ {
+ ret = add_string_to_array(&(p_vprop->name), p_enc_string);
+ }
+ else
+ {
+ ret = set_string_array_entry(&(p_vprop->name), p_enc_string, n);
+ }
+ }
+ }
+
+ if (ret)
+ {
+ p_vprop->value.encoding = encoding;
+ }
+
+ return ret;
+}
+
+
+/*===========================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_access_calendar.c b/src/vf_access_calendar.c
new file mode 100644
index 0000000..159c432
--- /dev/null
+++ b/src/vf_access_calendar.c
@@ -0,0 +1,528 @@
+/****************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_access.c $
+ $Revision: 1.7 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Wrappers on the core access functions & other utility functions.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_access_calendar.c,v $
+ * Revision 1.7 2002/11/24 14:26:22 tilda
+ * IID484686 - More vcard work.
+ *
+ * Revision 1.6 2002/11/15 09:15:00 tilda
+ * IID638823 - Various portability issues.
+ *
+ * Revision 1.5 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.4 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.3 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.2 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.1 2002/01/06 16:18:48 tilda
+ * Add dialog box for events / todos.
+ *
+ *****************************************************************************/
+
+#ifndef NORCSID
+static const char vf_access_calendar_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access_calendar.c,v 1.7 2002/11/24 14:26:22 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+#include <time.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/*===========================================================================*
+ Interface Header Files
+ *===========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*===========================================================================*
+ Local Header File
+ *===========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*===========================================================================*
+ Public Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Defines
+ *===========================================================================*/
+
+#define ISO8061_TOKEN_YEARS 'Y'
+#define ISO8061_TOKEN_MONTHS 'M'
+#define ISO8061_TOKEN_WEEKS 'W'
+#define ISO8061_TOKEN_DAYS 'D'
+#define ISO8061_TOKEN_HOURS 'H'
+#define ISO8061_TOKEN_MINUTES 'M'
+#define ISO8061_TOKEN_SECONDS 'S'
+
+#define ISO8061_TOKEN_TIME 'T'
+#define ISO8061_TOKEN_PERIOD 'P'
+
+/*===========================================================================*
+ Private Data Types
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Function Prototypes
+ *===========================================================================*/
+
+static void append_iso8061_value(char *p_string, uint32_t value, char symbol);
+static void append_iso8061_tag(char *p_string, char symbol);
+
+/*===========================================================================*
+ Private Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Public Function Implementations
+ *===========================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_value_time()
+ *
+ * DESCRIPTION
+ * Set a time_t value into a VF property.
+ *
+ * RETURNS
+ * TRUE iff property added & set OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_value_time(
+ VF_PROP_T *p_prop, /* The property */
+ uint32_t n_string, /* Which string we're encoding to */
+ const time_t t_value /* Time value */
+ )
+{
+ bool_t ret;
+ struct tm *p_tm;
+
+ p_tm = localtime(&t_value);
+
+ if (p_tm)
+ {
+ char value[256];
+
+ if (p_tm->tm_hour || p_tm->tm_min || p_tm->tm_sec)
+ {
+ sprintf(value, "%4d%02d%02dT%02d%02d%02d",
+ 1900 + p_tm->tm_year,
+ 1 + p_tm->tm_mon,
+ p_tm->tm_mday,
+ p_tm->tm_hour,
+ p_tm->tm_min,
+ p_tm->tm_sec);
+ }
+ else
+ {
+ sprintf(value, "%4d%02d%02d",
+ 1900 + p_tm->tm_year,
+ 1 + p_tm->tm_mon,
+ p_tm->tm_mday);
+ }
+
+ ret = vf_set_prop_value_string(p_prop, n_string, value);
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_value_time()
+ *
+ * DESCRIPTION
+ * Fetch a time_t value from a VF property.
+ *
+ * RETURNS
+ * TRUE iff foudn & converted OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_prop_value_time(
+ VF_PROP_T *p_prop, /* The property */
+ uint32_t n_string, /* Which string we're decoding */
+ time_t *p_t_value /* Pointer to output time value */
+ )
+{
+ bool_t ret;
+ const char *p_value;
+
+ p_value = vf_get_prop_value_string(p_prop, n_string);
+
+ if (p_value)
+ {
+ ret = vf_date_string_to_time(p_t_value, p_value);
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_date_string_to_time()
+ *
+ * DESCRIPTION
+ * Convert calendar string to absolute time. The basic formats are
+ * 19960401, 19960401T073000Z
+ *
+ * RETURNS
+ * TRUE <=> conversion OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_date_string_to_time(
+ uint32_t *p_time, /* Output time value */
+ const char *p_string /* Input string */
+ )
+{
+ bool_t ret = FALSE;
+
+ if (p_string && p_time)
+ {
+ time_t t;
+ struct tm tm;
+
+ p_memset(&tm, '\0', sizeof(tm));
+
+ /*
+ * p_string[8] is either 'T' or '\0' or an error.
+ */
+
+ if (ISO8061_TOKEN_TIME == p_string[8])
+ {
+ if (6 == sscanf(p_string, "%4d%2d%2dT%2d%2d%2d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec))
+ {
+ if ((1970 <= tm.tm_year) &&
+ ((1 <= tm.tm_mon) && (tm.tm_mon <= 12)) &&
+ ((1 <= tm.tm_mday) && (tm.tm_mday <= 28)) &&
+ ((0 <= tm.tm_hour) && (tm.tm_hour <= 23)) &&
+ ((0 <= tm.tm_min) && (tm.tm_hour <= 59)) &&
+ ((0 <= tm.tm_sec) && (tm.tm_sec <= 59)))
+ {
+ ret = TRUE;
+ }
+ }
+ }
+ else
+ if ('\0' == p_string[8])
+ {
+ if (3 == sscanf(p_string, "%4d%2d%2d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday))
+ {
+ if ((1970 <= tm.tm_year) &&
+ ((1 <= tm.tm_mon) && (tm.tm_mon <= 12)) &&
+ ((1 <= tm.tm_mday) && (tm.tm_mday <= 28)))
+ {
+ ret = TRUE;
+ }
+ }
+ }
+ else
+ {
+ /* Nor flesh nor fish nor fowl */
+ }
+
+ /*
+ * Reduce the year value to correct range & convert to time_t.
+ */
+
+ if (ret)
+ {
+ tm.tm_mon -= 1;
+ tm.tm_year -= 1900;
+ tm.tm_isdst = -1;
+
+ t = mktime(&tm);
+
+ if ((-1) == t)
+ {
+ ret = FALSE;
+ }
+ else
+ {
+ *p_time = (uint32_t)t;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_period_string_to_time()
+ *
+ * DESCRIPTION
+ * Convert period definition string to time value. The format is
+ * P[aaaY][bbbM][cccW][dddD]T[eeeH][fffM][gggS] where 'aaa' is a
+ * number of years, bbb months etc.
+ *
+ * RETURNS
+ * TRUE <=> conversion OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_period_string_to_time(
+ VF_ISO8601_PERIOD_T *p_period, /* Output time value */
+ const char *p_string /* Input string */
+ )
+{
+ bool_t ret = TRUE;
+ bool_t in_time_part = FALSE;
+
+ p_memset(p_period, '\0', sizeof(*p_period));
+
+ if (p_string && ('P' == p_string[0]) && *(++p_string))
+ {
+ while (ret && *p_string)
+ {
+ uint32_t value = 0;
+
+ while (isdigit((int)*p_string))
+ {
+ value = (value * 10) + *(p_string++) - '0';
+ }
+
+ switch (*p_string++)
+ {
+ case '\0':
+ {
+ ret = FALSE;
+ }
+ break;
+
+ case ISO8061_TOKEN_YEARS:
+ {
+ p_period->years = value;
+ }
+ break;
+
+ case ISO8061_TOKEN_MONTHS:
+ /*case ISO8061_TOKEN_MINUTES:*/
+ {
+ if (in_time_part)
+ {
+ p_period->minutes = value;
+ }
+ else
+ {
+ p_period->months = value;
+ }
+ }
+ break;
+
+ case ISO8061_TOKEN_WEEKS:
+ {
+ p_period->weeks = value;
+ }
+ break;
+
+ case ISO8061_TOKEN_DAYS:
+ {
+ p_period->days = value;
+ }
+ break;
+
+ case ISO8061_TOKEN_TIME:
+ {
+ if (in_time_part)
+ {
+ ret = FALSE;
+ }
+ else
+ {
+ in_time_part = TRUE;
+ }
+ }
+ break;
+
+ case ISO8061_TOKEN_HOURS:
+ {
+ p_period->hours = value;
+ }
+ break;
+
+ case ISO8061_TOKEN_SECONDS:
+ {
+ p_period->seconds = value;
+ }
+ break;
+
+ default:
+ {
+ ret = FALSE;
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_period_time_to_string()
+ *
+ * DESCRIPTION
+ * Convert a VF_ISO8601_PERIOD_T to a string.
+ *
+ * RETURNS
+ * Number of characters written.
+ *---------------------------------------------------------------------------*/
+
+uint32_t vf_period_time_to_string(
+ char *p_string, /* Output string */
+ const VF_ISO8601_PERIOD_T *p_period /* Input period value */
+ )
+{
+ uint32_t ret = 0;
+
+ if (p_string && p_period)
+ {
+ p_string[0] = '\0';
+
+ append_iso8061_tag(p_string, ISO8061_TOKEN_PERIOD);
+
+ append_iso8061_value(p_string, p_period->years, ISO8061_TOKEN_YEARS);
+ append_iso8061_value(p_string, p_period->months, ISO8061_TOKEN_MONTHS);
+ append_iso8061_value(p_string, p_period->weeks, ISO8061_TOKEN_WEEKS);
+ append_iso8061_value(p_string, p_period->days, ISO8061_TOKEN_DAYS);
+
+ if (p_period->hours || p_period->minutes || p_period->seconds)
+ {
+ append_iso8061_tag(p_string, ISO8061_TOKEN_TIME);
+ }
+
+ append_iso8061_value(p_string, p_period->hours, ISO8061_TOKEN_HOURS);
+ append_iso8061_value(p_string, p_period->minutes, ISO8061_TOKEN_MINUTES);
+ append_iso8061_value(p_string, p_period->seconds, ISO8061_TOKEN_SECONDS);
+
+ ret = p_strlen(p_string);
+ }
+
+ return ret;
+}
+
+
+
+/*===========================================================================*
+ Private Function Implementations
+ *===========================================================================*/
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * append_iso8061_value()
+ *
+ * DESCRIPTION
+ * Append xxxY value to the current encoded string.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+void append_iso8061_value(char *p_string, uint32_t value, char symbol)
+{
+ if (value)
+ {
+ sprintf(p_string + p_strlen(p_string), "%lu%c", (unsigned long)value, symbol);
+ }
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * append_iso8061_tag()
+ *
+ * DESCRIPTION
+ * Append indicated character to string.
+ *
+ * RETURNS
+ * (none).
+ *---------------------------------------------------------------------------*/
+
+void append_iso8061_tag(char *p_string, char symbol)
+{
+ p_string += p_strlen(p_string);
+
+ *p_string++ = symbol;
+ *p_string++ = '\0';
+}
+
+
+/*===========================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_access_wrappers.c b/src/vf_access_wrappers.c
new file mode 100644
index 0000000..2eea457
--- /dev/null
+++ b/src/vf_access_wrappers.c
@@ -0,0 +1,541 @@
+/****************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_access.c $
+ $Revision: 1.16 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Wrappers on the core access functions & other utility functions.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_access_wrappers.c,v $
+ * Revision 1.16 2002/11/16 13:19:10 tilda
+ * IID639288 - Implement method for adding subobjects.
+ *
+ * Revision 1.15 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.14 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.13 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.12 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.11 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.10 2001/11/18 22:07:02 tilda
+ * Ensure empty BASE64 properties get the encoding set correctly.
+ *
+ * Revision 1.9 2001/11/18 21:48:18 tilda
+ * Remove redundant code.
+ *
+ * Revision 1.8 2001/11/17 17:40:29 tilda
+ * Image / sound dialog box now works.
+ *
+ * Revision 1.7 2001/11/16 22:34:50 tilda
+ * New vf_get_property() allows append as well as find,
+ *
+ * Revision 1.6 2001/11/15 08:56:06 tilda
+ * Fix bug in qualifier location code.
+ *
+ * Revision 1.5 2001/11/14 22:36:56 tilda
+ * Add parameter to vf_find_prop_qual_index()
+ *
+ * Revision 1.4 2001/11/14 16:05:06 tilda
+ * Extend capabilities of vf_find_prop_qual_index().
+ *
+ * Revision 1.3 2001/11/06 22:51:05 tilda
+ * Supporting access functions for image selection / deletion.
+ *
+ * Revision 1.2 2001/10/24 18:56:29 tilda
+ * Tidy headers after import. Fix include path in release build.
+ *
+ * Revision 1.1 2001/10/24 18:34:35 tilda
+ * Initial Version.
+ *
+ *****************************************************************************/
+
+#ifndef NORCSID
+static const char vf_access_wrappers_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access_wrappers.c,v 1.16 2002/11/16 13:19:10 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+/*===========================================================================*
+ Interface Header Files
+ *===========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*===========================================================================*
+ Local Header File
+ *===========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*===========================================================================*
+ Public Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Defines
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Data Types
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Function Prototypes
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Public Function Implementations
+ *===========================================================================*/
+
+bool_t vf_prop_belongs_to_object(
+ VF_PROP_T *p_prop,
+ VF_OBJECT_T *p_object
+ );
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_value_string()
+ *
+ * DESCRIPTION
+ * Obtain string pointer value from VF_PROP_T. If the array contains
+ * an entry for the indicated string return it. Return NULL if out of
+ * range request, ie. n_string=3 for N=0;1;2
+ *
+ * RETURNS
+ * Pointer to string value if value present, NULL if index too large.
+ *---------------------------------------------------------------------------*/
+
+char *vf_get_prop_value_string(
+ VF_PROP_T *p_prop,
+ uint32_t n_string
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ char *p_ret = NULL;
+
+ if (p_vprop->value.v.s.pp_strings)
+ {
+ if (n_string < p_vprop->value.v.s.n_strings)
+ {
+ p_ret = p_vprop->value.v.s.pp_strings[n_string];
+ }
+ }
+
+ return p_ret;
+}
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_value_string()
+ *
+ * DESCRIPTION
+ * Set the value of a property.
+ *
+ * RETURNS
+ * TRUE <=> set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_value_string(
+ VF_PROP_T *p_prop,
+ uint32_t n_string,
+ const char *p_string
+ )
+{
+ return vf_set_prop_value(p_prop, (char *)p_string, n_string, VF_ENC_7BIT, TRUE);
+}
+
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_value_base64()
+ *
+ * DESCRIPTION
+ * Obtain data pointer for BASE64 data.
+ *
+ * RETURNS
+ * Pointer to data.
+ *---------------------------------------------------------------------------*/
+
+const uint8_t *vf_get_prop_value_base64(
+ VF_PROP_T *p_prop, /* Property we're setting a value in */
+ uint32_t *p_length /* Length of the binary data */
+ )
+{
+ const uint8_t *p_return = NULL;
+
+ if (p_prop)
+ {
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+
+ p_return = p_vprop->value.v.b.p_buffer;
+
+ if (p_length)
+ {
+ *p_length = p_vprop->value.v.b.n_bufsize;
+ }
+ }
+
+ return p_return;
+}
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_value_base64()
+ *
+ * DESCRIPTION
+ * Set the value of a property.
+ *
+ * RETURNS
+ * TRUE <=> set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_value_base64(
+ VF_PROP_T *p_prop, /* Property we're setting a value in */
+ const uint8_t *p_data, /* Pointer to the binary data */
+ uint32_t length, /* Length of the binary data */
+ bool_t copy /* Copy or keep pointer */
+ )
+{
+ return vf_set_prop_value(p_prop, (char *)p_data, length, VF_ENC_BASE64, copy);
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_value_object()
+ *
+ * DESCRIPTION
+ * Obtain object pointer value from VF_PROP_T.
+ *
+ * RETURNS
+ * Pointer to vobject value (or NULL if not found).
+ *---------------------------------------------------------------------------*/
+
+VF_OBJECT_T *vf_get_prop_value_object(
+ VF_PROP_T *p_prop
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+
+ if (VF_ENC_VOBJECT == p_vprop->value.encoding)
+ {
+ return (VF_OBJECT_T *)(p_vprop->value.v.o.p_object);
+ }
+
+ return NULL;
+}
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_value_object()
+ *
+ * DESCRIPTION
+ * Set the value of the indicated property to be a VOBJECT.
+ *
+ * RETURNS
+ * TRUE <=> set successfully.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_value_object(
+ VF_PROP_T *p_prop,
+ VF_OBJECT_T *p_object
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ bool_t ret = FALSE;
+
+ /*
+ * Avoid various sillies.
+ */
+ if (p_prop && p_object && !vf_prop_belongs_to_object(p_prop, p_object))
+ {
+ delete_prop_contents(p_prop, FALSE);
+
+ p_vprop->value.v.o.p_object = (VOBJECT_T *)p_object;
+ p_vprop->value.encoding = VF_ENC_VOBJECT;
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_prop_name_string()
+ *
+ * DESCRIPTION
+ * Get n'th name string.
+ *
+ * RETURNS
+ * Pointer to string value if value present, NULL if index too large.
+ *---------------------------------------------------------------------------*/
+
+char *vf_get_prop_name_string(
+ VF_PROP_T *p_prop,
+ uint32_t n_string
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ char *p_ret = NULL;
+
+ if (p_vprop->name.pp_strings)
+ {
+ if (n_string < p_vprop->name.n_strings)
+ {
+ p_ret = p_vprop->name.pp_strings[n_string];
+ }
+ }
+
+ return p_ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_prop_name_string()
+ *
+ * DESCRIPTION
+ * Set n'th name string.
+ *
+ * RETURNS
+ * TRUE iff allocation OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_prop_name_string(
+ VF_PROP_T *p_prop, /* Property we're setting a value in */
+ uint32_t n_string, /* Index to string */
+ const char *p_string /* Pointer to string */
+ )
+{
+ VPROP_T *p_vprop;
+ bool_t ret = FALSE;
+
+ p_vprop = (VPROP_T *)p_prop;
+
+ if (p_vprop)
+ {
+ if ((-1) == n_string)
+ {
+ ret = add_string_to_array(&p_vprop->name, p_string);
+ }
+ else
+ {
+ ret = set_string_array_entry(&p_vprop->name, p_string, n_string);
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_find_prop_qual_index()
+ *
+ * DESCRIPTION
+ * Locate property qualifier given either an array of possible values
+ * or a single token that is either present or absent. For example
+ * if we have a property:
+ *
+ * NAME;THIRD;TIME;LUCKY:VALUE1;VALUE2;VALUE3
+ *
+ * Then there are two possible searches.
+ *
+ * Firstly we can look for the property qualifier which can take values
+ * from the array { "FIRST", "SECOND", THIRD" } in which case the array
+ * is passed as pp_possible_values and the function returns with the
+ * values *p_found_value_index=2, p_qualifier_index=1
+ *
+ * Secondly we can look for the token with value "TIME" in which case
+ * p_token is set to "TIME" and the function returns *p_qualifier_index=2.
+ *
+ * RETURNS
+ * TRUE iff found, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_find_prop_qual_index(
+ VF_PROP_T *p_prop, /* The property we're querying */
+ uint32_t *p_qualifier_index, /* Ptr to output name index */
+ uint32_t *p_found_value_index, /* Ptr to output index in array */
+ const char **pp_possible_values, /* Array of possible values */
+ const char *p_token, /* Token searched for */
+ vf_search_flags_t match /* String comparison flags */
+ )
+{
+ uint32_t n;
+ bool_t ret;
+
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+
+ for (n = 0, ret = FALSE;!ret && (n < p_vprop->name.n_strings);n++)
+ {
+ const char *p_string = p_vprop->name.pp_strings[n];
+
+ if (p_string)
+ {
+ if (pp_possible_values)
+ {
+ uint32_t i;
+
+ for (i = 0;!ret && pp_possible_values[i];i++)
+ {
+ if (0 == p_stricmp(pp_possible_values[i], p_string))
+ {
+ if (p_found_value_index)
+ *p_found_value_index = i;
+ if (p_qualifier_index)
+ *p_qualifier_index = n;
+
+ ret = TRUE;
+ }
+ }
+ }
+ else
+ if (p_token)
+ {
+ if (0 == p_stricmp(p_token, p_string))
+ {
+ if (p_qualifier_index)
+ *p_qualifier_index = n;
+
+ ret = TRUE;
+ }
+ }
+ else
+ {
+ /*???*/
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_find_charset()
+ *
+ * DESCRIPTION
+ * Locate the charset
+ *
+ * RETURNS
+ * vf_charset_t.
+ *---------------------------------------------------------------------------*/
+
+const char *vf_find_charset(
+ VF_PROP_T *p_prop
+ )
+{
+ VPROP_T *p_vprop = (VPROP_T *)p_prop;
+ char *ret;
+
+ if (!string_array_contains_string(&p_vprop->name, &ret, -1, VFP_CHARSET, FALSE))
+ {
+ ret = NULL;
+ }
+ else
+ {
+ ret += 1 + p_strlen(VFP_CHARSET);
+ }
+
+ return ret;
+}
+
+
+
+
+
+/*===========================================================================*
+ Private Function Implementations
+ *===========================================================================*/
+
+bool_t vf_prop_belongs_to_object(
+ VF_PROP_T *p_prop,
+ VF_OBJECT_T *p_object
+ )
+{
+ return FALSE;
+}
+
+/*===========================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_config.h b/src/vf_config.h
new file mode 100644
index 0000000..2a4ff8f
--- /dev/null
+++ b/src/vf_config.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_common.h $
+ $Revision: 1.1 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Common header file for vformat library. This file is internal to vformat
+ (ie. changes here don't affect the interface) but contains the definitions
+ which affect the operation of various components eg. the memory debug.
+
+ This file is #included before all other header files within the library.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_config.h,v $
+ * Revision 1.1 2002/10/26 15:57:11 tilda
+ * Initial Version
+ *
+ *
+ *******************************************************************************/
+
+#ifndef _VF_CONFIG_H_
+#define _VF_CONFIG_H_
+
+#ifndef NORCSID
+static const char vf_config_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_config.h,v 1.1 2002/10/26 15:57:11 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+
+/*
+ * If building debug version under windows then include the memory debug interface.
+ */
+#if (defined(WIN) || defined(WIN32)) && defined(_DEBUG)
+#if !defined(VFORMAT_MEM_DEBUG)
+#define VFORMAT_MEM_DEBUG
+#endif
+#endif
+
+/*
+ * Conditional compiles allowing configuration of various string portability functions.
+ */
+/* #define HAVE_STRLEN */
+/* #define HAVE_STRCPY */
+/* #define HAVE_STRCMP */
+/* #define HAVE_STRCAT */
+/* #define HAVE_STRSTR */
+/* #define HAVE_STRICMP */
+/* #define HAVE_MEMCPY */
+/* #define HAVE_MEMSET */
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+#endif /*_VF_CONFIG_H_*/
diff --git a/src/vf_create_object.c b/src/vf_create_object.c
new file mode 100644
index 0000000..ab540b9
--- /dev/null
+++ b/src/vf_create_object.c
@@ -0,0 +1,158 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Revision: 1.8 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley.
+
+DESCRIPTION
+ The vf_create_object() function.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_create_object.c,v $
+ * Revision 1.8 2002/11/16 13:19:10 tilda
+ * IID639288 - Implement method for adding subobjects.
+ *
+ * Revision 1.7 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.6 2002/10/29 07:19:20 tilda
+ * Tidy headers.
+ *
+ * Revision 1.5 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.4 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.3 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.2 2002/01/06 13:11:55 tilda
+ * Update header.
+ *
+ * Revision 1.1 2002/01/06 13:08:15 tilda
+ * Change file name from vf_createobject.c
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_create_object_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_create_object.c,v 1.8 2002/11/16 13:19:10 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *===========================================================================*/
+
+#include <common/types.h>
+
+/*===========================================================================*
+ Interface Header Files
+ *==========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*===========================================================================*
+ Local Header File
+ *==========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*===========================================================================*
+ Public Data
+ *==========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Defines
+ *==========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Data Types
+ *==========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Function Prototypes
+ *==========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Data
+ *==========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Public Function Implementations
+ *==========================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_create_object()
+ *
+ * DESCRIPTION
+ * Creates and empty vformat object.
+ *
+ * RETURNS
+ * Ptr to object if created else NULL.
+ *---------------------------------------------------------------------------*/
+
+VF_OBJECT_T *vf_create_object(
+ const char *p_type, /* Type of object to create */
+ VF_OBJECT_T *p_parent /* Parent object if any */
+ )
+{
+ VOBJECT_T *p_new = NULL;
+
+ if (p_type)
+ {
+ p_new = vf_malloc(sizeof(VOBJECT_T));
+
+ if (p_new)
+ {
+ p_memset(p_new, '\0', sizeof(VOBJECT_T));
+
+ p_new->p_type = vf_malloc(1 + p_strlen(p_type));
+
+ p_new->p_parent = (VOBJECT_T *)p_parent;
+
+ if (p_new->p_type)
+ {
+ p_strcpy(p_new->p_type, p_type);
+ }
+ else
+ {
+ vf_free(p_new);
+ p_new = NULL;
+ }
+ }
+ }
+
+ return (VF_OBJECT_T *)p_new;
+}
+
+
+/*===========================================================================*
+ Private Function Implementations
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_delete.c b/src/vf_delete.c
new file mode 100644
index 0000000..d70b8e4
--- /dev/null
+++ b/src/vf_delete.c
@@ -0,0 +1,327 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_delete.c $
+ $Revision: 1.14 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Delete a vformat object.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_delete.c,v $
+ * Revision 1.14 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.13 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.12 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.11 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.10 2001/11/05 21:07:20 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.9 2001/10/24 18:36:06 tilda
+ * BASE64 bugfixes. Split reader/writer code. Start create/modify work.
+ *
+ * Revision 1.8 2001/10/14 19:53:36 tilda
+ * Group handling. NO group searching functions.
+ *
+ * Revision 1.7 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.6 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.5 2001/10/13 14:49:30 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ * Revision 1.4 2001/10/12 16:20:03 tilda
+ * Correctly parse compound quoted printable properties.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_delete_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_delete.c,v 1.14 2002/11/03 18:43:16 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *=============================================================================*/
+
+#include <common/types.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_string_arrays.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+
+static void free_prop_list(
+ VPROP_T *p_props /* List of properties to free */
+ );
+
+
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_delete_object()
+ *
+ * DESCRIPTION
+ * Cleans up the memory used by the indicated vformat object.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void vf_delete_object(
+ VF_OBJECT_T *p_object,
+ bool_t all
+ )
+{
+ VOBJECT_T *p_obj = (VOBJECT_T *)p_object;
+
+ if (p_obj)
+ {
+ VOBJECT_T *p_next = p_obj->p_next;
+
+ free_prop_list(p_obj->p_props);
+
+ if (p_obj->p_type)
+ {
+ vf_free(p_obj->p_type);
+ }
+
+ vf_free(p_obj);
+
+ if (all )
+ {
+ vf_delete_object((VF_OBJECT_T *)p_next, TRUE);
+ }
+ }
+}
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_delete_prop()
+ *
+ * DESCRIPTION
+ * Deletes indicated property from the indicated object. Deletes prop
+ * contents if dc is set.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void vf_delete_prop(
+ VF_OBJECT_T *p_object, /* The object we're deleting from */
+ VF_PROP_T *p_prop, /* The property we're removing */
+ bool_t dc /* Should property contents be deleted? */
+ )
+{
+ VOBJECT_T *p_obj = (VOBJECT_T *)p_object;
+
+ if (p_obj)
+ {
+ VPROP_T **p_vprop = &(p_obj->p_props);
+
+ while (*p_vprop)
+ {
+ if ((*p_vprop) == (VPROP_T *)p_prop)
+ {
+ *p_vprop = ((VPROP_T *)p_prop)->p_next;
+
+ if (dc)
+ {
+ delete_prop_contents(p_prop, TRUE);
+ }
+
+ vf_free(p_prop);
+
+ break;
+ }
+ else
+ {
+ p_vprop = &((*p_vprop)->p_next);
+ }
+ }
+ }
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * delete_prop_contents()
+ *
+ * DESCRIPTION
+ * Cleans up the memory used by the value associated with the property.
+ * The property is not deleted => can be a statically allocated variable.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void delete_prop_contents(
+ VF_PROP_T *p_vprop, /* The VF_PROP_T to clean */
+ bool_t delname /* Delete the name as well? */
+ )
+{
+ VPROP_T *p_prop = (VPROP_T *)p_vprop;
+
+ if (delname)
+ {
+ free_string_array_contents(&p_prop->name);
+
+ if (p_prop->p_group)
+ {
+ vf_free(p_prop->p_group);
+ p_prop->p_group = NULL;
+ }
+ }
+
+ if (p_prop->value.v.b.p_buffer)
+ {
+ vf_free(p_prop->value.v.b.p_buffer);
+ p_prop->value.v.b.p_buffer = NULL;
+ }
+
+ if (p_prop->value.v.s.pp_strings)
+ {
+ uint32_t n;
+
+ for (n = 0;n < p_prop->value.v.s.n_strings;n++)
+ {
+ if (p_prop->value.v.s.pp_strings[n])
+ {
+ vf_free(p_prop->value.v.s.pp_strings[n]);
+ p_prop->value.v.s.pp_strings[n] = NULL;
+ }
+ }
+
+ vf_free(p_prop->value.v.s.pp_strings);
+ p_prop->value.v.s.pp_strings = NULL;
+
+ p_prop->value.v.s.n_strings = 0;
+ }
+
+ if (p_prop->value.v.o.p_object)
+ {
+ vf_delete_object((VF_OBJECT_T *)p_prop->value.v.o.p_object, TRUE);
+ p_prop->value.v.o.p_object = NULL;
+ }
+}
+
+
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * free_prop_list()
+ *
+ * DESCRIPTION
+ * Cleans up the memory used by the indicated property list.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void free_prop_list(
+ VPROP_T *p_props /* List of properties to free */
+ )
+{
+ VPROP_T *p_tmp;
+
+ for (p_tmp = p_props;p_tmp;)
+ {
+ VPROP_T *p_next = p_tmp->p_next;
+
+ delete_prop_contents((VF_PROP_T *)p_tmp, TRUE);
+
+ vf_free(p_tmp);
+
+ p_tmp = p_next;
+ }
+}
+
+
+
+
+
+
+
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_internals.h b/src/vf_internals.h
new file mode 100644
index 0000000..98ddacc
--- /dev/null
+++ b/src/vf_internals.h
@@ -0,0 +1,223 @@
+/*******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_internals.h $
+ $Revision: 1.15 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Definition of the internal representation used for VOBJECTs.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_internals.h,v $
+ * Revision 1.15 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.14 2002/11/02 08:56:17 tilda
+ * Start of internationalisation changes.
+ *
+ * Revision 1.13 2002/10/26 16:09:24 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.12 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.11 2002/02/24 17:10:34 tilda
+ * Add API for "is modified" functionality.
+ *
+ * Revision 1.10 2001/10/24 18:36:06 tilda
+ * BASE64 bugfixes. Split reader/writer code. Start create/modify work.
+ *
+ * Revision 1.9 2001/10/14 19:53:36 tilda
+ * Group handling. NO group searching functions.
+ *
+ * Revision 1.8 2001/10/14 16:40:04 tilda
+ * Initial testing of access functions.
+ *
+ * Revision 1.7 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.6 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.5 2001/10/13 14:49:30 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ * Revision 1.4 2001/10/12 16:20:03 tilda
+ * Correctly parse compound quoted printable properties.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *******************************************************************************/
+
+#ifndef _VF_INTERNALS_H_
+#define _VF_INTERNALS_H_
+
+#ifndef NORCSID
+static const char vf_internals_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_internals.h,v 1.15 2002/11/02 18:29:26 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+
+#define VFP_BEGIN "BEGIN"
+#define VFP_END "END"
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VSTRARRAY_T encapsulates an array of strings.
+ *----------------------------------------------------------------------------*/
+
+typedef struct VSTRARRAY_T
+{
+ uint32_t n_strings; /* Then number of strings */
+ char **pp_strings; /* The strings */
+}
+VSTRARRAY_T;
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VBINDATA_T encapsulates a chunk of binary data. Yes, you could encode
+ * any and all vformat attributes in BASE64 but custom is to use BASE64
+ * for images etc.
+ *----------------------------------------------------------------------------*/
+
+typedef struct VBINDATA_T
+{
+ char *p_buffer; /* Binary data */
+ uint32_t n_bufsize;
+}
+VBINDATA_T;
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VOBJDATA_T
+ *----------------------------------------------------------------------------*/
+
+typedef struct VOBJDATA_T
+{
+ struct VOBJECT_T *p_object; /* Another vformat object */
+}
+VOBJDATA_T;
+
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VPROPVALUE_T encapsulates the "value" half of a property.
+ *----------------------------------------------------------------------------*/
+
+typedef struct VPROPVALUE_T
+{
+ vf_encoding_t encoding;
+
+ struct
+ {
+ VSTRARRAY_T s;
+ VBINDATA_T b;
+ VOBJDATA_T o;
+ }
+ v;
+}
+VPROPVALUE_T;
+
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VPROP_T defines a single property. It's an association of a name
+ * and value pair. A vformat object is simply a list of properties.
+ * Associated with a property is (possibly) a group name.
+ *----------------------------------------------------------------------------*/
+
+typedef struct VPROP_T
+{
+ char *p_group; /* Group - we keep the A.B.C format */
+ VSTRARRAY_T name; /* Name fields */
+ VPROPVALUE_T value; /* Value fields */
+
+ struct VPROP_T *p_next; /* Next property */
+ struct VPROP_T *p_next_srch; /* Next in current search */
+
+ bool_t modified; /* Property modified? */
+
+ struct VOBJECT_T *p_parent; /* Owning object (if any) */
+}
+VPROP_T;
+
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * VOBJECT_T defines a single vformat object.
+ *----------------------------------------------------------------------------*/
+
+typedef struct VOBJECT_T
+{
+ char *p_type; /* "VCARD" or "VCALENDAR" etc. */
+ VPROP_T *p_props; /* List of properties */
+
+ bool_t modified; /* Object modified? */
+
+ struct VOBJECT_T *p_parent; /* Owning object (if any) */
+ struct VOBJECT_T *p_next; /* Next object (if any) */
+}
+VOBJECT_T;
+
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * delete_prop_contents()
+ *
+ * DESCRIPTION
+ * Cleans up the memory used by the value associated with the property.
+ * The property is not deleted => can be a statically allocated variable.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+extern void delete_prop_contents(
+ VF_PROP_T *p_vprop, /* The VF_PROP_T to clean */
+ bool_t delname /* Delete the name as well? */
+ );
+
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+#endif /*_VF_INTERNALS_H_*/
+
diff --git a/src/vf_malloc.c b/src/vf_malloc.c
new file mode 100644
index 0000000..ef405d9
--- /dev/null
+++ b/src/vf_malloc.c
@@ -0,0 +1,270 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_malloc.c $
+ $Revision: 1.7 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Implements the memory allocation functions used by the rest of the vformat
+ library, defaulting to the functions provided by vf_malloc_stdlib.c which
+ uses malloc() etc.
+
+ Code below knows nothing about the specific allocation scheme in use or it's
+ debugging facilities and is simply provides the common functions and the
+ ability to point vformat at an alternative allocation module.
+
+ The only conditional compile option recognised is VFORMAT_MEM_DEBUG which
+ is described in the accompanying header file.
+
+ Note
+ ====
+ The original code merged the malloc() implementation with the debug facility
+ and also included a conditional compile VFORMAT_EXT_MALLOC to control the use
+ of external allocation functions. Given that this tripped up the _author_ on
+ at least one public test event (UPF-9, where the sync engine was unable to read
+ VCARDS & extract the X-IRMC stuff) it was considered overcomplicated and has
+ been considerably simplified ;) - T.
+
+MODIFICATION HISTORY
+ * $Log: vf_malloc.c,v $
+ * Revision 1.7 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.6 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.5 2002/10/08 21:08:43 tilda
+ * Improve memory debugging functions.
+ *
+ * Revision 1.4 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_malloc_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc.c,v 1.7 2002/10/26 16:09:23 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#if !defined(VFORMAT_EXCLUDE_MALLOC)
+#include "vf_malloc_stdlib.h"
+#endif
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+
+/*
+ * Pointers to the functions in use - initialised to the default CRT based allocation
+ * functions unless VFORMAT_EXCLUDE_MALLOC is set in which case they are initialised
+ * to NULL in the expectation that the user calls vf_set_mem_functions() at some point.
+ */
+
+#if defined(VFORMAT_EXCLUDE_MALLOC)
+static vf_malloc_fn_t vf_malloc_fn;
+static vf_realloc_fn_t vf_realloc_fn;
+static vf_free_fn_t vf_free_fn;
+#else
+static vf_malloc_fn_t vf_malloc_fn = _vf_stdlib_malloc;
+static vf_realloc_fn_t vf_realloc_fn = _vf_stdlib_realloc;
+static vf_free_fn_t vf_free_fn = _vf_stdlib_free;
+#endif
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_set_mem_functions()
+ *
+ * DESCRIPTION
+ * Set the memory allocation functions we're using.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void vf_set_mem_functions(
+ vf_malloc_fn_t malloc_fn, /* Allocation function */
+ vf_realloc_fn_t realloc_fn, /* Reallocation function */
+ vf_free_fn_t free_fn /* Free function */
+ )
+{
+ vf_realloc_fn = realloc_fn;
+ vf_malloc_fn = malloc_fn;
+ vf_free_fn = free_fn;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_malloc()
+ *
+ * DESCRIPTION
+ * Allocate chunk of memory.
+ *
+ * RETURNS
+ * Ptr to new block, or NULL if failed.
+ *----------------------------------------------------------------------------*/
+
+void *_vf_malloc(
+ uint32_t s /* Size required */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* Filename */
+ int line /* Line number */
+#endif
+ )
+{
+ void *p = NULL;
+
+ if (vf_malloc_fn)
+ {
+#if defined(VFORMAT_MEM_DEBUG)
+ p = vf_malloc_fn(s, file, line);
+#else
+ p = vf_malloc_fn(s);
+#endif
+ }
+
+ return p;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_realloc()
+ *
+ * DESCRIPTION
+ * Re-allocate chunk of memory allocated by _vf_malloc().
+ *
+ * RETURNS
+ * Ptr to new block, or NULL if failed.
+ *----------------------------------------------------------------------------*/
+
+void *_vf_realloc(
+ void *p, /* Original pointer */
+ uint32_t s /* Size required */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* filename */
+ int line /* line number */
+#endif
+ )
+{
+ void *np = NULL;
+
+ if (vf_realloc_fn)
+ {
+#if defined(VFORMAT_MEM_DEBUG)
+ np = vf_realloc_fn(p, s, file, line);
+#else
+ np = vf_realloc_fn(p, s);
+#endif
+ }
+
+ return np;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_free()
+ *
+ * DESCRIPTION
+ * De-allocate chunk of memory allocated by _vf_malloc().
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void _vf_free(
+ void *p /* Pointer */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* Filename */
+ int line /* Line number */
+#endif
+ )
+{
+ if (vf_free_fn)
+ {
+#if defined(VFORMAT_MEM_DEBUG)
+ vf_free_fn(p, file, line);
+#else
+ vf_free_fn(p);
+#endif
+ }
+}
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_malloc.h b/src/vf_malloc.h
new file mode 100644
index 0000000..7116d64
--- /dev/null
+++ b/src/vf_malloc.h
@@ -0,0 +1,166 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_malloc.h $
+ $Revision: 1.6 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Memory allocation functions / macros for vformat code. The code always uses
+ vf_malloc(), vf_realloc() and vf_free() which are replaced by macros with the
+ names of functions implemented in vf_malloc.c.
+
+ If the conditional compile VFORMAT_MEM_DEBUG is set then in addition to the
+ caller's allocation parameters, filename and line number information is
+ provided to the lower layer which may record this for debugging.
+
+ Additionally, a function vf_set_mem_functions() is provided which allows an
+ application to replace the allocation functions with it's own. This should
+ be done before vformat allocates any memory ie. during initialisation.
+
+ Unless the library is built with the symbol VFORMAT_EXCLUDE_MALLOC defined
+ then the library defaults to using malloc() etc.
+
+MODIFICATION HISTORY
+ * $Log: vf_malloc.h,v $
+ * Revision 1.6 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.5 2002/10/08 21:08:43 tilda
+ * Improve memory debugging functions.
+ *
+ * Revision 1.4 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *******************************************************************************/
+
+#ifndef _VF_MALLOC_H_
+#define _VF_MALLOC_H_
+
+#ifndef NORCSID
+static const char vf_malloc_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc.h,v 1.6 2002/10/26 16:09:23 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+
+/*
+ * If VFORMAT_MEM_DEBUG is defined, map the vf_xxx() allocation calls to
+ * the debugging versions found in vf_malloc.c
+ */
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+#define vf_malloc(x) _vf_malloc(x, __FILE__, __LINE__)
+#define vf_realloc(x, y) _vf_realloc(x, y, __FILE__, __LINE__)
+#define vf_free(x) _vf_free(x, __FILE__, __LINE__)
+
+#else /*defined(VFORMAT_MEM_DEBUG)*/
+
+#define vf_malloc(x) _vf_malloc(x)
+#define vf_realloc(x, y) _vf_realloc(x, y)
+#define vf_free(x) _vf_free(x)
+
+#endif /*defined(VFORMAT_MEM_DEBUG)*/
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+typedef void *(*vf_malloc_fn_t)(uint32_t s, const char *file, int line);
+typedef void *(*vf_realloc_fn_t)(void *p, uint32_t ns, const char *file, int line);
+typedef void (*vf_free_fn_t)(void *p, const char *file, int line);
+
+#else /*defined(VFORMAT_MEM_DEBUG)*/
+
+typedef void *(*vf_malloc_fn_t)(uint32_t s);
+typedef void *(*vf_realloc_fn_t)(void *p, uint32_t ns);
+typedef void (*vf_free_fn_t)(void *p);
+
+#endif /*defined(VFORMAT_MEM_DEBUG)*/
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_malloc(), _vf_realloc(), _vf_free()
+ *
+ * DESCRIPTION
+ * Memory allocation functions in use. If VFORMAT_MEM_DEBUG is defined
+ * the line & file are recorded as well.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+extern void *_vf_malloc(uint32_t s, const char *file, int line);
+extern void *_vf_realloc(void *p, uint32_t ns, const char *file, int line);
+extern void _vf_free(void *p, const char *file, int line);
+
+#else
+
+extern void *_vf_malloc(uint32_t s);
+extern void *_vf_realloc(void *p, uint32_t ns);
+extern void _vf_free(void *p);
+
+#endif
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_set_mem_functions()
+ *
+ * DESCRIPTION
+ * Set the memory allocation functions we're using.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+extern VFORMATDECLSPEC void vf_set_mem_functions(
+ vf_malloc_fn_t malloc_fn,
+ vf_realloc_fn_t realloc_fn,
+ vf_free_fn_t free_fn
+ );
+
+
+
+
+/*=============================================================================*
+ FIN
+ *============================================================================*/
+
+#endif /*_VF_MALLOC_H_*/
diff --git a/src/vf_malloc_stdlib.c b/src/vf_malloc_stdlib.c
new file mode 100644
index 0000000..6318fa5
--- /dev/null
+++ b/src/vf_malloc_stdlib.c
@@ -0,0 +1,392 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_malloc.c $
+ $Revision: 1.2 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ C standard library based memory allocation functions referenced by default in
+ the accompanying vf_malloc.c file. These are excluded from the build entirely
+ if VFORMAT_EXCLUDE_MALLOC is set in the build options.
+
+MODIFICATION HISTORY
+ * $Log: vf_malloc_stdlib.c,v $
+ * Revision 1.2 2002/11/15 09:15:00 tilda
+ * IID638823 - Various portability issues.
+ *
+ * Revision 1.1 2002/10/26 15:57:11 tilda
+ * Initial Version
+ *
+ *******************************************************************************/
+
+#if !defined(VFORMAT_EXCLUDE_MALLOC)
+
+#ifndef NORCSID
+static const char vf_malloc_stdlib_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc_stdlib.c,v 1.2 2002/11/15 09:15:00 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_strings.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+
+#define NUMMEMBLOCKS (1024)
+
+#if defined(WIN) || defined(WIN32)
+#define DEBUGBREAK _asm { int 3 }
+#endif
+
+#ifndef DEBUGBREAK
+#define DEBUGBREAK
+#endif
+
+#define ALLOCBREAK (-1)
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+
+typedef struct MEMBLOCK_T
+{
+ void *p; /* The block */
+ uint32_t s; /* The size */
+ char *file; /* filename it was allocated in */
+ int line; /* line number */
+}
+MEMBLOCK_T;
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+
+#if defined(VFORMAT_MEM_DEBUG)
+static void init_mem_debug(void);
+static void atexit_dump_mem(void);
+#endif
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+
+static MEMBLOCK_T blocks[NUMMEMBLOCKS];
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_stdlib_malloc()
+ *
+ * DESCRIPTION
+ * vformat compatible memory allocator using C standard library functions.
+ *
+ * RETURNS
+ * Ptr to new block, or NULL if failed.
+ *----------------------------------------------------------------------------*/
+
+void *_vf_stdlib_malloc(
+ uint32_t s /* Size required */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* filename */
+ int line /* line number */
+#endif
+ )
+{
+ void *p = NULL;
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+ uint32_t i;
+
+ init_mem_debug();
+
+ for (i = 0;i < NUMMEMBLOCKS;i++)
+ {
+ if (blocks[i].p)
+ {
+ }
+ else
+ {
+ p = malloc(s);
+
+ if (p)
+ {
+ blocks[i].p = p;
+ blocks[i].s = s;
+ blocks[i].file = (char *)file;
+ blocks[i].line = line;
+ }
+
+ if (i == ALLOCBREAK)
+ {
+ DEBUGBREAK;
+ }
+
+ break;
+ }
+ }
+
+#else /*defined(VFORMAT_MEM_DEBUG)*/
+
+ p = malloc(s);
+
+#endif
+
+ return p;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_stdlib_realloc()
+ *
+ * DESCRIPTION
+ * Re-allocate chunk of memory allocated by _vf_malloc().
+ *
+ * RETURNS
+ * Ptr to new block, or NULL if failed.
+ *----------------------------------------------------------------------------*/
+
+void *_vf_stdlib_realloc(
+ void *p, /* Original pointer */
+ uint32_t s /* Size required */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* Filename */
+ int line /* Line number */
+#endif
+ )
+{
+ void *np = NULL;
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+ uint32_t i;
+
+ init_mem_debug();
+
+ if (!p)
+ return _vf_stdlib_malloc(s, file, line);
+
+ for (i = 0;i < NUMMEMBLOCKS;i++)
+ {
+ if (blocks[i].p == p)
+ {
+ np = realloc(p, s);
+
+ if (np)
+ {
+ blocks[i].p = np;
+ blocks[i].s = s;
+ }
+
+ break;
+ }
+ }
+
+#else /*defined(VFORMAT_MEM_DEBUG)*/
+
+ np = realloc(p, s);
+
+#endif /*defined(VFORMAT_MEM_DEBUG)*/
+
+ return np;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_stdlib_free()
+ *
+ * DESCRIPTION
+ * De-allocate chunk of memory allocated by _vf_malloc().
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void _vf_stdlib_free(
+ void *p /* Pointer */
+#if defined(VFORMAT_MEM_DEBUG)
+ , const char *file, /* Filename */
+ int line /* Line number */
+#endif
+ )
+{
+#if defined(VFORMAT_MEM_DEBUG)
+
+ uint32_t i;
+
+ init_mem_debug();
+
+ for (i = 0;i < NUMMEMBLOCKS;i++)
+ {
+ if (blocks[i].p == p)
+ {
+ blocks[i].p = NULL;
+ blocks[i].s = 0;
+ blocks[i].line = 0;
+ blocks[i].file = NULL;
+
+ free(p);
+
+ break;
+ }
+ }
+
+#else
+
+ free(p);
+
+#endif
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_stdlib_dump_alloc_info()
+ *
+ * DESCRIPTION
+ * Display current state of memory allocator.
+ *
+ * RETURNS
+ * TRUE if blocks are currently allocated, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t vf_stdlib_dump_alloc_info()
+{
+ unsigned long i;
+ unsigned long c, s;
+
+ for (i = 0, c = 0, s = 0;i < NUMMEMBLOCKS;i++)
+ {
+ if (blocks[i].p)
+ {
+ c += 1;
+ s += blocks[i].s;
+
+ printf("block[%lu] size %lu, file %s, line %d\n",
+ i, (unsigned long)blocks[i].s, blocks[i].file, blocks[i].line);
+ }
+ }
+
+ if (c)
+ {
+ printf("... a total of %lu blocks, %lu bytes\n", c, s);
+ }
+
+ return (0 < c) ? TRUE : FALSE;
+}
+
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * init_mem_debug()
+ *
+ * DESCRIPTION
+ * Initialisation function.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+static void init_mem_debug()
+{
+ static bool_t init_yet = FALSE;
+
+ if (init_yet)
+ {
+ /* OK */
+ }
+ else
+ {
+ p_memset(blocks, '\0', sizeof(blocks));
+
+ atexit(atexit_dump_mem);
+
+ init_yet = TRUE;
+ }
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * atexit_dump_mem()
+ *
+ * DESCRIPTION
+ * atexit() callback function which dumps memory allocated info.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+static void atexit_dump_mem(void)
+{
+ vf_stdlib_dump_alloc_info();
+}
+
+#endif /*defined(VFORMAT_MEM_DEBUG)*/
+
+
+#endif /*defined(VFORMAT_EXCLUDE_MALLOC)*/
+
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_malloc_stdlib.h b/src/vf_malloc_stdlib.h
new file mode 100644
index 0000000..d765256
--- /dev/null
+++ b/src/vf_malloc_stdlib.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_malloc.h $
+ $Revision: 1.1 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Externs for the malloc() based memory allocator.
+
+MODIFICATION HISTORY
+ * $Log: vf_malloc_stdlib.h,v $
+ * Revision 1.1 2002/10/26 15:57:11 tilda
+ * Initial Version
+ *
+ *
+ *******************************************************************************/
+
+#ifndef _VF_MALLOC_STDLIB_H_
+#define _VF_MALLOC_STDLIB_H_
+
+#ifndef NORCSID
+static const char vf_malloc_stdlib_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc_stdlib.h,v 1.1 2002/10/26 15:57:11 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * _vf_stdlib_malloc(), _vf_stdlib_realloc(), _vf_stdlib_free()
+ *
+ * DESCRIPTION
+ * Memory allocation functions provided in terms of C runtime library
+ * malloc() etc. If VFORMAT_MEM_DEBUG is defined the line & file are
+ * passed through for ebugging purposes.
+ *
+ * RETURNS
+ * (various)
+ *----------------------------------------------------------------------------*/
+
+#if defined(VFORMAT_MEM_DEBUG)
+
+extern void *_vf_stdlib_malloc(uint32_t s, const char *file, int line);
+extern void *_vf_stdlib_realloc(void *p, uint32_t ns, const char *file, int line);
+extern void _vf_stdlib_free(void *p, const char *file, int line);
+
+#else
+
+extern void *_vf_stdlib_malloc(uint32_t s);
+extern void *_vf_stdlib_realloc(void *p, uint32_t ns);
+extern void _vf_stdlib_free(void *p);
+
+#endif
+
+/*=============================================================================*
+ FIN
+ *============================================================================*/
+
+#endif /*_VF_MALLOC_STDLIB_H_*/
diff --git a/src/vf_modified.c b/src/vf_modified.c
new file mode 100644
index 0000000..427698a
--- /dev/null
+++ b/src/vf_modified.c
@@ -0,0 +1,159 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_modified.c $
+ $Revision: 1.4 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Memory allocation system for vformat parser / editor.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_modified.c,v $
+ * Revision 1.4 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.3 2002/10/29 07:19:20 tilda
+ * Tidy headers.
+ *
+ * Revision 1.2 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.1 2002/10/11 20:29:25 tilda
+ * Include vf_modified.c
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_modified_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_modified.c,v 1.4 2002/11/02 18:29:26 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_modified.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_is_modified()
+ *
+ * DESCRIPTION
+ * Return the status of the modified flag for the indicated object.
+ *
+ * RETURNS
+ * TRUE/FALSE
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_is_modified(
+ VF_OBJECT_T *p_object
+ )
+{
+ bool_t ret = FALSE;
+
+ if (p_object)
+ {
+ ret = ((VOBJECT_T *)p_object)->modified;
+ }
+
+ return ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * mark_property_modified()
+ *
+ * DESCRIPTION
+ * Mark indicated property and it's owning object as modified. If the
+ * recurse flag is st, then the owning object's parent object is also
+ * marked as modified recursively up to the top of the tree.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+void mark_property_modified(
+ VPROP_T *p_prop, /* The property */
+ bool_t recurse /* Recurse? */
+ )
+{
+ p_prop->modified = TRUE;
+ p_prop->p_parent->modified = TRUE;
+
+ if (recurse)
+ {
+ VOBJECT_T *p_parent = p_prop->p_parent->p_parent;
+
+ for (;p_parent;p_parent = p_parent->p_parent)
+ {
+ p_parent->modified = TRUE;
+ }
+ }
+}
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+
+ /*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_modified.h b/src/vf_modified.h
new file mode 100644
index 0000000..f1616a4
--- /dev/null
+++ b/src/vf_modified.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_modified.h $
+ $Revision: 1.1 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Library internal access to the modification status.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_modified.h,v $
+ * Revision 1.1 2002/10/11 20:22:32 tilda
+ * Added / repaired vf_modified.h
+ *
+ *
+ * 2 9/05/02 3:49p Nm2
+ * Adjust memoruy allocation system for use in an embedded build.
+ *
+ * 1 7/08/02 7:24a Nm2
+ *
+ *******************************************************************************/
+
+#ifndef _VF_MODIFIED_H_
+#define _VF_MODIFIED_H_
+
+#ifndef NORCSID
+static const char vf_modified_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_modified.h,v 1.1 2002/10/11 20:22:32 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * mark_property_modified()
+ *
+ * DESCRIPTION
+ * Mark indicated property and it's owning object as modified. If the
+ * recurse flag is st, then the owning object's parent object is also
+ * marked as modified recursively up to the top of the tree.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+extern void mark_property_modified(
+ VPROP_T *p_prop, /* The property */
+ bool_t recurse /* Recurse? */
+ );
+
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+#endif /*_VF_MODIFIED_H_*/
diff --git a/src/vf_parser.c b/src/vf_parser.c
new file mode 100644
index 0000000..bf7b789
--- /dev/null
+++ b/src/vf_parser.c
@@ -0,0 +1,1182 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_parser.c $
+ $Revision: 1.22 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Parser for text stream in vobject format.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_parser.c,v $
+ * Revision 1.22 2002/11/16 13:19:10 tilda
+ * IID639288 - Implement method for adding subobjects.
+ *
+ * Revision 1.21 2002/11/15 09:15:00 tilda
+ * IID638823 - Various portability issues.
+ *
+ * Revision 1.20 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.19 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.18 2002/11/02 08:56:17 tilda
+ * Start of internationalisation changes.
+ *
+ * Revision 1.17 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.16 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.15 2002/10/08 21:25:28 tilda
+ * Assignment of parent property.
+ *
+ * Revision 1.14 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.13 2002/02/24 17:10:34 tilda
+ * Add API for "is modified" functionality.
+ *
+ * Revision 1.12 2001/12/13 06:45:35 tilda
+ * IID488021 - Various bugs with quoted printable format.
+ *
+ * Revision 1.11 2001/10/24 18:36:06 tilda
+ * BASE64 bugfixes. Split reader/writer code. Start create/modify work.
+ *
+ * Revision 1.10 2001/10/24 05:32:19 tilda
+ * BASE64 bugfixes - first part
+ *
+ * Revision 1.9 2001/10/14 20:42:37 tilda
+ * Addition of group searching.
+ *
+ * Revision 1.8 2001/10/14 19:53:36 tilda
+ * Group handling. NO group searching functions.
+ *
+ * Revision 1.7 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.6 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.5 2001/10/13 14:49:30 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ * Revision 1.4 2001/10/12 16:20:03 tilda
+ * Correctly parse compound quoted printable properties.
+ *
+ * Revision 1.3 2001/10/10 20:53:56 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *****************************************************************************/
+
+#ifndef NORCSID
+static const char vf_parser_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_parser.c,v 1.22 2002/11/16 13:19:10 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *===========================================================================*/
+
+#include <common/types.h>
+
+/*============================================================================*
+ Interface Header Files
+ *===========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *===========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*============================================================================*
+ Public Data
+ *===========================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *===========================================================================*/
+
+/*
+ * Significant characters.
+ */
+#define PERIOD '.'
+#define COLON ':'
+#define SEMICOLON ';'
+#define LINEFEED '\n'
+#define CRETURN '\r'
+#define TAB '\t'
+#define BACKSLASH '\\'
+#define SPACE ' '
+#define EQUALS '='
+#define PERIOD '.'
+
+/*
+ * dec hex oct char
+ * 10 0x0A 012 LF NL, line feed, new line, \n
+ * 13 0x0D 015 CR carriage return, \r
+ *
+ * => <CR><LF> = 0x0D 0x0A
+ */
+
+/*
+ * States associated with propname:propvalue parsing.
+ */
+#define _VF_STATE_PROPNAME (1) /* reading name (including groupings) */
+#define _VF_STATE_PROPNAMEESCAPE (2) /* escaped semicolon in name */
+#define _VF_STATE_RFC822VALUE (3) /* basic */
+#define _VF_STATE_RFC822VALUEFOLD (4) /* waiting for line fold (simple fields) */
+#define _VF_STATE_QPIDLE (5) /* Non escaped position in QP */
+#define _VF_STATE_QPIDLENL (6) /* Non escaped position in QP */
+#define _VF_STATE_QPEQUALSC1 (7) /* After = in QP */
+#define _VF_STATE_QPEQUALSC2 (8) /* After =X in QP */
+#define _VF_STATE_BASE64 (9) /* Reading BASE64 */
+
+#define ISCRORNL(c) ((CRETURN == (c)) || (LINEFEED == (c)))
+
+/*============================================================================*
+ Private Data Types
+ *===========================================================================*/
+
+/*----------------------------------------------------------------------------*
+ * PURPOSE
+ * Maintains state variables etc. for current VOBJECT_T parsing.
+ *----------------------------------------------------------------------------*/
+
+typedef struct
+{
+ int state; /* Main state variable */
+ char qpchar; /* Workspace for QuotedPrintable decoder */
+ char *p_b64buf; /* Workspace for BASE64 decoder */
+ VOBJECT_T **pp_root_object; /* Pointer to the root */
+ VOBJECT_T *p_object; /* Current position in tree */
+ VPROP_T prop; /* Current property, copied into tree on completion */
+}
+VPARSE_T;
+
+/*============================================================================*
+ Private Function Prototypes
+ *===========================================================================*/
+
+static bool_t append_value_to_object(
+ VPROP_T **pp_prop, /* Pointer to the new property */
+ VPARSE_T *p_parse /* The property we're naming */
+ );
+
+static bool_t handle_base64_chars(
+ VPARSE_T *p_parse, /* The property value we're adding to */
+ const char *p_chars, /* Pointer to characters to add */
+ int numchars /* Number of characters */
+ );
+
+static vf_encoding_t deduce_encoding(
+ VSTRARRAY_T *p_propname /* Property name */
+ );
+
+static uint8_t base64_to_char(
+ char c /* Character to convert */
+ );
+
+static bool_t is_hex_digit(
+ char *p_nibble, /* Output nibble value */
+ char c /* Character read from file */
+ );
+
+static bool_t handle_value_complete(
+ VPARSE_T *p_parse /* Current parse state info */
+ );
+
+static bool_t alloc_next_object(
+ VPARSE_T *p_parse, /* Current parse state info */
+ char *p_type /* Type of object */
+ );
+
+static bool_t alloc_sub_object(
+ VPARSE_T *p_parse, /* Current parse state info */
+ char *p_type /* Type of object */
+ );
+
+static bool_t alloc_object(
+ VOBJECT_T **pp_new, /* Pointer to output pointer */
+ VOBJECT_T *p_parent, /* Parent of new node */
+ char *p_type, /* Type of new node */
+ VPARSE_T *p_parse /* Current parse info */
+ );
+
+static bool_t append_group_name(
+ VPROP_T *p_prop /* Property we're updating */
+ );
+
+
+/*============================================================================*
+ Private Data
+ *===========================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *===========================================================================*/
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_parse_init()
+ *
+ * DESCRIPTION
+ * Initialise a parsing instance.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_parse_init(
+ VF_PARSER_T **pp_parser, /* The parser */
+ VF_OBJECT_T **pp_object /* The object we're parsing into */
+ )
+{
+ bool_t ret = FALSE;
+
+ if (pp_parser && pp_object)
+ {
+ VPARSE_T *p_parse = (VPARSE_T *)vf_malloc(sizeof(VPARSE_T));
+
+ if (p_parse)
+ {
+ p_memset(p_parse, '\0', sizeof(VPARSE_T));
+
+ p_parse->state = _VF_STATE_PROPNAME;
+ p_parse->p_object = NULL;
+ p_parse->pp_root_object = (VOBJECT_T **)pp_object;
+
+ *pp_parser = (VF_PARSER_T *)p_parse;
+
+ *pp_object = NULL;
+
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_parse_text()
+ *
+ * DESCRIPTION
+ * Parse indicated text into the object associated with the VPARSE_T.
+ *
+ * RETURNS
+ * TRUE <=> allocation & syntax OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_parse_text(
+ VF_PARSER_T *p_parser, /* The parser */
+ char *p_chars, /* New characters to parse into object */
+ int numchars /* Number of new characters */
+ )
+{
+ int i;
+ bool_t ok;
+ VPARSE_T *p_parse = (VPARSE_T *)p_parser;
+
+ /*
+ * Check pointer.
+ */
+ if (!p_parse)
+ {
+ return FALSE;
+ }
+
+ /*
+ * Push each character through the state machine.
+ */
+ for (i = 0, ok = TRUE;ok && (i < numchars);i++)
+ {
+ char c = p_chars[i];
+
+ switch (p_parse->state)
+ {
+ case _VF_STATE_RFC822VALUEFOLD:
+ {
+ if (ISCRORNL(c))
+ {
+ /* Ignore */
+ }
+ else
+ if (SPACE == c)
+ {
+ ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1);
+
+ p_parse->state = _VF_STATE_RFC822VALUE;
+ }
+ else
+ {
+ ok = handle_value_complete(p_parse);
+
+ p_parse->state = _VF_STATE_PROPNAME;
+ }
+ }
+ if (_VF_STATE_PROPNAME == p_parse->state)
+ {
+ /* Fall through */
+ }
+ else
+ {
+ break;
+ }
+
+ /* Fall through */
+
+
+ case _VF_STATE_PROPNAME:
+ {
+ if (COLON == c)
+ {
+ p_parse->prop.value.encoding = deduce_encoding(&p_parse->prop.name);
+
+ switch (p_parse->prop.value.encoding)
+ {
+ case VF_ENC_7BIT:
+ p_parse->state = _VF_STATE_RFC822VALUE;
+ break;
+
+ case VF_ENC_BASE64:
+ p_parse->state = _VF_STATE_BASE64;
+ break;
+
+ case VF_ENC_QUOTEDPRINTABLE:
+ p_parse->state = _VF_STATE_QPIDLE;
+ break;
+
+ default:
+ ok = FALSE;
+ break;
+ }
+ }
+ else
+ if (BACKSLASH == c)
+ {
+ p_parse->state = _VF_STATE_PROPNAMEESCAPE;
+ }
+ else
+ if (ISCRORNL(c))
+ {
+ /* ignore */
+
+ free_string_array_contents(&p_parse->prop.name);
+ }
+ else
+ if (SEMICOLON == c)
+ {
+ ok = add_string_to_array(&p_parse->prop.name, "");
+ }
+ else
+ if (PERIOD == c)
+ {
+ ok = append_group_name(&p_parse->prop);
+ }
+ else
+ {
+ ok = append_to_curr_string(&(p_parse->prop.name), NULL, &c, 1);
+ }
+ }
+ break;
+
+ case _VF_STATE_PROPNAMEESCAPE:
+ {
+ if (SEMICOLON == c)
+ {
+ ok = append_to_curr_string(&(p_parse->prop.name), NULL, &c, 1);
+ }
+ else
+ {
+ ok = FALSE;
+ }
+ }
+ break;
+
+ case _VF_STATE_RFC822VALUE:
+ {
+ if (p_parse->prop.value.v.s.pp_strings)
+ {
+ /* Already allocated */
+ }
+ else
+ {
+ ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL);
+ }
+
+ if (ISCRORNL(c))
+ {
+ p_parse->state = _VF_STATE_RFC822VALUEFOLD;
+ }
+ else
+ if (SEMICOLON == c)
+ {
+ ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL);
+ }
+ else
+ {
+ ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1);
+ }
+ }
+ break;
+
+ case _VF_STATE_QPIDLENL:
+ {
+ if (ISCRORNL(c))
+ {
+ break;
+ }
+ else
+ {
+ p_parse->state = _VF_STATE_QPIDLE;
+ }
+ }
+
+ case _VF_STATE_QPIDLE:
+ {
+ if (p_parse->prop.value.v.s.pp_strings)
+ {
+ /* Already allocated */
+ }
+ else
+ {
+ ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL);
+ }
+
+ if (EQUALS == c)
+ {
+ p_parse->qpchar = 0x00;
+ p_parse->state = _VF_STATE_QPEQUALSC1;
+ }
+ else
+ if (SEMICOLON == c)
+ {
+ ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL);
+ }
+ else
+ if (ISCRORNL(c))
+ {
+ ok = handle_value_complete(p_parse);
+ }
+ else
+ {
+ ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1);
+ }
+ }
+ break;
+
+ case _VF_STATE_QPEQUALSC1:
+ {
+ uint8_t nibble;
+
+ if (ISCRORNL(c))
+ {
+ p_parse->state = _VF_STATE_QPIDLENL;
+ }
+ else
+ if (is_hex_digit(&nibble, c))
+ {
+ (p_parse->qpchar) <<= 4;
+ (p_parse->qpchar) |= nibble;
+
+ p_parse->state = _VF_STATE_QPEQUALSC2;
+ }
+ else
+ {
+ ok = FALSE;
+ }
+ }
+ break;
+
+ case _VF_STATE_QPEQUALSC2:
+ {
+ uint8_t nibble;
+
+ if (is_hex_digit(&nibble, c))
+ {
+ (p_parse->qpchar) <<= 4;
+ (p_parse->qpchar) |= nibble;
+
+ ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &(p_parse->qpchar), 1);
+
+ p_parse->state = _VF_STATE_QPIDLE;
+ }
+ else
+ {
+ ok = FALSE;
+ }
+ }
+ break;
+
+ case _VF_STATE_BASE64:
+ {
+ /*
+ * The cr/nl stuff associated with line ends & termination of BASE64 encoding
+ * seems to be particularly problematic. Searching and reading vCards from the
+ * internet shows that all sorts of wierd things are out there in use! In the
+ * interests of interoperability we look for the next value as an indication of
+ * the end of the object. We build up each line and if it's still in BASE64
+ * format append the decoded data. Otherwise we use the parser recursively to
+ * decode the buffered text, which is probably something like "NEXT-VALUE:"
+ */
+
+ if (ISCRORNL(c))
+ {
+ if (p_parse->p_b64buf)
+ {
+ ok = handle_base64_chars(p_parse, p_parse->p_b64buf, p_strlen(p_parse->p_b64buf));
+
+ vf_free(p_parse->p_b64buf);
+ p_parse->p_b64buf = NULL;
+ }
+ }
+ else
+ {
+ ok = append_to_pointer(&(p_parse->p_b64buf), NULL, &c, 1);
+
+ if ((COLON == c) || (SEMICOLON == c))
+ {
+ ok = handle_value_complete(p_parse);
+
+ ok = vf_parse_text(p_parser, p_parse->p_b64buf, p_strlen(p_parse->p_b64buf));
+
+ vf_free(p_parse->p_b64buf);
+ p_parse->p_b64buf = NULL;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (ok)
+ {
+ /* no need to panic */
+ }
+ else
+ {
+ vf_delete_object((VF_OBJECT_T *)*(p_parse->pp_root_object), TRUE);
+ *(p_parse->pp_root_object) = NULL;
+ p_parse->p_object = NULL;
+
+ if (p_parse->p_b64buf)
+ {
+ vf_free(p_parse->p_b64buf);
+ p_parse->p_b64buf = NULL;
+ }
+
+ delete_prop_contents((VF_PROP_T *)&p_parse->prop, TRUE);
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_parse_end()
+ *
+ * DESCRIPTION
+ * Ensure parse completion.
+ *
+ * RETURNS
+ * TRUE <=> allocation & syntax OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_parse_end(
+ VF_PARSER_T *p_parser /* The parser */
+ )
+{
+ bool_t ret = FALSE;
+ VPARSE_T *p_parse = (VPARSE_T *)p_parser;
+
+ /*
+ * Check pointer.
+ */
+ if (p_parse)
+ {
+ ret = handle_value_complete(p_parse);
+
+ vf_free(p_parse);
+ }
+
+ return ret;
+}
+
+
+
+
+/*============================================================================*
+ Private Functions
+ *===========================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_group_name()
+ *
+ * DESCRIPTION
+ * After reading a ".", we transfer the segment of name we've read (which
+ * must be the first string <G>) into the group name. Keep the group name
+ * in one string of "." tokens for simplicity, so we may end up with a
+ * group called "X-PHONE-BOOK.ENTRY.1" etc.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t append_group_name(
+ VPROP_T *p_prop
+ )
+{
+ bool_t ok = TRUE;
+
+ if (p_prop->p_group)
+ {
+ ok &= append_to_pointer(&p_prop->p_group, NULL, ".", 1);
+ }
+
+ if (ok)
+ {
+ const char *p_string = p_prop->name.pp_strings[0];
+
+ ok &= append_to_pointer(&p_prop->p_group, NULL, p_string, p_strlen(p_string));
+
+ if (ok)
+ {
+ vf_free(p_prop->name.pp_strings[0]);
+ p_prop->name.pp_strings[0] = NULL;
+ }
+ }
+
+ return ok;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * handle_value_complete()
+ *
+ * DESCRIPTION
+ * Called when a complete value is parsed.
+ *
+ * RETURNS
+ * (none).
+ *---------------------------------------------------------------------------*/
+
+bool_t handle_value_complete(
+ VPARSE_T *p_parse /* Current parse state info */
+ )
+{
+ bool_t ret = TRUE;
+ VOBJECT_T *p_object;
+
+ /*
+ * If we've got no object open we ignore values until we read a BEGIN at which point
+ * we create a vformat object and start to parse properties into it. If we subsequently
+ * read a BEGIN we add a property & parse the next vobject into that. Each time we read
+ * an END we pop the pp_object pointer back up to the owner of the object we're parsing
+ * into. There should be an easier way of doing this <G> ...
+ */
+
+ p_object = p_parse->p_object;
+
+ if (p_object)
+ {
+ if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_BEGIN, TRUE))
+ {
+ char *p_type;
+
+ p_type = p_parse->prop.value.v.s.pp_strings[0];
+ p_parse->prop.value.v.s.pp_strings[0] = NULL;
+
+ delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE);
+
+ p_parse->prop.value.encoding = VF_ENC_VOBJECT;
+
+ ret = add_string_to_array(&(p_parse->prop.name), p_type) &&
+ alloc_sub_object(p_parse, p_type);
+ }
+ else
+ if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_END, TRUE))
+ {
+ delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE);
+
+ p_parse->p_object = p_parse->p_object->p_parent;
+ }
+ else
+ {
+ ret = append_value_to_object(NULL, p_parse);
+ }
+ }
+ else
+ {
+ if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_BEGIN, TRUE))
+ {
+ char *p_type;
+
+ p_type = p_parse->prop.value.v.s.pp_strings[0];
+ p_parse->prop.value.v.s.pp_strings[0] = NULL;
+
+ ret = alloc_next_object(p_parse, p_type);
+ }
+
+ delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE);
+ }
+
+ p_parse->state = _VF_STATE_PROPNAME;
+
+ return ret;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * alloc_next_object()
+ *
+ * DESCRIPTION
+ * Allocate the "next" object, ie. annother vformat tagged to the p_next
+ * pointer to the current one.
+ *
+ * RETURNS
+ * TRUE iff memory allocated OK, FALSE else OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t alloc_next_object(
+ VPARSE_T *p_parse, /* Current parse state info */
+ char *p_type /* Type of object */
+ )
+{
+ bool_t ok = TRUE;
+ VOBJECT_T *p_parent = p_parse->p_object;
+ VOBJECT_T *p_new = NULL;
+
+ ok = alloc_object(&p_new, p_parent ? p_parent->p_parent : NULL, p_type, p_parse);
+
+ if (ok)
+ {
+ if (*p_parse->pp_root_object)
+ {
+ /* root object already set */
+
+ if (p_new->p_parent)
+ {
+ /* Owned by property */
+ }
+ else
+ {
+ /* Need to tag to end of top list */
+
+ VOBJECT_T **pp_tmp = p_parse->pp_root_object;
+
+ while (*pp_tmp)
+ {
+ pp_tmp = &((*pp_tmp)->p_next);
+ }
+
+ *pp_tmp = p_new;
+ }
+ }
+ else
+ {
+ *p_parse->pp_root_object = p_new;
+ }
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * alloc_sub_object()
+ *
+ * DESCRIPTION
+ * Allocate "sub" object, ie. annother vformat tagged to the p_object
+ * pointer of a VPROP_T allocated to contain it.
+ *
+ * RETURNS
+ * TRUE iff memory allocated OK, FALSE else OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t alloc_sub_object(
+ VPARSE_T *p_parse, /* Current parse state info */
+ char *p_type /* Type of object */
+ )
+{
+ bool_t ok = FALSE;
+ VOBJECT_T *p_parent = p_parse->p_object;
+
+ if (p_parent)
+ {
+ VPROP_T *p_tmp;
+
+ ok = append_value_to_object(&p_tmp, p_parse);
+
+ if (ok && p_tmp)
+ {
+ ok = alloc_object(&p_tmp->value.v.o.p_object, p_parent, p_type, p_parse);
+ }
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * alloc_object()
+ *
+ * DESCRIPTION
+ * Allocate & initialise a new VOBJECT_T. The new element od made the
+ * current parse target (ie. new properties will be added to it).
+ *
+ * RETURNS
+ * TRUE <=> allocation went OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t alloc_object(
+ VOBJECT_T **pp_new, /* Pointer to output pointer */
+ VOBJECT_T *p_parent, /* Parent of new node */
+ char *p_type, /* Type of new node */
+ VPARSE_T *p_parse /* Current parse info */
+ )
+{
+ bool_t ok = TRUE;
+ VOBJECT_T *p_new;
+
+ p_new = (VOBJECT_T *)vf_malloc(sizeof(VOBJECT_T));
+
+ if (p_new)
+ {
+ p_memset(p_new, '\0', sizeof(VOBJECT_T));
+
+ p_new->p_parent = p_parent;
+ p_new->p_type = p_type;
+
+ p_parse->p_object = p_new;
+
+ *pp_new = p_new;
+ }
+ else
+ {
+ ok = FALSE;
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * handle_base64_chars()
+ *
+ * DESCRIPTION
+ * Handle BASE64 decoding.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t handle_base64_chars(
+ VPARSE_T *p_parse, /* The property value we're adding to */
+ const char *p_chars, /* Pointer to characters to add */
+ int numchars /* Number of characters */
+ )
+{
+ bool_t ok = TRUE;
+
+ /*
+ * Skip spaces.
+ */
+ while ((0 < numchars) && (SPACE == p_chars[0]))
+ {
+ numchars--;
+ p_chars++;
+ }
+
+ /*
+ * Convert groups of 4 characters to byte triplets & append the bytes
+ * to the binary data.
+ */
+ if (0 < numchars)
+ {
+ int i, j, len, num, left;
+ const char *p_quad;
+
+ len = numchars;
+ num = len / 4;
+ left = len % 4;
+
+ for (i = 0, p_quad = p_chars;(i < num);i++, p_quad += 4)
+ {
+ uint32_t b;
+ char bytes[3];
+ uint8_t bits;
+
+ for (j = 0, b = 0, bits = 0;(j < 4);j++)
+ {
+ b = (b << 6) | base64_to_char(p_quad[j]);
+
+ if (EQUALS != p_quad[j])
+ {
+ bits += 6;
+ }
+ }
+
+ for (j = 0;(j < 3);j++)
+ {
+ bytes[2 - j] = (unsigned char)(b & 0xFF);
+
+ b >>= 8;
+ }
+
+ ok = append_to_pointer(&(p_parse->prop.value.v.b.p_buffer), &(p_parse->prop.value.v.b.n_bufsize), bytes, bits / 8);
+ }
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_value_to_object()
+ *
+ * DESCRIPTION
+ * Append characters to the name half of a VOBJECT_T. The VOBJECT is
+ * allocated if not already present.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *---------------------------------------------------------------------------*/
+
+bool_t append_value_to_object(
+ VPROP_T **pp_prop, /* Pointer to the new property */
+ VPARSE_T *p_parse /* The property we're naming */
+ )
+{
+ bool_t ok = FALSE;
+
+ VPROP_T **pp_tmp;
+ VPROP_T *p_prop;
+
+ pp_tmp = &(p_parse->p_object->p_props);
+
+ while (*pp_tmp)
+ {
+ pp_tmp = &((*pp_tmp)->p_next);
+ }
+
+ *pp_tmp = p_prop = (VPROP_T *)vf_malloc(sizeof(VPROP_T));
+
+ if (pp_prop)
+ {
+ *pp_prop = p_prop;
+ }
+
+ if (p_prop)
+ {
+ p_memset(p_prop, '\0', sizeof(VPROP_T));
+
+ *p_prop = p_parse->prop;
+
+ p_memset(&(p_parse->prop), '\0', sizeof(VPROP_T));
+
+ p_prop->p_parent = p_parse->p_object;
+
+ ok = TRUE;
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * deduce_encoding()
+ *
+ * DESCRIPTION
+ * Check property name for encoding tags. If none present, return the
+ * default encoding.
+ *
+ * RETURNS
+ * vf_encoding_t.
+ *---------------------------------------------------------------------------*/
+
+vf_encoding_t deduce_encoding(
+ VSTRARRAY_T *p_propname /* Property name */
+ )
+{
+ vf_encoding_t ret = VF_ENC_7BIT;
+
+ if (string_array_contains_string(p_propname, NULL, -1, VFP_QUOTEDPRINTABLE, FALSE))
+ {
+ ret = VF_ENC_QUOTEDPRINTABLE;
+ }
+ else
+ if (string_array_contains_string(p_propname, NULL, -1, VFP_BASE64, FALSE))
+ {
+ ret = VF_ENC_BASE64;
+ }
+ else
+ if (string_array_contains_string(p_propname, NULL, -1, VFP_8BIT, FALSE))
+ {
+ ret = VF_ENC_8BIT;
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * is_hex_digit()
+ *
+ * DESCRIPTION
+ *
+ *
+ * RETURNS
+ * TRUE <=> valid HEX digit read.
+ *---------------------------------------------------------------------------*/
+
+bool_t is_hex_digit(
+ char *p_nibble, /* Output nibble value */
+ char c /* Character read from file */
+ )
+{
+ bool_t ret = TRUE;
+
+ if (('A' <= c) && (c <= 'F'))
+ {
+ *p_nibble = c - 'A' + 10;
+ }
+ else
+ if (('a' <= c) && (c <= 'f'))
+ {
+ *p_nibble = c - 'a' + 10;
+ }
+ else
+ if (('0' <= c) && (c <= '9'))
+ {
+ *p_nibble = c - '0';
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * base64_to_char()
+ *
+ * DESCRIPTION
+ * Convert base 64 char to byte.
+ *
+ * RETURNS
+ * Number corresponding to char.
+ *---------------------------------------------------------------------------*/
+
+uint8_t base64_to_char(char c)
+{
+ if (('A' <= c) && (c <= 'Z'))
+ return c - 'A';
+
+ if (('a' <= c) && (c <= 'z'))
+ return c - 'a' + 26;
+
+ if (('0' <= c) && (c <= '9'))
+ return c - '0' + 52;
+
+ if ('+' == c)
+ return 62;
+
+ if ('/' == c)
+ return 63;
+
+ return 0x00;
+}
+
+
+/*============================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_reader.c b/src/vf_reader.c
new file mode 100644
index 0000000..667279f
--- /dev/null
+++ b/src/vf_reader.c
@@ -0,0 +1,277 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_reader.c $
+ $Revision: 1.18 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley.
+
+DESCRIPTION
+ Code for reading vformat files from disk. Delegates the real responsibility
+ to vf_parser for actually converting chunks of text into the memory data
+ structure.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_reader.c,v $
+ * Revision 1.18 2002/11/15 09:20:59 tilda
+ * IID638823 - Don't include unistd.h unless required.
+ *
+ * Revision 1.17 2002/11/15 09:15:00 tilda
+ * IID638823 - Various portability issues.
+ *
+ * Revision 1.16 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.15 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.14 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.13 2001/12/13 06:45:35 tilda
+ * IID488021 - Various bugs with quoted printable format.
+ *
+ * Revision 1.12 2001/11/05 21:07:19 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.11 2001/10/24 18:36:06 tilda
+ * BASE64 bugfixes. Split reader/writer code. Start create/modify work.
+ *
+ * Revision 1.10 2001/10/24 05:32:19 tilda
+ * BASE64 bugfixes - first part
+ *
+ * Revision 1.9 2001/10/16 05:50:53 tilda
+ * Debug support for lists of vobjects from single file (ie. a phonebook).
+ *
+ * Revision 1.8 2001/10/14 19:53:36 tilda
+ * Group handling. NO group searching functions.
+ *
+ * Revision 1.7 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.6 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.5 2001/10/13 14:49:30 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ * Revision 1.4 2001/10/12 16:20:02 tilda
+ * Correctly parse compound quoted printable properties.
+ *
+ * Revision 1.3 2001/10/10 20:53:55 tilda
+ * Various minor tidy ups.
+ *
+ * Revision 1.2 2001/10/09 22:01:59 tilda
+ * Remove older version control comments.
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_reader_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_reader.c,v 1.18 2002/11/15 09:20:59 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *=============================================================================*/
+
+#include <common/types.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#if defined(HAS_UNISTD_H)
+#include <unistd.h>
+#endif
+
+#if defined(WIN) || defined(WIN32)
+#include <io.h>
+#endif
+
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include <vformat/vf_iface.h>
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_internals.h"
+#include "vf_malloc.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+
+#define PARSEBUFSIZE (1024)
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_read_file()
+ *
+ * DESCRIPTION
+ * Reads indicated VOBJECT_T file.
+ *
+ * RETURNS
+ * TRUE <=> read OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t vf_read_file(
+ VF_OBJECT_T **pp_object,
+ const char *p_name
+ )
+{
+ bool_t ret = FALSE;
+
+ if (pp_object)
+ {
+ FILE *fp;
+
+ fp = fopen(p_name, "rb");
+
+ if (fp)
+ {
+ char buffer[PARSEBUFSIZE];
+ int charsread;
+ VF_PARSER_T *p_parser;
+
+ if (vf_parse_init(&p_parser, pp_object))
+ {
+ do
+ {
+ charsread = read(fileno(fp), buffer, sizeof(buffer));
+
+ if (0 < charsread)
+ {
+ ret = vf_parse_text(p_parser, buffer, charsread);
+ }
+ }
+ while (ret && (0 < charsread))
+ ;
+
+ if (!vf_parse_end(p_parser))
+ {
+ ret = FALSE;
+ }
+ }
+
+ if (0 == fclose(fp))
+ {
+ /* OK */
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_set_property_from_file()
+ *
+ * DESCRIPTION
+ * Loads the indicated file into memory and sets the indicated property.
+ *
+ * RETURNS
+ * (none)
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_set_property_from_file(
+ VF_PROP_T *p_prop, /* The property */
+ vf_encoding_t encoding, /* Encoding to use */
+ const char *p_filename /* Source filename */
+ )
+{
+ bool_t ret = FALSE;
+ struct stat buf;
+
+ if (0 == stat(p_filename, &buf))
+ {
+ uint8_t *p_data = vf_malloc(buf.st_size);
+
+ if (p_data)
+ {
+ FILE *fp = fopen(p_filename, "rb");
+
+ if (fp)
+ {
+ if ((int)buf.st_size == read(fileno(fp), p_data, buf.st_size))
+ {
+ ret = TRUE;
+ }
+
+ if (0 == fclose(fp))
+ {
+ /* */
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ if (ret)
+ {
+ ret &= vf_set_prop_value(p_prop, p_data, buf.st_size, encoding, TRUE);
+ }
+ }
+
+ vf_free(p_data);
+ }
+ }
+
+ return ret;
+}
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_search.c b/src/vf_search.c
new file mode 100644
index 0000000..71be484
--- /dev/null
+++ b/src/vf_search.c
@@ -0,0 +1,457 @@
+/****************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_access.c $
+ $Revision: 1.11 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Basic searching functions for the vformat library.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_search.c,v $
+ * Revision 1.11 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.10 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.9 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.8 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.7 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.6 2002/02/24 17:10:34 tilda
+ * Add API for "is modified" functionality.
+ *
+ * Revision 1.5 2001/11/18 21:46:59 tilda
+ * Remove redundant code.
+ *
+ * Revision 1.4 2001/11/16 22:34:50 tilda
+ * New vf_get_property() allows append as well as find,
+ *
+ * Revision 1.3 2001/11/05 21:07:19 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.2 2001/10/24 18:56:29 tilda
+ * Tidy headers after import. Fix include path in release build.
+ *
+ * Revision 1.1 2001/10/24 18:34:35 tilda
+ * Initial Version.
+ *
+ *****************************************************************************/
+
+#ifndef NORCSID
+static const char vf_search_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_search.c,v 1.11 2002/11/03 18:43:16 tilda Exp $";
+#endif
+
+/*============================================================================*
+ ANSI C & System-wide Header Files
+ *============================================================================*/
+
+#include <common/types.h>
+
+/*===========================================================================*
+ Interface Header Files
+ *===========================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*===========================================================================*
+ Local Header File
+ *===========================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*===========================================================================*
+ Public Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Defines
+ *===========================================================================*/
+
+/*
+ * Maximum supported search tags.
+ */
+#define MAXNUMTAGS (10)
+
+/*===========================================================================*
+ Private Data Types
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Private Function Prototypes
+ *===========================================================================*/
+
+
+/*===========================================================================*
+ Private Data
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ Public Function Implementations
+ *===========================================================================*/
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_property()
+ *
+ * DESCRIPTION
+ * Basic searching function locating elements of the VOBJECT by qualified
+ * name. The function is a varargs function (like sprintf) and the list
+ * of arguments must be NULL terminated (hence the appearance of the
+ * p_qualifier argument in the arglist). Valid calls might be:
+ *
+ * vf_get_property(&p_out, p_object, FALSE, NULL, "N", NULL);
+ * vf_get_property(&p_out, p_object, FALSE, NULL, "TEL", "WORK", NULL);
+ * vf_get_property(&p_out, p_object, FALSE, "ME", "TEL", "WORK", NULL);
+ * vf_get_property(&p_out, p_object, FALSE, "ME", "*", NULL);
+ *
+ * A pointer to the first property matching the search criteria is returned
+ * the pp_prop argument. The search actually locates all such matches and
+ * pointer to subsequent entries (if there are >1) may be found by calling
+ * the vf_get_next_property() function.
+ *
+ * Qualifying tags (ie. not the name) may occur in any order
+ *
+ * Note that the VF_PROP_T returned vi pp_prop is an opaque type and the
+ * various accessor functions must be used to get to the data.
+ *
+ * RETURNS
+ * TRUE iff found/added successfully. ptr to prop returned via pp_prop.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_property(
+ VF_PROP_T **pp_prop, /* Output pointer */
+ VF_OBJECT_T *p_object, /* Object to add to */
+ vf_get_t ops, /* Search flags */
+ const char *p_group, /* Group name if any */
+ const char *p_name, /* Name of tag */
+ const char *p_qualifier, /* First qualifier if any */
+ ... /* Subequent qualifiers */
+ )
+{
+ bool_t ret = FALSE;
+ va_list args;
+
+ va_start(args, p_qualifier);
+
+ ret = vf_get_property_ex(pp_prop, p_object, ops, p_group, p_name, p_qualifier, args);
+
+ va_end(args);
+
+ return ret;
+}
+
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_property_ex()
+ *
+ * DESCRIPTION
+ * The grunt behind vf_get_property(). Manages the search as described
+ * vf_get_property() but takes the list of arguments as a va_list.
+ *
+ * RETURNS
+ * TRUE iff found / appended OK.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_property_ex(
+ VF_PROP_T **pp_prop, /* Output pointer */
+ VF_OBJECT_T *p_object, /* Object to search */
+ vf_get_t ops, /* Search flags */
+ const char *p_group, /* Group name if any */
+ const char *p_name, /* Name of tag */
+ const char *p_qualifier, /* First qualifier if any */
+ va_list args /* Argument list */
+ )
+{
+ bool_t ret = FALSE;
+ char **pp_tags = NULL;
+
+ if (!p_name || !p_object)
+ return ret;
+
+ if (pp_prop)
+ {
+ *pp_prop = NULL;
+ }
+
+ pp_tags = (char **)vf_malloc(MAXNUMTAGS * sizeof(char *));
+
+ if (pp_tags)
+ {
+ VOBJECT_T *p_obj = (VOBJECT_T *)p_object;
+ VPROP_T *p_props = p_obj->p_props;
+ int i;
+
+ VPROP_T **pp_lastprop = &(p_obj->p_props);
+ VPROP_T **pp_next_srch = NULL;
+
+ p_memset(pp_tags, '\0', MAXNUMTAGS * sizeof(char *));
+
+ pp_tags[0] = (char *)p_name;
+
+ /*
+ * The name is the first tag. We insist on there being at least one qualifier in the
+ * argument list to make sure callers terminate the list. Subsequent arguments are
+ * optional, but will be ignored if the (first) qualifier is NULL.
+ */
+ if (p_qualifier)
+ {
+ pp_tags[1] = (char *)p_qualifier;
+
+ for (i = 2;i < MAXNUMTAGS;i++)
+ {
+ char *p_tag = va_arg(args, char *);
+
+ if (p_tag)
+ {
+ pp_tags[i] = p_tag;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if (ops & VFGP_FIND)
+ {
+ /*
+ * Skip down the list or properties. I'm assuming that we only want to search the
+ * current object for properties not the current object AND any contained objects.
+ * Such a search sounds a bit application specific, ie. the caller would be looking
+ * for a particular structure of things. Each element that is found is stitched
+ * into the emerging list.
+ */
+ for (;NULL != p_props;p_props = p_props->p_next)
+ {
+ bool_t found = TRUE;
+
+ /*
+ * Check the name & qualifiers.
+ */
+ for (i = 0;found && (i < MAXNUMTAGS) && pp_tags[i];i++)
+ {
+ if (0 != p_strcmp(VFP_ANY, pp_tags[i]))
+ found &= string_array_contains_string(&p_props->name, NULL, -1, pp_tags[i], TRUE);
+ }
+ if (p_group && found)
+ {
+ found = FALSE;
+
+ if (p_props->p_group)
+ {
+ if (0 == p_stricmp(p_props->p_group, p_group))
+ {
+ found = TRUE;
+ }
+ }
+ else
+ {
+ /* Search group specified & property doesn't have a group => not required */
+ }
+ }
+
+ if (found)
+ {
+ if (pp_prop)
+ {
+ if (!*pp_prop)
+ {
+ pp_next_srch = &(p_props->p_next_srch);
+ p_props->p_next_srch = NULL;
+
+ *pp_prop = (VF_PROP_T *)p_props;
+ }
+ else
+ {
+ *pp_next_srch = p_props;
+
+ pp_next_srch = &(p_props->p_next_srch);
+ p_props->p_next_srch = NULL;
+ }
+ }
+
+ ret = TRUE;
+ }
+
+ if (p_props->p_next)
+ {
+ pp_lastprop = &(p_props->p_next);
+ }
+ }
+ }
+
+ if (!ret && (ops & VFGP_APPEND))
+ {
+ VPROP_T *p_new = (VPROP_T *)vf_malloc(sizeof(VPROP_T));
+
+ if (p_new)
+ {
+ ret = TRUE;
+
+ p_memset(p_new, '\0', sizeof(VPROP_T));
+
+ p_new->p_parent = p_obj;
+
+ for (i = 0;ret && (i < MAXNUMTAGS) && pp_tags[i];i++)
+ {
+ ret = add_string_to_array(&p_new->name, pp_tags[i]);
+ }
+
+ if (ret)
+ {
+ /* All OK */
+
+ p_new->value.encoding = VF_ENC_7BIT;
+ }
+ else
+ {
+ free_string_array_contents(&p_new->name);
+
+ vf_free(p_new);
+ p_new = NULL;
+ }
+ }
+
+ if (p_new)
+ {
+ if (pp_prop)
+ {
+ *pp_prop = (VF_PROP_T *)p_new;
+ }
+
+ p_new->p_next = *pp_lastprop;
+ *pp_lastprop = p_new;
+
+ ret = TRUE;
+ }
+ }
+
+ vf_free(pp_tags);
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_next_property()
+ *
+ * DESCRIPTION
+ * Find the next property given the current search critera.
+ *
+ * RETURNS
+ * TRUE iff found, FALSE else. *pp_prop points to the next property.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_next_property(
+ VF_PROP_T **pp_prop /* Output pointer */
+ )
+{
+ bool_t ret = FALSE;
+
+ if (pp_prop)
+ {
+ VPROP_T **pp_vprop = (VPROP_T **)pp_prop;
+
+ if (*pp_vprop)
+ {
+ *pp_prop = (VF_PROP_T *)((*pp_vprop)->p_next_srch);
+
+ if (*pp_prop)
+ {
+ ret = TRUE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+/*---------------------------------------------------------------------------*
+ * NAME
+ * vf_get_next_object()
+ *
+ * DESCRIPTION
+ * Find "next" vobject.
+ *
+ * RETURNS
+ * TRUE iff found next object.
+ *---------------------------------------------------------------------------*/
+
+bool_t vf_get_next_object(
+ VF_OBJECT_T **pp_object
+ )
+{
+ bool_t ret = FALSE;
+
+ if (pp_object)
+ {
+ if (*pp_object)
+ {
+ *pp_object = (VF_OBJECT_T *)(((VOBJECT_T *)(*pp_object))->p_next);
+
+ if (*pp_object)
+ {
+ ret = TRUE;
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+/*===========================================================================*
+ Private Function Implementations
+ *===========================================================================*/
+/* None */
+
+/*===========================================================================*
+ End Of File
+ *===========================================================================*/
diff --git a/src/vf_string_arrays.c b/src/vf_string_arrays.c
new file mode 100644
index 0000000..eee27f4
--- /dev/null
+++ b/src/vf_string_arrays.c
@@ -0,0 +1,435 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_access.c $
+ $Revision: 1.4 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Utility functions handling string arrays - the VSTRARRAY_T type.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_string_arrays.c,v $
+ * Revision 1.4 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.3 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.2 2002/10/29 07:19:20 tilda
+ * Tidy headers.
+ *
+ * Revision 1.1 2002/10/26 15:57:11 tilda
+ * Initial Version
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_string_arrays_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_string_arrays.c,v 1.4 2002/11/03 18:43:16 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *=============================================================================*/
+
+#include <common/types.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_malloc.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+#include "vf_string_arrays.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * string_array_contains_string()
+ *
+ * DESCRIPTION
+ * Checks the strings in the indicated array to see if it contains a
+ * particulr value. Can check a particular index or the whole array.
+ * Can perform an exact match or check wether one of the strings simply
+ * contains the value.
+ *
+ * RETURNS
+ * TRUE <=> includes indicated value, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t string_array_contains_string(
+ VSTRARRAY_T *p_strarray, /* String array */
+ char **pp_string_found, /* String found */
+ uint32_t index, /* Which entry, (-1) => any */
+ const char *p_string, /* The string we're looking for */
+ bool_t exact /* Exact or partial match */
+ )
+{
+ bool_t ret = FALSE;
+ uint32_t i;
+ uint32_t s, e;
+
+ if (index == (-1))
+ {
+ s = 0;
+ e = p_strarray->n_strings;
+ }
+ else
+ {
+ s = index;
+ e = index + 1;
+ }
+
+ for (i = s;!ret && (i < e);i++)
+ {
+ if ((i < p_strarray->n_strings) && p_strarray->pp_strings[i])
+ {
+ if (exact)
+ {
+ if (0 == p_stricmp(p_strarray->pp_strings[i], p_string))
+ ret = TRUE;
+ }
+ else
+ {
+ if (p_strstr(p_strarray->pp_strings[i], p_string))
+ ret = TRUE;
+ }
+ }
+
+ if (ret && pp_string_found)
+ {
+ *pp_string_found = p_strarray->pp_strings[i];
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * add_string_to_array()
+ *
+ * DESCRIPTION
+ * Append string to indicated array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t add_string_to_array(
+ VSTRARRAY_T *p_strarray, /* String array */
+ const char *p_string /* String to add */
+ )
+{
+ char **pp_new;
+ bool_t ret = FALSE;
+
+ pp_new = vf_realloc(p_strarray->pp_strings, sizeof(char *) * (1 + p_strarray->n_strings));
+
+ if (pp_new)
+ {
+ if (p_string)
+ {
+ uint32_t l;
+ char *p_strcopy;
+
+ l = p_strlen(p_string);
+
+ p_strcopy = vf_malloc(1 + l);
+
+ if (p_strcopy)
+ {
+ p_strcpy(p_strcopy, p_string);
+
+ pp_new[p_strarray->n_strings] = p_strcopy;
+
+ ret = TRUE;
+ }
+ else
+ {
+ vf_free(pp_new);
+ }
+ }
+ else
+ {
+ pp_new[p_strarray->n_strings] = NULL;
+
+ ret = TRUE;
+ }
+
+ if (ret)
+ {
+ p_strarray->n_strings += 1;
+ p_strarray->pp_strings = pp_new;
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * free_string_array_contents()
+ *
+ * DESCRIPTION
+ * Delete contents of a string array. The structure itself is not free()d.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void free_string_array_contents(
+ VSTRARRAY_T *p_strarray /* String array */
+ )
+{
+ if (p_strarray && p_strarray->pp_strings)
+ {
+ uint32_t i;
+
+ for (i = 0;i < p_strarray->n_strings;i++)
+ {
+ if (p_strarray->pp_strings[i])
+ {
+ vf_free(p_strarray->pp_strings[i]);
+ p_strarray->pp_strings[i] = NULL;
+ }
+ }
+
+ vf_free(p_strarray->pp_strings);
+ p_strarray->pp_strings = NULL;
+
+ p_strarray->n_strings = 0;
+ }
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_to_curr_string()
+ *
+ * DESCRIPTION
+ * Append characters to the current string in a string array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t append_to_curr_string(
+ VSTRARRAY_T *p_strarray, /* String array */
+ uint32_t *p_length, /* Pointer to length, NULL if zero terminated */
+ const char *p_chars, /* Characters to append */
+ uint32_t numchars /* Number of characters */
+ )
+{
+ bool_t ret = TRUE;
+
+ if (p_strarray && !p_strarray->pp_strings)
+ {
+ ret = add_string_to_array(p_strarray, "");
+ }
+
+ if (ret)
+ {
+ ret = append_to_pointer(&(p_strarray->pp_strings[p_strarray->n_strings - 1]), p_length, p_chars, numchars);
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_to_pointer()
+ *
+ * DESCRIPTION
+ * Append characters to indicated pointer. Handles both NULL terminated
+ * strings (for simple 7-bit values) and buffer/length pairs. Passing
+ * the p_length field indicates that we're building up binary data.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t append_to_pointer(
+ char **pp_string, /* String we're appending to */
+ uint32_t *p_length, /* Pointer to length, NULL if ZT */
+ const char *p_chars, /* Chars we're appending */
+ int numchars /* Number of chars we're appending */
+ )
+{
+ bool_t ok = FALSE;
+
+ if (pp_string)
+ {
+ int newlen, currlen;
+ char *p_new;
+
+ newlen = numchars;
+
+ if (*pp_string)
+ {
+ currlen = p_length ? *p_length : p_strlen(*pp_string);
+
+ newlen += currlen;
+ }
+ else
+ {
+ currlen = 0;
+ }
+
+ p_new = vf_realloc(*pp_string, newlen + (p_length ? 0 : 1));
+
+ if (p_new)
+ {
+ p_memcpy(p_new + currlen, p_chars, numchars);
+
+ if (p_length)
+ {
+ *p_length = newlen;
+ }
+ else
+ {
+ p_new[newlen] = '\0';
+ }
+
+ *pp_string = p_new;
+ ok = TRUE;
+ }
+ }
+
+ return ok;
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * set_string_array_entry()
+ *
+ * DESCRIPTION
+ * Set indicated entry in a string array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t set_string_array_entry(
+ VSTRARRAY_T *p_strarray, /* String array */
+ const char *p_string, /* String to insert */
+ uint32_t n_string /* Insertion point */
+ )
+{
+ bool_t ret = FALSE;
+
+ if (n_string < p_strarray->n_strings)
+ {
+ if (p_strarray->pp_strings[n_string])
+ {
+ vf_free(p_strarray->pp_strings[n_string]);
+ p_strarray->pp_strings[n_string] = NULL;
+ }
+
+ if (p_string)
+ {
+ uint32_t len = p_strlen(p_string);
+
+ p_strarray->pp_strings[n_string] = vf_malloc(1 + len);
+
+ if (p_strarray->pp_strings[n_string])
+ {
+ p_strcpy(p_strarray->pp_strings[n_string], p_string);
+
+ ret = TRUE;
+ }
+ }
+ else
+ {
+ /* NULL = "delete" */
+
+ ret = TRUE;
+ }
+ }
+
+ return ret;
+}
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_string_arrays.h b/src/vf_string_arrays.h
new file mode 100644
index 0000000..252da03
--- /dev/null
+++ b/src/vf_string_arrays.h
@@ -0,0 +1,177 @@
+/*******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile: vf_internals.h $
+ $Revision: 1.2 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ Utility functions handling string arrays - the VSTRARRAY_T type.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_string_arrays.h,v $
+ * Revision 1.2 2002/11/02 18:29:26 tilda
+ * IID485157 - UI does character conversion based on CHARSET property.
+ *
+ * Revision 1.1 2002/10/26 15:57:11 tilda
+ * Initial Version
+ *
+ *******************************************************************************/
+
+#ifndef _VF_STRING_ARRAYS_H_
+#define _VF_STRING_ARRAYS_H_
+
+#ifndef NORCSID
+static const char vf_string_arrays_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_string_arrays.h,v 1.2 2002/11/02 18:29:26 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * string_array_contains_string()
+ *
+ * DESCRIPTION
+ * Checks the strings in the indicated array to see if it contains a
+ * particulr value. Can check a particular index or the whole array.
+ * Can perform an exact match or check wether one of the strings simply
+ * contains the value.
+ *
+ * RETURNS
+ * TRUE <=> includes indicated value, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+extern bool_t string_array_contains_string(
+ VSTRARRAY_T *p_strarray, /* String array */
+ char **pp_string_found, /* String found */
+ uint32_t index, /* Which entry, (-1) => any */
+ const char *p_string, /* The string we're looking for */
+ bool_t exact /* Exact or partial match */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * add_string_to_array()
+ *
+ * DESCRIPTION
+ * Append string to indicated array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+extern bool_t add_string_to_array(
+ VSTRARRAY_T *p_strarray, /* String array */
+ const char *p_string /* String to add */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * free_string_array_contents()
+ *
+ * DESCRIPTION
+ * Delete contents of a string array. The structure itself is not free()d.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+extern void free_string_array_contents(
+ VSTRARRAY_T *p_strarray /* String array */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_to_curr_string()
+ *
+ * DESCRIPTION
+ * Append characters to the current string in a string array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+extern bool_t append_to_curr_string(
+ VSTRARRAY_T *p_strarray, /* String array */
+ uint32_t *p_length, /* Pointer to length, NULL if zero terminated */
+ const char *p_chars, /* Characters to append */
+ uint32_t numchars /* Number of characters */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * append_to_pointer()
+ *
+ * DESCRIPTION
+ * Append characters to indicated pointer. Handles both NULL terminated
+ * strings (for simple 7-bit values) and buffer/length pairs. Passing
+ * the p_length field indicates that we're building up binary data.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+extern bool_t append_to_pointer(
+ char **pp_string, /* String we're appending to */
+ uint32_t *p_length, /* Pointer to length, NULL if ZT */
+ const char *p_chars, /* Chars we're appending */
+ int numchars /* Number of chars we're appending */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * set_string_array_entry()
+ *
+ * DESCRIPTION
+ * Set indicated entry in a string array.
+ *
+ * RETURNS
+ * TRUE <=> allocation OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+extern bool_t set_string_array_entry(
+ VSTRARRAY_T *p_strarray, /* String array */
+ const char *p_string, /* String to insert */
+ uint32_t n_string /* Insertion point */
+ );
+
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+#endif /*_VF_STRING_ARRAYS_H_*/
diff --git a/src/vf_strings.c b/src/vf_strings.c
new file mode 100644
index 0000000..204a188
--- /dev/null
+++ b/src/vf_strings.c
@@ -0,0 +1,472 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile$
+ $Revision: 1.9 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ String handling functions. The library uses the p_ functions (where hopefully
+ the 'p' stands for 'portable') and they are provided here in terms of C runtime
+ functions or implemented explicitly.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_strings.c,v $
+ * Revision 1.9 2002/11/15 09:15:00 tilda
+ * IID638823 - Various portability issues.
+ *
+ * Revision 1.8 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.7 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.6 2002/10/08 21:11:36 tilda
+ * Remove common.h.
+ *
+ * Revision 1.5 2001/11/05 21:07:19 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.4 2001/10/14 20:42:37 tilda
+ * Addition of group searching.
+ *
+ * Revision 1.3 2001/10/13 16:22:08 tilda
+ * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals.
+ *
+ * Revision 1.2 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.1 2001/10/13 14:50:33 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_strings_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_strings.c,v 1.9 2002/11/15 09:15:00 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *=============================================================================*/
+
+#include <common/types.h>
+
+#include <ctype.h>
+#include <string.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include "vformat/vf_iface.h"
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_internals.h"
+#include "vf_strings.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strlen()
+ *
+ * DESCRIPTION
+ * Find length of string.
+ *
+ * RETURNS
+ * Length of strings.
+ *----------------------------------------------------------------------------*/
+
+int p_strlen(
+ const char *p_string /* String to measure */
+ )
+{
+#if defined(HAVE_STRLEN)
+ return strlen(p_string);
+#else
+ int len = 0;
+
+ while (*p_string)
+ {
+ p_string++;
+ len++;
+ }
+
+ return len;
+#endif
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcpy()
+ *
+ * DESCRIPTION
+ * Copy string to buffer.
+ *
+ * RETURNS
+ * Pointer to buffer.
+ *----------------------------------------------------------------------------*/
+
+char *p_strcpy(
+ char *p_string1, /* Buffer to copy to */
+ const char *p_string2 /* String to copy */
+ )
+{
+#if defined(HAVE_STRCPY)
+ return strcpy(p_string1, p_string2);
+#else
+ char *p_return = p_string1;
+
+ while ((*p_string1++ = *p_string2++))
+ ;
+
+ return p_return;
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcmp()
+ *
+ * DESCRIPTION
+ * Case sensitive string comparison.
+ *
+ * RETURNS
+ * 0<=>strings match, !=0 else.
+ *----------------------------------------------------------------------------*/
+
+int p_strcmp(
+ const char *p_string1,
+ const char *p_string2
+ )
+{
+#if defined(HAVE_STRCMP)
+ return strcmp(p_string1, p_string2);
+#else
+ while (*p_string1 && (*p_string1 == *p_string2))
+ {
+ p_string1++;
+ p_string2++;
+ }
+
+ return (*(unsigned char *)p_string1) - (*(unsigned char *)p_string2);
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcat()
+ *
+ * DESCRIPTION
+ * Append one string to another.
+ *
+ * RETURNS
+ * Pointer to resulting string.
+ *----------------------------------------------------------------------------*/
+
+char *p_strcat(
+ char *p_string1, /* String to append to */
+ const char *p_string2 /* String to append */
+ )
+{
+#if defined(HAVE_STRCAT)
+ return strcat(p_string1, p_string2);
+#else
+ char *p_return = p_string1;
+
+ while (*p_string1)
+ p_string1++;
+
+ while ((*p_string1++ = *p_string2++))
+ ;
+
+ return p_return;
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strstr()
+ *
+ * DESCRIPTION
+ * Case sensitive string searching function.
+ *
+ * RETURNS
+ * Pointer to position "looked for" has been located or NULL if !found.
+ *----------------------------------------------------------------------------*/
+
+char *p_strstr(
+ const char *p_searched, /* Buffer searched */
+ const char *p_lookedfor /* String we're looking for */
+ )
+{
+#if defined(HAVE_STRSTR)
+ return strstr(p_searched, p_lookedfor);
+#else
+ if (*p_searched == 0)
+ {
+ if (*p_lookedfor)
+ {
+ return (char *)NULL;
+ }
+
+ return (char *)p_searched;
+ }
+
+ while (*p_searched)
+ {
+ uint32_t i;
+
+ for (i = 0;;i++)
+ {
+ if (p_lookedfor[i] == 0)
+ {
+ return (char *)p_searched;
+ }
+
+ if (p_lookedfor[i] != p_searched[i])
+ {
+ break;
+ }
+ }
+
+ p_searched++;
+ }
+
+ return (char *)NULL;
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_stricmp()
+ *
+ * DESCRIPTION
+ * Case insensitive string comparison function.
+ *
+ * RETURNS
+ * 0<=>strings match, !=0 else.
+ *----------------------------------------------------------------------------*/
+
+int p_stricmp(
+ const char *p_string1, /* First string */
+ const char *p_string2 /* Second string */
+ )
+{
+#if defined(HAVE_STRCASECMP)
+ return strcasecmp(p_string1, p_string2);
+#elif defined(HAVE_STRICMP)
+ return stricmp(p_string1, p_string2);
+#else
+ while (*p_string1 && (tolower(*p_string1) == tolower(*p_string2)))
+ {
+ p_string1++;
+ p_string2++;
+ }
+
+ return tolower(*(unsigned char *)p_string1) - tolower(*(unsigned char *)p_string2);
+#endif
+}
+
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_stristr()
+ *
+ * DESCRIPTION
+ * Case insensitive string searching function.
+ *
+ * RETURNS
+ * Pointer to position "looked for" has been located or NULL if !found.
+ *----------------------------------------------------------------------------*/
+
+char *p_stristr(
+ const char *p_searched, /* Buffer searched */
+ const char *p_lookedfor /* String we're looking for */
+ )
+{
+#if defined(HAVE_STRISTR)
+ return strstr(p_searched, p_lookedfor);
+#else
+ if (*p_searched == 0)
+ {
+ if (*p_lookedfor)
+ {
+ return (char *)NULL;
+ }
+
+ return (char *)p_searched;
+ }
+
+ while (*p_searched)
+ {
+ uint32_t i;
+
+ for (i = 0;;i++)
+ {
+ if (p_lookedfor[i] == 0)
+ {
+ return (char *)p_searched;
+ }
+
+ if (tolower(p_lookedfor[i]) != tolower(p_searched[i]))
+ {
+ break;
+ }
+ }
+
+ p_searched++;
+ }
+
+ return (char *)NULL;
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_memcpy()
+ *
+ * DESCRIPTION
+ * Copy characetrs between buffers. No checks on overlap.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void p_memcpy(
+ void *p_destination, /* Pointer to buffer */
+ const void *p_source, /* Source of copy */
+ uint32_t length /* Number of characters to copy */
+ )
+{
+#if defined(HAVE_MEMCPY)
+ memcpy(p_destination, p_source, length);
+#else
+ uint8_t *p_dst = (uint8_t *)p_destination;
+ uint8_t *p_src = (uint8_t *)p_source;
+
+ while (length--)
+ {
+ *p_dst++ = *p_src++;
+ }
+#endif
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_memset()
+ *
+ * DESCRIPTION
+ * Fill buffer with indicated character.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+void p_memset(
+ void *p_destination, /* Pointer to buffer */
+ uint8_t v, /* Character to fill with */
+ uint32_t length /* Length of buffer to set */
+ )
+{
+#if defined(HAVE_MEMSET)
+ memset(p_destination, v, length);
+#else
+ uint8_t *p_dst = (uint8_t *)p_destination;
+
+ while (length--)
+ *p_dst++ = v;
+#endif
+}
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/
diff --git a/src/vf_strings.h b/src/vf_strings.h
new file mode 100644
index 0000000..29ccd78
--- /dev/null
+++ b/src/vf_strings.h
@@ -0,0 +1,230 @@
+/*******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile$
+ $Revision: 1.6 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley
+
+DESCRIPTION
+ String handling functions. The library uses the p_ functions (where hopefully
+ the 'p' stands for 'portable') and they are provided here in terms of C runtime
+ functions or implemented explicitly.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_strings.h,v $
+ * Revision 1.6 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.5 2002/10/08 21:27:20 tilda
+ * Correct #endif directive.
+ *
+ * Revision 1.4 2001/11/05 21:07:19 tilda
+ * Various changes for initial version of vfedit.
+ *
+ * Revision 1.3 2001/10/14 20:42:37 tilda
+ * Addition of group searching.
+ *
+ * Revision 1.2 2001/10/13 14:58:56 tilda
+ * Tidy up version headers, add vf_strings.h where needed.
+ *
+ * Revision 1.1 2001/10/13 14:50:33 tilda
+ * Add string array code to unify handling of names / values.
+ *
+ *******************************************************************************/
+
+#ifndef _VF_STRINGS_H_
+#define _VF_STRINGS_H_
+
+#ifndef NORCSID
+static const char vf_strings_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_strings.h,v 1.6 2002/10/26 16:09:23 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ Public Includes
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Defines
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Types
+ *============================================================================*/
+/* None */
+
+/*=============================================================================*
+ Public Functions
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strlen()
+ *
+ * DESCRIPTION
+ * Find length of string.
+ *
+ * RETURNS
+ * Length of strings.
+ *----------------------------------------------------------------------------*/
+
+extern int p_strlen(
+ const char *p_string /* String to measure */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcpy()
+ *
+ * DESCRIPTION
+ * Copy string to buffer.
+ *
+ * RETURNS
+ * Pointer to buffer.
+ *----------------------------------------------------------------------------*/
+
+extern char *p_strcpy(
+ char *p_string1, /* Buffer to copy to */
+ const char *p_string2 /* String to copy */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcmp()
+ *
+ * DESCRIPTION
+ * Case sensitive string comparison.
+ *
+ * RETURNS
+ * 0<=>strings match, !=0 else.
+ *----------------------------------------------------------------------------*/
+
+extern int p_strcmp(
+ const char *p_string1,
+ const char *p_string2
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strcat()
+ *
+ * DESCRIPTION
+ * Append one string to another.
+ *
+ * RETURNS
+ * Pointer to resulting string.
+ *----------------------------------------------------------------------------*/
+
+extern char *p_strcat(
+ char *p_string1, /* String to append to */
+ const char *p_string2 /* String to append */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_strstr()
+ *
+ * DESCRIPTION
+ * Case sensitive string searching function.
+ *
+ * RETURNS
+ * Pointer to position "looked for" has been located or NULL if !found.
+ *----------------------------------------------------------------------------*/
+
+extern char *p_strstr(
+ const char *p_searched, /* Buffer searched */
+ const char *p_lookedfor /* String we're looking for */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_stricmp()
+ *
+ * DESCRIPTION
+ * Case insensitive string comparison function.
+ *
+ * RETURNS
+ * 0<=>strings match, !=0 else.
+ *----------------------------------------------------------------------------*/
+
+extern int p_stricmp(
+ const char *p_string1, /* First string */
+ const char *p_string2 /* Second string */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_stristr()
+ *
+ * DESCRIPTION
+ * Case insensitive string searching function.
+ *
+ * RETURNS
+ * Pointer to position "looked for" has been located or NULL if !found.
+ *----------------------------------------------------------------------------*/
+
+extern char *p_stristr(
+ const char *p_searched, /* Buffer searched */
+ const char *p_lookedfor /* String we're looking for */
+ );
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_memcpy()
+ *
+ * DESCRIPTION
+ * Copy characetrs between buffers. No checks on overlap.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+extern void p_memcpy(
+ void *p_destination, /* Pointer to buffer */
+ const void *p_source, /* Source of copy */
+ uint32_t length /* Number of characters to copy */
+ );
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * p_memset()
+ *
+ * DESCRIPTION
+ * Fill buffer with indicated character.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+extern void p_memset(
+ void *p_destination, /* Pointer to buffer */
+ uint8_t v, /* Character to fill with */
+ uint32_t length /* Length of buffer to set */
+ );
+
+
+/*=============================================================================*
+ End of file
+ *============================================================================*/
+
+#endif /*_VF_STRINGS_H_*/
diff --git a/src/vf_writer.c b/src/vf_writer.c
new file mode 100644
index 0000000..ef3298a
--- /dev/null
+++ b/src/vf_writer.c
@@ -0,0 +1,616 @@
+/******************************************************************************
+
+ (C) Nick Marley, 2001 -
+
+ This software is distributed under the GNU Lesser General Public Licence.
+ Please read and understand the comments at the top of vf_iface.h before use!
+
+FILE
+ $Workfile$
+ $Revision: 1.12 $
+ $Author: tilda $
+
+ORIGINAL AUTHOR
+ Nick Marley.
+
+DESCRIPTION
+ Code for writing vformat files. This is temporary as it is not based
+ around a state machine for converting the object to a character stream.
+
+REFERENCES
+ (none)
+
+MODIFICATION HISTORY
+ * $Log: vf_writer.c,v $
+ * Revision 1.12 2002/11/03 18:43:16 tilda
+ * IID619851 - Update and check headers and function prototypes.
+ *
+ * Revision 1.11 2002/11/02 08:56:17 tilda
+ * Start of internationalisation changes.
+ *
+ * Revision 1.10 2002/10/26 16:09:23 tilda
+ * IID629125 - Ensure string functions used are portable.
+ *
+ * Revision 1.9 2002/10/08 21:45:07 tilda
+ * IID620473 - reduce c-runtime dependencies.
+ *
+ * Revision 1.8 2002/10/08 21:11:35 tilda
+ * Remove common.h.
+ *
+ * Revision 1.7 2002/02/24 17:10:34 tilda
+ * Add API for "is modified" functionality.
+ *
+ * Revision 1.6 2001/12/13 06:45:35 tilda
+ * IID488021 - Various bugs with quoted printable format.
+ *
+ * Revision 1.5 2001/11/18 21:45:10 tilda
+ * Add newline after BASE64 encodings
+ *
+ * Revision 1.4 2001/11/14 22:36:55 tilda
+ * Add parameter to vf_find_prop_qual_index()
+ *
+ * Revision 1.3 2001/11/06 22:51:05 tilda
+ * Supporting access functions for image selection / deletion.
+ *
+ * Revision 1.2 2001/10/24 18:56:29 tilda
+ * Tidy headers after import. Fix include path in release build.
+ *
+ * Revision 1.1 2001/10/24 18:34:35 tilda
+ * Initial Version.
+ *
+ *******************************************************************************/
+
+#ifndef NORCSID
+static const char vf_writer_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_writer.c,v 1.12 2002/11/03 18:43:16 tilda Exp $";
+#endif
+
+/*=============================================================================*
+ ANSI C & System-wide Header Files
+ *=============================================================================*/
+
+#include <common/types.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+/*============================================================================*
+ Interface Header Files
+ *============================================================================*/
+
+#include <vformat/vf_iface.h>
+
+/*============================================================================*
+ Local Header File
+ *============================================================================*/
+
+#include "vf_config.h"
+#include "vf_internals.h"
+#include "vf_malloc.h"
+#include "vf_strings.h"
+
+/*============================================================================*
+ Public Data
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Defines
+ *============================================================================*/
+
+#define QPMAXPERLINE (76)
+#define BASE64PERLINE (64)
+
+/*============================================================================*
+ Private Data Types
+ *============================================================================*/
+/* None */
+
+/*============================================================================*
+ Private Function Prototypes
+ *============================================================================*/
+
+static bool_t write_name_fields(
+ FILE *fp,
+ uint32_t *p_charsonline,
+ VPROP_T *p_prop
+ );
+
+static void write_base64_chars(
+ FILE *fp, /* File we're writing */
+ uint8_t *s, /* Pointer to buffer */
+ uint32_t len /* buffer length */
+ );
+
+static bool_t write_quoted_printable(
+ FILE *fp, /* File we're writing */
+ uint8_t *s, /* Pointer to buffer */
+ uint32_t *p_charsonline /* Num on line so far */
+ );
+
+static char char_to_base64(
+ uint8_t b /* Byte to convert */
+ );
+
+static bool_t qp_needs_quoting(
+ uint8_t c /* Char to test */
+ );
+
+static bool_t write_vobject_to_file(
+ FILE *fp,
+ VOBJECT_T *p_object,
+ bool_t write_all
+ );
+
+/*============================================================================*
+ Private Data
+ *============================================================================*/
+
+static const char szEndOfLine[3] = { 0x0D, 0x0A, 0x00 };
+
+/*============================================================================*
+ Public Function Implementations
+ *============================================================================*/
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * vf_write_file()
+ *
+ * DESCRIPTION
+ * Write indicated vobject to file.
+ *
+ * RETURNS
+ * TRUE <=> written OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t vf_write_file(
+ const char *p_name, /* Outpt filename */
+ VF_OBJECT_T *p_object, /* The object to write */
+ bool_t write_all /* Should write p_next as well? */
+ )
+{
+ FILE *fp;
+ bool_t ret = FALSE;
+
+ fp = fopen(p_name, "wb");
+
+ if (fp)
+ {
+ ret = write_vobject_to_file(fp, (VOBJECT_T *)p_object, write_all);
+
+ if (0 == fclose(fp))
+ {
+ /* as is */
+ }
+ else
+ {
+ ret = FALSE;
+ }
+ }
+
+ return ret;
+}
+
+
+
+
+
+
+/*============================================================================*
+ Private Function Implementations
+ *============================================================================*/
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * write_vobject_to_file()
+ *
+ * DESCRIPTION
+ * Write each field of the indicated vformat object to the indicated FILE*
+ * invoking write_vobject_to_file() recursively if a field is found which
+ * contains a vformat object.
+ *
+ * RETURNS
+ * TRUE <=> file acces OK, FALSE else.
+ *----------------------------------------------------------------------------*/
+
+bool_t write_vobject_to_file(
+ FILE *fp,
+ VOBJECT_T *p_object,
+ bool_t write_all
+ )
+{
+ bool_t ret = TRUE;
+
+ VOBJECT_T *p_obj = (VOBJECT_T *)p_object;
+ VPROP_T *p_props = p_obj->p_props;
+
+ fprintf(fp, "%s:%s", VFP_BEGIN, p_obj->p_type);
+
+ fprintf(fp, szEndOfLine);
+
+ for (;NULL != p_props;p_props = p_props->p_next)
+ {
+ uint32_t charsonline;
+
+ switch (p_props->value.encoding)
+ {
+ default:
+ case VF_ENC_7BIT:
+ {
+ ret = write_name_fields(fp, &charsonline, p_props);
+
+ if (ret)
+ {
+ uint32_t n;
+
+ for (n = 0;ret && (n < p_props->value.v.s.n_strings);n++)
+ {
+ if (n)
+ fprintf(fp, ";");
+
+ if (p_props->value.v.s.pp_strings[n])
+ {
+ fprintf(fp, "%s", p_props->value.v.s.pp_strings[n]);
+ }
+ }
+ }
+ }
+ break;
+
+ case VF_ENC_BASE64:
+ {
+ ret = write_name_fields(fp, &charsonline, p_props);
+
+ if (ret)
+ {
+ write_base64_chars(fp, p_props->value.v.b.p_buffer, p_props->value.v.b.n_bufsize);
+ }
+ }
+ break;
+
+ case VF_ENC_QUOTEDPRINTABLE:
+ {
+ ret = write_name_fields(fp, &charsonline, p_props);
+
+ if (ret)
+ {
+ uint32_t n;
+
+ for (n = 0;ret && (n < p_props->value.v.s.n_strings);n++)
+ {
+ if (n)
+ fprintf(fp, ";");
+
+ if (p_props->value.v.s.pp_strings[n])
+ {
+ ret = write_quoted_printable(fp, p_props->value.v.s.pp_strings[n], &charsonline);
+ }
+ }
+ }
+ }
+ break;
+
+ case VF_ENC_VOBJECT:
+ {
+ write_vobject_to_file(fp, p_props->value.v.o.p_object, TRUE);
+ }
+ break;
+ }
+
+ if (VF_ENC_VOBJECT != p_props->value.encoding)
+ fprintf(fp, szEndOfLine);
+ }
+
+ fprintf(fp, "%s:%s", VFP_END, p_obj->p_type);
+
+ fprintf(fp, szEndOfLine);
+
+ if (ret && p_obj->p_next && write_all)
+ {
+ ret = write_vobject_to_file(fp, p_obj->p_next, TRUE);
+ }
+
+ p_obj->modified = !ret;
+
+ return ret;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * write_base64_chars()
+ *
+ * DESCRIPTION
+ * Write the indicated binary data stream out to FILE* using BASE64
+ * encoding.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+static void write_base64_chars(
+ FILE *fp, /* File we're writing */
+ uint8_t *p_buffer, /* Pointer to buffer */
+ uint32_t n_chars /* buffer length */
+ )
+{
+ uint32_t posn;
+ char quad[5];
+ uint8_t b;
+
+ quad[4] = 0;
+
+ for (posn = 0;posn < n_chars;)
+ {
+ int i;
+ uint32_t triplet = 0;
+ uint8_t bits = 0;
+
+ /* Form triplet from data if available */
+
+ for (i = 0;i < 3;i++, posn++)
+ {
+ triplet = triplet << 8;
+
+ if (posn < n_chars)
+ {
+ triplet |= *(p_buffer + posn);
+
+ bits += 8;
+ }
+ }
+
+ /* Convert the triplet to text */
+
+ for (i = 0;i < 4;i++)
+ {
+ b = (uint8_t)((0xFC0000 & triplet) >> 18);
+
+ triplet = triplet << 6;
+
+ quad[i] = (i <= (bits/6)) ? char_to_base64(b) : '=';
+ }
+
+ /* Output the text prefixed by newlines if necessary */
+
+ if (((posn - 3) % (BASE64PERLINE / 4)) == 0)
+ {
+ fprintf(fp, szEndOfLine);
+ fprintf(fp, " ");
+ }
+
+ fprintf(fp, "%s", quad);
+ }
+
+ fprintf(fp, szEndOfLine);
+}
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * write_quoted_printable()
+ *
+ * DESCRIPTION
+ * Write the indicated field back to the file in quoted printable format.
+ *
+ * RETURNS
+ * (none)
+ *----------------------------------------------------------------------------*/
+
+static bool_t write_quoted_printable(
+ FILE *fp, /* File we're writing */
+ uint8_t *s, /* Pointer to buffer */
+ uint32_t *p_charsonline /* Num on line so far */
+ )
+{
+ uint32_t i;
+ uint32_t charsonline = *p_charsonline;
+
+ for (i = 0;s;i++)
+ {
+ uint8_t c = s[i];
+
+ if ('\0' == c)
+ {
+ break;
+ }
+ else
+ {
+ if (3 + charsonline > QPMAXPERLINE)
+ {
+ fprintf(fp, "=");
+ fprintf(fp, szEndOfLine);
+ charsonline = 0;
+ }
+
+ if (qp_needs_quoting(c))
+ {
+ fprintf(fp, "=%02X", c);
+ charsonline += 3;
+
+ if (0x0D == c)
+ {
+ fprintf(fp, "=");
+ fprintf(fp, szEndOfLine);
+ charsonline = 0;
+ }
+ }
+ else
+ {
+ fprintf(fp, "%c", c);
+ charsonline += 1;
+ }
+ }
+ }
+
+ *p_charsonline = charsonline;
+
+ return TRUE;
+}
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * char_to_base64()
+ *
+ * DESCRIPTION
+ * Converts byte to BASE64.
+ *
+ * RETURNS
+ * Character encoded.
+ *----------------------------------------------------------------------------*/
+
+static char char_to_base64(
+ uint8_t b /* Byte to convert */
+ )
+{
+ char ret;
+
+ if (b < 26)
+ {
+ ret = (char)b + 'A';
+ }
+ else
+ if (b < 52)
+ {
+ ret = (char)(b - 26) + 'a';
+ }
+ else
+ if (b < 62)
+ {
+ ret = (char)(b - 52) + '0';
+ }
+ else
+ if (b == 62)
+ {
+ ret = '+';
+ }
+ else
+ {
+ ret = '/';
+ }
+
+ return ret;
+}
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * qp_needs_quoting()
+ *
+ * DESCRIPTION
+ * Works out of 'c' needs quoting in quoted printable format.
+ *
+ * RETURNS
+ * TRUE <=> need to quote.
+ *----------------------------------------------------------------------------*/
+
+static bool_t qp_needs_quoting(
+ uint8_t c /* Char to test */
+ )
+{
+ /* TBD - look in the RFC?! */
+
+ bool_t needs_quoting = FALSE;
+
+ switch (c)
+ {
+ case ' ':
+ case ',':
+ case '-':
+ case '.':
+ case '!':
+ case '?':
+ case '\'':
+ return FALSE;
+
+ default:
+ if (isalnum(c))
+ needs_quoting = FALSE;
+ else
+ needs_quoting = TRUE;
+ break;
+ }
+
+ return needs_quoting;
+}
+
+
+
+
+
+
+/*----------------------------------------------------------------------------*
+ * NAME
+ * write_name_fields()
+ *
+ * DESCRIPTION
+ * Write name fields to file.
+ *
+ * RETURNS
+ * TRUE <=> OK so far.
+ *----------------------------------------------------------------------------*/
+
+bool_t write_name_fields(
+ FILE *fp,
+ uint32_t *p_charsonline,
+ VPROP_T *p_prop
+ )
+{
+ VSTRARRAY_T *p_strarray = &(p_prop->name);
+ bool_t ret = FALSE;
+
+ *p_charsonline = 0;
+
+ if (p_prop->p_group)
+ {
+ *p_charsonline += fprintf(fp, "%s.", p_prop->p_group);
+ }
+
+ if (p_strarray->pp_strings)
+ {
+ uint32_t i;
+
+ for (i = 0;i < p_strarray->n_strings;i++)
+ {
+ char *p_name_field = p_strarray->pp_strings[i];
+
+ if (p_name_field && (0 < p_strlen(p_name_field)))
+ {
+ if (0 < i)
+ {
+ fprintf(fp, ";");
+ *p_charsonline += 1;
+ }
+
+ *p_charsonline += fprintf(fp, "%s", p_name_field);
+ }
+ }
+
+ fprintf(fp, ":");
+ *p_charsonline += 1;
+
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+
+/*============================================================================*
+ End Of File
+ *============================================================================*/