Patch title: Release 95 bulk changes
Abstract:
File: /pliant/language/type/text/str.c
Key:
    Removed line
    Added line
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 2
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// version 2 along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/*
abstract
  text "'Str' data type"
*/
 

FUNCTION uInt string_len(const Char *string) {
  Int l;
  for(l=0; *string++!='\0'; l++);
  return l; }


FUNCTION Void string_Str(Char *src,struct Str *dest) {
  Char *c; Int l;
  l=string_len(src);
  c=(Char *)memory_allocate(l,dest);
  memory_copy(src,c,l);
  Str_set(dest,c,l,true); }


/*****************************************************************************/


INLINE Int Str_len(struct Str *s) { /// section "len"
  return s->len2&~Str_allocated; }


FUNCTION Void Str_build(struct Str *str) {
  str->chars=null;
  str->len2=0; }


FUNCTION Void Str_destroy(struct Str *str) {
  if(str->len2&Str_allocated) memory_free(str->chars); }


FUNCTION Void Str_copy(struct Str *src,struct Str *dest) {
  Char *c; Int l;
  l=Str_len(src);
  c=(Char *)memory_allocate(l,dest);
  memory_copy(src->chars,c,l);
  Str_set(dest,c,l,true); }


/*****************************************************************************/


FUNCTION Void Str_set(struct Str *dest,Char *chars,Int len,Bool allocated) { /// section "set"
  if(dest->len2&Str_allocated) memory_free(dest->chars);
  dest->chars=chars;
  dest->len2=len|(allocated ? Str_allocated : 0); }
  

FUNCTION Void Str_resize(struct Str *dest,Int len) {
  Char *c;
  check(len>=0);
  if(dest->len2&Str_allocated) {
    c=(Char *)memory_resize(dest->chars,len,dest);
  other
    c=(Char *)memory_allocate(len,dest); 
    memory_copy(dest->chars,c,dest->len2); }
  dest->chars=c;
  dest->len2=len|Str_allocated; }


/*****************************************************************************/


FUNCTION Int compare_str(struct Str *s1,struct Str *s2) {
  return memory_compare(s1->chars,Str_len(s1),s2->chars,Str_len(s2)); }


FUNCTION Int Str_search(struct Str *string,struct Str *pattern,Int ifnotfound) { /// section "search"
  Address a=memory_search(string->chars,Str_len(string),pattern->chars,Str_len(pattern));
  if(a!=null) return integer_from_address(a)-integer_from_address(string->chars);
  else return ifnotfound; }


FUNCTION Void Str_add(struct Str *src,struct Str *dest) {
  Int src_len,dest_len;
  src_len=Str_len(src),dest_len=Str_len(dest);
  Str_resize(dest,src_len+dest_len);
  memory_copy(src->chars,dest->chars+dest_len,src_len); }

FUNCTION Void Str_addz(Char *src,struct Str *dest) {
  Int src_len,dest_len;
  src_len=string_len(src),dest_len=Str_len(dest);
  Str_resize(dest,src_len+dest_len);
  memory_copy(src,dest->chars+dest_len,src_len); }


FUNCTION Void Str_concat(struct Str *dest, ...) {
  struct ErrorStatus *s;
  va_list arguments; Int kind;
  Int l,u; Char *c;
  struct Str *str; char *string; struct Str temp;
  l=Str_len(dest);
  va_start(arguments,dest);
  for(;;) {
    kind=va_arg(arguments,Int);
    if(kind==S) {
      str=va_arg(arguments,struct Str *);
      l+=Str_len(str);
    orif(kind==Z)
      string=va_arg(arguments,char *);
      l+=string_len(string);
    orif(kind==(Int)END)
      break;
    orif(kind==EOS)
      l++;
      break;
    other
      error_notify_fatalz(error_id_unexpected,"Invalid Str_concat"); } }
  va_end(arguments);
  c=(Char *)memory_allocate(l,dest);
  l=0;
  va_start(arguments,dest);
  for(;;) {
    kind=va_arg(arguments,Int);
    if(kind==S) {
      str=va_arg(arguments,struct Str *); u=Str_len(str);
      memory_copy(str->chars,c+l,u); l+=u;
    orif(kind==Z)
      string=va_arg(arguments,char *); u=string_len(string);
      memory_copy(string,c+l,u); l+=u;
    orif(kind==(Int)END)
      break;
    orif(kind==EOS)
      c[l]='\0';
      break;
    other
      error_notify_fatalz(error_id_unexpected,"Invalid Str_concat"); } }
  va_end(arguments);
  Str_set(dest,c,l,true); }


FUNCTION Char *Str_string(struct Str *str) {
  Str_resize(str,Str_len(str)+1);
  str->chars[Str_len(str)-1]='\0';
  str->len2--;
  return str->chars; }


FUNCTION Void Str_substring(struct Str *fullstr,Int first_char_pos,Int maximum_length,struct Str *substr) { /// section "substring"
  check(first_char_pos>=0 && maximum_length>=0);
  if(substr->len2&Str_allocated) memory_free(substr->chars); 
  substr->chars=fullstr->chars+first_char_pos;
  substr->len2=maximum(minimum(Str_len(fullstr)-first_char_pos,maximum_length),0); }


FUNCTION Void convert_to_string(Int i,struct Str *s) {
  Char buffer[16]; Char *c; Int l;
  l=Int_str2(i,10,buffer);
  c=(Char *)memory_allocate(l,s);
  memory_copy(buffer,c,l);
  Str_set(s,c,l,true); }


/*****************************************************************************/

/*
doc
  text "the following functions are not intended to be applyed on real Str "
  text "buildd by Str_build, but are rather providing easily building of "
  text "temporary strings in C functions"
*/


FUNCTION struct Str *Str_map_string(struct Str *str,Char *string) {
  str->chars=string;
  str->len2=string_len(string);
  return str; }


FUNCTION struct Str *Str_map_area(struct Str *str,Char *chars,Int len) {
  check(len>=0);
  str->chars=chars;
  str->len2=len;
  return str; }