Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5e08e49

Browse files
committed
contrib/isn updates from Jeremy Kronuz.
1 parentf5b4d9a commit5e08e49

File tree

4 files changed

+224
-73
lines changed

4 files changed

+224
-73
lines changed

‎contrib/isn/README.isn

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

2-
EAN13 - UPC - ISBN (books) - ISMN (music) - ISSN (serials)
3-
----------------------------------------------------------
2+
--EAN13 - UPC - ISBN (books) - ISMN (music) - ISSN (serials)
3+
-------------------------------------------------------------
44

55
Copyright Germ�n M�ndez Bravo (Kronuz), 2004 - 2006
66
This module is released under the same BSD license as the rest of PostgreSQL.
@@ -24,7 +24,7 @@ THIS MODULE IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
2424
OF ANY KIND, EXPRESS OR IMPLIED.
2525
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2626

27-
Content of the Module
27+
--Content of the Module
2828
-------------------------------------------------
2929

3030
This directory contains definitions for a few PostgreSQL
@@ -143,7 +143,7 @@ On success:
143143

144144
(on failure, the functions 'ereport' the error)
145145

146-
Testing/Playing Functions
146+
--Testing/Playing Functions
147147
-------------------------------------------------
148148
isn_weak(boolean) - Sets the weak input mode.
149149
This function is intended for testing use only!
@@ -173,17 +173,20 @@ To work with invalid numbers, you can use two functions:
173173
+ make_valid(), which validates an invalid number (deleting the invalid flag)
174174
+ is_valid(), which checks for the invalid flag presence.
175175

176-
Examples of Use
176+
--Examples of Use
177177
-------------------------------------------------
178178
--Using the types directly:
179179
select isbn('978-0-393-04002-9');
180180
select isbn13('0901690546');
181181
select issn('1436-4522');
182182

183183
--Casting types:
184-
-- note that you can't cast from ean13 to other type, thus the following
185-
-- will NOT work: select upc(ean13('0220356483481'));
186-
select ean13(upc('220356483481'));
184+
-- note that you can only cast from ean13 to other type when the casted
185+
-- number would be valid in the realm of the casted type;
186+
-- thus, the following will NOT work: select isbn(ean13('0220356483481'));
187+
-- but these will:
188+
select upc(ean13('0220356483481'));
189+
select ean13(upc('220356483481'));
187190

188191
--Create a table with a single column to hold ISBN numbers:
189192
create table test ( id isbn );
@@ -210,7 +213,7 @@ Examples of Use
210213

211214
select isbn13(id) from test;
212215

213-
Contact
216+
--Contact
214217
-------------------------------------------------
215218
Please suggestions or bug reports to kronuz at users.sourceforge.net
216219

‎contrib/isn/isn.c

Lines changed: 164 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.1 2006/09/09 04:07:52 tgl Exp $
10+
* $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.2 2006/09/10 20:45:17 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -31,7 +31,7 @@ PG_MODULE_MAGIC;
3131

3232
enumisn_type {INVALID,ANY,EAN13,ISBN,ISMN,ISSN,UPC };
3333

34-
staticconstchar*isn_names[]= {"ISN","ISN","EAN13","ISBN","ISMN","ISSN","UPC" };
34+
staticconstchar*isn_names[]= {"EAN13/UPC/ISxN","EAN13/UPC/ISxN","EAN13","ISBN","ISMN","ISSN","UPC" };
3535

3636
staticboolg_weak= false;
3737
staticboolg_initialized= false;
@@ -43,11 +43,11 @@ static bool g_initialized = false;
4343

4444
/***********************************************************************
4545
**
46-
**Routines forISNs.
46+
**Routines forEAN13/UPC/ISxNs.
4747
**
4848
** Note:
4949
** In this code, a normalized string is one that is known to be a valid
50-
**ISN number containing only digits and hyphens and with enough space
50+
**ISxN number containing only digits and hyphens and with enough space
5151
** to hold the full 13 digits plus the maximum of four hyphens.
5252
***********************************************************************/
5353

