Added files in areacode.
This commit is contained in:
parent
2c2477711c
commit
cee09b6d7c
|
@ -0,0 +1,41 @@
|
|||
#
|
||||
# This Makefile is used for compatibility to the
|
||||
# isdn4k-utils package. In order to superseede
|
||||
# the original Makefile, it is called GNUmakefile.
|
||||
#
|
||||
|
||||
ifeq (../.config,$(wildcard ../.config))
|
||||
include ../.config
|
||||
DATAOPTS := DATATARGET=$(shell echo $(CONFIG_AREACODE_DATA))/areacodes
|
||||
#
|
||||
# Install as root with numeric Id's, since these are the
|
||||
# only ones that _really_ exist on _every_ system.
|
||||
#
|
||||
BUILDOPTS := $(DATAOPTS)
|
||||
INSTALLOPTS := $(DATAOPTS) INSTALL="install -o 0 -g 0 -m 644"
|
||||
endif
|
||||
|
||||
all: .depend
|
||||
$(MAKE) -f make/linux.mak $(BUILDOPTS) all
|
||||
|
||||
.depend:
|
||||
$(MAKE) -f make/linux.mak $(BUILDOPTS) depend
|
||||
|
||||
config:
|
||||
@cp Makefile.in GNUmakefile
|
||||
|
||||
clean:
|
||||
$(MAKE) -f make/linux.mak clean
|
||||
|
||||
distclean:
|
||||
$(MAKE) -f make/linux.mak distclean
|
||||
rm -f GNUmakefile
|
||||
|
||||
install-man:
|
||||
|
||||
install:
|
||||
mkdir -p $(CONFIG_AREACODE_DATA)
|
||||
$(MAKE) -f make/linux.mak $(INSTALLOPTS) install
|
||||
|
||||
uninstall:
|
||||
rm -f $(shell echo $(CONFIG_AREACODE_DATA))/areacodes
|
|
@ -0,0 +1,100 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* ACTEST.C */
|
||||
/* */
|
||||
/* Test an areacode data file */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1996,97 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.com */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any express or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "areacode.h"
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv [])
|
||||
{
|
||||
acInfo AC;
|
||||
char Buf [256];
|
||||
unsigned RC;
|
||||
acMaxMem = 0;
|
||||
|
||||
/* See if there is an argument given. If so, use it as name and path of
|
||||
* the database.
|
||||
*/
|
||||
if (argc >= 2) {
|
||||
acFileName = argv [1];
|
||||
}
|
||||
|
||||
/* Test loop */
|
||||
while (1) {
|
||||
|
||||
printf ("Enter phone number: ");
|
||||
fflush (stdout);
|
||||
gets (Buf);
|
||||
if (strlen (Buf) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((RC = GetAreaCodeInfo (&AC, Buf))) {
|
||||
|
||||
case acOk:
|
||||
printf ("acOK:\n"
|
||||
" PrefixLen = %d\n"
|
||||
" Info = %s\n",
|
||||
AC.AreaCodeLen, AC.Info);
|
||||
break;
|
||||
|
||||
case acFileError:
|
||||
printf ("acFileError\n");
|
||||
break;
|
||||
|
||||
case acInvalidFile:
|
||||
printf ("acInvalidFile\n");
|
||||
break;
|
||||
|
||||
case acWrongVersion:
|
||||
printf ("acWrongVersion\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("Unknown return: %u\n", RC);
|
||||
break;
|
||||
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* ACVERS.C */
|
||||
/* */
|
||||
/* Get the version and build of an areacode data file */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1996,97 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.com */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any express or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* This code assumes 8 bit bytes */
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#define MAGIC0 0x68
|
||||
#define MAGIC1 0x57
|
||||
#define MAGIC2 0x46
|
||||
#define MAGIC3 0x35
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void Usage (const char* ProgName)
|
||||
/* Print usage information and exit */
|
||||
{
|
||||
printf ("%s: Print the version of an areacode database\n\n"
|
||||
"Usage: \t%s file ...\n",
|
||||
ProgName, ProgName);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char* argv [])
|
||||
{
|
||||
int I;
|
||||
|
||||
if (argc < 2) {
|
||||
Usage (argv [0]);
|
||||
}
|
||||
|
||||
for (I = 1; I < argc; I++) {
|
||||
|
||||
FILE* F;
|
||||
const char* Filename = argv [I];
|
||||
unsigned char MagicBuf [4];
|
||||
unsigned char BuildBuf [2];
|
||||
unsigned char VersionBuf [2];
|
||||
unsigned Build;
|
||||
|
||||
if ((F = fopen (Filename, "rb")) == 0) {
|
||||
perror ("Cannot open input file");
|
||||
exit (2);
|
||||
}
|
||||
|
||||
fread (MagicBuf, sizeof (MagicBuf), 1, F);
|
||||
if (MagicBuf [0] != MAGIC0 || MagicBuf [1] != MAGIC1 ||
|
||||
MagicBuf [2] != MAGIC2 || MagicBuf [3] != MAGIC3) {
|
||||
fprintf (stderr, "No dial prefix database\n");
|
||||
exit (3);
|
||||
}
|
||||
|
||||
fread (BuildBuf, sizeof (BuildBuf), 1, F);
|
||||
fread (VersionBuf, sizeof (VersionBuf), 1, F);
|
||||
fclose (F);
|
||||
|
||||
Build = ((unsigned) BuildBuf [1]) * 256 + ((unsigned) BuildBuf [0]);
|
||||
printf ("%d %d %u\n", VersionBuf [1], VersionBuf [0], Build);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,567 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* AREACODE.C */
|
||||
/* */
|
||||
/* Portable library module to search for an area code in a database. */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1996,97 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.com */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any express or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The code assumes
|
||||
* - 8 bit bytes
|
||||
* - unsigned long is 32 bit. This may be changed by #defining u32 to
|
||||
* a data type that is an 32 bit unsigned when compiling this module.
|
||||
* - ascii character set
|
||||
*
|
||||
* The code does *not* assume
|
||||
* - a specific byte order. Currently the code autoadjusts to big or
|
||||
* little endian data. If you have something more weird than that,
|
||||
* you have to add conversion code.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "areacode.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Externally visible data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* The name of the areacode data file. The default is what is #defined as
|
||||
* DATA_FILENAME. If this is not #defined, the default is "areacode.dat",
|
||||
* which is probably not what you want. In the latter case set this to
|
||||
* the correct filename *before* your first call to GetAreaCodeInfo.
|
||||
*/
|
||||
#ifdef DATA_FILENAME
|
||||
char* acFileName = DATA_FILENAME;
|
||||
#else
|
||||
char* acFileName = "areacode.dat";
|
||||
#endif
|
||||
|
||||
/* How much dynamic memory is GetAreaCodeInfo allowed to consume? Having less
|
||||
* memory means more disk access and vice versa. The function does even work
|
||||
* if you set this value to zero. For maximum performance, the function needs
|
||||
* 4 byte per area code stored in the data file. The default is 32KB.
|
||||
*/
|
||||
unsigned long acMaxMem = 0x8000L;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data and structures */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Define an unsigned quantity with 32 bits. Try to make some clever
|
||||
* assumptions using the data from limits.h. This may break some older
|
||||
* (non ISO compliant) compilers, but I can't help...
|
||||
*/
|
||||
#if !defined(u32) && defined(ULONG_MAX)
|
||||
# if ULONG_MAX == 4294967295UL
|
||||
# define u32 unsigned long
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(u32) && defined(UINT_MAX)
|
||||
# if UINT_MAX == 4294967295UL
|
||||
# define u32 unsigned
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(u32) && defined(USHRT_MAX)
|
||||
# if USHRT_MAX == 4294967295UL
|
||||
# define u32 unsigned short
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(u32)
|
||||
# define u32 unsigned long
|
||||
#endif
|
||||
|
||||
/* The version of the data file we support */
|
||||
#define acVersion 0x100
|
||||
|
||||
/* The magic words in little and big endian format */
|
||||
#define LittleMagic 0x35465768L
|
||||
#define BigMagic 0x68574635L
|
||||
|
||||
/* Defining the byte ordering */
|
||||
#define boLittleEndian 0
|
||||
#define boBigEndian 1
|
||||
|
||||
/* The byte order used in the file is little endian (intel) format */
|
||||
#define FileByteOrder boLittleEndian
|
||||
|
||||
/* This is the header data of the data file. It is not used anywhere in
|
||||
* the code, just have a look at it since it describes the layout in the
|
||||
* file.
|
||||
*/
|
||||
typedef struct {
|
||||
u32 Magic;
|
||||
u32 Version; /* Version in hi word, build in lo word */
|
||||
u32 Count;
|
||||
u32 AreaCodeStart;
|
||||
u32 NameIndexStart;
|
||||
u32 NameStart;
|
||||
} PrefixHeader;
|
||||
|
||||
/* This is what's really used: */
|
||||
typedef struct {
|
||||
|
||||
/* The file we read from */
|
||||
FILE* F;
|
||||
|
||||
/* Machine byte order */
|
||||
unsigned ByteOrder;
|
||||
|
||||
/* Stuff from the file header */
|
||||
unsigned Version;
|
||||
unsigned Build;
|
||||
u32 Count;
|
||||
u32 AreaCodeStart;
|
||||
u32 NameIndexStart;
|
||||
u32 NameStart;
|
||||
|
||||
/* Control data */
|
||||
long First;
|
||||
long Last;
|
||||
u32* Table;
|
||||
|
||||
} AreaCodeDesc;
|
||||
|
||||
/* Translation table for translation CP850 --> ISO-8859-1. To save some space,
|
||||
* the table covers only values > 127
|
||||
*/
|
||||
#ifdef CHARSET_ISO
|
||||
static char ISOMap [128] = {
|
||||
0xC7, 0xFC, 0xE9, 0xE2, 0xE4, 0xE0, 0xE5, 0xE7,
|
||||
0xEA, 0xEB, 0xE8, 0xEF, 0xEE, 0xEC, 0xC4, 0xC5,
|
||||
0xC9, 0xE6, 0xC6, 0xF4, 0xF6, 0xF2, 0xFC, 0xF9,
|
||||
0xFF, 0xD6, 0xDC, 0xA2, 0xA3, 0xA5, 0x50, 0x66,
|
||||
0xE1, 0xED, 0xF3, 0xFA, 0xF1, 0xD1, 0xAA, 0xBA,
|
||||
0xBF, 0x2D, 0xAC, 0xC6, 0xBC, 0xA1, 0xAB, 0xBB,
|
||||
0xFE, 0xFE, 0xFE, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x7C, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B, 0x2B, 0x2D, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2D, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
|
||||
0x2B, 0x2B, 0x2B, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0x61, 0xDF, 0x63, 0x70, 0x5A, 0x73, 0xB5, 0x74,
|
||||
0x70, 0x54, 0x4F, 0x64, 0x38, 0x30, 0x65, 0x55,
|
||||
0x3D, 0xB1, 0x3E, 0x3C, 0x66, 0x4A, 0xF7, 0x7E,
|
||||
0xB0, 0xB7, 0xB7, 0x2F, 0x6E, 0xB2, 0xFE, 0xFF
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Macro to convert from big endian to little endian format and vice versa.
|
||||
* Beware: The macro evaluates its parameter more than once!
|
||||
*/
|
||||
#define _ByteSwap(__V) ((((__V) & 0x000000FF) << 24) | \
|
||||
(((__V) & 0xFF000000) >> 24) | \
|
||||
(((__V) & 0x0000FF00) << 8) | \
|
||||
(((__V) & 0x00FF0000) >> 8))
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Helper functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static u32 _ByteSwapIfNeeded (u32 D, unsigned ByteOrder)
|
||||
/* Put the bytes into the correct order according to ByteOrder */
|
||||
{
|
||||
/* Swap bytes if needed and return the result */
|
||||
switch (ByteOrder) {
|
||||
case boLittleEndian: return D;
|
||||
default: return _ByteSwap (D);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 ByteSwapIfNeeded (u32 D, const AreaCodeDesc* Desc)
|
||||
/* Put the bytes into the correct order according to ByteOrder in Desc */
|
||||
{
|
||||
/* Swap bytes if needed and return the result */
|
||||
return _ByteSwapIfNeeded (D, Desc->ByteOrder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 _Load_u32 (FILE* F, unsigned ByteOrder)
|
||||
/* Load an u32 from the current file position and swap it if needed */
|
||||
{
|
||||
u32 D;
|
||||
|
||||
/* Read the data from the file */
|
||||
fread (&D, sizeof (D), 1, F);
|
||||
|
||||
/* Swap bytes if needed and return the result */
|
||||
return _ByteSwapIfNeeded (D, ByteOrder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 Load_u32 (const AreaCodeDesc* Desc)
|
||||
/* Load an u32 from the current file position and swap it if needed */
|
||||
{
|
||||
return _Load_u32 (Desc->F, Desc->ByteOrder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned LoadFileHeader (AreaCodeDesc* Desc)
|
||||
/* Load the header of a data file. Return one of the acXXX codes. */
|
||||
{
|
||||
u32 Version;
|
||||
|
||||
/* Load the magic word in the format used int the file (do not convert) */
|
||||
u32 Magic = _Load_u32 (Desc->F, FileByteOrder);
|
||||
|
||||
/* Check what we got from the file, determine the byte order */
|
||||
switch (Magic) {
|
||||
|
||||
case BigMagic:
|
||||
Desc->ByteOrder = boBigEndian;
|
||||
break;
|
||||
|
||||
case LittleMagic:
|
||||
Desc->ByteOrder = boLittleEndian;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* OOPS - the file is probably not a valid data file */
|
||||
return acInvalidFile;
|
||||
|
||||
}
|
||||
|
||||
/* Now read the rest of the header data */
|
||||
Version = Load_u32 (Desc);
|
||||
Desc->Version = (Version >> 16);
|
||||
Desc->Build = (Version & 0xFFFF);
|
||||
Desc->Count = Load_u32 (Desc);
|
||||
Desc->AreaCodeStart = Load_u32 (Desc);
|
||||
Desc->NameIndexStart = Load_u32 (Desc);
|
||||
Desc->NameStart = Load_u32 (Desc);
|
||||
|
||||
/* Check for some error conditions */
|
||||
if (ferror (Desc->F)) {
|
||||
/* Some sort of file problem */
|
||||
return acFileError;
|
||||
} else if (feof (Desc->F) || Desc->Count == 0) {
|
||||
/* This should not happen on a valid file */
|
||||
return acInvalidFile;
|
||||
} else if (Desc->Version != acVersion) {
|
||||
return acWrongVersion;
|
||||
} else {
|
||||
/* Data is sane */
|
||||
return acOk;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 EncodeNumber (const char* Phone)
|
||||
/* Encode the number we got from the caller into the internally used BCD
|
||||
* format.
|
||||
*/
|
||||
{
|
||||
unsigned I;
|
||||
unsigned Len;
|
||||
u32 P = 0; /* Initialize to make gcc happy */
|
||||
|
||||
/* Get the amount of characters to convert */
|
||||
Len = strlen (Phone);
|
||||
if (Len > 8) {
|
||||
Len = 8;
|
||||
}
|
||||
|
||||
/* Convert the characters */
|
||||
for (I = 0; I < Len; I++) {
|
||||
P = (P << 4) | ((unsigned) ((unsigned char) Phone [I]) & 0x0F);
|
||||
}
|
||||
|
||||
/* Fill the rest of the number with 0x0F */
|
||||
I = 8 - Len;
|
||||
while (I--) {
|
||||
P = (P << 4) | 0x0F;
|
||||
}
|
||||
|
||||
/* Done - return the result */
|
||||
return P;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static u32 ReadPhone (const AreaCodeDesc* Desc, long Index)
|
||||
/* Read the phone number that is located at the given index. If we have a
|
||||
* part of the table already loaded into memory, use the memory copy, else
|
||||
* read the phone number from disk.
|
||||
*/
|
||||
{
|
||||
if (Desc->Table && Index >= Desc->First && Index <= Desc->Last) {
|
||||
/* Use the already loaded table, but don't forget to swap bytes */
|
||||
return ByteSwapIfNeeded (Desc->Table [Index - Desc->First], Desc);
|
||||
} else {
|
||||
/* Load the value from the file */
|
||||
fseek (Desc->F, Desc->AreaCodeStart + Index * sizeof (u32), SEEK_SET);
|
||||
return Load_u32 (Desc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void LoadTable (AreaCodeDesc* Desc)
|
||||
/* Load a part of the table into memory */
|
||||
{
|
||||
u32 SpaceNeeded = (Desc->Last - Desc->First + 1) * sizeof (u32);
|
||||
Desc->Table = malloc (SpaceNeeded);
|
||||
if (Desc->Table == 0) {
|
||||
/* Out of memory. There is no problem with this now since we do
|
||||
* not really need the table in core memory (it speeds things up,
|
||||
* that's all). In addition to that, the memory requirement halves
|
||||
* with each iteration, so maybe we have more luck next time.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* Seek to the correct position in the file */
|
||||
fseek (Desc->F, Desc->AreaCodeStart + Desc->First * sizeof (u32), SEEK_SET);
|
||||
|
||||
/* Read the data */
|
||||
fread (Desc->Table, SpaceNeeded, 1, Desc->F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static unsigned CalcCodeLen (u32 Code)
|
||||
/* Calculate the length of a given (encoded) area code in characters */
|
||||
{
|
||||
u32 Mask;
|
||||
unsigned Len = 0;
|
||||
for (Mask = 0xF0000000L; Mask; Mask >>= 4) {
|
||||
if ((Code & Mask) != Mask) {
|
||||
Len++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
unsigned GetAreaCodeInfo (acInfo* AC, const char* PhoneNumber)
|
||||
/* Return - if possible - an information for the area code of the given number.
|
||||
* The function returns one of the error codes defined in areacode.h. If the
|
||||
* returned value is acOk, the AC struct is filled with the data of the
|
||||
* area code found. If we did not have an error, but there is no area code
|
||||
* that corresponds to the given number, the function returns acOk, but the
|
||||
* AC struct is filled with an empty Info field and a AreaCodeLen of zero.
|
||||
*/
|
||||
{
|
||||
u32 Phone; /* PhoneNumber encoded in BCD */
|
||||
long First, Last, Current; /* For binary search */
|
||||
u32 CurrentVal; /* The value at Table [Current] */
|
||||
unsigned AreaCodeLen; /* The length of the area code found */
|
||||
unsigned char InfoLen; /* Length of info string */
|
||||
unsigned RC = acOk; /* Result code of the function */
|
||||
u32 Mask;
|
||||
AreaCodeDesc Desc;
|
||||
|
||||
|
||||
/* Clear the fields of the AC struct. Write a zero to the last field of
|
||||
* Info - this field is never written to by the rest of the code. So by
|
||||
* setting this to zero, we will assure a terminated string in case some
|
||||
* problem prevents the code below from executing correctly.
|
||||
*/
|
||||
AC->Info [0] = '\0';
|
||||
AC->Info [sizeof (AC->Info) - 1] = '\0';
|
||||
AC->AreaCodeLen = 0;
|
||||
|
||||
/* If the number is empty, return immidiately */
|
||||
if (strlen (PhoneNumber) == 0) {
|
||||
return acOk;
|
||||
}
|
||||
|
||||
/* Open the database file, check for errors */
|
||||
Desc.F = fopen (acFileName, "rb");
|
||||
if (Desc.F == 0) {
|
||||
/* We had an error opening the file */
|
||||
return acFileError;
|
||||
}
|
||||
|
||||
/* Initialize descriptor data where needed */
|
||||
Desc.Table = 0;
|
||||
|
||||
/* Read the header from the file */
|
||||
RC = LoadFileHeader (&Desc);
|
||||
if (RC != acOk) {
|
||||
/* Wrong file or file read error */
|
||||
goto ExitWithClose;
|
||||
}
|
||||
|
||||
/* Convert the phone number into the internal representation */
|
||||
Phone = EncodeNumber (PhoneNumber);
|
||||
|
||||
/* Add dead code to work around gcc warnings */
|
||||
Current = 0;
|
||||
CurrentVal = 0;
|
||||
|
||||
/* Now do a binary search over the data */
|
||||
First = 0;
|
||||
Last = (long) Desc.Count - 1;
|
||||
while (First <= Last) {
|
||||
|
||||
/* If we don't have read the table into memory, check if we can do
|
||||
* so now.
|
||||
*/
|
||||
if (Desc.Table == 0) {
|
||||
u32 NeedMemory = (Last - First + 1) * sizeof (u32);
|
||||
if (NeedMemory <= acMaxMem) {
|
||||
/* Ok, the current part of the table is now small enough to
|
||||
* load it into memory.
|
||||
*/
|
||||
Desc.First = First;
|
||||
Desc.Last = Last;
|
||||
LoadTable (&Desc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set current to mid of range */
|
||||
Current = (Last + First) / 2;
|
||||
|
||||
/* Get the phone number from that place */
|
||||
CurrentVal = ReadPhone (&Desc, Current);
|
||||
|
||||
/* Do a compare */
|
||||
if (Phone > CurrentVal) {
|
||||
First = Current + 1;
|
||||
} else {
|
||||
Last = Current - 1;
|
||||
if (Phone == CurrentVal) {
|
||||
/* Set the condition to terminate the loop */
|
||||
First = Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* First is the index of the area code, we eventually found. Put the index
|
||||
* into Current and the value into CurrentVal.
|
||||
*/
|
||||
if (Current != First) {
|
||||
Current = First;
|
||||
CurrentVal = ReadPhone (&Desc, Current);
|
||||
}
|
||||
|
||||
/*
|
||||
* We may now delete an eventually allocated table space since it is
|
||||
* not needed any more.
|
||||
*/
|
||||
free (Desc.Table);
|
||||
Desc.Table = 0;
|
||||
|
||||
/* If Current points behind Last, we did not find anything */
|
||||
if (Current >= (long) Desc.Count) {
|
||||
/* Not found */
|
||||
goto ExitWithClose;
|
||||
}
|
||||
|
||||
/* Calculate the length of the area code */
|
||||
AreaCodeLen = CalcCodeLen (CurrentVal);
|
||||
|
||||
/* Check if the Prefix is actually the first part of the phone number */
|
||||
Mask = 0xFFFFFFFFL << ((8 - AreaCodeLen) * 4);
|
||||
if ((Phone & Mask) != (CurrentVal & Mask)) {
|
||||
/* They are different */
|
||||
goto ExitWithClose;
|
||||
}
|
||||
|
||||
/* Ok, we have now definitely found the code. Set up the data structure,
|
||||
* we return to the caller.
|
||||
*/
|
||||
AC->AreaCodeLen = AreaCodeLen;
|
||||
|
||||
/* Current is the index of the area code. Seek to the corresponding
|
||||
* position in the name index, get the name position from there and seek
|
||||
* to that place.
|
||||
*/
|
||||
fseek (Desc.F, Desc.NameIndexStart + Current * sizeof (u32), SEEK_SET);
|
||||
fseek (Desc.F, Desc.NameStart + Load_u32 (&Desc), SEEK_SET);
|
||||
|
||||
/* Read the length of the name and add the trailing zero to the info
|
||||
* field in the result struct.
|
||||
*/
|
||||
fread (&InfoLen, 1, 1, Desc.F);
|
||||
AC->Info [InfoLen] = '\0';
|
||||
|
||||
/* Read the info into the result struct */
|
||||
fread (AC->Info, 1, InfoLen, Desc.F);
|
||||
|
||||
#ifdef CHARSET_ISO
|
||||
/* Translate the info to the ISO-8859-1 charset */
|
||||
{
|
||||
unsigned I;
|
||||
for (I = 0; I < InfoLen; I++) {
|
||||
unsigned char C = (unsigned char) AC->Info [I];
|
||||
if (C >= 128) {
|
||||
AC->Info [I] = ISOMap [C - 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ExitWithClose:
|
||||
/* Close the data file */
|
||||
fclose (Desc.F);
|
||||
|
||||
/* Done, return the result */
|
||||
return RC;
|
||||
}
|
||||
|
||||
|
||||
|
Binary file not shown.
|
@ -0,0 +1,165 @@
|
|||
|
||||
AREACODE
|
||||
|
||||
|
||||
Portable library module to search for an area code in a database.
|
||||
|
||||
Version 1.01
|
||||
|
||||
(C) Copyright 1996,97 by Ullrich von Bassewitz
|
||||
<uz@musoftware.com>
|
||||
|
||||
|
||||
|
||||
1. Overview
|
||||
-----------
|
||||
|
||||
The areacode module together with its database serves as a helper for
|
||||
finding names for area codes. It is freely available, subject to the
|
||||
copyright notice below.
|
||||
|
||||
|
||||
|
||||
2. Function
|
||||
-----------
|
||||
|
||||
The module exports a few data types and one function. The function resolves
|
||||
a phone number (including the country code) to some text describing the area
|
||||
code found in the phone number. Current descriptions are in german, the
|
||||
database contains german, swiss and austrian area codes.
|
||||
|
||||
Usage is easy, just have a look into the header file areacode.h.
|
||||
|
||||
|
||||
|
||||
3. Supported systems and limitations
|
||||
------------------------------------
|
||||
|
||||
The module should run on nearly all system that have the following
|
||||
characteristics:
|
||||
|
||||
* 8 bit bytes
|
||||
|
||||
* An unsigned data type with 32 bits. The code makes some checks with the
|
||||
values in limits.h to find such a datatype for itself, if all checks
|
||||
fail, unsigned long is used. This may be overriden by #defining the
|
||||
macro u32 to the datatype needed.
|
||||
|
||||
* An ANSI compatible compiler supporting prototypes. The code should also
|
||||
compile with a C++ compiler, the header file uses the #ifdef __cpluplus
|
||||
checks.
|
||||
|
||||
* Big or little endian architectures. For something more weird (old
|
||||
Vaxes?) code has to be added.
|
||||
|
||||
* Systems with CP437, CP850 or ISO-8859-1 character sets. The "native"
|
||||
format is CP850/CP437, for ISO-8859-1, the #define CHARSET_ISO has to
|
||||
be added when compiling the module.
|
||||
|
||||
The code has been tested under
|
||||
|
||||
* DOS (Watcom C/C++ 10.6)
|
||||
|
||||
* Windows-NT (Watcom C/C++ 10.6)
|
||||
|
||||
* OS/2 2.x (Watcom C/C++ 10.6)
|
||||
|
||||
* i386-Linux (gcc 2.7.2)
|
||||
|
||||
For these environments makefiles can be found in the make subdirectory.
|
||||
|
||||
The package has some limits as stated below:
|
||||
|
||||
* Current language is german.
|
||||
|
||||
* The data file contains area codes for germany and switzerland.
|
||||
|
||||
* The area code including the country code (but not including the
|
||||
international prefix, often 00) may not exceed 8 digits. This may be
|
||||
bumped up to 9 digits if needed with some disadvantages (more
|
||||
complicated code).
|
||||
|
||||
* An area code description must be shorter than 256 characters.
|
||||
|
||||
|
||||
|
||||
4. How to get the source & data files
|
||||
-------------------------------------
|
||||
|
||||
You may get the source for the package itself, for the datafile builder and
|
||||
for new datafiles from
|
||||
|
||||
ftp://ftp.musoftware.com/areacode
|
||||
|
||||
Note: Please do not distribute modified data files. The data files contain
|
||||
a version stamp to make shure, users don't overwrite newer versions with
|
||||
older ones. This scheme will no longer work if data files are distributed
|
||||
by third parties.
|
||||
|
||||
Note: The datafile builder needs spunk, a C++ class library to compile.
|
||||
You may want to have a look in
|
||||
|
||||
ftp://ftp.musoftwware.com/spunk
|
||||
|
||||
for the current spunk version.
|
||||
|
||||
|
||||
|
||||
5. Installing the package
|
||||
-------------------------
|
||||
|
||||
For all systems the location of the data file has to be known. The default
|
||||
name (including the path) may be compiled into the module by #defining
|
||||
DATA_FILENAME, or set at runtime (see areacode.h).
|
||||
The Linux makefile will install the data file in a common place, so more
|
||||
than one software package depending on areacode is able to use the data file.
|
||||
|
||||
The data file contains a version stamp, to avoid overwriting a newer file
|
||||
by an older one, when installing more than one software package. The
|
||||
program acvers is used to determine the build version, it will output three
|
||||
numbers, the last one is the data file build (the first two are format
|
||||
version numbers that - hopefully - will not change).
|
||||
|
||||
|
||||
|
||||
6. Copying
|
||||
----------
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
|
||||
|
||||
7. Credits
|
||||
----------
|
||||
|
||||
Many thanks to all people that helped developing the module:
|
||||
|
||||
|
||||
Andreas Kool (akool@kool.f.eunet.de), author of isdnlog,
|
||||
for many suggestions and code testing.
|
||||
|
||||
Norbert Staudt (VKRG.Staudt@t-online.de),
|
||||
who sent me lots of sample programs resolving area codes.
|
||||
|
||||
Andreas Gutzwiller (andy@hippo.proxyon.imp.com),
|
||||
for the swiss area codes.
|
||||
|
||||
Alois Schneider (Alois.Schneider@magnet.at),
|
||||
for the austrian area codes.
|
||||
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*****************************************************************************/
|
||||
/* */
|
||||
/* AREACODE.H */
|
||||
/* */
|
||||
/* Portable library module to search for an area code in a database. */
|
||||
/* */
|
||||
/* */
|
||||
/* */
|
||||
/* (C) 1996,97 Ullrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.com */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any express or implied */
|
||||
/* warranty. In no event will the authors be held liable for any damages */
|
||||
/* arising from the use of this software. */
|
||||
/* */
|
||||
/* Permission is granted to anyone to use this software for any purpose, */
|
||||
/* including commercial applications, and to alter it and redistribute it */
|
||||
/* freely, subject to the following restrictions: */
|
||||
/* */
|
||||
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||
/* claim that you wrote the original software. If you use this software */
|
||||
/* in a product, an acknowledgment in the product documentation would be */
|
||||
/* appreciated but is not required. */
|
||||
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||
/* be misrepresented as being the original software. */
|
||||
/* 3. This notice may not be removed or altered from any source */
|
||||
/* distribution. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The code assumes
|
||||
* - 8 bit bytes
|
||||
* - unsigned long is 32 bit. This may be changed by #defining u32 to
|
||||
* a data type that is an 32 bit unsigned when compiling this module.
|
||||
* - ascii character set
|
||||
*
|
||||
* The code does *not* assume
|
||||
* - a specific byte order. Currently the code autoadjusts to big or
|
||||
* little endian data. If you have something more weird than that,
|
||||
* you have to add conversion code.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _AREACODE_H
|
||||
#define _AREACODE_H
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data, structs and constants */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* The name of the areacode data file. The default is what is #defined as
|
||||
* DATA_FILENAME. If this is not #defined, the default is "areacode.dat",
|
||||
* which is probably not what you want. In the latter case set this to
|
||||
* the correct filename *before* your first call to GetAreaCodeInfo.
|
||||
*/
|
||||
extern char* acFileName;
|
||||
|
||||
/* How much dynamic memory is GetAreaCodeInfo allowed to consume? Having less
|
||||
* memory means more disk access and vice versa. The function does even work
|
||||
* if you set this value to zero. For maximum performance, the function needs
|
||||
* 4 byte per area code stored in the data file. The default is 32KB.
|
||||
*/
|
||||
extern unsigned long acMaxMem;
|
||||
|
||||
/* Result codes of GetAreaCodeInfo */
|
||||
#define acOk 0 /* Done */
|
||||
#define acFileError 1 /* Cannot open/read file */
|
||||
#define acInvalidFile 2 /* The file exists but is no area code data file */
|
||||
#define acWrongVersion 3 /* Wrong version of data file */
|
||||
|
||||
/* The result of an area code search */
|
||||
typedef struct {
|
||||
unsigned AreaCodeLen; /* The length of the area code found */
|
||||
char Info [256]; /* An info string */
|
||||
} acInfo;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
unsigned GetAreaCodeInfo (acInfo* /*AC*/ , const char* /*PhoneNumber*/);
|
||||
/* Return - if possible - an information for the area code of the given number.
|
||||
* The function returns one of the error codes defined in areacode.h. If the
|
||||
* returned value is acOk, the AC struct is filled with the data of the
|
||||
* area code found. If we did not have an error, but there is no area code
|
||||
* that corresponds to the given number, the function returns acOk, but the
|
||||
* AC struct is filled with an empty Info field and a AreaCodeLen of zero.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* End of AREACODE.H */
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue