/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* file: abtable.h
** Some portions derive from public domain IronDoc code and interfaces.
**
** This is the public address book interface that should be included by
** clients that want to access address book content without knowing any
** more details than necessary about the internal implementation. This
** interface deliberately hides details concerning how this database
** independent layer can be targeted by third parties by subclassing.
**
** The private address book interface is specified in abmodel.h, which
** defines the interfaces of classes that allow third parties to target
** the address book interface by subclassing appropriate classes in the
** address book model. The private interface defines the structure and
** polymorphic vtables (if needed) for any classes in the public interface
** whose structure is hidden. If the public interface is constrained to
** call "factory" methods to construct and generate objects needed to
** access address book content, then under the covers these objects might
** be dynamically bound subclasses appropriate for use in a given model.
**
** Changes:
** <0> 22Oct1997 first draft
*/
#ifndef _ABTABLE_
#define _ABTABLE_ 1
/* ----- ----- ----- ----- switches ----- ----- ----- ----- */
#define AB_CONFIG_MACINTOSH /*i*/ 1
/* #define AB_CONFIG_UNIX 1 */ /*i*/
/* #define AB_CONFIG_WINDOWS 1 */ /*i*/
/*#define AB_CONFIG_LOGGING 1 */
/* #define AB_CONFIG_MOZ_NEWADDR 1 */ /*i*/
#ifdef AB_CONFIG_MOZ_NEWADDR
#define AB_CONFIG_SMALLER_INDEXES 1 /* use new smaller indexes */
#define AB_CONFIG_FIRST_LAST_INDEXES 1 /* use new name indexes */
#define AB_CONFIG_TUPLE_ENTRY 1 /* use new tuple entry class */
#endif /*AB_CONFIG_MOZ_NEWADDR*/
#define AB_CONFIG_USE_NEO_CACHE_TABLES 1 /*i*/
#define AB_CONFIG_TRUNCATE_FULL_NAME 1 /* force rather short */
/*#define AB_CONFIG_ENABLE_INDEX_REFRESH 1*/ /* allow */
#define AB_CONFIG_DEBUG /*i*/ 1
#ifdef AB_CONFIG_DEBUG
#define AB_CONFIG_PRINT /*i*/ 1
#endif
#ifdef AB_CONFIG_DEBUG
#define AB_CONFIG_TRACE /*i*/ 1
#endif
#ifdef AB_CONFIG_DEBUG
#define AB_CONFIG_MAXIMIZE_FEATURES /*i*/ 1
#endif
#ifdef AB_CONFIG_TRACE
#define AB_CONFIG_TRACE_CALL_TREE /*i*/ 1
#else
#define AB_CONFIG_TRACE_CALL_TREE 0
#endif
#if defined(AB_CONFIG_TRACE) || defined(AB_CONFIG_DEBUG) \
|| defined(AB_CONFIG_PRINT)
#define AB_CONFIG_TRACE_orDEBUG_orPRINT /*i*/ 1
#else
#define AB_CONFIG_TRACE_orDEBUG_orPRINT 0
#endif
#if defined(AB_CONFIG_TRACE) || defined(AB_CONFIG_LOGGING)
#define AB_CONFIG_TRACE_andLOGGING /*i*/ 1
#else
#define AB_CONFIG_TRACE_andLOGGING 0
#endif
#ifdef AB_CONFIG_DEBUG
#define AB_CONFIG_KNOW_FAULT_STRINGS 1
#endif
/* ----- ----- ----- disable unused param warnings ----- ----- ----- */
#define AB_USED_PARAMS_1(x) (void)(&x)
#define AB_USED_PARAMS_2(x,y) (void)(&x,&y)
#define AB_USED_PARAMS_3(x,y,z) (void)(&x,&y,&z)
#define AB_USED_PARAMS_4(w,x,y,z) (void)(&w,&x,&y,&z)
/* ----- ----- ----- assertions ----- ----- ----- */
#define AB_ASSERT(x) XP_ASSERT(x)
/* ----- ----- ----- utilities ----- ----- ----- */
#define AB_MEMCPY(dest,src,size) XP_MEMCPY(dest,src,size)
#define AB_MEMMOVE(dest,src,size) XP_MEMMOVE(dest,src,size)
#define AB_MEMSET(dest,byte,size) XP_MEMSET(dest,byte,size)
#define AB_STRCPY(dest,src) XP_STRCPY(dest,src)
#define AB_STRCAT(dest,src) XP_STRCAT(dest,src)
#define AB_STRCMP(one,two) XP_STRCMP(one,two)
#define AB_STRNCMP(one,two,length) XP_STRNCMP(one,two,length)
#define AB_STRLEN(string) XP_STRLEN(string)
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
/* ----- ----- ----- ----- signatures ----- ----- ----- ----- */
#include "xp_core.h"
#include "xp.h"
#if defined(XP_CPLUSPLUS)
# define AB_BEGIN_C_PROTOS extern "C" {
# define AB_END_C_PROTOS }
#else
# define AB_BEGIN_C_PROTOS
# define AB_END_C_PROTOS
#endif
#define AB_PUBLIC_API(returnType) /*i*/ returnType
/* API() wraps return types of header file library public methods */
#define AB_API_IMPL(returnType) returnType
/* API_IMPL() wraps return types of .c file library public methods */
#define AB_MODEL(returnType) /*i*/ returnType
/* MODEL() wraps return types of header file semi-private model methods */
#define AB_MODEL_IMPL(returnType) returnType
/* MODEL_IMPL() wraps return types of .c file semi-private model methods */
#define AB_LIB(returnType) /*i*/ returnType
/* LIB() wraps return types of header file library private methods */
#define AB_LIB_IMPL(returnType) /*i*/ returnType
/* LIB_IMPL() wraps return types of .c file library private methods */
#define AB_FILE_IMPL(returnType) static returnType
/* FILE_IMPL() wraps return types of .c file scoped methods */
/* ----- ----- ----- ----- primitives ----- ----- ----- ----- */
#ifdef AB_BOOL_STAND_ALONE
typedef unsigned char ab_bool /*d*/; /* any nonzero value implies true */
#define AB_kFalse /*i*/ 0
#define AB_kTrue /*i*/ 1
#else /* else ! AB_BOOL_STAND_ALONE ------- */
#include "xp_core.h"
typedef XP_Bool ab_bool; /* boolean */
#define AB_kFalse FALSE
#define AB_kTrue TRUE
#endif /* end AB_BOOL_STAND_ALONE ------- */
typedef unsigned char ab_u1 /*d*/; /* unsigned 1 byte */
typedef short ab_i2 /*d*/; /* signed 2 bytes */
typedef unsigned short ab_u2 /*d*/; /* unsigned 2 bytes */
typedef long ab_i4 /*d*/; /* signed 4 bytes */
typedef unsigned long ab_u4 /*d*/; /* unsigned 4 bytes */
typedef ab_u4 ab_num /*d*/; /* a "count" with many bits */
typedef ab_u4 ab_pos /*d*/; /* an index "position" with many bits */
typedef ab_u4 ab_uid /*d*/; /* a unique id with many bits */
typedef ab_i4 ab_map_int /*d*/; /* size must be at least sizeof(void*) */
typedef ab_u4 ab_policy /*d*/; /* generally to hold policy enum values */
/* ----- ----- ----- ----- forwards ----- ----- ----- ----- */
#ifndef AB_Fault_typedef
typedef struct AB_Fault AB_Fault;
#define AB_Fault_typedef 1
#endif
#ifndef AB_PosPair_typedef
typedef struct AB_PosPair AB_PosPair;
#define AB_PosPair_typedef 1
#endif
#ifndef AB_PosRange_typedef
typedef struct AB_PosRange AB_PosRange;
#define AB_PosRange_typedef 1
#endif
#ifndef AB_Env_typedef
typedef struct AB_Env AB_Env;
#define AB_Env_typedef 1
#endif
#ifndef AB_Sink_typedef
typedef struct AB_Sink AB_Sink;
#define AB_Sink_typedef 1
#endif
#ifndef AB_Debugger_typedef
typedef struct AB_Debugger AB_Debugger;
#define AB_Debugger_typedef 1
#endif
#ifndef AB_Tracer_typedef
typedef struct AB_Tracer AB_Tracer;
#define AB_Tracer_typedef 1
#endif
#ifndef AB_Table_typedef
typedef struct AB_Table AB_Table;
#define AB_Table_typedef 1
#endif
#ifndef AB_AsyncTask_typedef
typedef struct AB_AsyncTask AB_AsyncTask;
#define AB_AsyncTask_typedef 1
#endif
#ifndef AB_AsyncResult_typedef
typedef struct AB_AsyncResult AB_AsyncResult;
#define AB_AsyncResult_typedef 1
#endif
#ifndef AB_Column_typedef
typedef struct AB_Column AB_Column;
#define AB_Column_typedef 1
#endif
#ifndef AB_Row_typedef
typedef struct AB_Row AB_Row;
#define AB_Row_typedef 1
#endif
#ifndef AB_Cell_typedef
typedef struct AB_Cell AB_Cell;
#define AB_Cell_typedef 1
#endif
#ifndef AB_Store_typedef
typedef struct AB_Store AB_Store;
#define AB_Store_typedef 1
#endif
#ifndef AB_Thumb_typedef
typedef struct AB_Thumb AB_Thumb;
#define AB_Thumb_typedef 1
#endif
#ifndef AB_File_typedef
typedef struct AB_File AB_File;
#define AB_File_typedef 1
#endif
#ifndef DIR_Server_typedef
typedef struct DIR_Server DIR_Server;
#define DIR_Server_typedef 1
#endif
/* ----- ----- ----- ----- types ----- ----- ----- ----- */
typedef ab_u4 ab_ref_count; /* counts times any object is acquired */
/*- This reference count is needed for tables and might be used by other
runtime objects as well. A reference count is a runtime session effect and
not a persistent value. Nothing stored persistently in a database implies
anything about runtime reference counts. -*/
#define AB_Fault_kNone 0 /* zero means no error */
/*- No error unique id uses the value of zero. -*/
typedef ab_i4 ab_error_uid; /* unique id for an error */
/*- Unique id for an error specific to address books.
Zero means no error. -*/
typedef ab_num ab_error_count; /* numeric count of errors */
/*- Type that clearly counts errors. -*/
typedef ab_num ab_count; /* numeric count of something */
typedef ab_num ab_uid_count; /* numeric count of uids */
typedef ab_pos ab_uid_pos; /* array index for individual uid */
typedef ab_uid ab_db_uid; /* unique id from a database */
/*- A db uid is a unique id generated by a database, which need not
follow any conventions used by address books. The unique ids used by
address books for rows and columns are constructed from database uids
by bitshifting the db uids and ORing in tag bits that distinguish
various kinds of address book unique ids. This db uid type is intended
to explicitly indicate that tag bits are not present as understood by
address books, and that bitshifting and other transformations are needed
to convert between db uids and other kinds of uids. -*/
typedef ab_db_uid ab_db_index_uid; /* unique id for db index */
typedef ab_db_uid ab_db_name_uid; /* unique id for db name token */
typedef ab_db_uid ab_db_set_uid; /* unique id for db set of things */
typedef ab_db_set_uid ab_db_list_set_uid; /* uid for db set of lists */
typedef ab_db_uid ab_db_row_uid; /* unique id for db row */
typedef ab_db_row_uid ab_db_parent_uid; /* uid for parent db row */
typedef ab_db_row_uid ab_db_child_uid; /* uid for child db row */
typedef ab_db_uid ab_db_list_uid; /* unique id for db row with children */
typedef ab_num ab_list_count; /* numeric count of lists */
typedef ab_pos ab_list_pos; /* array index for individual list */
typedef ab_uid ab_row_uid; /* unique id for a row */
typedef ab_uid ab_column_uid; /* unique id for a column */
/*- Row and column unique ids have address book scope, so all tables
inside a single address book share the same unique id name space for
rows and columns. There need not be a unique id type for tables
because all tables are alwo rows. -*/
typedef ab_uid ab_model_uid; /* unique id for a model */
typedef ab_uid ab_store_uid; /* unique id for a store */
typedef ab_row_uid ab_table_uid; /* unique id for a table */
typedef ab_table_uid ab_container_uid; /* unique id for database container */
typedef ab_num ab_row_count; /* numeric count of rows */
typedef ab_num ab_column_count; /* numeric count of columns */
/*- These types help clarify when integer values are intended to count
differnt kinds of objects. -*/
typedef ab_pos ab_row_pos; /* array index for individual row */
typedef ab_pos ab_column_pos; /* array index for individual column */
typedef ab_pos ab_cell_pos; /* array index for individual cell */
/*- These types help clarify when integer values are intended to specifiy
an array position within an ordered sequence of rows, columns, or cells.
Currently row and column positions are one-based so zero can be
reserved to mean an exceptional condition. -*/
/* `````` `````` protos `````` `````` */
AB_BEGIN_C_PROTOS
/* `````` `````` protos `````` `````` */
/* ----- ----- ----- ----- position sets ----- ----- ----- ----- */
struct AB_PosPair /*d*/ {
ab_pos sPosPair_First; /* first position in a sequence */
ab_pos sPosPair_Last; /* last position in a sequence */
};
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
AB_PUBLIC_API(char*) /* abtable.cpp */
AB_PosPair_AsXmlString(const AB_PosPair* self, char* outXmlBuf);
/* */
#endif /*AB_CONFIG_TRACE_orDEBUG_orPRINT*/
struct AB_PosRange /*d*/ {
ab_pos sPosRange_First; /* first position in a sequence */
ab_count sPosRange_Count; /* number of positions in sequence */
};
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
AB_PUBLIC_API(char*) /* abtable.cpp */
AB_PosRange_AsXmlString(const AB_PosRange* self, char* outXmlBuf);
/* */
#endif /*AB_CONFIG_TRACE_orDEBUG_orPRINT*/
/* ----- ----- ----- ----- Unique Ids ----- ----- ----- ----- */
#define AB_Bit_kTempBit ( 1 << 0 ) /* 2^0 bit: not persistent */
#define AB_Bit_kGlobalBit ( 1 << 1 ) /* 2^1 bit: global if also temp */
#define AB_Bit_kColumnBit ( 1 << 1 ) /* 2^1 bit: column if also persistent */
#define AB_Bit_kStandardBit ( 1 << 2 ) /* 2^2 bit: uid is standard constant */
#define AB_Uid_kGlobal ( AB_Bit_kGlobalBit | AB_Bit_kTempBit )
#define AB_Uid_kColumn AB_Bit_kColumnBit
#define AB_Uid_kPersistentRow 0
#define AB_Uid_kStandardColumn ( AB_Bit_kColumnBit | AB_Bit_kStandardBit )
#define AB_Uid_kTagBitCount 3
#define AB_Bit_kLowTwoBits 0x3
#define AB_Bit_kLowThreeBits 0x7
/*- These constants define bit patterns used to encode unique ids to
determine the purpose of a specific uids. Unique ids which are only
meaningful during a single session are called temporary or transient
(as opposed to persistent). Transient uids are to global tables and to
tables generated dynamically to describe the results of queries or
searches.
The column bit and the global bit are the same bit because there is no
overlap in practical usage, because columns are never transient, and
globals are always transient. (We want to use as few bits for encoding as
possible because this reserves most of the bits for a larger name space
for uids. Using only two bits leaves 30 bits for 2^30 distinct persistent
ids in a db.) -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
#define AB_Uid_IsTransient(uid) ((uid) & AB_Bit_kTempBit)
/*- IsTransientId indicates whether a uid is transient (not persistent)
withmeaning only during the current session. -*/
#define AB_Uid_IsGlobal(uid) (((uid) & AB_Bit_kLowTwoBits) == AB_Uid_kGlobal)
/*- IsGlobal indicates whether a uid is the transient uid assigned to a
globaltable for a personal address book or an LDAP directory. -*/
#define AB_Uid_IsPersistent(uid) (((uid) & AB_Bit_kTempBit) == 0)
/*- IsPersistent indicates whether a uid has meaning across multiple
sessions because a database persistently associates this uid with some
entity. -*/
#define AB_Uid_IsPersistentRow(uid) \
(((uid) & AB_Bit_kLowTwoBits) == AB_Uid_kPersistentRow)
#define AB_Uid_IsRow(uid) \
(((uid) & AB_Bit_kLowTwoBits) != AB_Uid_kColumn)
/*- IsRow indicates whether a uid denotes a row. This includes both
transient and persistent rows. Basically anything not a column is a row.
All tables are considered rows, including address books and directories. -*/
#define AB_Uid_IsColumn(uid) \
(((uid) & AB_Bit_kLowTwoBits) == AB_Uid_kColumn)
/*- IsColumn indicates whether a uid denotes a column. Column uids are
always peristent and have a non-overlapping scope only inside specific
address books. That is, all column uids for a given address book are
unique, but different address books can use the same column uids to
mean different column names. -*/
#define AB_Uid_IsStandard(uid) \
(((uid) & AB_Bit_kStandardBit) != 0)
#define AB_Uid_IsStandardColumn(uid) \
(((uid) & AB_Bit_kLowThreeBits) == AB_Uid_kStandardColumn)
#define AB_Attrib_AsStdColUid(attrib) \
(( ((ab_column_uid) attrib) << AB_Uid_kTagBitCount) | AB_Uid_kStandardColumn)
#define AB_ColumnUid_AsAttrib(uid) \
( (AB_Uid_IsStandard(uid))? ( (uid) >> AB_Uid_kTagBitCount ) : 0 )
#define AB_DbUid_AsColumnUid(uid) \
(( (uid) << AB_Uid_kTagBitCount) | AB_Uid_kColumn)
#define AB_ColumnUid_AsDbUid(uid) \
( (AB_Uid_IsColumn(uid))? ( (uid) >> AB_Uid_kTagBitCount ) : 0 )
#define AB_UidSeed_AsTempRowUid(uid) \
( ((uid) << AB_Uid_kTagBitCount) | AB_Bit_kTempBit )
#define AB_DbUid_AsRowUid(uid) \
( (uid) << AB_Uid_kTagBitCount )
#define AB_RowUid_AsDbUid(uid) \
( (AB_Uid_IsRow(uid))? ( (uid) >> AB_Uid_kTagBitCount ) : 0 )
#define AB_PersistentRowUid_AsDbUid(uid) \
( (AB_Uid_IsPersistentRow(uid))? ( (uid) >> AB_Uid_kTagBitCount ) : 0 )
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
typedef ab_num ab_cell_length; /* amount of cell content in AB_Row */
/*- This number characterizes the length of content bytes in a AB_Row,
buffered in memory, and is typically less than ab_cell_size. In other
words this is the length of content stored in memory, as opposed to the
extent (which is persistent content size). -*/
typedef ab_num ab_cell_extent; /* amount of cell content in table row */
/*- This number characterizes the persistent size of content in a row's
cell inside a table. This is the persistent idea content length but which
might be greater than ab_cell_length when a memory buffer is not big
enough to hold the persistent value. -*/
typedef ab_num ab_cell_size; /* bytes for a cell in row column */
/*- This number characterizes a number of bytes of space used to buffer a
row's cell value. This is independent of either length or extent. -*/
typedef ab_num ab_cell_count; /* number of cells in a row */
/*- This is a number of cells inside a row. -*/
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
/* ----- ----- ----- ----- Fault ----- ----- ----- ----- */
#define AB_Fault_kErrnoSpace /*i*/ 0x65526E4F /* ASCII 'eRnO' */
#define AB_Fault_kAbookSpace /*i*/ 0x61426752 /* ASCII 'aBgR' (no endian) */
/* AB_Fault structure and interface derive from public domain IronDoc */
struct AB_Fault /*d*/ {
ab_error_uid sFault_Code;
ab_u4 sFault_Space;
};
#define AB_Fault_Clear(f) /*i*/ \
((f)->sFault_Code = 0, (f)->sFault_Space = 0)
#define AB_Fault_Assign(e,other) /*i*/ (*(e) = *(other))
#define AB_Fault_Init(f,c,s) /*i*/ \
((f)->sFault_Code = (c), (f)->sFault_Space = (s))
#define AB_Fault_Code(f) /*i*/ ((f)->sFault_Code)
#define AB_Fault_Space(f) /*i*/ ((f)->sFault_Space)
enum AB_Fault_ePartition { /* number ranges for AB classes and features */
AB_Fault_kErrno = 0, /*i*/
AB_Fault_kErrno_end = 99, /*i*/
AB_Fault_kEnv = 100, /*i*/
AB_Fault_kEnv_end = 149, /*i*/
AB_Fault_kObject = 150, /*i*/
AB_Fault_kObject_end = 199, /*i*/
AB_Fault_kTable = 200, /*i*/
AB_Fault_kTable_end = 299, /*i*/
AB_Fault_kRow = 300, /*i*/
AB_Fault_kRow_end = 349, /*i*/
AB_Fault_kColumn = 350, /*i*/
AB_Fault_kColumn_end = 399, /*i*/
AB_Fault_kFile = 400, /*i*/
AB_Fault_kFile_end = 449, /*i*/
AB_Fault_kEntry = 450, /*i*/
AB_Fault_kEntry_end = 499, /*i*/
AB_Fault_kCell = 500, /*i*/
AB_Fault_kCell_end = 549, /*i*/
AB_Fault_kView = 550, /*i*/
AB_Fault_kView_end = 574, /*i*/
AB_Fault_kModel = 575, /*i*/
AB_Fault_kModel_end = 599, /*i*/
AB_Fault_kPort = 600, /*i*/
AB_Fault_kPort_end = 624, /*i*/
AB_Fault_kMap = 625, /*i*/
AB_Fault_kMap_end = 649, /*i*/
AB_Fault_kPart = 650, /*i*/
AB_Fault_kPart_end = 674, /*i*/
AB_Fault_kRowSet = 675, /*i*/
AB_Fault_kRowSet_end = 699, /*i*/
AB_Fault_kDebugger = 700, /*i*/
AB_Fault_kDebugger_end = 724, /*i*/
AB_Fault_kPrinter = 725, /*i*/
AB_Fault_kPrinter_end = 749, /*i*/
AB_Fault_kTracer = 750, /*i*/
AB_Fault_kTracer_end = 774, /*i*/
AB_Fault_kObjectSet = 775, /*i*/
AB_Fault_kObjectSet_end = 799, /*i*/
AB_Fault_kTuple = 800, /*i*/
AB_Fault_kTuple_end = 849, /*i*/
AB_Fault_kSearch = 850, /*i*/
AB_Fault_kSearch_end = 874, /*i*/
AB_Fault_kString = 875, /*i*/
AB_Fault_kString_end = 899, /*i*/
AB_Fault_kStore = 900, /*i*/
AB_Fault_kStore_end = 924, /*i*/
AB_Fault_kRowContent = 925, /*i*/
AB_Fault_kRowContent_end = 949 /*i*/
};
enum {
AB_Entry_kFaultDuplicateNickname = /*i*/ AB_Fault_kEntry, /* 450 */
AB_Entry_kFaultNotPersonType, /*i*/ /* 451 */
AB_Entry_kFaultNotListType, /*i*/ /* 452 */
AB_Entry_kFaultNotListOrPersonType, /*i*/ /* 453 */
AB_Entry_kFaultMissingGivenName, /*i*/ /* 454 */
AB_Entry_kFaultMissingEmailAddress, /*i*/ /* 455 */
AB_Entry_kFaultDuplicateEmail, /*i*/ /* 456 */
AB_Entry_kFaultNoSuchRowUid, /*i*/ /* 457 */
AB_Entry_kFaultNotFoundByIter, /*i*/ /* 458 */
AB_Entry_kFaultMissingFullName /*i*/ /* 459 */
};
AB_PUBLIC_API(const char*) /* abfault.c */
AB_Fault_String(const AB_Fault* self);
/* Return a static string describing error e, provided the space is equal
* to either AB_Fault_kErrnoSpace or AB_Fault_kAbookSpace,
* and provided AB_CONFIG_KNOW_FAULT_STRINGS is
* defined. Otherwise returns a static string for "{unknown-fault-space}"
* or for "{no-fault-strings}".
*/
#define AB_Fault_kXmlBufSize /*i*/ 128 /* size AB_Fault_AsXmlString() needs */
#if AB_CONFIG_TRACE_orDEBUG_orPRINT
AB_PUBLIC_API(char*) /* abfault.c */
AB_Fault_AsXmlString(const AB_Fault* self, AB_Env* ev, char* outXmlBuf);
/* */
#endif /* end AB_CONFIG_TRACE_orDEBUG_orPRINT*/
#ifdef AB_CONFIG_DEBUG
AB_PUBLIC_API(void) /* abfault.c */
AB_Fault_Break(const AB_Fault* self, AB_Env* ev);
/* e.g. AB_Env_Break(ev, AB_Fault_AsXmlString(self, ev, buf)); */
#endif /*AB_CONFIG_DEBUG*/
#ifdef AB_CONFIG_TRACE
AB_PUBLIC_API(void) /* abfault.c */
AB_Fault_Trace(const AB_Fault* eself, AB_Env* ev);
/* e.g. AB_Env_Trace(ev, AB_Fault_AsXmlString(self, ev, buf)); */
#endif /*AB_CONFIG_TRACE*/
/* ----- ----- ----- ----- Env ----- ----- ----- ----- */
#ifndef AB_Env_typedef
typedef struct AB_Env AB_Env;
#define AB_Env_typedef 1
#endif
#define AB_Env_kFormatBufferSize /*i*/ 512 /* for var arg format methods */
/* AB_Env structures and interfaces derive from public domain IronDoc */
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
enum AB_Policy_eImportConflicts {
AB_Policy_ImportConflicts_kUnknown = 0, /* need to call policy method */
AB_Policy_ImportConflicts_kSignalError, /* AB_Env_kFaultImportDuplicate */
AB_Policy_ImportConflicts_kIgnoreNewDuplicates, /* quietly ignore new */
AB_Policy_ImportConflicts_kReportAndIgnore, /* report, then ignore */
AB_Policy_ImportConflicts_kReplaceOldWithNew, /* use new entry defn */
AB_Policy_ImportConflicts_kReportAndReplace, /* report, then replace */
AB_Policy_ImportConflicts_kUpdateOldWithNew, /* merge new entry defn */
AB_Policy_ImportConflicts_kReportAndUpdate, /* report, then merge */
/* default: report conflicts (to file "ab.import.conflicts") and ignore */
AB_Policy_ImportConflicts_kDefault =
AB_Policy_ImportConflicts_kIgnoreNewDuplicates,
AB_Policy_ImportConflicts_kMax =
AB_Policy_ImportConflicts_kReportAndUpdate
};
#define AB_Env_kConflictReportFileNameSize 256 /* plus one byte for end null */
typedef ab_policy (* AB_Env_mImportConflictPolicy /*d*/)
(AB_Env* ev, char* outReportFileName256); /* only 255 bytes for file name */
struct AB_Env /*d*/ {
ab_num sEnv_FaultCount; /* total number of stored faults */
ab_bool sEnv_DoTrace;
ab_bool sEnv_DoDebug;
ab_bool sEnv_DoErrBreak;
ab_bool sEnv_BeParanoid;
/* ````` callbacks (slots similar to polymorphic object vtable) ````` */
AB_Env_mImportConflictPolicy sEnv_ImportConflictPolicy;
};
#define AB_Env_Good(ev) /*i*/ ((ev)->sEnv_FaultCount == 0)
#define AB_Env_Bad(ev) /*i*/ ((ev)->sEnv_FaultCount != 0)
#define AB_Env_DoTrace(ev) /*i*/ ((ev)->sEnv_DoTrace)
enum AB_Env_eError {
AB_Env_kFaultNullMethods = /*i*/ AB_Fault_kEnv, /* 100 null vtable pointer */
AB_Env_kFaultWrongMethodTag, /*i*/ /* 101 vtable tag is wrong */
AB_Env_kFaultNullCheckStack, /*i*/ /* 102 missing CheckStack() method */
AB_Env_kFaultNullFree, /*i*/ /* 103 missing Free() method */
AB_Env_kFaultNullForgetErrors, /*i*/ /* 104 missing ForgetErrors() method */
AB_Env_kFaultNullErrorCount, /*i*/ /* 105 missing ErrorCount() method */
AB_Env_kFaultNullGetError, /*i*/ /* 106 missing GetError() method */
AB_Env_kFaultNullGetAllErrors, /*i*/ /* 107 missing GetAllErrors() method */
AB_Env_kFaultNullNewFault, /*i*/ /* 108 missing NewFault() method */
AB_Env_kFaultNullBreakString, /*i*/ /* 109 missing NewFault() method */
AB_Env_kFaultNullTraceString, /*i*/ /* 110 missing NewFault() method */
AB_Env_kFaultZeroErrno, /*i*/ /* 111 errno is unexpectedly zero */
AB_Env_kFaultBrokenEndian, /*i*/ /* 112 bad number in endianess code */
AB_Env_kFaultMethodStubOnly, /*i*/ /* 113 method not implemented */
AB_Env_kFaultWrongTag, /*i*/ /* 114 method not implemented */
AB_Env_kFaultNullSelfHandle, /*i*/ /* 115 method not implemented */
AB_Env_kFaultOutOfMemory, /*i*/ /* 116 failed memory allocation */
AB_Env_kFaultImportDuplicate, /*i*/ /* 117 duplicate entry imported */
AB_Env_kFaultOddImportPolicy /*i*/ /* 118 unknown import polity */
};
/* ----- ----- polymorphic dispatching virtual methods ----- ----- */
#define AB_Table_MakeEnv AB_OBSOLETE_METHOD
/*- MakeEnv creates a new AB_Env instances that must be destroyed later
with AB_Env_Free(), unless the caller feels like leaking the env, which
might be okay if very few are ever created.
The frontend will not need more than one environment, but making more
won't hurt. They are all interchangeable. Each env returns error status
after methods return. -*/
/* ----- ----- creation / ref counting ----- ----- */
AB_PUBLIC_API(AB_Env*) /* abenv.cpp */
AB_Env_New();
AB_PUBLIC_API(AB_Env*) /* abenv.cpp */
AB_Env_GetLogFileEnv(); /* do *not* release this (unless you first acquire) */
AB_PUBLIC_API(ab_ref_count) /* abenv.cpp */
AB_Env_Acquire(AB_Env* self);
AB_PUBLIC_API(ab_ref_count) /* abenv.cpp */
AB_Env_Release(AB_Env* self);
/* ----- ----- error access ----- ----- */
AB_PUBLIC_API(ab_error_count) /* abenv.cpp */
AB_Env_ForgetErrors(AB_Env* self);
/*- Discard all error information. -*/
AB_PUBLIC_API(ab_error_count) /* abenv.cpp */
AB_Env_ErrorCount(const AB_Env* self);
/*- Number of errors since last forget/reset. -*/
AB_PUBLIC_API(ab_error_uid) /* abenv.cpp */
AB_Env_GetError(const AB_Env* self);
/*- Last error since forget/reset, otherwise zero. -*/
AB_PUBLIC_API(ab_error_count) /* abenv.cpp */
AB_Env_GetAllErrors(const AB_Env* self,
ab_error_uid* outVector, ab_error_count inSize,
ab_error_count* outLength);
/*- All errors (up to inSize) since forget/reset. -*/
AB_PUBLIC_API(ab_error_uid) /* abenv.cpp */
AB_Env_NewFault(AB_Env* ev, ab_error_uid faultCode, ab_u4 faultSpace);
/* ----- ----- static dispatching methods ----- ----- */
AB_PUBLIC_API(ab_error_uid) /* abenv.cpp */
AB_Env_NewAbookFault(AB_Env* ev, ab_error_uid faultCode);
AB_PUBLIC_API(void) /* abenv.cpp */
AB_Env_Break(AB_Env* ev, const char* format, ...);
AB_PUBLIC_API(void) /* abenv.cpp */
AB_Env_Trace(AB_Env* ev, const char* format, ...);
AB_PUBLIC_API(void) /* abenv.cpp */
AB_Env_TraceBeginMethod(const AB_Env* ev, const char* cls, const char* method);
AB_PUBLIC_API(void) /* abenv.cpp */
AB_Env_TraceEndMethod(const AB_Env* ev);
/* ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ */
#if defined(AB_CONFIG_TRACE_CALL_TREE) && AB_CONFIG_TRACE_CALL_TREE
#define AB_Env_BeginMethod(ev,c,m) /*i*/ \
{ if ( (ev)->sEnv_DoTrace ) AB_Env_TraceBeginMethod((ev), (c), (m)); } {
#define AB_Env_EndMethod(ev) /*i*/ \
} { if ( (ev)->sEnv_DoTrace ) AB_Env_TraceEndMethod(ev); }
#else /* end AB_CONFIG_TRACE_CALL_TREE*/
#define AB_Env_BeginMethod(ev,c,m)
#define AB_Env_EndMethod(ev)
#endif /* end AB_CONFIG_TRACE_CALL_TREE*/
/* ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ */
/* ----- ----- ----- ----- Async ----- ----- ----- ----- */
/*- We could arrange for AB_AsyncTask and AB_AsyncResult to be the
same object, but this causes interfaces that are less clear with respect to
cause an effect. -*/
#ifndef AB_AsyncTask_typedef
typedef struct AB_AsyncTask AB_AsyncTask;
#define AB_AsyncTask_typedef 1
#endif
/*- AB_AsyncTask is an abstract data type. You don't know its internal
structure. All that is known about this class is the methods that use this
type as an argument or return value.
AB_AsyncTask is a request to perform some operation asynchronously,
plus any information and callback hooks required to send progress
information and notifications to the task requestor. -*/
AB_PUBLIC_API(AB_AsyncResult*)
AB_AsyncTask_OpenTable(AB_AsyncTask* self, AB_Env* ev, DIR_Server* dir);
/*- OpenBook is an asynchronous version of AB_InitAddressBook(). -*/
#ifndef AB_AsyncResult_typedef
typedef struct AB_AsyncResult AB_AsyncResult;
#define AB_AsyncResult_typedef 1
#endif
/*- AB_AsyncResult is an abstract data type. You don't know its internal
structure. All that is known about this class is the methods that use this
type as an argument or return value.
AB_AsyncResult is a ticket (a task receipt) that allows a caller to
manipulate, examine, signal, etc. the asynchronous task assoociated
with an earlier task request (AB_AsyncTask). -*/
AB_PUBLIC_API(AB_Table*)
AB_AsyncResult_GetTable(AB_AsyncResult* self, AB_Env* ev);
/*- GetTable returns the table opened if ticket t was used in the call to
AB_Env_OpenTable(). This is a way of turning the OpenTable()
asynchronous call into a synchronous wait for the table to open. -*/
/* ----- ----- ----- ----- Tables ----- ----- ----- ----- */
#ifndef AB_Table_typedef
typedef struct AB_Table AB_Table;
#define AB_Table_typedef 1
#endif
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
typedef enum AB_Table_eError { /* AT_Table errors */
AB_Table_kFaultNullMethods = /*i*/ AB_Fault_kTable, /* 200 */
AB_Table_kFaultWrongMethodTag, /*i*/ /* 201 */
AB_Table_kFaultNullMakeEnv, /*i*/ /* 202 */
AB_Table_kFaultNullGetBookTable, /*i*/ /* 203 */
AB_Table_kFaultNullGetType, /*i*/ /* 204 */
AB_Table_kFaultNullGetTableRowUid, /*i*/ /* 205 */
AB_Table_kFaultNullGetRefCount, /*i*/ /* 206 */
AB_Table_kFaultNullAcquire, /*i*/ /* 207 */
AB_Table_kFaultNullRelease, /*i*/ /* 208 */
AB_Table_kFaultNullGetColumnName, /*i*/ /* 209 */
AB_Table_kFaultNullGetColumnId, /*i*/ /* 210 */
AB_Table_kFaultNullNewColumnId, /*i*/ /* 211 */
AB_Table_kFaultNullHasDisplayColumnProperty, /*i*/ /* 212 */
AB_Table_kFaultNullCountColumns, /*i*/ /* 213 */
AB_Table_kFaultNullGetColumnLayout, /*i*/ /* 214 */
AB_Table_kFaultNullGetDefaultLayout, /*i*/ /* 215 */
AB_Table_kFaultNullChangeColumnLayout, /*i*/ /* 216 */
AB_Table_kFaultNullGetColumnAt, /*i*/ /* 217 */
AB_Table_kFaultNullPutColumnAt, /*i*/ /* 218 */
AB_Table_kFaultNullAddColumnAt, /*i*/ /* 219 */
AB_Table_kFaultNullCutColumn, /*i*/ /* 220 */
AB_Table_kFaultNullCanSortByUid, /*i*/ /* 221 */
AB_Table_kFaultNullCanSortByName, /*i*/ /* 222 */
AB_Table_kFaultNullSortByUid, /*i*/ /* 223 */
AB_Table_kFaultNullSortByName, /*i*/ /* 224 */
AB_Table_kFaultNullGetSortColumn, /*i*/ /* 225 */
AB_Table_kFaultNullAcquireSortedTable, /*i*/ /* 226 */
AB_Table_kFaultNullAcquireSearchTable, /*i*/ /* 227 */
AB_Table_kFaultNullAddAllRows, /*i*/ /* 228 */
AB_Table_kFaultNullAddRow, /*i*/ /* 229 */
AB_Table_kFaultNullCutRow, /*i*/ /* 230 */
AB_Table_kFaultNullDestroyRow, /*i*/ /* 231 */
AB_Table_kFaultNullCountRows, /*i*/ /* 232 */
AB_Table_kFaultNullAcquireListsTable, /*i*/ /* 233 */
AB_Table_kFaultNullCountRowParents, /*i*/ /* 234 */
AB_Table_kFaultNullAcquireRowParentsTable, /*i*/ /* 235 */
AB_Table_kFaultNullCountRowChildren, /*i*/ /* 236 */
AB_Table_kFaultNullAcquireRowChildrenTable, /*i*/ /* 237 */
AB_Table_kFaultNullGetRowAt, /*i*/ /* 238 */
AB_Table_kFaultNullGetRows, /*i*/ /* 239 */
AB_Table_kFaultNullDoesSortRows, /*i*/ /* 240 */
AB_Table_kFaultNullRowPos, /*i*/ /* 241 */
AB_Table_kFaultNullChangeRowPos, /*i*/ /* 242 */
AB_Table_kFaultNullCountRowCells, /*i*/ /* 243 */
AB_Table_kFaultNullMakeDefaultRow, /*i*/ /* 244 */
AB_Table_kFaultNullMakeRow, /*i*/ /* 245 */
AB_Table_kFaultNullMakeRowFromColumns, /*i*/ /* 246 */
AB_Table_kFaultNullGetPersonCells, /*i*/ /* 247 */
AB_Table_kFaultNullGetListCells, /*i*/ /* 248 */
AB_Table_kFaultNullCutRowRange, /*i*/ /* 249 */
AB_Table_kFaultNullNewRowAt, /*i*/ /* 250 */
AB_Table_kFaultNullReadRowAt, /*i*/ /* 251 */
AB_Table_kFaultNullReadRow, /*i*/ /* 252 */
AB_Table_kFaultNullReadAllRowCells, /*i*/ /* 253 */
AB_Table_kFaultNullUpdateRow, /*i*/ /* 254 */
AB_Table_kFaultNullResetRow, /*i*/ /* 255 */
AB_Table_kFaultWrongBodyTag, /*i*/ /* 256 */
AB_Table_kFaultMiscTagTypeFailure, /*i*/ /* 257 */
AB_Table_kFaultWrongTag, /*i*/ /* 258 */
AB_Table_kFaultOutOfMemory, /*i*/ /* 259 */
AB_Table_kFaultMissingDeadTag, /*i*/ /* 260 */
AB_Table_kFaultBodyNotAvailable, /*i*/ /* 261 */
AB_Table_kFaultMissingContainerTable, /*i*/ /* 262 */
AB_Table_kFaultRowsNotSortable, /*i*/ /* 263 */
AB_Table_kFaultRowsNotSearchable, /*i*/ /* 264 */
AB_Table_kFaultNullDefaultsSlot, /*i*/ /* 265 */
AB_Table_kFaultNullNameSetSlot, /*i*/ /* 266 */
AB_Table_kFaultNullColumnSetSlot, /*i*/ /* 267 */
AB_Table_kFaultNullRowSetSlot, /*i*/ /* 268 */
AB_Table_kFaultNullRowContentSlot, /*i*/ /* 269 */
AB_Table_kFaultNotOpenTable, /*i*/ /* 270 */
AB_Table_kFaultUnknownStaticFail, /*i*/ /* 271 */
AB_Table_kFaultNullViewSlot /*i*/ /* 272 */
} AB_Table_eError;
/*#define AB_Table_kFaultNull Foo (AB_Fault_kTable + x)*/
/*- AB_Table is an abstract data type. You don't know its internal structure.
All that is known about this class is the methods that use this type as an
argument or return value. -*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_GetGlobalTable();
/*- GetGlobalTable returns a global table manager. All address book
content is part of this table. If there are multiple personal address books,
then each of these address books appears as one row inside this uber
table. Among other things, this interface unifies the appearance of per
address book properties, because address book properties are just values
appearing in the cells of columns for each.
(This global table can have a row describing itself, but this might be
sick.)
We could put LDAP directories into this table to unify directories and
address books. At least this would allow directories to be described by
propertries appearing in columns for each directory row. -*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_GetBookTable(const AB_Table* self, AB_Env* ev);
/*- GetBookTable returns the address book table containing this table. If
self is itself the address book then self is returned. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
typedef enum AB_Table_eType /*d*/ {
AB_Table_kNone = 0, /* row is not a table */
AB_Table_kGlobal = 1, /* see AB_GetGlobalTable() */
AB_Table_kAddressBook = 2, /* personal address book */
AB_Table_kDirectory = 3, /* LDAP directory */
AB_Table_kMailingList = 4, /* a mailing list entry */
AB_Table_kParentList = 5, /* all tables containing a table or row */
AB_Table_kListSubset = 6, /* row subset of lists only */
AB_Table_kSearchResult = 7, /* typedown or other search result */
AB_Table_kNumberOfTypes = 8 /* must be last of enums */
} AB_Table_eType;
AB_PUBLIC_API(AB_Table_eType) /* abtable.cpp */
AB_Table_GetType(AB_Table* self, AB_Env* ev);
/*- IsBookTable returns whether table t is an address book. -*/
AB_PUBLIC_API(ab_row_uid) /* abtable.cpp */
AB_Table_GetTableRowUid(AB_Table* self, AB_Env* ev);
/*- GetTableRowUid returns the row uid for table self. If self is a global
table (AB_Type_kGlobalTable, AB_GetGlobalTable()), then all such
global uid's are globally unique. If self is a list inside a p -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_ref_count) /* abtable.cpp */
AB_Table_GetRefCount(const AB_Table* self, AB_Env* ev);
/*- GetRefCount returns the current number of references to this table
instance in the current runtime session. This reference count is not
persistent. It only reflects the number of times that a table has been
acquired and not released. When a table is released enough times that it's
ref count becomes zero, then the table is deallocated.
Frontends might not need to deal with table reference counts. The
interface will try to be set up so this issue can be ignored as long as all
usage rules are followed. -*/
AB_PUBLIC_API(ab_ref_count) /* abtable.cpp */
AB_Table_Acquire(AB_Table* self, AB_Env* ev);
/*- Acquire increments the table's refcount. Perhaps frontends will never
need to do this. For example, this occurs automatically when a frontend
allocates a row by calling AB_Table_MakeRow(); -*/
AB_PUBLIC_API(ab_ref_count) /* abtable.cpp */
AB_Table_Release(AB_Table* self, AB_Env* ev);
/*- Release decrements the table's refcount. Perhaps frontends will never
need to do this. For example, this occurs automatically when a frontend
deallocates a row by calling AB_Row_Free(); -*/
AB_PUBLIC_API(void) /* abtable.cpp */
AB_Table_Close(AB_Table* self, AB_Env* ev);
/*- Close closes the table. -*/
/* ----- ----- ----- ----- Columns ----- ----- ----- ----- */
/*- (The notion of column replaces the old notion of token. A token
means something more general, but the previously described address
book model was only using tokens to descibe attribute names in
schemas, and in the table model these are just names of columns.) -*/
AB_PUBLIC_API(const char*) /* abtable.cpp */
AB_Table_GetColumnName(AB_Table* self, AB_Env* ev, ab_column_uid col);
/*- GetColumnName returns a constant string (do not modify or delete)
which is the string representation of col. A null pointer is returned if
this table does not know this given column uid.
The self table need not be the address book, but if not the address book
table will be looked up (with AB_Table_GetBookTable()) and this table
will be used instead. -*/
AB_PUBLIC_API(ab_column_uid) /* abtable.cpp */
AB_Table_GetColumnId(const AB_Table* self, AB_Env* ev, const char* name);
/*- GetColumnId returns the column id associated. A zero uid is returned if
this table does not know the given column name. This method must be
used instead of NewColumnId when the address book is readonly and
cannot be modified.
The self table need not be the address book, but if not the address book
table will be looked up (with AB_Table_GetBookTable()) and this table
will be used instead. -*/
AB_PUBLIC_API(ab_column_uid) /* abtable.cpp */
AB_Table_NewColumnId(AB_Table* self, AB_Env* ev, const char* name);
/*- NewColumnId is like GetColumnId except that if name is not
already known as a column in the address book, this method will modify
the address book and its table so that in the future name is known by
the persisent column uid returned. So a zero uid will not be returned
unless an error occurs.
The self table need not be the address book, but if not the address book
table will be looked up (with AB_Table_GetBookTable()) and this table
will be used instead. -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_HasDisplayColumnProperty(const AB_Table* self, AB_Env* ev);
/*- HasDisplayColumnProperty returns whether this table has its own
specialized property that configures which columns it will display. If
not, this table will default to using the columns for the containing
address book. This method allows inspection of whether this table has
overriden the address book defaults that will otherwise be used by the
various column methods defined on AB_Table. -*/
AB_PUBLIC_API(ab_column_count) /* abtable.cpp */
AB_Table_CountColumns(const AB_Table* self, AB_Env* ev);
/*- CountColumns returns the number of display columns for this table.
This is just a subset of information returned by GetColumns. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
#ifndef AB_Column_typedef
typedef struct AB_Column AB_Column;
#define AB_Column_typedef 1
#endif
struct AB_Column {
const char* sColumn_Name; /* the "real" name of this column */
const char* sColumn_DisplayName; /* display name for column if non-null */
ab_column_uid sColumn_Uid; /* the uid for sColumn_Name if nonzero */
ab_column_uid sColumn_SecondSort; /* if non-zero, secondary sort attribute */
ab_cell_size sColumn_CellSize; /* size of row cells for this column */
ab_bool sColumn_CanSort; /* the table can sort by this column */
};
enum {
AB_Column_kFaultNotStandardName = /*i*/ AB_Fault_kColumn, /* 400 */
AB_Column_kFaultNotStandardUid, /*i*/ /* 401 */
AB_Column_kFaultNotColumnUid, /*i*/ /* 402 */
AB_Column_kFaultSortNotSupported, /*i*/ /* 403 */
AB_Column_kFaultColumnUidTooLarge /*i*/ /* 404 */
};
/* You *cannot* change following enum names or values. So comments containing
** the numbers will never need different numbers, so you'll never experience
** the tedium of changing the comment numbers. The enum names and column
** name strings should have exactly the same (case independent) letters.
**
** So if you feel compelled to change column names, by all means do so, but
** add a new enum with the new column name, and *do not change existing enums*
** either by name or numerical value. Just stop using old standard columns
** if you don't want to use them.
**
** Don't even bother changing the white space that groups names five at a
** time, since grouping no longer matters as much as not moving names. This
** enum represents a pre-tokenized standard name table, and the names and
** tokens cannot be changed without breaking the table.
*/
typedef enum {
AB_Attrib_kIsPerson = 0, /* 00 - "isperson" (t or f) */
AB_Attrib_kModTime, /* 01 - "modtime" */
AB_Attrib_kFullName, /* 02 - "fullname" */
AB_Attrib_kNickname, /* 03 - "nickname" */
AB_Attrib_kMiddleName, /* 04 - "middlename" */
AB_Attrib_kFamilyName, /* 05 - "familyname" */
AB_Attrib_kCompanyName, /* 06 - "companyname" */
AB_Attrib_kRegion, /* 07 - "region" */
AB_Attrib_kEmail, /* 08 - "email" */
AB_Attrib_kInfo, /* 09 - "info" */
AB_Attrib_kHtmlMail, /* 10 - "htmlmail" (t or f) */
AB_Attrib_kExpandedName, /* 11 - "expandedname" */
AB_Attrib_kTitle, /* 12 - "title" */
AB_Attrib_kAddress, /* 13 - "address" */
AB_Attrib_kZip, /* 14 - "zip" */
AB_Attrib_kCountry, /* 15 - "country" */
AB_Attrib_kWorkPhone, /* 16 - "workphone" */
AB_Attrib_kHomePhone, /* 17 - "homephone" */
AB_Attrib_kSecurity, /* 18 - "security" */
AB_Attrib_kCoolAddress, /* 19 - "cooladdress" (conference related) */
AB_Attrib_kUseServer, /* 20 - "useserver" (conference related) */
AB_Attrib_kPager, /* 21 - "pager" */
AB_Attrib_kFax, /* 22 - "fax" */
AB_Attrib_kDisplayName, /* 23 - "displayname" */
AB_Attrib_kSender, /* 24 - "sender" (mail and news) */
AB_Attrib_kSubject, /* 25 - "subject" */
AB_Attrib_kBody, /* 26 - "body" */
AB_Attrib_kDate, /* 27 - "date" */
AB_Attrib_kPriority, /* 28 - "priority" (mail only) */
AB_Attrib_kMsgStatus, /* 29 - "msgstatus" */
AB_Attrib_kTo, /* 30 - "to" */
AB_Attrib_kCC, /* 31 - "cc" */
AB_Attrib_kToOrCC, /* 32 - "toorcc" */
AB_Attrib_kCommonName, /* 33 - "commonname" (LDAP only) */
AB_Attrib_k822Address, /* 34 - "822address" */
AB_Attrib_kPhoneNumber, /* 35 - "phonenumber" */
AB_Attrib_kOrganization, /* 36 - "organization" */
AB_Attrib_kOrgUnit, /* 37 - "orgunit" */
AB_Attrib_kLocality, /* 38 - "locality" */
AB_Attrib_kStreetAddress, /* 39 - "streetaddress" */
AB_Attrib_kSize, /* 40 - "size" */
AB_Attrib_kAnyText, /* 41 - "anytext" (any header or body) */
AB_Attrib_kKeywords, /* 42 - "keywords" */
AB_Attrib_kDistName, /* 43 - "distname" (distinguished name) */
AB_Attrib_kObjectClass, /* 44 - "objectclass" */
AB_Attrib_kJpegFile, /* 45 - "jpegfile" */
AB_Attrib_kLocation, /* 46 - "location" (result list only */
AB_Attrib_kMessageKey, /* 47 - "messagekey" (message result elems) */
AB_Attrib_kAgeInDays, /* 48 - "ageindays" (purging old news) */
AB_Attrib_kGivenName, /* 49 - "givenname" (sorting LDAP results) */
AB_Attrib_kSurname, /* 50 - "surname" */
AB_Attrib_kFolderInfo, /* 51 - "folderinfo" (view thread context) */
AB_Attrib_kCustom1, /* 52 - "custom1" (custom LDAP attribs) */
AB_Attrib_kCustom2, /* 53 - "custom2" */
AB_Attrib_kCustom3, /* 54 - "custom3" */
AB_Attrib_kCustom4, /* 55 - "custom4" */
AB_Attrib_kCustom5, /* 56 - "custom5" */
AB_Attrib_kMessageId, /* 57 - "messageid" */
AB_Attrib_kHomeUrl, /* 58 - "homeurl" */
AB_Attrib_kWorkUrl, /* 59 - "workurl" */
AB_Attrib_kImapUrl, /* 60 - "imapurl" */
AB_Attrib_kNotifyUrl, /* 61 - "notifyurl" */
AB_Attrib_kPrefUrl, /* 62 - "prefurl" */
AB_Attrib_kPagerEmail, /* 63 - "pageremail" */
AB_Attrib_kParentPhone, /* 64 - "parentphone" */
AB_Attrib_kGender, /* 65 - "gender" */
AB_Attrib_kPostalAddress, /* 66 - "postaladdress" */
AB_Attrib_kEmployeeId, /* 67 - "employeeid" */
AB_Attrib_kAgent, /* 68 - "agent" */
AB_Attrib_kBbs, /* 69 - "bbs" */
AB_Attrib_kBday, /* 70 - "bday" (birthdate) */
AB_Attrib_kCalendar, /* 71 - "calendar" */
AB_Attrib_kCar, /* 72 - "car" */
AB_Attrib_kCarPhone, /* 73 - "carphone" */
AB_Attrib_kCategories, /* 74 - "categories" */
AB_Attrib_kCell, /* 75 - "cell" */
AB_Attrib_kCellPhone, /* 76 - "cellphone" */
AB_Attrib_kCharSet, /* 77 - "charset" (cs, csid) */
AB_Attrib_kClass, /* 78 - "class" */
AB_Attrib_kGeo, /* 79 - "geo" */
AB_Attrib_kGif, /* 80 - "gif" */
AB_Attrib_kKey, /* 81 - "key" (publickey) */
AB_Attrib_kLanguage, /* 82 - "language" */
AB_Attrib_kLogo, /* 83 - "logo" */
AB_Attrib_kModem, /* 84 - "modem" */
AB_Attrib_kMsgPhone, /* 85 - "msgphone" */
AB_Attrib_kN, /* 86 - "n" */
AB_Attrib_kNote, /* 87 - "note" */
AB_Attrib_kPagerPhone, /* 88 - "pagerphone" */
AB_Attrib_kPgp, /* 89 - "pgp" */
AB_Attrib_kPhoto, /* 90 - "photo" */
AB_Attrib_kRev, /* 91 - "rev" */
AB_Attrib_kRole, /* 92 - "role" */
AB_Attrib_kSound, /* 93 - "sound" */
AB_Attrib_kSortString, /* 94 - "sortstring" */
AB_Attrib_kTiff, /* 95 - "tiff" */
AB_Attrib_kTz, /* 96 - "tz" (timezone) */
AB_Attrib_kUid, /* 97 - "uid" (uniqueid) */
AB_Attrib_kVersion, /* 98 - "version" */
AB_Attrib_kVoice, /* 99 - "voice" */
AB_Attrib_kNumColumnAttributes /* 100 - must be last enum value listed */
} AB_Column_eAttribute;
/*3456789_123456789_123456789_123456789_123456789_123456789_123456789_12345678*/
typedef enum AB_Column_eDefaultSizes { /* defaults for new row cell sizes */
AB_Column_kSize_IsPerson = 4,
AB_Column_kSize_ModTime = 18,
AB_Column_kSize_FullName = 256,
AB_Column_kSize_Nickname = 64,
AB_Column_kSize_MiddleName = 64,
AB_Column_kSize_FamilyName = 64,
AB_Column_kSize_CompanyName = 128,
AB_Column_kSize_Region = 128,
AB_Column_kSize_Email = 256,
AB_Column_kSize_Info = 1024,
AB_Column_kSize_HtmlMail = 8,
AB_Column_kSize_ExpandedName = 256,
AB_Column_kSize_Title = 64,
AB_Column_kSize_Address = 256,
AB_Column_kSize_Zip = 48,
AB_Column_kSize_Country = 48,
AB_Column_kSize_WorkPhone = 48,
AB_Column_kSize_HomePhone = 48,
AB_Column_kSize_Security = 16,
AB_Column_kSize_CoolAddress = 256,
AB_Column_kSize_UseServer = 16,
AB_Column_kSize_Pager = 48,
AB_Column_kSize_Fax = 48,
AB_Column_kSize_DisplayName = 64,
AB_Column_kSize_Sender = 128,
AB_Column_kSize_Subject = 256,
AB_Column_kSize_Body = 1024,
AB_Column_kSize_Date = 64,
AB_Column_kSize_Priority = 32,
AB_Column_kSize_MsgStatus = 32,
AB_Column_kSize_To = 256,
AB_Column_kSize_CC = 256,
AB_Column_kSize_ToOrCC = 256,
AB_Column_kSize_CommonName = 256,
AB_Column_kSize_822Address = 256,
AB_Column_kSize_PhoneNumber = 64,
AB_Column_kSize_Organization = 128,
AB_Column_kSize_OrgUnit = 64,
AB_Column_kSize_Locality = 128,
AB_Column_kSize_StreetAddress = 256,
AB_Column_kSize_Size = 32,
AB_Column_kSize_AnyText = 256,
AB_Column_kSize_Keywords = 256,
AB_Column_kMaxSize_DistName = (32 * 1024),
AB_Column_kSize_DistName = 512,
AB_Column_kSize_ObjectClass = 32,
AB_Column_kSize_JpegFile = 1024,
AB_Column_kSize_Location = 64,
AB_Column_kSize_MessageKey = 32,
AB_Column_kSize_AgeInDays = 16,
AB_Column_kSize_GivenName = 64,
AB_Column_kSize_Surname = 64,
AB_Column_kSize_FolderInfo = 256,
AB_Column_kSize_Custom1 = 64,
AB_Column_kSize_Custom2 = 64,
AB_Column_kSize_Custom3 = 64,
AB_Column_kSize_Custom4 = 64,
AB_Column_kSize_Custom5 = 64,
AB_Column_kSize_MessageId = 32,
AB_Column_kSize_HomeUrl = 128,
AB_Column_kSize_WorkUrl = 128,
AB_Column_kSize_ImapUrl = 128,
AB_Column_kSize_NotifyUrl = 128,
AB_Column_kSize_PrefUrl = 128,
AB_Column_kSize_PagerEmail = 48,
AB_Column_kSize_ParentPhone = 48,
AB_Column_kSize_Gender = 16,
AB_Column_kSize_PostalAddress = 128,
AB_Column_kSize_EmployeeId = 32,
AB_Column_kSize_Agent = 128,
AB_Column_kSize_Bbs = 48,
AB_Column_kSize_Bday = 32,
AB_Column_kSize_Calendar = 256,
AB_Column_kSize_Car = 48,
AB_Column_kSize_CarPhone = 48,
AB_Column_kSize_Categories = 64,
AB_Column_kSize_Cell = 48,
AB_Column_kSize_CellPhone = 48,
AB_Column_kSize_CharSet = 16,
AB_Column_kSize_Class = 64,
AB_Column_kSize_Geo = 256,
AB_Column_kSize_Gif = 1024,
AB_Column_kSize_Key = 256,
AB_Column_kSize_Language = 64,
AB_Column_kSize_Logo = 1024,
AB_Column_kSize_Modem = 48,
AB_Column_kSize_MsgPhone = 48,
AB_Column_kSize_N = 256,
AB_Column_kSize_Note = 512,
AB_Column_kSize_PagerPhone = 48,
AB_Column_kSize_Pgp = 512,
AB_Column_kSize_Photo = 1024,
AB_Column_kSize_Rev = 128,
AB_Column_kSize_Role = 64,
AB_Column_kSize_Sound = 1024,
AB_Column_kSize_SortString = 64,
AB_Column_kSize_Tiff = 1024,
AB_Column_kSize_Tz = 64,
AB_Column_kSize_Uid = 128,
AB_Column_kSize_Version = 64,
AB_Column_kSize_Voice = 48
} AB_Column_eDefaultSizes;
typedef enum AB_Column_eUid {
AB_Column_kIsPerson = AB_Attrib_AsStdColUid(AB_Attrib_kIsPerson),
AB_Column_kModTime = AB_Attrib_AsStdColUid(AB_Attrib_kModTime),
AB_Column_kFullName = AB_Attrib_AsStdColUid(AB_Attrib_kFullName),
AB_Column_kNickname = AB_Attrib_AsStdColUid(AB_Attrib_kNickname),
AB_Column_kMiddleName = AB_Attrib_AsStdColUid(AB_Attrib_kMiddleName),
AB_Column_kFamilyName = AB_Attrib_AsStdColUid(AB_Attrib_kFamilyName),
AB_Column_kCompanyName = AB_Attrib_AsStdColUid(AB_Attrib_kCompanyName),
AB_Column_kRegion = AB_Attrib_AsStdColUid(AB_Attrib_kRegion),
AB_Column_kEmail = AB_Attrib_AsStdColUid(AB_Attrib_kEmail),
AB_Column_kInfo = AB_Attrib_AsStdColUid(AB_Attrib_kInfo),
AB_Column_kHtmlMail = AB_Attrib_AsStdColUid(AB_Attrib_kHtmlMail),
AB_Column_kExpandedName = AB_Attrib_AsStdColUid(AB_Attrib_kExpandedName),
AB_Column_kTitle = AB_Attrib_AsStdColUid(AB_Attrib_kTitle),
AB_Column_kAddress = AB_Attrib_AsStdColUid(AB_Attrib_kAddress),
AB_Column_kZip = AB_Attrib_AsStdColUid(AB_Attrib_kZip),
AB_Column_kCountry = AB_Attrib_AsStdColUid(AB_Attrib_kCountry),
AB_Column_kWorkPhone = AB_Attrib_AsStdColUid(AB_Attrib_kWorkPhone),
AB_Column_kHomePhone = AB_Attrib_AsStdColUid(AB_Attrib_kHomePhone),
AB_Column_kSecurity = AB_Attrib_AsStdColUid(AB_Attrib_kSecurity),
AB_Column_kCoolAddress = AB_Attrib_AsStdColUid(AB_Attrib_kCoolAddress),
AB_Column_kUseServer = AB_Attrib_AsStdColUid(AB_Attrib_kUseServer),
AB_Column_kPager = AB_Attrib_AsStdColUid(AB_Attrib_kPager),
AB_Column_kFax = AB_Attrib_AsStdColUid(AB_Attrib_kFax),
AB_Column_kDisplayName = AB_Attrib_AsStdColUid(AB_Attrib_kDisplayName),
AB_Column_kSender = AB_Attrib_AsStdColUid(AB_Attrib_kSender),
AB_Column_kSubject = AB_Attrib_AsStdColUid(AB_Attrib_kSubject),
AB_Column_kBody = AB_Attrib_AsStdColUid(AB_Attrib_kBody),
AB_Column_kDate = AB_Attrib_AsStdColUid(AB_Attrib_kDate),
AB_Column_kPriority = AB_Attrib_AsStdColUid(AB_Attrib_kPriority),
AB_Column_kMsgStatus = AB_Attrib_AsStdColUid(AB_Attrib_kMsgStatus),
AB_Column_kTo = AB_Attrib_AsStdColUid(AB_Attrib_kTo),
AB_Column_kCC = AB_Attrib_AsStdColUid(AB_Attrib_kCC),
AB_Column_kToOrCC = AB_Attrib_AsStdColUid(AB_Attrib_kToOrCC),
AB_Column_kCommonName = AB_Attrib_AsStdColUid(AB_Attrib_kCommonName),
AB_Column_k822Address = AB_Attrib_AsStdColUid(AB_Attrib_k822Address),
AB_Column_kPhoneNumber = AB_Attrib_AsStdColUid(AB_Attrib_kPhoneNumber),
AB_Column_kOrganization = AB_Attrib_AsStdColUid(AB_Attrib_kOrganization),
AB_Column_kOrgUnit = AB_Attrib_AsStdColUid(AB_Attrib_kOrgUnit),
AB_Column_kLocality = AB_Attrib_AsStdColUid(AB_Attrib_kLocality),
AB_Column_kStreetAddress = AB_Attrib_AsStdColUid(AB_Attrib_kStreetAddress),
AB_Column_kSize = AB_Attrib_AsStdColUid(AB_Attrib_kSize),
AB_Column_kAnyText = AB_Attrib_AsStdColUid(AB_Attrib_kAnyText),
AB_Column_kKeywords = AB_Attrib_AsStdColUid(AB_Attrib_kKeywords),
AB_Column_kDistName = AB_Attrib_AsStdColUid(AB_Attrib_kDistName),
AB_Column_kObjectClass = AB_Attrib_AsStdColUid(AB_Attrib_kObjectClass),
AB_Column_kJpegFile = AB_Attrib_AsStdColUid(AB_Attrib_kJpegFile),
AB_Column_kLocation = AB_Attrib_AsStdColUid(AB_Attrib_kLocation),
AB_Column_kMessageKey = AB_Attrib_AsStdColUid(AB_Attrib_kMessageKey),
AB_Column_kAgeInDays = AB_Attrib_AsStdColUid(AB_Attrib_kAgeInDays),
AB_Column_kGivenName = AB_Attrib_AsStdColUid(AB_Attrib_kGivenName),
AB_Column_kSurname = AB_Attrib_AsStdColUid(AB_Attrib_kSurname),
AB_Column_kFolderInfo = AB_Attrib_AsStdColUid(AB_Attrib_kFolderInfo),
AB_Column_kCustom1 = AB_Attrib_AsStdColUid(AB_Attrib_kCustom1),
AB_Column_kCustom2 = AB_Attrib_AsStdColUid(AB_Attrib_kCustom2),
AB_Column_kCustom3 = AB_Attrib_AsStdColUid(AB_Attrib_kCustom3),
AB_Column_kCustom4 = AB_Attrib_AsStdColUid(AB_Attrib_kCustom4),
AB_Column_kCustom5 = AB_Attrib_AsStdColUid(AB_Attrib_kCustom5),
AB_Column_kMessageId = AB_Attrib_AsStdColUid(AB_Attrib_kMessageId),
AB_Column_kHomeUrl = AB_Attrib_AsStdColUid(AB_Attrib_kHomeUrl),
AB_Column_kWorkUrl = AB_Attrib_AsStdColUid(AB_Attrib_kWorkUrl),
AB_Column_kImapUrl = AB_Attrib_AsStdColUid(AB_Attrib_kImapUrl),
AB_Column_kNotifyUrl = AB_Attrib_AsStdColUid(AB_Attrib_kNotifyUrl),
AB_Column_kPrefUrl = AB_Attrib_AsStdColUid(AB_Attrib_kPrefUrl),
AB_Column_kPagerEmail = AB_Attrib_AsStdColUid(AB_Attrib_kPagerEmail),
AB_Column_kParentPhone = AB_Attrib_AsStdColUid(AB_Attrib_kParentPhone),
AB_Column_kGender = AB_Attrib_AsStdColUid(AB_Attrib_kGender),
AB_Column_kPostalAddress = AB_Attrib_AsStdColUid(AB_Attrib_kPostalAddress),
AB_Column_kEmployeeId = AB_Attrib_AsStdColUid(AB_Attrib_kEmployeeId),
AB_Column_kAgent = AB_Attrib_AsStdColUid(AB_Attrib_kAgent),
AB_Column_kBbs = AB_Attrib_AsStdColUid(AB_Attrib_kBbs),
AB_Column_kBday = AB_Attrib_AsStdColUid(AB_Attrib_kBday),
AB_Column_kCalendar = AB_Attrib_AsStdColUid(AB_Attrib_kCalendar),
AB_Column_kCar = AB_Attrib_AsStdColUid(AB_Attrib_kCar),
AB_Column_kCarPhone = AB_Attrib_AsStdColUid(AB_Attrib_kCarPhone),
AB_Column_kCategories = AB_Attrib_AsStdColUid(AB_Attrib_kCategories),
AB_Column_kCell = AB_Attrib_AsStdColUid(AB_Attrib_kCell),
AB_Column_kCellPhone = AB_Attrib_AsStdColUid(AB_Attrib_kCellPhone),
AB_Column_kCharSet = AB_Attrib_AsStdColUid(AB_Attrib_kCharSet),
AB_Column_kClass = AB_Attrib_AsStdColUid(AB_Attrib_kClass),
AB_Column_kGeo = AB_Attrib_AsStdColUid(AB_Attrib_kGeo),
AB_Column_kGif = AB_Attrib_AsStdColUid(AB_Attrib_kGif),
AB_Column_kKey = AB_Attrib_AsStdColUid(AB_Attrib_kKey),
AB_Column_kLanguage = AB_Attrib_AsStdColUid(AB_Attrib_kLanguage),
AB_Column_kLogo = AB_Attrib_AsStdColUid(AB_Attrib_kLogo),
AB_Column_kModem = AB_Attrib_AsStdColUid(AB_Attrib_kModem),
AB_Column_kMsgPhone = AB_Attrib_AsStdColUid(AB_Attrib_kMsgPhone),
AB_Column_kN = AB_Attrib_AsStdColUid(AB_Attrib_kN),
AB_Column_kNote = AB_Attrib_AsStdColUid(AB_Attrib_kNote),
AB_Column_kPagerPhone = AB_Attrib_AsStdColUid(AB_Attrib_kPagerPhone),
AB_Column_kPgp = AB_Attrib_AsStdColUid(AB_Attrib_kPgp),
AB_Column_kPhoto = AB_Attrib_AsStdColUid(AB_Attrib_kPhoto),
AB_Column_kRev = AB_Attrib_AsStdColUid(AB_Attrib_kRev),
AB_Column_kRole = AB_Attrib_AsStdColUid(AB_Attrib_kRole),
AB_Column_kSound = AB_Attrib_AsStdColUid(AB_Attrib_kSound),
AB_Column_kSortString = AB_Attrib_AsStdColUid(AB_Attrib_kSortString),
AB_Column_kTiff = AB_Attrib_AsStdColUid(AB_Attrib_kTiff),
AB_Column_kTz = AB_Attrib_AsStdColUid(AB_Attrib_kTz),
AB_Column_kUid = AB_Attrib_AsStdColUid(AB_Attrib_kUid),
AB_Column_kVersion = AB_Attrib_AsStdColUid(AB_Attrib_kVersion),
AB_Column_kVoice = AB_Attrib_AsStdColUid(AB_Attrib_kVoice)
} AB_Column_eUid;
AB_PUBLIC_API(const char*) /* abcolumn.c */
AB_ColumnUid_AsString(ab_column_uid inStandardColumnUid, AB_Env* ev);
AB_PUBLIC_API(ab_column_uid) /* abcolumn.c */
AB_String_AsStandardColumnUid(const char* inStandardColumnName, AB_Env* ev);
AB_PUBLIC_API(ab_column_count) /* abtable.cpp */
AB_Table_GetColumnLayout(const AB_Table* self, AB_Env* ev,
AB_Column* outVector, ab_column_count inSize,
ab_column_count* outLength);
/*- GetColumnLayout fills the vector of AB_Column instances with
descriptions of the column layout for this table. (If this table does not
override settings from the address book, then this is the same as the
address book column layout.)
Note that columns described by GetColumnLayout are the default
columns added to AB_Row instances created by
AB_Table_MakeDefaultRow().
The outVector out parameter must be an array of at least inSize
AB_Column instances, but preferrably AB_Table_CountColumns() plus
one, because given enough instances the last column will be null
terminated by means of a zero pointer written in the sColumn_Name slot.
The actual number of columns (exactly equal to
AB_Table_CountColumns()) is returned from the method as the function
value. The number of columns actually described in outVector is
returned in outLength, and this is the same as the method value only
when inSize is greater than AB_Table_CountColumns(). If inSize is
greater than AB_Table_CountColumns(), then the column after the last
one described is null terminated with zero in the sColumn_Name slot.
Each column in the layout is described as follows. sColumn_Uid gets a
copy of the column uid returned from AB_Table_GetColumnId() for the
name written in sColumn_Name.
sColumn_Name gets a copy of the column name returned from
AB_Table_GetColumnName(). Callers must not modify or delete these
name strings, because these pointers are aliases to strings stored in a
dictionary within the self table instance, and modifying the strings
might have catastrophic effect.
sColumn_PrettyName gets either a null pointer (when the pretty name
and the real name are identical), or a string different from sColumn_Name
which the user prefers to see in the table display. Like sColumn_Name,
the storage for this string also belongs to self and must not be
modified, on pain of potential catastrophic effect.
sColumn_CanSort gets a boolean indicating whether the table can be
sorted by the column named by sColumn_Name. -*/
AB_PUBLIC_API(ab_column_count) /* abtable.cpp */
AB_Table_GetDefaultLayout(const AB_Table* self, AB_Env* ev,
AB_Column* outVector, ab_column_count inSize,
ab_column_count* outLength);
/*- GetDefaultLayout is nearly the same as
AB_Table_GetColumnLayout() except it returns the default layout used
for a new address book table, as opposed to a specific layour currently
in use by either this table or the actual address book table containing this
table. -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_ChangeColumnLayout(AB_Table* self, AB_Env* ev,
const AB_Column* inVector, ab_bool changeIndex);
/*- ChangeColumnLayout modifies the column layout of this table to be
equal to whatever is described in inVector, which must be null
terminated by means of a zero pointer in the final sColumn_Name slot of
the last column instance.
Note changing table columns will change the default set of columns
added to AB_Row instances created by subsequent calls to
AB_Table_MakeDefaultRow().
If changing the column layout implies a change of address book indexes,
then changeIndex must be true in order to actually cause this change to
occur, because removing an index can be a very expensive (slow)
operation. (We'll add asynchronous versions of this later.) -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_GetColumnAt(const AB_Table* self, AB_Env* ev,
AB_Column* outColumn, ab_column_pos inColPos);
/*- GetColumnAt gets the table's column layout information from column
position pos, which must be a one-based index from one to
AB_Table_CountColumns() (or otherwise false is returned and nothing
happens to the col parameter). -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_PutColumnAt(const AB_Table* self, AB_Env* ev,
const AB_Column* col, ab_column_pos pos, ab_bool changeIndex);
/*- PutColumnAt overwrites the table's column layout information at
column position pos, which must be a one-based index from one to
AB_Table_CountColumns() (or otherwise false is returned and nothing
happens to the table's column layout).
If the column named (sColumnName) already occurs at some other
position in the layout, then an error occurs. Otherwise the existing
column at pos is changed to col.
If the value of sColumn_CanSort implies a change of address book
indexes, then changeIndex must be true in order to actually cause this
change to occur, because adding or removing an index can be a very
expensive (slow) operation. (We'll add asynchronous versions of this
later.) -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_AddColumnAt(const AB_Table* self, AB_Env* ev,
const AB_Column* col, ab_column_pos pos, ab_bool changeIndex);
/*- AddColumnAt inserts new table column layout information at column
position pos, which must be a one-based index from one to
AB_Table_CountColumns() plus one (or otherwise false is returned and
nothing happens to the table's column layout).
If the column named (sColumnName) already occurs at some other
position in the layout, then an error occurs. Otherwise a new column at
pos is inserted in the layout.
If the value of sColumn_CanSort implies a change of address book
indexes, then changeIndex must be true in order to actually cause this
change to occur, because adding an index can be a very expensive
(slow) operation. (We'll add asynchronous versions of this later.) -*/
AB_PUBLIC_API(ab_column_pos) /* abtable.cpp */
AB_Table_CutColumn(const AB_Table* self, AB_Env* ev,
ab_column_uid col, ab_bool changeIndex);
/*- CutColumn removes an old column from the table column layout. The
col parameter must name a column currently in the layout (or otherwise
false is returned and nothing happens to the table's column layout).
If removing the column implies a change of address book indexes, then
changeIndex must be true in order to actually cause this change to
occur, because removing an index can be a very expensive (slow)
operation. (We'll add asynchronous versions of this later.) -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_CanSortByUid(const AB_Table* self, AB_Env* ev, ab_column_uid col);
/*- CanSortByUid indicates whether this table can sort rows by the
specified column uid col. Frontends might prefer to call
CanSortByName. -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_CanSortByName(const AB_Table* self, AB_Env* ev, const char* name);
/*- CanSortByName indicates whether this table can sort rows by the
specified column name.
CanSortByName is implemented by calling
AB_Table_CanSortByUid(self, ev,
AB_Table_GetColumnId(self, ev, name)); -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_SortByUid(const AB_Table* self, AB_Env* ev, ab_column_uid col);
/*- SortByUid sorts this table by the specified column col. If col is zero
this means make the table unsorted, which causes the table to order rows
in the most convenient internal form (which is by row uid for address
books, and some user specified order for mailing lists). -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_SortByName(const AB_Table* self, AB_Env* ev, const char* name);
/*- SortByName sorts this table by the specified column name. The
name parameter can be null, and this means make the table unsorted
(with respect to specific cell values). Making a table unsorted makes
particular sense for mailing lists.
SortByName is implemented by calling
AB_Table_SortByUid(self, ev, AB_Table_GetColumnId(self,
ev, name)); -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_SortFoward(const AB_Table* self, AB_Env* ev, ab_bool inAscend);
/*- If inAscend is true, arrange sorted rows in ascending order,
and otherwise arrange sorted rows in descending order -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_GetSortFoward(const AB_Table* self, AB_Env* ev);
/*- Return whether rows are arranged in ascending order -*/
AB_PUBLIC_API(ab_column_uid) /* abtable.cpp */
AB_Table_GetSortColumn(const AB_Table* self, AB_Env* ev);
/*- GetSortColumn returns the column currently used by the table for
sorting. Zero is returned when this table is currently unsorted (and also
when any error occurs). Unsorted tables might be common for mailing
lists. -*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_AcquireSortedTable(AB_Table* self, AB_Env* ev,
ab_column_uid newSortColumn);
/*- AcquireSortedTable returns a new table instance that has the same
content as the old table, but sorts on a different column. This is similar
to AB_Table_SortByUid(), but lets one have two different views of the
same table with different sortings.
If newSortColumn is zero this means return an unsorted table. If
newSortColumn is the same value as the current sorting returned by
AB_Table_GetSortColumn(), this means the returned table might be
exactly the same AB_Table instance as self. However, it will have been
acquired one more time, so self and the returned table act as if refcounted
separately even if they are the same table instance.
The caller must eventually release the returned table by calling
AB_Table_Release(), and then make sure not to refer to this table again
after released because it might be destroyed. -*/
#define AB_Table_AcquireUnsortedTable(table,ev) \
AB_Table_AcquireSortedTable(table,ev, /*unsorted*/ 0)
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
/* ----- ----- ----- ----- Search ----- ----- ----- ----- */
AB_PUBLIC_API(ab_row_uid) /* abtable.cpp */
AB_Table_FindFirstRowWithPrefix(AB_Table* self, AB_Env* ev,
const char* cellValuePrefix, ab_column_uid inColumnUid);
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_AcquireSearchTable(AB_Table* self, AB_Env* ev,
const char* cellValue, const ab_column_uid* inColumnVector);
/*- AcquireSearchTable returns a table giving the non-persistent results of
a search for cellValue in one or more columns of table self. The
columns to search are given in the array specified by inColumnVector
which should be null-terminated with a zero ab_column_uid value after
the last column to be searched.
The returned table will contain no duplicates, even if cellValue causes a
match in more than one column. The table content is virtual (not
persistent, and possibly listed only by indirect reference) and will not
exist after the table is released down to a zero refcount. (If the caller
wants a persistent table, the caller can make a new mailing list and iterate
over this table, adding all rows to the new mailing list.)
The caller must eventually release the returned table by calling
AB_Table_Release(), and then make sure not to refer to this table again
after released because it might be destroyed. (Debug builds might keep
around "destroyed" tables for a time to detect invalid access after ref
counts reach zero.) -*/
/* ----- ----- ----- ----- Rows ----- ----- ----- ----- */
/*- (The notion of row replaces both the old notions of entry and tuple. In
more detail, ab_row_uid replaces ABID, and AB_Row replaces
HgAbTuple. Nothing replaces HgAbSchema which simply goes away
because this behavior is folded into AB_Row. We could introduce the idea
of a meta-row to replace schema, but this is really just an performance
issue and we can hide these details from the FEs.)
A persistent row is identified by its uid, ab_row_uid, but callers can
only read and write such persistent objects by means of a runtime object
named AB_Row which can describe the content of a persisent row.
AB_Row denotes a transient session object and not a persistent object.
Any given instance of AB_Row has no associated ab_row_uid because
the runtime object is not intended to have a close association with a
single persisent row.
However, each AB_Row instance is associated with a specific instance of
AB_Table (even though this could be avoided) because this runtime
relationship happens to be convenient, and causes no awkwardness in
the interfaces. AB_Row can effectively be considered a view onto the
collection of persisent rows inside a given table, except AB_Row is not
focused on a specific row in the table. -*/
#ifndef AB_Row_typedef
typedef struct AB_Row AB_Row;
#define AB_Row_typedef 1
#endif
/*- AB_Row is an abstract data type. You don't know its internal structure.
All that is known about this class is the methods that use this type as an
argument or return value. -*/
enum {
AB_Row_kFaultNullMethods = /*i*/ AB_Fault_kRow, /* 300 */
AB_Row_kFaultWrongMethodTag, /*i*/ /* 301 */
AB_Row_kFaultNotRowUid, /*i*/ /* 302 */
AB_Row_kFaultNullTable, /*i*/ /* 303 */
AB_Row_kFaultOutOfMemory, /*i*/ /* 304 */
AB_Row_kFaultNonStandardColumn, /*i*/ /* 305 */
AB_Row_kFaultCountNotUnderSize, /*i*/ /* 306 */
AB_Row_kFaultNotOpen /*i*/ /* 307 */
};
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_AddAllRows(AB_Table* self, AB_Env* ev,
const AB_Table* other);
/*- AddAllRows adds all the rows in other to self, as if by iterating over
all rows in other and adding them one at a time with
AB_Table_AddRow(). -*/
AB_PUBLIC_API(ab_row_uid)
AB_Table_CopyRow(AB_Table* self, AB_Env* cev,
const AB_Table* inOther, ab_row_uid inRowUid);
/*- copy row inRowUid from inOther to this table -*/
AB_PUBLIC_API(ab_row_pos) /* abtable.cpp */
AB_Table_AddRow(AB_Table* self, AB_Env* ev, ab_row_uid row);
/*- AddRow aliases an existing row in the address book containing table
self (see AB_Table_GetBookTable()) so this table also contains this
row. If self already contains this row, nothing happens and false is
returned. If row does not denote a row in the address book, an error
occurs and zero is returned. (The error is indicated by
AB_Env_GetError().)
If self did not previously contain row, it is added and true is returned.
This is a way to alias an existing row into a new location, rather than
creaing a new persistent row. (New persistent rows are created with
AB_Row_NewTableRowAt().) -*/
AB_PUBLIC_API(ab_row_pos) /* abtable.cpp */
AB_Table_CutRow(AB_Table* self, AB_Env* ev, ab_row_uid row);
/*- CutRow removes the indicated row from the table. This does not
actually destroy the row unless this was the last reference to the row.
False is returned when the table did not previously contain row (but it's
okay to attempt cutting it again because the same desired result obtains
when the row is not in the table afterwards). -*/
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_CutRowRange(AB_Table* self, AB_Env* ev, ab_row_pos p, ab_row_count c);
/*- CutRow removes the indicated set of c rows from the table, starting
at one-based position p. This does not actually destroy the rows unless
they were the last references to the rows. -*/
AB_PUBLIC_API(ab_row_pos) /* abtable.cpp */
AB_Table_DestroyRow(AB_Table* self, AB_Env* ev, ab_row_uid row);
/*- DestroyRow removes the indicated row from this table and from
every other table containing the same row. False is returned when the
containing address book did not previously contain row anywhare (but
it's okay to attempt destroying it again because the same desired result
obtains when the row is not in the table afterwards). An error might
occur if the table can determine that row was never a valid row inside
the address book (perhaps the size of the uid indicates it has never been
assigned). -*/
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_CountRows(const AB_Table* self, AB_Env* ev);
/*- CountRows returns the number of rows in the table. (In other words,
how many entries does this address book or mailing list contain?) -*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_AcquireListsTable(AB_Table* self, AB_Env* ev);
/*- AcquireListsTable -*/
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_CountRowParents(const AB_Table* self, AB_Env* ev,
ab_row_uid id);
/*- CountRowParents returns the number of parent tables that contain the
row known by id. If zero, this means id does not exist because no
row corresponds to this uid. If more than one, this means that more than
one table contains an alias to this row. The value returned by
CountRowParents is effectively the persistent reference count for row
id. -*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_AcquireRowParentsTable(const AB_Table* self, AB_Env* ev,
ab_row_uid id);
/*- AcquireRowParentsTable returns a table representing the collection of
tables that contain the row known by id. A null pointer is returned
when any problem occurs (such as id not existing (i.e. zero
AB_Table_CountRowParents())).
The caller must eventually release the table by calling
AB_Table_Release(), and then make sure not to refer to this table again
after released because it might be destroyed. (Debug builds might keep
around "destroyed" tables for a time to detect invalid access after ref
counts reach zero.) -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_CountRowChildren(const AB_Table* self, AB_Env* ev,
ab_row_uid id);
/*- CountRowChildren returns the number of children rows in the row
known by id. When this number is positive the row is a table.
Otherwise when zero the row is simply a row. -*/
#define AB_Table_IsRowTable(t,ev,row) \
(AB_Table_CountRowChildren(t,ev,row) != 0)
/*- IsRowTable returns whether the row known by row is a table.-*/
AB_PUBLIC_API(AB_Table*) /* abtable.cpp */
AB_Table_AcquireRowChildrenTable(const AB_Table* self, AB_Env* ev,
ab_row_uid tableId);
/*- AcquireRowChildrenTable returns a table representing the set of rows
inside the table known by tableId. Typically tableId is a mailing list
and the returned table shows the content of this mailing list. A null
pointer is returned when any problem occurs.
If tableId was previously not a table (because it had no children and so
AB_Table_IsRowTable() returns false), then the table returned is
empty. However, when the caller adds any row to this table, then
tableId becomes a table as a result. In other words, any row can be
made a mailing list by adding children, and this is done by acquiring the
row's children table and adding some children. Presto, changeo, now
the row is a table.
The caller must eventually release the table by calling
AB_Table_Release(), and then make sure not to refer to this table again
after released because it might be destroyed. (Debug builds might keep
around "destroyed" tables for a time to detect invalid access after ref
counts reach zero.) -*/
AB_PUBLIC_API(ab_row_uid) /* abtable.cpp */
AB_Table_GetRowAt(const AB_Table* self, AB_Env* ev, ab_row_pos p);
/*- GetRowAt returns the uid of the row at position p, where each row in
a table has a position from one to AB_Table_RowCount(). (One-based
indexes are used rather than zero-based indexes, because zero is
convenient for indicating when a row is not inside a table.) -*/
AB_PUBLIC_API(ab_row_count) /* abtable.cpp */
AB_Table_GetRows(const AB_Table* self, AB_Env* ev,
ab_row_uid* outVector, ab_row_count inSize, ab_row_pos pos);
/*- GetRows is roughly equivalent to calling AB_Table_GetRowAt()
inSize times. It is a good way to read a contiguous sequence of row
uids starting at position pos inside the table.
At most inSize uids are written to outVector, and the actual number
written there is returned as the value of function. The only reason why
fewer might be written is if fewer than inSize rows are in the table
starting at position pos.
Remember that pos is one-based, so one is the position of the first row
and AB_Table_CountRows() is the position of the last. -*/
AB_PUBLIC_API(ab_bool) /* abtable.cpp */
AB_Table_DoesSortRows(const AB_Table* self, AB_Env* ev);
/*- DoesSortRows returns whether table self maintains its row collection
in sorted order. Presumably this is always true for address books
(AB_Type_kAddressBookTable) but always false for mailing lists
(AB_Type_kMailingListTable). At least this would be consistent with
4.0 behavior.
DoesSortRows is equivalent to the expression
(AB_Table_GetSortColumn()!=0).
We might want to permit mailing lists to sort rows by cell values, just
like address books do. But in that case an unsorted representation should
be kept so users can keep list recipients in a preferred order. (A user
specified ordering might be important for social constraints in showing
proper acknowledgement to individuals according to some ranking
scheme.)
If we decide to sort mailing lists, the sorting will likely be maintained in
memory, as opposed to persistently. (Users with huge mailing lists
should use a separate address book for this purpose.) This would let
users easily revert to the original unsorted view of a list.
Getting a sorted interface to a list is done with
AB_Table_AcquireSortedTable(), and getting the unsorted version of
a list is done with AB_Table_AcquireUnsortedTable(). -*/
AB_PUBLIC_API(ab_row_pos) /* abtable.cpp */
AB_Table_RowPos(const AB_Table* self, AB_Env* ev, ab_row_uid id);
/*- RowPos returns the position of the row known by id, where each row
in a table has a position from one to AB_Table_RowCount(). Zero is
returned when this row is not inside the table. -*/
#define AB_Table_HasRow(t,ev,row) (AB_Table_RowPos(t,ev,row) != 0)
/*- HasRow returns whether table self contains the indicated row.-*/
AB_PUBLIC_API(ab_row_pos) /* abtable.cpp */
AB_Table_ChangeRowPos(const AB_Table* self, AB_Env* ev,
ab_row_uid existingRow, ab_row_pos toNewPos);
/*- ChangeRowPos moves the row known by existingRow to new
position toNewPos, provided AB_Table_DoesSortRows() is true.
Otherwise ChangeRowPos does nothing (and returns false) if the table
is in sorted order, or if existingRow is not in the table
(AB_Table_HasRow() returns false).
Specifically, ChangeRowPos is expected to be useful for mailing list
tables (AB_Type_kMailingListTable), but not useful for address book
tables (AB_Type_kAddressBookTable) nor useful for some other table
types (e.g. AB_Type_kSearchResultTable).
If FEs wish, they need not worry about this restriction, but simply let
users see that dragging rows in mailing lists is useful, but dragging rows
in address books has no effect. It does not seem feasible to prevent users
from attempting to drag within an address book, because FEs will not
know whether the user intends to drop elsewhere, say in another address
book. FEs might want to figure out whether a drop makes sense in the
same table, but they can simply call ChangeRowPos and find out
(through both the return value and notifications) whether it has any
effect. -*/
AB_PUBLIC_API(ab_column_count) /* abtable.cpp */
AB_Table_CountRowCells(const AB_Table* self, AB_Env* ev,
ab_row_uid id);
/*- CountRowCells returns the number of cells in the row known by id,
which means the number of columns that have non-empty values in the
row. (In other words, how many attributes does this entry have?) -*/
AB_PUBLIC_API(AB_Row*) /* abtable.cpp */
AB_Table_MakeDefaultRow(AB_Table* self, AB_Env* ev);
/*- MakeDefaultRow creates a runtime description of a row (but not a
persistent row). (Creating a persistent table row is done with
AB_Row_NewTableRowAt().) This instance must be deallocated later with
AB_Row_Free().
This instance of AB_Row will already have cells corresponding to the
columns used by the table (see AB_Table_GetColumnLayout()), so
frontends that intend to use this row to display columns from the table
will no need not do any more work before calling
AB_Row_ReadTableRow() to read row content from the table. -*/
AB_PUBLIC_API(AB_Row*) /* abtable.cpp */
AB_Table_MakeRow(AB_Table* self, AB_Env* ev, const AB_Cell* inVector);
/*- MakeRow creates a runtime description of a row (but not a persistent
row) with N cells as described by the array of (at least) N+1 cells
pointed to by inVector. Only the sCell_Column and sCell_Size slots
matter. Other cell slots are ignored. The length of the inVector array is
inferred by the first cell that contains zero in the sCell_Column slot,
which is used for null termination.
If the first N cells of inVector have nonzero sCell_Column slots, then
those first N cells must also have nonzero sCell_Size slots, or else an
error occurs.
The sCell_Column slot values should be all distinct, without duplicate
columns. If inVector has duplicate columns, the last one wins and no
error occurs (so callers should check before calling if they care).
After a row is created, more cells can be added with
AB_Row_AddCells(). -*/
AB_PUBLIC_API(AB_Row*) /* abtable.cpp */
AB_Table_MakeRowFromColumns(AB_Table* self, AB_Env* ev,
const AB_Column* inColumns);
/*- MakeRowFromColumns is just like AB_Table_MakeRow() except that
sColumn_Uid and sColumn_CellSize slots are used (instead of
sCell_Column and sCell_Size) and the vector is null terminated with a
zero in sColumn_Uid. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(AB_Row*) /* abtable.cpp */
AB_Table_MakePersonRow(AB_Table* self, AB_Env* ev);
/*- MakePersonRow creates a runtime description of a row (but not a
persistent row) that seems most suited for editing a description of a
person. This is like calling AB_Table_MakeRow() with the cell vector
returned by AB_Table_GetPersonCells(). -*/
AB_PUBLIC_API(AB_Row*) /* abtable.cpp */
AB_Table_MakePersonList(AB_Table* self, AB_Env* ev);
/*- MakePersonList creates a runtime description of a row (but not a
persistent row) that seems most suited for editing a description of a
mailing list. This is like calling AB_Table_MakeRow() with the cell vector
returned by AB_Table_GetListCells(). -*/
AB_PUBLIC_API(ab_cell_count) /* abtable.cpp */
AB_Table_GetPersonCells(const AB_Table* self, AB_Env* ev,
AB_Cell* outVector, ab_cell_count inSize, ab_cell_count* outLength);
/*- GetPersonCells returns a copy of the standard cells for a person in
cell array outVector. This cell vector is address book specific because
column uids in the sCell_Column slots have address book scope. The
actual number of standard cells is returned as the function value, but the
size of outVector is assumed to be inSize, so no more than inSize
cells will be written to outVector. The actual number of cells written is
returned in outLength (unless outLength is a null pointer to suppress
this output).
If inSize is greater than the number of cells, N, then outVector[N] will
be null terminated by placing all zero values in all the cell slots.
All the sCell_Content slots will be null pointers because these cells
will not represent actual storage in a row. GetPersonCells is expected
to be used in the implementation of methods like
AB_Table_MakePersonRow(). -*/
AB_PUBLIC_API(ab_cell_count) /* abtable.cpp */
AB_Table_GetListCells(const AB_Table* self, AB_Env* ev,
AB_Cell* outVector, ab_cell_count inSize, ab_cell_count* outLength);
/*- GetListCells returns a copy of the standard cells for a mailing list
in cell array outVector. This cell vector is address book specific because
column uids in the sCell_Column slots have address book scope. The
actual number of standard cells is returned as the function value, but the
size of outVector is assumed to be inSize, so no more than inSize
cells will be written to outVector. The actual number of cells written is
returned in outLength (unless outLength is a null pointer to suppress
this output).
If inSize is greater than the number of cells, N, then outVector[N] will
be null terminated by placing all zero values in all the cell slots.
All the sCell_Content slots will be null pointers because these cells
will not represent actual storage in a row. GetListCells is expected to be
used in the implementation of methods like
AB_Table_MakePersonList(). -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(AB_Row*) /* abrow.c */
AB_Row_MakeRowClone(const AB_Row* self, AB_Env* ev);
/*- MakeRowClone allocates a duplicate of row self with exactly the same
table, cell structure, and cell content. A caller might use this method to
create a copy of a row prior to making changes when the original row
must be kept intact. -*/
AB_PUBLIC_API(ab_ref_count) /* abrow.c */
AB_Row_Acquire(AB_Row* self, AB_Env* ev);
AB_PUBLIC_API(ab_ref_count) /* abrow.c */
AB_Row_Release(AB_Row* self, AB_Env* ev);
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_CopyRowContent(AB_Row* self, AB_Env* ev, const AB_Row* other);
/*- CopyRowContent makes all cells in self contain the same content as
corresponding cells (with the same sCell_Column) in other. This
affects cell content only, and does not change the cell structure of self at
all, so number and size of cells does not change. If a cell in self is too
small to receive all content in other, the content is truncated rather than
enlarging the cell (in contrast to AB_Row_BecomeRow()). -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_BecomeRowClone(AB_Row* self, AB_Env* ev, const AB_Row* other);
/*- BecomeRowClone causes self to be a clone of other, with exactly the
same cell structure and cell content. (If self and other belong to
different tables, then self changes its table to that of other.) -*/
AB_PUBLIC_API(AB_Table*) /* abrow.c */
AB_Row_GetTable(const AB_Row* self, AB_Env* ev);
/*- GetTable returns the table that created this row.
(Null returns on error.)-*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_ChangeTable(AB_Row* self, AB_Env* ev, AB_Table* table);
/*- ChangeTable sets the table for this row to table (and this does any
necessary table reference counting). -*/
AB_PUBLIC_API(ab_row_uid) /* abrow.c */
AB_Row_NewTableRowAt(const AB_Row* self, AB_Env* ev, ab_row_pos pos);
/*- New creates a new row in the table at position pos by writing the
cells specified by this row. Zero is returned on error (zero is never a
valid uid), and the specific error is indicated by AB_Env_GetError().
The position pos can be any value, not just one to
AB_Table_CountRows(). If zero, this means put the new row wherever
seems best. If greater than the number of rows, it means append to the
end. If the table is currently sorted in some order, pos is ignored and
the new row is goes in sorted position. -*/
#define AB_Row_NewTableRow(table,ev) AB_Row_NewTableRowAt(table,ev,0)
/*- NewTableRow is just like AB_Row_NewTableRowAt() except with the
position argument curried with the constant value zero, which is ignored
anyway by address books, but for mailing lists might cause the new row
to be, say, appended after the last existing row. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_ReadTableRowAt(AB_Row* self, AB_Env* ev, ab_row_pos pos);
/*- ReadTableRowAt reads the row in the table at postion pos, filling cell
values from the persistent content for the row found in the table. All cells
are given values read from row id in the table, and this includes making
cells empty when the persistent row has no such cell value. -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_ReadTableRow(AB_Row* self, AB_Env* ev, ab_row_uid id);
/*- ReadTableRow reads the row in the table known by id, filling cell
values from the persistent content for the row found in the table. All cells
are given values read from row id in the table, and this includes making
cells empty when the persistent row has no such cell value. If cells in
self are too small to read the entire content from the table, only the -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_GrowToReadEntireTableRow(AB_Row* self, AB_Env* ev,
ab_row_uid id, ab_cell_size maxCellSize);
/*- GrowToReadEntireTableRow reads the row in the table known by id,
filling cell values from the persistent content for the row found in the
table. All cells are given values read from row id in the table, and this
includes making cells empty when the persistent row has no such cell
value.
In contrast to AB_Row_ReadTableRow() which does not change cell
structure to read content from the table, GrowToReadEntireTableRow
will add cells as needed and grow the size of cells as needed in order to
hold every byte of every persistent cell value. In other words,
GrowToReadEntireTableRow will read the entire persistent content of
the table row while growing to the extent necessary to capture all this
content.
The maxCellSize parameter can be zero to cause it to be ignored, but if
nonzero, maxCellSize is used to cap cell growth so to no more than
maxCellSize. This lets callers attempt to accomodate all persistent
content up to some reasonable threshold over which the caller might no
longer care whether more cell content is present. So if a persistent value
is too big to fit in a cell, and is also bigger than maxCellSize, then the
cell has its size increased only to maxCellSize before reading the cell
value. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(ab_row_pos) /* abrow.c */
AB_Row_UpdateTableRow(const AB_Row* self, AB_Env* ev, ab_row_uid id);
/*- UpdateTableRow writes part of the row known by id in the table,
updating all cells with non-empty content in self, so that empty cells in
self have no effect on the persistent row in the table. Also, cells not
described at all in self are not touched at all in the table. -*/
AB_PUBLIC_API(ab_row_pos) /* abrow.c */
AB_Row_ResetTableRow(const AB_Row* self, AB_Env* ev, ab_row_uid id);
/*- ResetTableRow writes all of the row known by id in the table, updating
all of the table row cells, whether they are described by self or not.
Cells not in self and empty cells in self are removed from row id.
Non-empty cells in self have their values written to row id so that each
table row cell contains only the content described by self. -*/
/* ----- ----- ----- ----- Cells ----- ----- ----- ----- */
#ifndef AB_Cell_typedef
typedef struct AB_Cell AB_Cell;
#define AB_Cell_typedef 1
#endif
struct AB_Cell { /* interface to buffer a single row attribute */
ab_column_uid sCell_Column; /* the column associated with this row cell */
ab_cell_size sCell_Size; /* the size of sCell_Content in bytes */
ab_cell_length sCell_Length; /* the length of content in sCell_Content */
ab_cell_extent sCell_Extent; /* the amount of persistent cell content */
char* sCell_Content; /* buffer to hold cell content */
};
enum AB_Cell_eError { /* AB_Cell errors */
AB_Cell_kFaultOutOfMemory = /*i*/ AB_Fault_kCell, /* 500 */
AB_Cell_kFaultBadColumnUid, /*i*/ /* 501 */
AB_Cell_kFaultNullContent, /*i*/ /* 502 */
AB_Cell_kFaultZeroCellSize, /*i*/ /* 503 */
AB_Cell_kFaultSizeExceedsMax, /*i*/ /* 504 */
AB_Cell_kFaultSizeTooSmall, /*i*/ /* 505 */
AB_Cell_kFaultLengthExceedsSize /*i*/ /* 506 */
};
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_ClearAllCells(AB_Row* self, AB_Env* ev);
/*- ClearAllCells makes all the cells in this row empty of content. -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_WriteCell(AB_Row* self, AB_Env* ev,
const char* content, ab_column_uid col);
/*- WriteCell ensures that row self has a cell with column col and sets
the content of this cell to content, with length strlen(content). If
the row did not previously have such a cell, it gets one just as if
AB_Row_AddCell() had been called. Also, if the length of content is
greater than the old size of the cell, the cell's size is increased to make it
big enough to hold all the content (also just as if AB_Row_AddCell() had
been called).
(WriteCell is implemented by calling AB_Row_PutCell().) -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_PutCell(AB_Row* self, AB_Env* ev, const AB_Cell* c);
/*- PutCell is the internal form of WriteCell which assumes the length of
the content to write is already known. Only the sCell_Content,
sCell_Length, and sCell_Column slots are used from c. -*/
AB_PUBLIC_API(ab_cell_count) /* abrow.c */
AB_Row_CountCells(const AB_Row* self, AB_Env* ev);
/*- CountCells returns the number of cells in this row. -*/
AB_PUBLIC_API(ab_cell_count) /* abrow.c */
AB_Row_GetCells(const AB_Row* self, AB_Env* ev,
AB_Cell* outVector, ab_cell_count inSize, ab_cell_count* outLength);
/*- GetCells returns a copy of the row's cells in outVector. The actual
number of row cells is returned as the function value, but the size of
outVector is assumed to be inSize, so no more than inSize cells will
be written to outVector. The actual number of cells written is returned
in outLength (unless outLength is a null pointer to suppress this
output).
If inSize is greater than the number of cells, N, then outVector[N] will
be null terminated by placing all zero values in all the cell slots.
Each sCell_Content slot points to space owned by the row. This space
might change whenever the row changes, so callers must not cause the
row to change while cell content is still being accessed. -*/
/* ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- */
AB_PUBLIC_API(const AB_Cell*) /* abrow.c */
AB_Row_GetCellAt(const AB_Row* self, AB_Env* ev, ab_cell_pos pos);
/*- GetCellAt returns a pointer to a AB_Cell inside the self instance. This
is a potentially dangerous exposure of internal structure for the sake of
performance. Callers are expected to use this cell only long enough to
see cell slots like sCell_Content that might be needed, and then forget
this pointer as soon as possible.
Whenever the row is changed so that cell structure is modified, this
AB_Cell instance might no longer exist afterwards. So using this cell
must be only of transient nature. Clients should call GetCellAt again
later, each time a cell is desired.
GetCellAt returns a null pointer if pos is zero, or if pos is greater
than the number of cells (AB_Row_CountCells()). The cells have
one-based positions numbered from one to the number of cells.
The cell returned must not be modified, on pain of undefined behavior.
Callers must not assume anything about adjacency of other cells in the
row. Cells might be stored discontiguously. -*/
AB_PUBLIC_API(const AB_Cell*) /* abrow.c */
AB_Row_GetColumnCell(const AB_Row* self, AB_Env* ev, ab_column_uid id);
/*- GetColumnCell is just like AB_Row_GetCellAt() except that the cell is
found by matching the column uid. If the row has no such column, then
a null pointer is returned. -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_AddCells(AB_Row* self, AB_Env* ev, const AB_Cell* inVector);
/*- AddCells changes the row's cell structure to include the cells described
in inVector which must be null terminated by a zero value in the
sCell_Column slot after the last cell to be added. Only the
sCell_Column and sCell_Size slots matter and other slots are ignored.
The sCell_Column slot values should be all distinct, without duplicate
columns. If inVector has duplicate columns, the last one wins and no
error occurs (so callers should check before calling if they care).
AddCells is implemented by calling AB_Row_AddCell(). -*/
#define AB_Cell_kMaxCellSize (32 * 1024)
/*- kMaxCellSize is the maximum size cell. It's main function is to sanity
check reasonable values for cell size passed to AB_Row_AddCell(), but
this is also effectively the largest piece of contiguous memory we want
to guarantee we can allocate in cross platform code. -*/
AB_PUBLIC_API(AB_Cell*) /* abrow.c */
AB_Row_AddCell(AB_Row* self, AB_Env* ev, ab_column_uid id, ab_cell_size size);
/*- AddCell gives the row another cell for column id which can hold size
substract one content bytes. Both id and size must be nonzero, and
id must denote a valid column in the address book, and size must be no
greater than AB_Cell_kMaxCellSize. If the cell known by id
previously existed, then it's size is changed to equal the maximum of
either the old size or the new size. (To shrink the size of a cell, remove
it first with AB_Row_CutCell() and then re-add the cell. The specified
size behavior here is most convenient for upgrading rows to hold bigger
content.) -*/
AB_PUBLIC_API(ab_bool) /* abrow.c */
AB_Row_CutCell(AB_Row* self, AB_Env* ev, ab_column_uid id);
/*- CutCell removes any cell identified by column uid id. True is returned
only if such a cell existed (and was removed). False returns when no
such cell was found (or if an error occurs). No error occurs from cutting
a cell which does not exist, because the desired end result -*/
AB_PUBLIC_API(char *) /* abrow.c */
AB_Row_AsVCardString(AB_Row* self, AB_Env* ev);
/*- returned string allocated by ab_Env::CopyString() which advertises
itself as using XP_ALLOC for space allocation. A null pointer is
typically returned in case of error. (It would not be that safe
to return an empty static string which could not be deallocated.) -*/
/* ----- ----- ----- ----- Stores ----- ----- ----- ----- */
#define AB_Store_kMinFootprint /*i*/ (48 * 1024)
#define AB_Store_kMinFootprintGrowth /*i*/ (32 * 1024)
#define AB_Store_kGoodFootprintSpace /*i*/ (512 * 1024)
#define AB_Store_kGoodFootprintGrowth /*i*/ (1024 * 1024)
#define AB_Store_kBigStartingFootprint /*i*/ (8 * 1024 * 1024)
#define AB_Store_kBigFootprintGrowth /*i*/ (4 * 1024 * 1024)
/* ````` making a new store instance (need AB_Env instance) ````` */
AB_PUBLIC_API(AB_Store*) /* abstore.cpp */
AB_Env_NewStore(AB_Env* self, const char* inFileName,
ab_num inTargetFootprint);
/*- Open and/or create a database named inFileName (which must
yield type AB_StoreType_kTable from AB_FileName_GetStoreType(),
or else an error occurs). -*/
/* ````` regarding file names for stores ````` */
typedef enum AB_Store_eType /*d*/ {
AB_StoreType_kUnknown = 0, /* unknown: cannot be opened or imported */
AB_StoreType_kTable = 1, /* use AB_Env_NewStore() to access store */
AB_StoreType_kImport = 2, /* import only using AB_Store_NewImportFile() */
AB_StoreType_kStale = 3, /* unsupported transient development format */
AB_StoreType_kFuture = 4 /* unsupported furture final format */
} AB_Store_eType;
AB_PUBLIC_API(AB_Store_eType) /* abstore.cpp */
AB_FileName_GetStoreType(const char* inFileName, AB_Env* ev);
/*- GetStoreType() returns an enum value that describes how the file
can be handled. Currently this is based on the file name itself, but
later this might also involve looking inside the file to examine the
bytes to determine correct usage. The file can only be opened and
used as an instance of AB_Store (using AB_Env_NewStore()) if the type
equals AB_StoreType_kTable, which means the store supports the table
interface. Otherwise, if the file type is AB_StoreType_kImport, this
means one should create a new database with an appropriate name (see
AB_FileName_MakeNativeName()), and import this file. (Or the new file
might already exist from earlier, openable with AB_Env_NewStore().)
Formats which cannot opened nor imported might be either "unknown"
or "stale" (AB_StoreType_kUnknown or AB_StoreType_kStale), where the
stale formats are recognizably retired transient development formats,
while unknown formats might still be importable by other means. When
a "future" format is detected which has not yet been implemented, the
type returned is AB_StoreType_kFuture, and presumably this means that
neither opening nor importing is feasible (like stale formats) but
that products with later versions should read the format.
The native format will be ".na2", but we can use transient development
formats before the final format with different suffixes like ".na0".
Later a ".na0" format will return AB_StoreType_kStale.
The imported formats will include ".ldi" and ".ldif" for LDIF, with
".htm" and ".html" for HTML. Later we'll support more formats.
The unknown file formats might still be importable using more general
purpose import code that can recognize a broader range of formats. -*/
AB_PUBLIC_API(void) /* abstore.cpp */
AB_FileName_GetNativeSuffix(char* outFileNameSuffix8, AB_Env* ev);
/*- GetNativeSuffix() writes into outFileNameSuffix8 the file name
extension suffix (for example, ".na2") that is preferred for the
current native database format created for new database files. The
space should be at least eight characters in length for safety, though
in practice five bytes will be written: a period, followed by three
alphanumeric characters, followed by a null byte. Whenever one wishes
to make a new database, the filename for the database should end with
this string suffix. (Note that implementations might return more than
one string suffix, assuming the environment has access to prefs or some
other indication of which format to choose among possibilities.) -*/
AB_PUBLIC_API(ab_bool) /* abstore.cpp */
AB_FileName_HasNativeSuffix(const char* inFileName, AB_Env* ev);
/*- HasNativeSuffix() returns true only if inFileName ends with a
suffix equal to that returned by AB_FileName_GetNativeSuffix(). -*/
AB_PUBLIC_API(const char*) /* abstore.cpp */
AB_FileName_FindSuffix(const char* inFileName);
/*- FindSuffix() returns the address of the last period "." in the
string inFileName, or null if no period is found at all. This method
is used to locate the suffix for comparison in HasNativeSuffix().
Typically file format judgments will be made on the three characters
that follow the final period in the filename. -*/
AB_PUBLIC_API(char*) /* abstore.cpp */
AB_FileName_MakeNativeName(const char* inFileName, AB_Env* ev);
/*- MakeNativeName() allocates a new string (which must be freed
later using XP_FREE()) for which AB_FileName_HasNativeSuffix()
is true. If inFileName already has the native suffix, the string
returned is a simple copy; otherwise the returned string appends
the value of AB_FileName_GetNativeSuffix() to the end. (Note that
the environment might select one of several format choices.) -*/
/* ````` destroying an old store instance (need AB_Env instance) ````` */
AB_API_IMPL(void) /* abstore.cpp */
AB_Env_DestroyStoreWithFileName(AB_Env* self, const char* inFileName);
/* DestroyStoreWithFileName() deletes the file from the file system
containing the store that would be opened if a store instance was
created using inFileName for the file name. This method is provided
to keep file destruction equally as abstract as the implicit file
creation occuring when a new store is created. Otherwise it would
be difficult to discard databases as easily as they are created. But
this method is dangerous in the sense that destruction of data is
definitely intended, so don't call this method unless the total
destruction of data in the store is what you have in mind. This
method does not attempt to verify the file contains a database before
destroying the file with name inFileName in whatever directory is
used to host the database files. Make sure you name the right file. */
/* ````` opening store CONTENT ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_OpenStoreContent(AB_Store* self, AB_Env* ev);
/* ````` closing store CONTENT (aborts unsaved changes) ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_CloseStoreContent(AB_Store* self, AB_Env* ev); /* abort */
/* ````` saving store CONTENT (commits unsaved changes) ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_SaveStoreContent(AB_Store* self, AB_Env* ev); /* commit */
/* ````` importing store CONTENT ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_ImportWithPromptForFileName(AB_Store* self, AB_Env* ev, MWContext* ioContext);
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_ImportEntireFileByName(AB_Store* self, AB_Env* ev, const char* inFileName);
/* ImportEntireFileByName() just calls ImportFileByName() with a
thumb instance intended to convey "all the file content". */
/* ````` exporting store CONTENT ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_ExportWithPromptForFileName(AB_Store* self, AB_Env* ev, MWContext* ioContext);
/* ````` thumbs ````` */
AB_PUBLIC_API(AB_Thumb*) /* abthumb.cpp */
AB_Store_NewThumb(AB_Store* self, AB_Env* ev, ab_row_count inRowLimit,
ab_num inFileByteCountLimit);
AB_PUBLIC_API(ab_bool) /* abthumb.cpp */
AB_Thumb_IsProgressFinished(const AB_Thumb* self, AB_Env* ev);
AB_PUBLIC_API(void) /* abthumb.cpp */
AB_Thumb_SetPortingLimits(AB_Thumb* self, AB_Env* ev, ab_row_count inRowLimit,
ab_num inFileByteCountLimit);
AB_PUBLIC_API(ab_ref_count) /* abthumb.cpp */
AB_Thumb_Acquire(AB_Thumb* self, AB_Env* ev);
AB_PUBLIC_API(ab_ref_count) /* abthumb.cpp */
AB_Thumb_Release(AB_Thumb* self, AB_Env* ev);
/*| ImportProgress: return the current position in the import file, and also
**| the actual length of the import file in outFileLength, since this can be
**| used to show percentage progress through the import file. However, we
**| can only show progress through the current pass through the file, which
**| is returned in outPass (typically either 1 or 2 for first or second pass).
**|
**|| Note that when outPass turns over from 1 to 2, the progress through the
**| file will revert back to a smaller percentage of the file, so a progress
**| bar might want to reveal to users which pass is currently in progress.
|*/
AB_PUBLIC_API(ab_pos) /* abthumb.cpp */
AB_Thumb_ImportProgress(AB_Thumb* self, AB_Env* ev, ab_pos* outFileLength,
ab_count* outPass);
/*| ExportProgress: return the row position of the row that was last exported,
**| and also the total number of rows to be exported in outTotalRows, since this
**| can be used to show percentage progress through the export task.
|*/
AB_PUBLIC_API(ab_row_pos) /* abthumb.cpp */
AB_Thumb_ExportProgress(AB_Thumb* self, AB_Env* ev, ab_row_count* outTotalRows);
typedef enum AB_File_eFormat {
AB_File_kUnknownFormat = 0x3F3F3F3F, /* '????' */
AB_File_kLdifFormat = 0x6C646966, /* 'ldif' */
AB_File_kHtmlFormat = 0x68746D6C, /* 'hmtl' */
AB_File_kXmlFormat = 0x61786D6C, /* 'axml' */
AB_File_kVCardFormat = 0x76637264, /* 'vcrd' */
AB_File_kBinaryFormat = 0x626E7279, /* 'bnry' */
AB_File_kNativeFormat = 0x6E617476 /* 'natv' current native format */
} AB_File_eFormat;
/*| ImportFileFormat: describe the current file format being imported
|*/
AB_PUBLIC_API(AB_File_eFormat) /* abthumb.cpp */
AB_Thumb_ImportFileFormat(AB_Thumb* self, AB_Env* ev);
/* ````` file-and-thumb based import and export ````` */
AB_PUBLIC_API(AB_File*) /* abstore.cpp */
AB_Store_NewImportFile(AB_Store* self, AB_Env* ev, const char* inFileName);
AB_PUBLIC_API(ab_bool) /* abstore.cpp, true iff !AB_Thumb_IsProgressFinished() */
AB_Store_ContinueImport(AB_Store* self, AB_Env* ev, AB_File* ioFile,
AB_Thumb* ioThumb);
AB_PUBLIC_API(AB_File*) /* abstore.cpp */
AB_Store_NewExportFile(AB_Store* self, AB_Env* ev,
const char* inFileName);
AB_PUBLIC_API(ab_bool) /* abstore.cpp, true iff !AB_Thumb_IsProgressFinished() */
AB_Store_ContinueExport(AB_Store* self, AB_Env* ev, AB_File* ioFile,
AB_Thumb* ioThumb);
AB_PUBLIC_API(ab_ref_count) /* abfile.cpp */
AB_File_Acquire(AB_File* self, AB_Env* ev);
AB_PUBLIC_API(ab_ref_count) /* abfile.cpp */
AB_File_Release(AB_File* self, AB_Env* ev);
/* ````` batching changes (these calls should nest okay) ````` */
AB_PUBLIC_API(void) /* abstore.cpp, commit every inEventThreshold changes */
AB_Store_StartBatchMode(AB_Store* self, AB_Env* ev,
ab_num inEventThreshold);
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_EndBatchMode(AB_Store* self, AB_Env* ev);
/* ````` open/close content status querying ````` */
AB_PUBLIC_API(ab_bool) /* abstore.cpp */
AB_Store_IsOpenStoreContent(AB_Store* self);
AB_PUBLIC_API(ab_bool) /* abstore.cpp */
AB_Store_IsShutStoreContent(AB_Store* self);
/* ````` closing store INSTANCE ````` */
AB_PUBLIC_API(void) /* abstore.cpp */
AB_Store_CloseObject(AB_Store* self, AB_Env* ev);
/* ````` store refcounting ````` */
AB_PUBLIC_API(ab_ref_count) /* abstore.cpp */
AB_Store_Acquire(AB_Store* self, AB_Env* ev);
AB_PUBLIC_API(ab_ref_count) /* abstore.cpp */
AB_Store_Release(AB_Store* self, AB_Env* ev);
/* ````` accessing top store table (with or without acquire) ````` */
AB_PUBLIC_API(AB_Table*) /* abstore.cpp */
AB_Store_GetTopStoreTable(AB_Store* self, AB_Env* ev);
AB_PUBLIC_API(AB_Table*) /* abstore.cpp */
AB_Store_AcquireTopStoreTable(AB_Store* self, AB_Env* ev);
/* `````` `````` protos `````` `````` */
AB_END_C_PROTOS
/* `````` `````` protos `````` `````` */
#endif /* _ABTABLE_ */