@@ -217,7 +217,7 @@ unsigned hyphenate(char *bufO, char *bufI, const char *(*TABLE)[2], const unsign
217217
}
218218

219219
/*
220-
* weight_checkdig -- Receives a buffer with a normalizedISN string number,
220+
* weight_checkdig -- Receives a buffer with a normalizedISxN string number,
221221
* and the length to weight.
222222
*
223223
* Returns the weight of the number (the check digit value, 0-10)
@@ -239,7 +239,7 @@ unsigned weight_checkdig(char *isn, unsigned size)
239239

240240

241241
/*
242-
* checkdig --- Receives a buffer with a normalizedISN string number,
242+
* checkdig --- Receives a buffer with a normalizedISxN string number,
243243
* and the length to check.
244244
*
245245
* Returns the check digit value (0-9)
@@ -267,8 +267,94 @@ unsigned checkdig(char *num, unsigned size)
267267
}
268268

269269
/*
270-
* ean2isn --- Convert in-place a normalized EAN13 string to the corresponding
271-
* ISN string number. Assumes the input string is normalized.
270+
* ean2isn --- Try to convert an ean13 number to a UPC/ISxN number.
271+
* This doesn't verify for a valid check digit.
272+
*
273+
* If errorOK is false, ereport a useful error message if the ean13 is bad.
274+
* If errorOK is true, just return "false" for bad input.
275+
*/
276+
static
277+
boolean2isn(ean13ean,boolerrorOK,ean13*result,enumisn_typeaccept)
278+
{
279+
enumisn_typetype=INVALID;
280+
281+
charbuf[MAXEAN13LEN+1];
282+
char*firstdig,*aux;
283+
unsigneddigval;
284+
unsignedsearch;
285+
ean13ret=ean;
286+
287+
ean >>=1;
288+
/* verify it's in the EAN13 range */
289+
if(ean>UINT64CONST(9999999999999))
290+
gotoeantoobig;
291+
292+
/* convert the number */
293+
search=0;
294+
firstdig=aux=buf+13;
295+
*aux='\0';/* terminate string; aux points to last digit */
296+
do {
297+
digval= (unsigned)(ean %10);/* get the decimal value */
298+
ean /=10;/* get next digit */
299+
*--aux= (char)(digval+'0');/* convert to ascii and store */
300+
}while(ean&&search++<12);
301+
while(search++<12)*--aux='0';/* fill the remaining EAN13 with '0' */
302+
303+
/* find out the data type: */
304+
if(!strncmp("978",buf,3)) {/* ISBN */
305+
type=ISBN;
306+
}elseif(!strncmp("977",buf,3)) {/* ISSN */
307+
type=ISSN;
308+
}elseif(!strncmp("9790",buf,4)) {/* ISMN */
309+
type=ISMN;
310+
}elseif(!strncmp("979",buf,3)) {/* ISBN-13 */
311+
type=ISBN;
312+
}elseif(*buf=='0') {/* UPC */
313+
type=UPC;
314+
}else {
315+
type=EAN13;
316+
}
317+
if(accept!=ANY&&accept!=EAN13&&accept!=type) gotoeanwrongtype;
318+
319+
*result=ret;
320+
return true;
321+
322+
eanwrongtype:
323+
if(!errorOK) {
324+
if(type!=EAN13) {
325+
ereport(ERROR,
326+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
327+
errmsg("cannot cast EAN13(%s) to %s for number: \"%s\"",
328+
isn_names[type],isn_names[accept],buf)));
329+
}else {
330+
ereport(ERROR,
331+
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
332+
errmsg("cannot cast %s to %s for number: \"%s\"",
333+
isn_names[type],isn_names[accept],buf)));
334+
}
335+
}
336+
return false;
337+
338+
eantoobig:
339+
if(!errorOK) {
340+
chareanbuf[64];
341+
342+
/*
343+
* Format the number separately to keep the machine-dependent
344+
* format code out of the translatable message text
345+
*/
346+
snprintf(eanbuf,sizeof(eanbuf),EAN13_FORMAT,ean);
347+
ereport(ERROR,
348+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
349+
errmsg("value \"%s\" is out of range for %s type",
350+
eanbuf,isn_names[type])));
351+
}
352+
return false;
353+
}
354+
355+
/*
356+
* ean2UPC/ISxN --- Convert in-place a normalized EAN13 string to the corresponding
357+
* UPC/ISxN string number. Assumes the input string is normalized.
272358
*/
273359
staticinline
274360
voidean2ISBN(char*isn)
@@ -325,7 +411,8 @@ ean13 str2ean(const char *num)
325411
{
326412
ean13ean=0;/* current ean */
327413
while(*num) {
328-
ean=10*ean+ ((*num++)-'0');
414+
if(isdigit(*num))ean=10*ean+ (*num-'0');
415+
num++;
329416
}
330417
return (ean<<1);/* also give room to a flag */
331418
}
@@ -336,7 +423,7 @@ ean13 str2ean(const char *num)
336423
* the string (maximum MAXEAN13LEN+1 bytes)
337424
* This doesn't verify for a valid check digit.
338425
*
339-
* If shortType is true, the returned string is in the oldISN short format.
426+
* If shortType is true, the returned string is in the oldISxN short format.
340427
* If errorOK is false, ereport a useful error message if the string is bad.
341428
* If errorOK is true, just return "false" for bad input.
342429
*/
@@ -369,8 +456,8 @@ bool ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
369456
digval= (unsigned)(ean %10);/* get the decimal value */
370457
ean /=10;/* get next digit */
371458
*--aux= (char)(digval+'0');/* convert to ascii and store */
372-
if(++search==1)*--aux='-';/* the check digit is always there */
373-
}while(ean);
459+
if(search==0)*--aux='-';/* the check digit is always there */
460+
}while(ean&&search++<13);
374461
while(search++<13)*--aux='0';/* fill the remaining EAN13 with '0' */
375462

