Click here to Skip to main content
15,884,537 members
Articles / Desktop Programming / MFC

MsAccess MdbTools with MFC and .NET

Rate me:
Please Sign up or sign in to vote.
4.82/5 (9 votes)
13 Jan 2012LGPL310 min read 68.9K   9.9K   49  
Viewer of MsAccess databases directly from MFC and .NET - Repair corrupt databases
/*
 * Copyright © 2008 Ryan Lortie
 * Copyright © 2010 Codethink Limited
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Ryan Lortie <desrt@desrt.ca>
 */

#ifndef __G_VARIANT_TYPE_INFO_H__
#define __G_VARIANT_TYPE_INFO_H__

#include <glib/gvarianttype.h>

#define G_VARIANT_TYPE_INFO_CHAR_MAYBE      'm'
#define G_VARIANT_TYPE_INFO_CHAR_ARRAY      'a'
#define G_VARIANT_TYPE_INFO_CHAR_TUPLE      '('
#define G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY '{'
#define G_VARIANT_TYPE_INFO_CHAR_VARIANT    'v'
#define g_variant_type_info_get_type_char(info) \
  (g_variant_type_info_get_type_string(info)[0])

typedef struct _GVariantTypeInfo GVariantTypeInfo;

/* < private >
 * GVariantMemberInfo:
 *
 * This structure describes how to construct a GVariant instance
 * corresponding to a given child of a tuple or dictionary entry in a
 * very short constant time.  It contains the typeinfo of the child,
 * along with 4 constants that allow the bounds of the child's
 * serialised data within the container's serialised data to be found
 * very efficiently.
 *
 * Since dictionary entries are serialised as if they were tuples of 2
 * items, the term "tuple" will be used here in the general sense to
 * refer to tuples and dictionary entries.
 *
 * BACKGROUND:
 *   The serialised data for a tuple contains an array of "offsets" at
 *   the end.  There is one "offset" in this array for each
 *   variable-sized item in the tuple (except for the last one).  The
 *   offset points to the end point of that item's serialised data.  The
 *   procedure for finding the start point is described below.  An
 *   offset is not needed for the last item because the end point of the
 *   last item is merely the end point of the container itself (after
 *   the offsets array has been accounted for).  An offset is not needed
 *   for fixed-sized items (like integers) because, due to their fixed
 *   size, the end point is a constant addition to the start point.
 *
 *   It is clear that the starting point of a given item in the tuple is
 *   determined by the items that preceed it in the tuple.  Logically,
 *   the start point of a particular item in a given type of tuple can
 *   be determined entirely by the end point of the nearest
 *   variable-sized item that came before it (or from the start of the
 *   container itself in case there is no preceeding variable-sized
 *   item).  In the case of "(isis)" for example, in order to find out
 *   the start point of the last string, one must start at the end point
 *   of the first string, align to 4 (for the integer's alignment) and
 *   then add 4 (for storing the integer).  That's the point where the
 *   string starts (since no special alignment is required for strings).
 *
 *   Of course, this process requires iterating over the types in the
 *   tuple up to the item of interest.  As it turns out, it is possible
 *   to determine 3 constants 'a', 'b', and 'c' for each item in the
 *   tuple, such that, given the ending offset of the nearest previous
 *   variable-sized item (prev_end), a very simple calculation can be
 *   performed to determine the start of the item of interest.
 *
 * The constants in this structure are used as follows:
 *
 * First, among the array of offets contained in the tuple, 'i' is the
 * index of the offset that refers to the end of the variable-sized item
 * preceeding the item of interest.  If no variable-sized items preceed
 * this item, then 'i' will be -1.
 *
 * Let 'prev_end' be the end offset of the previous item (or 0 in the
 * case that there was no such item).  The start address of this item
 * can then be calculate using 'a', 'b', and 'c':
 *
 *    item_start = ((prev_end + a) & b) | c;
 *
 * For details about how 'a', 'b' and 'c' are calculated, see the
 * comments at the point of the implementation in gvariantypeinfo.c.
 *
 * The end address of the item is then determined in one of three ways,
 * according to the 'end_type' field.
 *
 *   - FIXED: For fixed sized items, the end address is equal to the
 *     start address plus the fixed size.
 *
 *   - LAST: For the last variable sized item in the tuple, the end
 *     address is equal to the end address of the tuple, minus the size
 *     of the offset array.
 *
 *   - OFFSET: For other variable sized items, the next index past 'i'
 *     (ie: 'i + 1') must be consulted to find the end of this item.
 */

typedef struct
{
  GVariantTypeInfo *type_info;

  gsize i, a;
  gint8 b, c;

  guint8 ending_type;
} GVariantMemberInfo;

#define G_VARIANT_MEMBER_ENDING_FIXED   0
#define G_VARIANT_MEMBER_ENDING_LAST    1
#define G_VARIANT_MEMBER_ENDING_OFFSET  2

/* query */
const gchar *                   g_variant_type_info_get_type_string     (GVariantTypeInfo   *typeinfo);

void                            g_variant_type_info_query               (GVariantTypeInfo   *typeinfo,
                                                                         guint              *alignment,
                                                                         gsize              *size);

/* array */
GVariantTypeInfo *              g_variant_type_info_element             (GVariantTypeInfo   *typeinfo);
void                            g_variant_type_info_query_element       (GVariantTypeInfo   *typeinfo,
                                                                         guint              *alignment,
                                                                         gsize              *size);

/* structure */
gsize                           g_variant_type_info_n_members           (GVariantTypeInfo   *typeinfo);
const GVariantMemberInfo *      g_variant_type_info_member_info         (GVariantTypeInfo   *typeinfo,
                                                                         gsize               index);

/* new/ref/unref */
GVariantTypeInfo *              g_variant_type_info_get                 (const GVariantType *type);
GVariantTypeInfo *              g_variant_type_info_ref                 (GVariantTypeInfo   *typeinfo);
void                            g_variant_type_info_unref               (GVariantTypeInfo   *typeinfo);
void                            g_variant_type_info_assert_no_infos     (void);

#endif /* __G_VARIANT_TYPE_INFO_H__ */

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer
Argentina Argentina
System developer from Argentina.

Programmed in VB 5,6,.NET, C#, Java, PL-SQL, Transac-SQL, C, C++ and even some "calculator" language.

Love to build small, useful applications.
Usually building big and complicated apps based on solid, reliable components.

Hobbies: reading, photography, chess, paddle, running.

Comments and Discussions