Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Extra libraries, Code snippets, applications etc. » U++ users applications in progress and useful code snippets, including reference examples! » SetLineKeyValue - in memory (a helper fn to set key/value through regular String - ini like)
SetLineKeyValue - in memory [message #47907] Fri, 21 April 2017 17:55 Go to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
Empty lines and (// or ;) at start of line are ignored
chkForEqualSign:
  when true - there must be '=' after key(even if it's empty)
  when false - line can contain only a key(withNo=), but it's added before fn returns

NewLine: \n, \r and \r\n are accepted

Update:
  -func now accepts key that has some kind of header,eg SetLineKeyValue(lines,"key","value"); while
   lines has somewhere 'keyAnyHdr'(eg keyLine1\nLine2=value, or key:flg:20,flg2:coffee=value)
  -added 2helperfuncs for pack 2vals in value - chk down code - can be used eg with WithDropChoice<EditString>

bool SetLineKeyValue(String& lines,const String& key,const String& val,dword startAt=0,bool chkForEqualSign=true,dword *chkForExistanceOnly=0,String *prevBack=0){
  if(!lines.GetCount())return false;
  ASSERT(key.GetCount());
  ASSERT(startAt<lines.GetCount());
  register char *p=(char*)~lines+startAt;
  int64 fpos; char *pst;
  int pos,off,linenum;
  if(prevBack)*prevBack="";
  while(*p){
    fpos=p-~lines; linenum=0;pos=0;pst=p;
    while(*p){if(*p=='\r'&&*p=='\n'){linenum=p-pst;break;}if(*p=='\r'||*p=='\n'){linenum=p-pst;break;}if(*p=='=')pos=p-pst; ++p;}
    if(*p)++p;
    if(linenum==0 && 0==(linenum=p-(*p?1:0)-pst))continue;
    if(linenum&&*pst==';'||linenum>=2&&pst[0]=='/'&&pst[1]=='/')continue;
    if(chkForEqualSign&&!pos)continue;
    if(linenum<key.GetCount()+(chkForEqualSign?1:0)||0!=memcmp(pst,~key,key.GetCount()))continue;
    if(prevBack&&linenum>pos/*key.GetCount()*/+1)*prevBack=lines.Mid(fpos+pos/*key.GetCount()*/+1,linenum-(/*key.GetCount()*/pos+1));
    if(chkForExistanceOnly){*chkForExistanceOnly=(dword)(int32)fpos;return true;}
    fpos+=/*key.GetCount()*/pos+1;
    off=(/*key.GetCount()*/pos+1+val.GetCount())-linenum; //speedup a litle - don't insert/remove twice
    if(off<0)lines.Remove(fpos,abs(off)); else if(off)lines.Insert(fpos,"R",off);
    *(char*)lines.GetIter(fpos-1)='='; memcpy((void*)lines.GetIter(fpos),~val,val.GetCount());
    return true;
    }
  /*
  StringStream ss(lines);
  while(!ss.IsEof()){
    fpos=ss.GetPos();
    line=ss.GetLine();if(chkForEqualSign&&-1==(pos=line.Find('=')))continue;
    if(!line.StartsWith(key+(chkForEqualSign?"=":"")))continue;
    if(pos==-1){insEq;pos=key.GetCount();}
    off=(key.GetCount()+1+val.GetCount())-line.GetCount(); //speedup a litle - don't insert/remove twice
    fpos+=key.GetCount();
    if(off<0)lines.Remove(fpos,abs(off)); else if(off)lines.Insert(fpos," ",off);
    *(char*)lines.GetIter(fpos)='='; memcpy((void*)lines.GetIter(fpos+1),~val,val.GetCount());
    //lines
    break;
    }*/
  return false;
}


//when editor that edit this can't handle fe \1 chars, use something else
//errline is just an errorlike func PromptOK can be used instead of it
inline String SLKVValue2Pack(const String& val1,const String& val2,String withCh="\1"){return val1+withCh+val2;}
static String SLKVValue2Get(const String& val,String *val1=0,const String& sepCh="\1",bool mustBeSepCh=false){
  /*if(val1)*val1="";ifval1==in*/int i=val.ReverseFind(sepCh);
  if(i==-1){if(mustBeSepCh){errline(el,"could not find SLKVValue2Get sepChar");if(val1)*val1="";return String::GetVoid();}if(val1)*val1=val; return "";}
  String ret=val.Mid(i+sepCh.GetCount()); if(val1)*val1=val.Mid(0,i&&sepCh.GetCount()==1&&val[i]=='\n'&&val[i-1]=='\r'?i-1:i); return ret;
}

[Updated on: Mon, 01 May 2017 20:52]

Report message to a moderator

Re: SetLineKeyValue - in memory [message #47920 is a reply to message #47907] Mon, 24 April 2017 10:42 Go to previous messageGo to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
These can be used when info is known to be contignous,
errline is just an errorlike func PromptOK can be used instead of it
All are readOnly funcs

inline bool SLKVSkipEmpty(StringStream &ss){
  bool is=0;
  while(!ss.IsEof()&&(ss.Peek()=='\n'||ss.Peek()=='\r'||ss.Peek()==';'||*(word*)ss.PeekPtr(2)==*(word*)"//")){
    is=1;ss.GetLine();
  }
  return is;
}

inline String SLKVKey(StringStream &ss,bool withEqSign=true){
  String ln=ss.GetLine();
  int i=ln.Find('=');if(i==-1){if(withEqSign){errline(el,"char '=' not found near %s",~ln);return String::GetVoid();}}else ln=ln.Mid(0,i);
  return ln;
}

inline String SLKVValue(StringStream &ss){
  String ln=ss.GetLine();
  int i=ln.Find('=');if(i==-1){errline(el,"char '=' not found near %s",~ln);return String::GetVoid();}
  return ln.Mid(i+1);
}

inline bool SLKVKeyValue(StringStream &ss,String& key,String& val,bool withEqSign=true){
  key=val="";String ln=ss.GetLine();
  int i=ln.Find('=');if(i==-1){if(withEqSign){errline(el,"char '=' not found near %s",~ln);return false;}key=ln;return true;}
  key=ln.Mid(0,i); val=ln.Mid(i+1);
  return true;
}

[Updated on: Tue, 25 April 2017 23:09]

Report message to a moderator

Re: SetLineKeyValue - in memory: smallBugFix [message #47944 is a reply to message #47907] Tue, 25 April 2017 21:43 Go to previous messageGo to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
Modified upper SLKVKey(from ln.Mid(i) to ln.Mid(0,i))
now returns right result...
Re: SetLineKeyValue - in memory: bugFix [message #47945 is a reply to message #47907] Wed, 26 April 2017 01:21 Go to previous messageGo to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
SetLineKeyValue,
now returns right result...
Re: SetLineKeyValue - in memory: update [message #47977 is a reply to message #47907] Sun, 30 April 2017 13:25 Go to previous messageGo to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
update -> check original message
Re: SetLineKeyValue - in memory:update2 [message #47979 is a reply to message #47907] Sun, 30 April 2017 14:33 Go to previous messageGo to next message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
Using SetLineKeyValue with StringStream:
-StringStream: a few funcs should be added to use this,chk down

If you read this, there was also original func update - chk original message
Usage:
-to speedup and data(lines) is/are known to be contignous,then;
   SetLineKeyValue(ss,"a key","a value");
   ss.GetLine(); //advance pos to next line,so next is found immediatelly
-when keys(data) is not known to be contignous(butAreSearchable),then;
   SetLineKeyValue(ss,"a key","a value"); //just this

bool SetLineKeyValue(StringStream& ss,const String& key,const String& val,bool chkForEqualSign,dword *chkForExistanceOnly,String *prevBack){
  if(ss.IsEof())return false;
  register char *p=(char*)ss.PeekPtr();
  int64 fpos=ss.GetPos();ss.Seek(0);
  char *pst,*porg=p,*ssSt=(char*)ss.PeekPtr();
  int pos,off,linenum;
  ss.Seek(fpos);
  if(prevBack)*prevBack="";
  while(*p){
    fpos=ss.GetPos(); linenum=0;pos=0;pst=p;
    while(*p){if(*p=='\r'&&*p=='\n'){linenum=p-pst/*p-~lines-fpos*/;break;}if(*p=='\r'||*p=='\n'){linenum=p-pst/*p-~lines-fpos*/;break;}if(*p=='=')pos=p-pst/*p-~lines-fpos*/; ++p;}
    if(*p!=0)++p;
    if(linenum==0 && 0==(linenum=p-(*p?1:0)-pst/*~lines-fpos*/))continue;
    if(linenum&&*pst==';'||linenum>=2&&pst[0]=='/'&&pst[1]=='/')continue;
    if(chkForEqualSign&&!pos)continue;
    if(linenum<key.GetCount()+(chkForEqualSign?1:0)||0!=memcmp(pst,~key,key.GetCount()))continue;if(chkForEqualSign&&pst[key.GetCount()]!='=')continue;
    if(prevBack&&linenum>fpos+/*key.GetCount()*/pos+1)*prevBack=String(pst+/*key.GetCount()*/pos+1/*lines.Mid(fpos+key.GetCount()+1*/,linenum-(/*key.GetCount()*/pos+1));
    if(chkForExistanceOnly){*chkForExistanceOnly=(dword)(int32)fpos;return true;}
    fpos+=/*key.GetCount()*/pos+1;
    off=(/*key.GetCount()*/pos+1+val.GetCount())-linenum; //speedup a litle - don't insert/remove twice
    if(off<0)ss.Remove(abs(off),fpos); else if(off)ss.Insert('R',off,fpos);
    *(char*)ss.GetIter(fpos-1)='='; memcpy((void*)ss.GetIter(fpos),~val,val.GetCount());
    //if(off<0)slns. lines.Remove(fpos,abs(off)); else if(off)lines.Insert(fpos," ",off);
    //*(char*)lines.GetIter(fpos-1)='='; memcpy((void*)lines.GetIter(fpos),~val,val.GetCount());
    return true;
    }
  return false;
}


StringStream added code for this - but should be revisited;
StringStream has Put methods but no Remove(Pos isTakenInConsideration), here they are - but are not yet 100% tested
optimally it should be added between SetSize and Open
	virtual  void  Insert(int ch,int num=1,int at=-1);
	virtual  void  Insert(const String& str,int at=-1);
	virtual  void  Remove(int num=1,int at=-1);
	virtual  const byte* GetIter(int at){ASSERT(at<GetSize());return buffer+at;}

//cpp files
void StringStream::Insert(int ch,int num,int at){
	Insert(String(ch,num),at);
}
void StringStream::Insert(const String& str,int at){
	if(at==-1)at=GetPos();
	ASSERT(at+str.GetCount()<=GetSize());
	SetReadMode(); //justToKnowWhichToUse...
	int64 npos=at<GetPos()?GetPos()+GetPos()-at:GetPos();
	data.Insert(at,str);
	buffer = (byte *) ~data;  //<=this should be checked,may point to another unknown buffer
	//ptr = wrlim = buffer;
	rdlim = buffer + data.GetCount();
	Seek(npos);
}
void StringStream::Remove(int num,int at){
	if(at==-1)at=GetPos();
	ASSERT(at+num<=GetSize());
	SetReadMode(); //justToKnowWhichToUse...
	int64 npos=at<=GetPos()?GetPos()-num/*+GetPos()-at*/:GetPos();
	data.Remove(at,num);
	//memmove(buffer+at,buffer+at+num,n);
	buffer = (byte *) ~data;
	rdlim = buffer + data.GetCount();
	Seek(npos);
}

[Updated on: Mon, 01 May 2017 20:33]

Report message to a moderator

Re: SetLineKeyValue - in memory: minorBugFix [message #47986 is a reply to message #47907] Mon, 01 May 2017 20:55 Go to previous message
luoganda is currently offline  luoganda
Messages: 193
Registered: November 2016
Experienced Member
prevBack sometimes returned empty string - even when there was a value,
chk original message

[Updated on: Mon, 01 May 2017 20:55]

Report message to a moderator

Previous Topic: LinuxInfoPkgr, SMailer,... linux stuff x64
Next Topic: FormatBytes function
Goto Forum:
  


Current Time: Thu Mar 28 22:29:26 CET 2024

Total time taken to generate the page: 0.01174 seconds