#help_index "Char/Conversion" F64 Str2F64(U8 *src,U8 **_end_ptr=NULL) { /*String to F64. Does not allow more than 18-digits before or after the decimal point because the numbers before and after the decimal point are stored in 64-bits. Use exponentiated forms to avoid this. */ I64 i,j,k,ch; F64 d; Bool neg=FALSE,neg_e=FALSE; ch=*src++; while (Bt(char_bmp_white_space,ch)) ch=*src++; if (ch=='-') { neg=TRUE; ch=*src++; } if (!StrNCmp(src-1,"inf",3)) { d=inf; src+=3; goto a2f_end; } if (*src=='inf') { d=inf; src++; goto a2f_end; } i=0; while (TRUE) { if (Bt(char_bmp_dec_numeric,ch)) i=i*10+ch-'0'; else { if (ch=='.' || ch=='e' || ch=='E') break; d=i; goto a2f_end; } ch=*src++; } if (ch=='.') ch=*src++; k=0; while (TRUE) { if (Bt(char_bmp_dec_numeric,ch)) { i=i*10+ch-'0'; k++; } else { if (ch=='e' || ch=='E') break; d=i*Pow10I64(-k); goto a2f_end; } ch=*src++; } ch=*src++; if (ch=='-') { neg_e=TRUE; ch=*src++; } j=0; while (TRUE) { if (Bt(char_bmp_dec_numeric,ch)) j=j*10+ch-'0'; else { if (neg_e) d=i*Pow10I64(-j-k); else d=i*Pow10I64(j-k); goto a2f_end; } ch=*src++; } a2f_end: if (_end_ptr) *_end_ptr=src-1; if (neg) return -d; else return d; } #help_index "Char/Conversion;Time/Date/CDate;Date/CDate" CDate Str2Date(U8 *_src) { /*"*+nnnn", "*-nnnn", "mm/dd", "mm/dd/yy" It also supports some funs SM() start of mon EM() end of mon SY() start of year EY() end of year Full expressions are not implimented but you can do stuff like SM(*-7)+3 and it will return the 3rd day after the start of mon for seven days before today. */ CDate res=0; CDateStruct ds,ds_now; U8 *src=MStrUtil(_src,SUF_REM_SPACES|SUF_TO_UPPER), *v=StrNew(src), *ptr=src; Bool start_mon=FALSE,end_mon=FALSE, start_year=FALSE,end_year=FALSE; MemSet(&ds,0,sizeof(CDateStruct)); if (!StrNCmp(ptr,"SM(",3)) { ptr+=3; start_mon=TRUE; } else if (!StrNCmp(ptr,"EM(",3)) { ptr+=3; end_mon=TRUE; } else if (!StrNCmp(ptr,"SY(",3)) { ptr+=3; start_year=TRUE; } else if (!StrNCmp(ptr,"EY(",3)) { ptr+=3; end_year=TRUE; } if (*ptr=='*') { ptr++; if (*ptr=='+' || *ptr=='-') res.date=Str2I64(ptr,,&ptr); res+=Now+local_time_offset; } else { StrFirstRem(ptr,"/",v); //Put mon into v ds.mon=Str2I64(v); if (StrOcc(ptr,'/')) { StrFirstRem(ptr,"/",v); //Put day into v leaving year in ptr ds.day_of_mon=Str2I64(v); ds.year=Str2I64(ptr,,&ptr); if (ds.year<100) //if not 4 digit year ds.year+=2000; } else { ds.day_of_mon=Str2I64(ptr,,&ptr); Date2Struct(&ds_now,Now+local_time_offset); ds.year=ds_now.year; } res=Struct2Date(&ds); } if (*ptr==')') ptr++; if (start_mon) res.date=FirstDayOfMon(res.date); else if (end_mon) res.date=LastDayOfMon(res.date); else if (start_year) res.date=FirstDayOfYear(res.date); else if (end_year) res.date=LastDayOfYear(res.date); if (*ptr=='+' || *ptr=='-') res.date+=Str2I64(ptr); Free(src); Free(v); return res-local_time_offset; } #help_index "Char/Conversion" U8 *StrScan(U8 *src,U8 *fmt,...) { /*Opposite of sprintf(). Pass ptrs to data to be scanned-in. For "%s", pass ptr to ptr (be careful because addr of array is the same as array--create ptr to array and take addr. */ U8 *buf,*ptr,**pptr; Bool left_justify=FALSE; I64 ch,cur_arg=0,i,len,*i_ptr,dec_len; F64 *d_ptr; if (!fmt) throw('Scan'); while (ch = *fmt++) { if (ch=='%') { if (*fmt=='%') { src++; fmt++; } else { if (*fmt=='-') { left_justify=TRUE; fmt++; } else left_justify=FALSE; len=0; while ('0'<=*fmt<='9') len=len*10+ (*fmt++ -'0'); if (*fmt=='*') { fmt++; if (cur_arg>=argc) throw('Scan'); len=argv[cur_arg++]; } ch=*fmt++; if (ch && !len) { ptr=src; while (*ptr && *ptr!=*fmt) ptr++; len=ptr-src; } else { if (ch=='.') { dec_len=0; while ('0'<=*fmt<='9') dec_len=dec_len*10+ (*fmt++-'0'); if (*fmt=='*') { fmt++; if (cur_arg>=argc) throw('Scan'); dec_len=argv[cur_arg++]; } ch=*fmt++; } } buf=MAlloc(len+1); for (i=0; i<len; i++) buf[i]=*src++; buf[i]=0; switch (ch) { case 's': if (cur_arg>=argc) throw('Scan'); pptr=argv[cur_arg++]; StrCpy(*pptr,buf); break; case 'c': if (cur_arg>=argc) throw('Scan'); ptr=argv[cur_arg++]; *ptr=*buf; break; case 'C': if (cur_arg>=argc) throw('Scan'); ptr=argv[cur_arg++]; *ptr=ToUpper(*buf); break; case 'z': if (cur_arg+1>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=LstMatch(buf,argv[cur_arg++]); break; case 'Z': if (cur_arg+1>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=DefineMatch(buf,argv[cur_arg++]); break; case 'd': if (cur_arg>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=Str2I64(buf); break; case 'X': if (cur_arg>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=Str2I64(buf,16); break; case 'b': if (cur_arg>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=Str2I64(buf,2); break; case 'e': case 'f': case 'g': case 'n': if (cur_arg>=argc) throw('Scan'); d_ptr=argv[cur_arg++]; *d_ptr=Str2F64(buf); break; case 'D': if (cur_arg>=argc) throw('Scan'); i_ptr=argv[cur_arg++]; *i_ptr=Str2Date(buf); break; } Free(buf); } } else src++; } return src; } I64 ToLower(I64 ch) {// Basic lower case conversion implementation I64 res=ch; if ('A'<=ch<='Z') res = ch ^ 0x20; return res; } Bool YorN(I64 enter_default=0) {//Wait for user to answer Y or N. I64 ch; if (ToLower(enter_default)=='y' || ToLower(enter_default)=='n') "(y or n, default: %c)? ",ToLower(enter_default); else "(y or n)? "; while (TRUE) { ch=ToUpper(GetChar(,FALSE)); if (enter_default && ch=='\n') ch=ToUpper(enter_default); if (ch=='Y') { "$PT$YES$FG$\n"; return TRUE; } else if (ch=='N') { "$PT$NO$FG$\n"; return FALSE; } } } Bool AreYouSure() {//Print "Are you sure" and waits for Y or N. "ARE YOU SURE "; return YorN; } #help_index "Char/Operations" U8 *StrFind(U8 *needle,U8 *haystack_str,I64 flags=0) {//Find needle_str in haystack_str with options. Bool cont; U8 *saved_haystack_str=haystack_str; I64 plen=StrLen(needle); do { cont=FALSE; if (flags & SFF_IGNORE_CASE) haystack_str=StrIMatch(needle,haystack_str); else haystack_str=StrMatch(needle,haystack_str); if (haystack_str && flags & SFF_WHOLE_LABELS_BEFORE && haystack_str!=saved_haystack_str && Bt(char_bmp_alpha_numeric,*(haystack_str-1))) { haystack_str++; if (*haystack_str) cont=TRUE; else haystack_str=NULL; } if (haystack_str && flags & SFF_WHOLE_LABELS_AFTER && Bt(char_bmp_alpha_numeric,*(haystack_str+plen))) { haystack_str++; if (*haystack_str) cont=TRUE; else haystack_str=NULL; } } while (cont); return haystack_str; } U8 *StrReplace(U8 *str, U8 *old, U8 *new, I64 sff_flags=0, Bool free_str=FALSE) {//Replace all instances of old with new in str. free_str aids in chain replacement. U8 *str_start, *str_end = str, *str_loc, *tmpm = NULL; if (!*old) { str_start = StrNew(new); goto sr_end2; } if (!StrCmp(old, new)) goto sr_end; while (str_loc = str_end = StrFind(old, str_end, sff_flags)) { str_start = str; str_end += StrLen(old); //Move start marker past old str, cutting it out //End str_start right before where old was str_start[StrLen(str_start) - StrLen(str_loc)] = '\0'; Free(tmpm); tmpm = MStrPrint("%s%s%s", str_start, new, str_end); str = tmpm; } sr_end: str_start = StrNew(str); sr_end2: if (free_str) Free(str); return str_start; } #help_index ""