376463
/* The string should be in this form: ???DDDDDDDDDDDD-D" */
@@ -409,7 +496,7 @@ bool ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
409496
TABLE_index=NULL;
410497
}
411498

412-
/* verify it's a logically valid EAN13/ISN */
499+
/* verify it's a logically valid EAN13/UPC/ISxN */
413500
digval=search;
414501
search=hyphenate(result+digval,result+digval+2,TABLE,TABLE_index);
415502

@@ -452,8 +539,8 @@ bool ean2string(ean13 ean, bool errorOK, char *result, bool shortType)
452539
snprintf(eanbuf,sizeof(eanbuf),EAN13_FORMAT,ean);
453540
ereport(ERROR,
454541
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
455-
errmsg("value \"%s\" is out of range forISN type",
456-
eanbuf)));
542+
errmsg("value \"%s\" is out of range for%s type",
543+
eanbuf,isn_names[type])));
457544
}
458545
return false;
459546
}
@@ -483,7 +570,7 @@ bool string2ean(const char *str, bool errorOK, ean13 *result,
483570
/* recognize and validate the number: */
484571
while(*aux2&&length <=13) {
485572
last= (*(aux2+1)=='!'||*(aux2+1)=='\0');/* is the last character */
486-
digit=isdigit(*aux2);/* is current character a digit? */
573+
digit=(isdigit(*aux2)!=0);/* is current character a digit? */
487574
if(*aux2=='?'&&last)/* automagically calculate check digit if it's '?' */
488575
magic=digit= true;
489576
if(length==0&& (*aux2=='M'||*aux2=='m')) {
@@ -583,19 +670,25 @@ bool string2ean(const char *str, bool errorOK, ean13 *result,
583670
break;
584671
}
585672

586-
if(!valid&& !magic) gotoeanbadcheck;
587-
673+
/* fix the check digit: */
588674
for(aux1=buf;*aux1&&*aux1 <=' ';aux1++);
589675
aux1[12]=checkdig(aux1,13)+'0';
590676
aux1[13]='\0';
591677

678+
if(!valid&& !magic) gotoeanbadcheck;
679+
592680
*result=str2ean(aux1);
593681
*result |=valid?0:1;
594-
595682
return true;
596683

597684
eanbadcheck:
598-
if(!g_weak) {
685+
if(g_weak) {/* weak input mode is activated: */
686+
/* set the "invalid-check-digit-on-input" flag */
687+
*result=str2ean(aux1);
688+
*result |=1;
689+
return true;
690+
}
691+
599692
if(!errorOK) {
600693
if(rcheck== (unsigned)-1) {
601694
ereport(ERROR,
@@ -610,30 +703,6 @@ bool string2ean(const char *str, bool errorOK, ean13 *result,
610703
}
611704
}
612705
return false;
613-
}
614-
615-
if(accept!=EAN13&&accept!=ANY&&type!=accept) gotoeanwrongtype;
616-
617-
/* fix the check digit: */
618-
for(aux1=buf;*aux1&&*aux1 <=' ';aux1++);
619-
aux1[12]=checkdig(aux1,13)+'0';
620-
aux1[13]='\0';
621-
*result=str2ean(aux1);
622-
623-
/* set the "invalid-check-digit-on-input" flag */
624-
*result |=1;
625-
626-
/* just warn about the error when there was a real check digit error: */
627-
if(check!=rcheck) {
628-
if(rcheck== (unsigned)-1) {
629-
elog(WARNING,"invalid %s number: \"%s\"",
630-
isn_names[accept],str);
631-
}else {
632-
elog(WARNING,"invalid check digit for %s number: \"%s\", should be %c",
633-
isn_names[accept],str, (rcheck==10)?('X'):(rcheck+'0'));
634-
}
635-
}
636-
return true;
637706

638707
eaninvalid:
639708
if(!errorOK)
@@ -647,8 +716,8 @@ bool string2ean(const char *str, bool errorOK, ean13 *result,
647716
if(!errorOK)
648717
ereport(ERROR,
649718
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
650-
errmsg("invalid%stype for number: \"%s\"",
651-
isn_names[accept],str)));
719+
errmsg("cannot cast%sto %s for number: \"%s\"",
720+
isn_names[type],isn_names[accept],str)));
652721
return false;
653722

654723
eantoobig:
@@ -804,6 +873,55 @@ isn_cast_to_text(PG_FUNCTION_ARGS)
804873
PG_RETURN_TEXT_P(GET_TEXT(buf));
805874
}
806875

876+
PG_FUNCTION_INFO_V1(isbn_cast_from_ean13);
877+
Datum
878+
isbn_cast_from_ean13(PG_FUNCTION_ARGS)
879+
{
880+
ean13val=PG_GETARG_EAN13(0);
881+
ean13result;
882+
883+
(void)ean2isn(val, false,&result,ISBN);
884+
885+
PG_RETURN_EAN13(result);
886+
}
887+
888+
PG_FUNCTION_INFO_V1(ismn_cast_from_ean13);
889+
Datum
890+
ismn_cast_from_ean13(PG_FUNCTION_ARGS)
891+
{
892+
ean13val=PG_GETARG_EAN13(0);
893+
ean13result;
894+
895+
(void)ean2isn(val, false,&result,ISMN);
896+
897+
PG_RETURN_EAN13(result);
898+
}
899+
900+
PG_FUNCTION_INFO_V1(issn_cast_from_ean13);
901+
Datum
902+
issn_cast_from_ean13(PG_FUNCTION_ARGS)
903+
{
904+
ean13val=PG_GETARG_EAN13(0);
905+
ean13result;
906+
907+
(void)ean2isn(val, false,&result,ISSN);
908+
909+
PG_RETURN_EAN13(result);
910+
}
911+
912+
PG_FUNCTION_INFO_V1(upc_cast_from_ean13);
913+
Datum
914+
upc_cast_from_ean13(PG_FUNCTION_ARGS)
915+
{
916+
ean13val=PG_GETARG_EAN13(0);
917+
ean13result;
918+
919+
(void)ean2isn(val, false,&result,UPC);
920+
921+
PG_RETURN_EAN13(result);
922+
}
923+
924+
807925
PG_FUNCTION_INFO_V1(ean13_cast_from_text);
808926
Datum
809927
ean13_cast_from_text(PG_FUNCTION_ARGS)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp