グローバル関数 ローカル関数
mssVadd
mssVclear
mssVclearMax
mssVclearMin
mssVcmp
mssVcntDown
mssVcntUp
mssVd2i
mssVd2s
mssVdbl2d
mssVdbl2i
mssVdbl2s
mssVdiv
mssVi2d
mssVi2s
mssVinit
mssVint2d
mssVint2i
mssVint2s
mssVmax
mssVmin
mssVmod
mssVmul
mssVs2d
mssVs2i
mssVsqrt
mssVstr2d
mssVstr2i
mssVstr2s
mssVsub
mssVwrite
mssVwriteDbl
mssVwriteInt
mssVwriteStr
errorDiffType
errorInvalidType
0001: /**
0002: * # CHAPTER #
0003: * ============================================================================
0004: * MUSASHIで用いられるMssValue型に関する関数
0005: * ============================================================================
0006: * NULLに対する演算は全てNULL
0007: */
0008:
0009:
0010: #include <mssValue.h>
0011: #include <mssBase.h>
0012:
0013: #include <stdio.h>
0014: #include <stdlib.h>
0015: #include <string.h>
0016: #include <ctype.h>
0017: #include <sys/types.h>
0018: #include <sys/time.h>
0019: #include <regex.h>
0020: #include <math.h>
0021: #include <errno.h>
0022: #include <limits.h>
0023: #include <float.h>
0024:
0025:
0026: /**
0027: * # FUNCTION #
0028: * MssValueの初期化
0029: * MssValueを0クリアし、指定のデータタイプをセットする。
0030: */
0031: void mssVinit(MssValue *v, enum vType vType)
0032: {
0033: v->vType=vType;
0034: mssVclear(v);
0035: }
0036:
0037: /**
0038: * # FUNCTION #
0039: * MssValueの0クリア
0040: */
0041: void mssVclear(MssValue *v)
0042: {
0043: v->nul=0;
0044: v->v.d=0; /*最もサイズの大きい型(double)で初期化*/
0045: }
0046:
0047: /**
0048: * # FUNCTION #
0049: * MssValueの型に応じた最小値でのクリア
0050: * INT型:INT_MINに設定
0051: * DBL型:-DBL_MAXに設定
0052: * その他の型:NULLをセット
0053: */
0054: void mssVclearMin(MssValue *v)
0055: {
0056: v->nul=0;
0057: switch(v->vType){
0058: case INT: v->v.i= INT_MIN; break;
0059: case DBL: v->v.d=-DBL_MAX; break;
0060: default : MssVnull(*v); break;
0061: }
0062: }
0063:
0064: /**
0065: * # FUNCTION #
0066: * MssValueの型に応じた最大値でのクリア
0067: * INT型:INT_MAXに設定
0068: * DBL型:DBL_MAXに設定
0069: * その他の型:NULLをセット
0070: */
0071: void mssVclearMax(MssValue *v)
0072: {
0073: v->nul=0;
0074: switch(v->vType){
0075: case INT: v->v.i= INT_MAX; break;
0076: case DBL: v->v.d= DBL_MAX; break;
0077: default : MssVnull(*v); break;
0078: }
0079: }
0080:
0081: /**
0082: * # FUNCTION #
0083: * int型をMssValueのINT型に変換
0084: */
0085: MssValue mssVint2i(int i)
0086: {
0087: MssValue v;
0088:
0089: mssVinit(&v,INT);
0090: v.v.i=i;
0091: return(v);
0092: }
0093:
0094: /**
0095: * # FUNCTION #
0096: *int型をMssValueのDBL型に変換
0097: */
0098: MssValue mssVint2d(int i)
0099: {
0100: MssValue v;
0101:
0102: mssVinit(&v,DBL);
0103: v.v.d=(double)i;
0104: return(v);
0105: }
0106:
0107: /**
0108: * # FUNCTION #
0109: * int型をMssValueのSTR型に変換
0110: * MssValueのSTR型に新たに文字列領域を確保する。
0111: */
0112: MssValue mssVint2s(int i)
0113: {
0114: MssValue v;
0115:
0116: mssVinit(&v,STR);
0117: v.v.s=mssItoA(i);
0118: return(v);
0119: }
0120:
0121: /**
0122: * # FUNCTION #
0123: * double型をMssValueのINT型に変換
0124: */
0125: MssValue mssVdbl2i(double d)
0126: {
0127: MssValue v;
0128:
0129: mssVinit(&v,INT);
0130: v.v.i=(int)d;
0131: return(v);
0132: }
0133:
0134: /**
0135: * # FUNCTION #
0136: * double型をMssValueのDBL型に変換
0137: */
0138: MssValue mssVdbl2d(double d)
0139: {
0140: MssValue v;
0141:
0142: mssVinit(&v,DBL);
0143: v.v.d=d;
0144: return(v);
0145: }
0146:
0147: /**
0148: * # FUNCTION #
0149: * double型をMssValueのSTR型に変換
0150: * MssValueのSTR型に新たに文字列領域を確保する。
0151: */
0152: MssValue mssVdbl2s(double d)
0153: {
0154: MssValue v;
0155:
0156: mssVinit(&v,STR);
0157: v.v.s=mssFtoA(d);
0158: return(v);
0159: }
0160:
0161: /**
0162: * # FUNCTION #
0163: * 文字列型(char *)をMssValueのINT型に変換
0164: * 文字列の先頭が"*"(NULL値)の時は、MssValueもNULLにセットする。
0165: * 変換にはatoi関数を利用している。
0166: */
0167: MssValue mssVstr2i(char *str)
0168: {
0169: MssValue v;
0170:
0171: mssVinit(&v,INT);
0172:
0173: if(MssIsNull(str)){
0174: MssVnull(v);
0175: }else{
0176: v.v.i=atoi(str);
0177: }
0178: return(v);
0179: }
0180:
0181: /**
0182: * # FUNCTION #
0183: * 文字列型(char *)をMssValueのDBL型に変換
0184: * 文字列の先頭が"*"(NULL値)の時は、MssValueもNULLにセットする。
0185: * 変換にはatof関数を利用している。
0186: */
0187: MssValue mssVstr2d(char *str)
0188: {
0189: MssValue v;
0190:
0191: mssVinit(&v,DBL);
0192:
0193: if(MssIsNull(str)){
0194: MssVnull(v);
0195: }else{
0196: v.v.d=atof(str);
0197: }
0198: return(v);
0199: }
0200:
0201: /**
0202: * # FUNCTION #
0203: * 文字列型(char *)をMssValueのSTR型に変換
0204: * 文字列の先頭が"*"(NULL値)の時は、MssValueもNULLにセットする。
0205: * 新たに文字領域をコピーすることはしない。
0206: * すなわち、単に引数strのアドレスをセットするだけ。
0207: */
0208: MssValue mssVstr2s(char *str)
0209: {
0210: MssValue v;
0211:
0212: mssVinit(&v,STR);
0213:
0214: if(MssIsNull(str)){
0215: MssVnull(v);
0216: }else{
0217: v.v.s=str;
0218: }
0219: return(v);
0220: }
0221:
0222: /**
0223: * # FUNCTION #
0224: * 引数の型が合わない場合の、エラーメッセージ&終了
0225: */
0226: static void errorInvalidType(char *msg)
0227: {
0228: mssShowErrMsg("internal error: invalid type of value is assigned: %s",msg);
0229: mssEnd(mssErrorNoDefault);
0230: }
0231:
0232: /**
0233: * # FUNCTION #
0234: * MssValueのINT型をMssValueのDBL型に変換
0235: */
0236: MssValue mssVi2d(MssValue v)
0237: {
0238:
0239: if(v.vType!=INT) errorInvalidType("mssVi2d");
0240:
0241: v.vType=DBL;
0242:
0243: if(!v.nul){
0244: v.v.d=(double)v.v.i;
0245: }
0246: return(v);
0247: }
0248:
0249: /**
0250: * # FUNCTION #
0251: * MssValueのINT型をMssValueのSTR型に変換
0252: */
0253: MssValue mssVi2s(MssValue v)
0254: {
0255:
0256: if(v.vType!=INT) errorInvalidType("mssVi2s");
0257:
0258: v.vType=STR;
0259:
0260: if(!v.nul){
0261: v.v.s=mssItoA(v.v.i);
0262: }
0263: return(v);
0264: }
0265:
0266: /**
0267: * # FUNCTION #
0268: * MssValueのDBL型をMssValueのINT型に変換
0269: */
0270: MssValue mssVd2i(MssValue v)
0271: {
0272:
0273: if(v.vType!=DBL) errorInvalidType("mssVd2i");
0274:
0275: v.vType=INT;
0276:
0277: if(!v.nul){
0278: v.v.i=(int)v.v.d;
0279: }
0280: return(v);
0281: }
0282:
0283: /**
0284: * # FUNCTION #
0285: * MssValueのDBL型をMssValueのSTR型に変換
0286: * MssValueのSTR型に新たに文字列領域を確保する。
0287: */
0288: MssValue mssVd2s(MssValue v)
0289: {
0290:
0291: if(v.vType!=DBL) errorInvalidType("mssVd2s");
0292:
0293: v.vType=STR;
0294:
0295: if(!v.nul){
0296: v.v.s=mssFtoA(v.v.d);
0297: }
0298: return(v);
0299: }
0300:
0301: /**
0302: * # FUNCTION #
0303: * MssValueのSTR型をMssValueのINT型に変換
0304: * 引数で与えられたMssValueのSTR型の文字列領域は開放しない。
0305: * 変換にはatoi関数を利用している。
0306: */
0307: MssValue mssVs2i(MssValue v)
0308: {
0309:
0310: if(v.vType!=STR) errorInvalidType("mssVs2i");
0311:
0312: v.vType=INT;
0313:
0314: if(!v.nul){
0315: v.v.i=atoi(v.v.s);
0316: }
0317: return(v);
0318: }
0319:
0320: /**
0321: * # FUNCTION #
0322: * MssValueのSTR型をMssValueのDBL型に変換
0323: * 引数で与えられたMssValueのSTR型の文字列領域は開放しない。
0324: * 変換にはatof関数を利用している。
0325: */
0326: MssValue mssVs2d(MssValue v)
0327: {
0328:
0329: if(v.vType!=STR) errorInvalidType("mssVs2d");
0330:
0331: v.vType=DBL;
0332:
0333: if(!v.nul){
0334: v.v.d=atof(v.v.s);
0335: }
0336: return(v);
0337: }
0338:
0339: /**
0340: * # FUNCTION #
0341: * 2つの引数の型が異る場合の、エラーメッセージ&終了
0342: */
0343: static void errorDiffType(char *msg)
0344: {
0345: mssShowErrMsg("internal error: operation with different types of values");
0346: mssEnd(mssErrorNoDefault);
0347: }
0348:
0349: /**
0350: * # FUNCTION #
0351: * MssValueの足し算
0352: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0353: * メッセージを表示し、終了する。
0354: * 2つのMssValue引数(v1,v2)の型が一致しなければエラーを出力する。
0355: * 返す値の型は、引数の型に同じ。
0356: */
0357: MssValue mssVadd(MssValue v1, MssValue v2)
0358: {
0359:
0360: if(v1.nul || v2.nul){
0361: MssVnull(v1);
0362: }else{
0363: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0364:
0365: v1.nul=0;
0366: switch(v1.vType){
0367: case INT: v1.v.i += v2.v.i; break;
0368: case DBL: v1.v.d += v2.v.d; break;
0369: default : errorInvalidType("mssVadd");
0370: }
0371: }
0372: return(v1);
0373: }
0374:
0375: /**
0376: * # FUNCTION #
0377: * MssValueの引き算
0378: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0379: * メッセージを表示し、終了する。
0380: * 2つのMssValue引数(v1,v2)の型が一致しなければエラーを出力する。
0381: * 返す値の型は、引数の型に同じ。
0382: */
0383: MssValue mssVsub(MssValue v1, MssValue v2)
0384: {
0385:
0386: if(v1.nul || v2.nul){
0387: MssVnull(v1);
0388: }else{
0389: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0390:
0391: v1.nul=0;
0392: switch(v1.vType){
0393: case INT: v1.v.i -= v2.v.i; break;
0394: case DBL: v1.v.d -= v2.v.d; break;
0395: default : errorInvalidType("mssVadd");
0396: }
0397: }
0398: return(v1);
0399: }
0400:
0401: /**
0402: * # FUNCTION #
0403: * MssValueのかけ算
0404: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0405: * メッセージを表示し、終了する。
0406: * 2つのMssValue引数(v1,v2)の型が一致しなければエラーを出力する。
0407: * 返す値の型は、引数の型に同じ。
0408: */
0409: MssValue mssVmul(MssValue v1, MssValue v2)
0410: {
0411:
0412: if(v1.nul || v2.nul){
0413: MssVnull(v1);
0414: }else{
0415: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0416:
0417: v1.nul=0;
0418: switch(v1.vType){
0419: case INT: v1.v.i *= v2.v.i; break;
0420: case DBL: v1.v.d *= v2.v.d; break;
0421: default : errorInvalidType("mssVadd");
0422: }
0423: }
0424: return(v1);
0425: }
0426:
0427: /**
0428: * # FUNCTION #
0429: * MssValueの割り算
0430: * MssValueのDBL型に対してのみ利用可能で、その他の型が指定されればエラー
0431: * メッセージを表示し、終了する。
0432: * 2つのMssValue引数(v1,v2)の型が一致しなければエラーを出力する。
0433: * 返す値の型は、引数の型に同じ(DBL)。
0434: * v2が0の場合はNULL値を返す。
0435: */
0436: MssValue mssVdiv(MssValue v1, MssValue v2)
0437: {
0438:
0439: if(v1.nul || v2.nul){
0440: MssVnull(v1);
0441: }else{
0442: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0443:
0444: v1.nul=0;
0445: switch(v1.vType){
0446: case DBL:
0447: if(v2.v.d==0) MssVnull(v1);
0448: else v1.v.d /= v2.v.d;
0449: break;
0450: default : errorInvalidType("mssVadd");
0451: }
0452: }
0453: return(v1);
0454: }
0455:
0456: /**
0457: * # FUNCTION #
0458: * MssValueの剰余算
0459: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0460: * メッセージを表示し、終了する。
0461: * 2つのMssValue引数(v1,v2)の型が一致しなければエラーを出力する。
0462: * 返す値の型は、引数の型に同じ。
0463: * v2が0の場合はNULL値を返す。
0464: * INTの場合は"%"演算子を使い、DBLの場合はfmod関数を利用している。
0465: * ex. 5 % 2 = 1, 5.2 % 1.2 = 0.3
0466: */
0467: MssValue mssVmod(MssValue v1, MssValue v2)
0468: {
0469:
0470: if(v1.nul || v2.nul){
0471: MssVnull(v1);
0472: }else{
0473: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0474:
0475: v1.nul=0;
0476: switch(v1.vType){
0477: case INT:
0478: if(v2.v.i==0) MssVnull(v1);
0479: else v1.v.i %= v2.v.i;
0480: break;
0481: case DBL:
0482: if(v2.v.d==0) MssVnull(v1);
0483: else v1.v.d=fmod(v1.v.d,v2.v.d);
0484: break;
0485: default : errorInvalidType("mssVadd");
0486: }
0487: }
0488: return(v1);
0489: }
0490:
0491: /**
0492: * # FUNCTION #
0493: * MssValueの平方根
0494: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0495: * メッセージを表示し、終了する。
0496: * 返す値の型は、引数の型に関わらずDBL型。
0497: * v2が負の数の場合はNULL値を返す。
0498: */
0499: MssValue mssVsqrt(MssValue v)
0500: {
0501:
0502: if(!v.nul){
0503: switch(v.vType){
0504: case INT:
0505: if(v.v.i<0) MssVnull(v);
0506: else v.v.d=sqrt((double)v.v.i);
0507: break;
0508: case DBL:
0509: if(v.v.d<0) MssVnull(v);
0510: else v.v.d=sqrt(v.v.d);
0511: break;
0512: default : errorInvalidType("mssVsqrt");
0513: }
0514: }
0515: v.vType=DBL;
0516: return(v);
0517: }
0518:
0519: /**
0520: * # FUNCTION #
0521: * MssValueのカウントアップ
0522: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0523: * メッセージを表示し、終了する。
0524: * 返す値の型は、引数の型に同じ。
0525: */
0526: MssValue mssVcntUp(MssValue v)
0527: {
0528:
0529: if(!v.nul){
0530: switch(v.vType){
0531: case INT: v.v.i++; break;
0532: case DBL: v.v.d++; break;
0533: default : errorInvalidType("mssVcntUp");
0534: }
0535: }
0536: return(v);
0537: }
0538:
0539: /**
0540: * # FUNCTION #
0541: * MssValueのカウントダウン
0542: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0543: * メッセージを表示し、終了する。
0544: * 返す値の型は、引数の型に同じ。
0545: */
0546: MssValue mssVcntDown(MssValue v)
0547: {
0548:
0549: if(!v.nul){
0550: switch(v.vType){
0551: case INT: v.v.i--; break;
0552: case DBL: v.v.d--; break;
0553: default : errorInvalidType("mssVcntUp");
0554: }
0555: }
0556: return(v);
0557: }
0558:
0559: /**
0560: * # FUNCTION #
0561: * 2つのMssValue引数v1,v2で小さい値を返す
0562: * 2つのMssValue引数が同じ場合はv1を返す
0563: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0564: * メッセージを表示し、終了する。
0565: * 返す値の型は、引数の型に同じ。
0566: */
0567: MssValue mssVmin(MssValue v1, MssValue v2)
0568: {
0569:
0570: if(v1.nul || v2.nul){
0571: MssVnull(v1);
0572: }else{
0573: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0574:
0575: switch(v1.vType){
0576: case DBL:
0577: if(v1.v.d>v2.v.d) v1=v2;
0578: break;
0579: case INT:
0580: if(v1.v.i>v2.v.i) v1=v2;
0581: break;
0582: default : errorInvalidType("mssVcntUp");
0583: }
0584: }
0585: return(v1);
0586: }
0587:
0588: /**
0589: * # FUNCTION #
0590: * 2つのMssValue引数v1,v2で大きい値を返す
0591: * 2つのMssValue引数が同じ場合はv1を返す
0592: * MssValueのINT型およびDBL型に対して利用可能で、その他の型が指定されればエラー
0593: * メッセージを表示し、終了する。
0594: * 返す値の型は、引数の型に同じ。
0595: */
0596: MssValue mssVmax(MssValue v1, MssValue v2)
0597: {
0598:
0599: if(v1.nul || v2.nul){
0600: MssVnull(v1);
0601: }else{
0602: if(v1.vType!=v2.vType) errorDiffType("mssVadd");
0603:
0604: switch(v1.vType){
0605: case DBL:
0606: if(v1.v.d<v2.v.d) v1=v2;
0607: break;
0608: case INT:
0609: if(v1.v.i<v2.v.i) v1=v2;
0610: break;
0611: default : errorInvalidType("mssVcntUp");
0612: }
0613: }
0614: return(v1);
0615: }
0616:
0617: /**
0618: * # FUNCTION #
0619: * 2つのMssValue引数a,bの比較演算
0620: * "a ope b"を評価し、真ならば1、偽なら0を返す。
0621: * a,bいずれかがNULLなら-1を返す。
0622: * MssValueのINT型,DBL型,DBL型に対して利用可能で、その他の型が指定されればエラー
0623: * メッセージを表示し、終了する。
0624: * 返す値の型は、常にint型。
0625: */
0626: int mssVcmp(MssValue a, enum OpeType ope, MssValue b)
0627: {
0628: double d=0;
0629: int flag=0;
0630:
0631: if(a.nul || b.nul) return(-1);
0632:
0633: switch(a.vType){
0634: /*Double型 ------- -DBL0 0 +DBL0 ++++++++ */
0635: case DBL:
0636: d=a.v.d-b.v.d;
0637: switch(ope){
0638: case OPE_LT: if(d<-DBL0) flag=1; break;
0639: case OPE_LE: if(d< DBL0) flag=1; break;
0640: case OPE_GT: if(d> DBL0) flag=1; break;
0641: case OPE_GE: if(d>-DBL0) flag=1; break;
0642: case OPE_EQ: if(d>=-DBL0&&d<=DBL0) flag=1; break;
0643: case OPE_NE: if(d< -DBL0||d >DBL0) flag=1; break;
0644: }
0645: break;
0646:
0647: /*INT型*/
0648: case INT:
0649: switch(ope){
0650: case OPE_LT: if(a.v.i <b.v.i) flag=1; break;
0651: case OPE_LE: if(a.v.i<=b.v.i) flag=1; break;
0652: case OPE_GT: if(a.v.i >b.v.i) flag=1; break;
0653: case OPE_GE: if(a.v.i>=b.v.i) flag=1; break;
0654: case OPE_EQ: if(a.v.i==b.v.i) flag=1; break;
0655: case OPE_NE: if(a.v.i!=b.v.i) flag=1; break;
0656: }
0657: break;
0658:
0659: /*STR型*/
0660: case STR:
0661: switch(ope){
0662: case OPE_LT: if(0> strcmp(a.v.s,b.v.s)) flag=1; break;
0663: case OPE_LE: if(0>=strcmp(a.v.s,b.v.s)) flag=1; break;
0664: case OPE_GT: if(0< strcmp(a.v.s,b.v.s)) flag=1; break;
0665: case OPE_GE: if(0<=strcmp(a.v.s,b.v.s)) flag=1; break;
0666: case OPE_EQ: if(0==strcmp(a.v.s,b.v.s)) flag=1; break;
0667: case OPE_NE: if(0!=strcmp(a.v.s,b.v.s)) flag=1; break;
0668: }
0669: break;
0670:
0671: default : errorInvalidType("mssVcmp");
0672: break;
0673: }
0674: return(flag);
0675: }
0676:
0677: /**
0678: * # FUNCTION #
0679: * MssValueの出力
0680: * MssValueの型を時動的に判断し、適切に出力する。
0681: */
0682: void mssVwrite(MssValue v, struct mssFPW *fp)
0683: {
0684: if(v.nul){
0685: mssWriteNull(fp);
0686: }else{
0687: switch(v.vType){
0688: case INT: mssWriteInt(v.v.i,fp); break;
0689: case DBL: mssWriteDbl(v.v.d,fp); break;
0690: case STR: mssWriteStr(v.v.s,fp); break;
0691: case ADD: mssWriteInt((int)v.v.a,fp); break;
0692: case USI: mssWriteInt(v.v.usi,fp); break;
0693: }
0694: }
0695: }
0696:
0697: /**
0698: * # FUNCTION #
0699: * MssValueのINT型の出力
0700: */
0701: void mssVwriteInt(MssValue v, struct mssFPW *fp)
0702: {
0703:
0704: if(v.nul){
0705: mssWriteNull(fp);
0706: }else{
0707: mssWriteInt(v.v.i,fp);
0708: }
0709: }
0710:
0711: /**
0712: * # FUNCTION #
0713: * MssValueのDBL型の出力
0714: */
0715: void mssVwriteDbl(MssValue v, struct mssFPW *fp)
0716: {
0717:
0718: if(v.nul){
0719: mssWriteNull(fp);
0720: }else{
0721: mssWriteDbl(v.v.d,fp);
0722: }
0723: }
0724:
0725: /**
0726: * # FUNCTION #
0727: * MssValueのSTR型の出力
0728: */
0729: void mssVwriteStr(MssValue v, struct mssFPW *fp)
0730: {
0731:
0732: if(v.nul){
0733: mssWriteNull(fp);
0734: }else{
0735: mssWriteStr(v.v.s,fp);
0736: }
0737: }
0738: