Files
mercury/extras/posix/text.m
Zoltan Somogyi bdb4a83570 Add necessary MR_ prefixes.
Estimated hours taken: 0.5

extras/*/*.m:
	Add necessary MR_ prefixes.
2000-12-05 02:07:23 +00:00

239 lines
6.5 KiB
Mathematica

%------------------------------------------------------------------------------%
% Copyright (C) 1999-2000 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%------------------------------------------------------------------------------%
%
% module: text.m
% main author: conway@cs.mu.oz.au
%
% This module provides a byte-array module intended for storing text and
% binary byte-oriented data.
%
%------------------------------------------------------------------------------%
:- module text.
:- interface.
:- type text.
:- type byte == int. % Using low 8 bits only.
% text(String) = Text
% takes a Mercury string `String' and returns the same data in the
% text representation `Text'.
:- func text(string) = text.
:- mode (text(in) = uo) is det.
% create(Size, Init, Text)
% creates a text object of `Size' bytes each initialized to `Init',
% and binds it to `Text'.
:- pred create(int, byte, text).
:- mode create(in, in, uo) is det.
% index(Text, Index, Value)
% binds `Value' to the `Index'th element of `Text'. Indices are
% 0 offset (Like C arrays). index/3 aborts if `Index' is out of
% range.
:- pred index(text, int, byte).
:- mode index(ui, in, out) is det.
:- mode index(in, in, out) is det.
% update(Index, Value, OldText, NewText)
% destroys `OldText' and binds `NewText' to a text object that
% is the same as `OldText' except that the byte at `Index' is
% replaced with `Value'. update/4 aborts if `Index' is out of
% range.
:- pred update(int, byte, text, text).
:- mode update(in, in, di, uo) is det.
% length(Text, Length)
% binds `Length' to the number of bytes in the text object `Text'.
:- pred length(text, int).
:- mode length(ui, out) is det.
:- mode length(in, out) is det.
% unique(SharedText) = UniqueText
% performs an unsafe uniqueness cast on `SharedText' to make
% `UniqueText'. This is useful if you're storing text objects
% inside other data structures, but is of course risky since
% it is unchecked by the compiler. USE AT OWN RISK!
:- func unique(text) = text.
:- mode unique(in) = uo is det.
% split(WholeText, Index, FirstPart, SecondPart)
% splits `WholeText' into two parts: `FirstPart' and `SecondPart'
% on the boundary `Index'.
:- pred split(text, int, text, text).
:- mode split(di, in, uo, uo) is det.
% combine(FirstPart, SecondPart, WholeText)
% combines two text objects that were created by splitting `WholeText'.
% combine/3 aborts if `FirstPart' and `SecondPart' did not come from
% the same text object (in an operational sense, not a declarative
% sense - this is a bug, or at least a missing feature).
:- pred combine(text, text, text).
:- mode combine(di, di, uo) is det.
%------------------------------------------------------------------------------%
:- implementation.
:- import_module char, int, list, std_util, string.
:- type text
---> text(c_pointer).
:- pragma c_header_code("
#include ""text_header.h""
/*
** ME_words(amt) returns the number of words necessary to
** to store `amt' bytes.
*/
#define ME_words(x) (((x) + sizeof(MR_Word) - 1) / sizeof(MR_Word))
").
%------------------------------------------------------------------------------%
text(Str) = Text :-
length(Str, Len),
create(Len, 0, Text0),
string__to_char_list(Str, Chars),
text_2(Chars, 0, Text0, Text).
:- pred text_2(list(char), int, text, text).
:- mode text_2(in, in, di, uo) is det.
text_2([], _, Text, Text).
text_2([C|Cs], N, Text0, Text) :-
char__to_int(C, I),
update(N, I, Text0, Text1),
text_2(Cs, N+1, Text1, Text).
%------------------------------------------------------------------------------%
:- pragma c_code(create(Len::in, Val::in, Txt::uo),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
MR_Word tmp;
int i;
MR_incr_hp(Txt, ME_words(sizeof(ME_Text)));
MR_incr_hp_atomic(tmp, ME_words(Len));
txtptr = (ME_Text *) Txt;
txtptr->len = Len;
txtptr->data = (char *) tmp;
for (i=0; i < Len; i++)
txtptr->data[i] = Val;
}").
%------------------------------------------------------------------------------%
:- pragma c_code(index(Txt::ui, Ind::in, Val::out),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
txtptr = (ME_Text *) Txt;
if (Ind < 0 || Ind >= txtptr->len) {
MR_fatal_error(""text:index : index out of range"");
}
Val = txtptr->data[Ind];
}").
:- pragma c_code(index(Txt::in, Ind::in, Val::out),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
txtptr = (ME_Text *) Txt;
if (Ind < 0 || Ind >= txtptr->len) {
MR_fatal_error(""text:index : index out of range"");
}
Val = txtptr->data[Ind];
}").
%------------------------------------------------------------------------------%
:- pragma c_code(update(Ind::in, Val::in, Txt0::di, Txt::uo),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
txtptr = (ME_Text *) Txt0;
if (Ind < 0 || Ind >= txtptr->len) {
MR_fatal_error(""text:index : index out of range"");
}
txtptr->data[Ind] = Val;
Txt = Txt0;
}").
%------------------------------------------------------------------------------%
:- pragma c_code(length(Txt::ui, Len::out),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
txtptr = (ME_Text *) Txt;
Len = txtptr->len;
}").
:- pragma c_code(length(Txt::in, Len::out),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr;
txtptr = (ME_Text *) Txt;
Len = txtptr->len;
}").
%------------------------------------------------------------------------------%
:- pragma c_code(unique(A::in) = (B::uo),
[will_not_call_mercury, thread_safe], "{
B = A;
}").
%------------------------------------------------------------------------------%
:- pragma c_code(split(Text0::di, Where::in, Text1::uo, Text2::uo),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr1, *txtptr2;
txtptr1 = (ME_Text *) Text0;
if (Where < 0 || Where >= txtptr1->len) {
MR_fatal_error(""text:split : index out of range"");
}
Text1 = Text0;
MR_incr_hp(Text2, ME_words(sizeof(ME_Text)));
txtptr2 = (ME_Text *) Text2;
txtptr2->len = txtptr1->len - Where;
txtptr2->data = txtptr1->data + Where;
txtptr1->len = Where;
}").
%------------------------------------------------------------------------------%
:- pragma c_code(combine(Text0::di, Text1::di, Text::uo),
[will_not_call_mercury, thread_safe], "{
ME_Text *txtptr1, *txtptr2;
txtptr1 = (ME_Text *) Text0;
txtptr2 = (ME_Text *) Text1;
if (txtptr1->data + txtptr1->len != txtptr2->data) {
MR_fatal_error(""text:combine : not adjacent text"");
}
txtptr1->len = txtptr1->len + txtptr2->len;
Text = Text0;
}").