comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: set_index and and end_of_file with just a stream reference
  @ 2021-02-23 17:21  6%           ` Shark8
  0 siblings, 0 replies; 12+ results
From: Shark8 @ 2021-02-23 17:21 UTC (permalink / raw)


On Saturday, February 20, 2021 at 12:08:16 PM UTC-7, 0012com wrote:
> Okay :-) 
> what I wanted is: 
> I read an acronyme in the stream file, if good I input the adjacent record type, otherwise I would advance on the stream until the next acronyme with set_index(stream_access, index(stream_access) + composite_type_stream_size) and read the next acronyme (unbounded_string). 
> Now I just input both objects and verify the acronyme. 
> But I don't like writing an object that maybe won't be used.
Hm, what are your datatypes? Is this ONLY text, or are you able to impose your own structure?
You could have something like this:

-- Instantiated Container Packages.
Package String_Holder is new Ada.Containers.Indefinite_Holders(
       Element_Type => String,
       "="          => Ada.Strings.Equal_Case_Insensitive
      );
Package String_Map is new Ada.Containers.Indefinite_Ordered_Maps(
       "<"          => Ada.Strings.Less_Case_Insensitive,
       "="          => Ada.Strings.Equal_Case_Insensitive,
       Key_Type     => String,
       Element_Type => String
      );

-- The heart of the operating program.
With String_Holder, String_Map;
Package Acronyms is
  -- Because this is it's own type, you can put other things in the record, like a link to the place that it's defined, if needed.
  Type Initialism is new String_Holder.Holder with null record;

  Function Expand( Acronym : Initialism ) return String;
  Procedure Register( Acronym, Expansion : String );
--...
End Acronyms;

Package Body Acronyms is
    Acronym_Map : String_Map.Map;
  Procedure Register( Acronym, Expansion : String ) is
  Begin
    Acronym_Map.Insert( New_Item => Expansion, Key => Acronym );
  End Register;  

  Function Expand( Acronym : Initialism ) return String is
  Begin
    Return Acronym_Map( Acronym );
  Exception
    when others => Return Acronym; -- I forget if it's CONSTRAINT_ERROR or ASSERT_ERROR when the element is not present.
  End Expand;
End Acronyms;

-- in your main Acronym-Stream package...
-- Text_Soup is a variant record for handling portions of an acronym-expanding string; your main data-structure would probably be an Indefinite_Vector of Text_Soup'Class,
-- you might not need Input or output, depending on your usage, but for automatically expanding the initialism you'd need to use Acronyms.Expand.

    Type Text_Soup(<>) is tagged private;
    procedure Output(
       Stream : not null access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Text_Soup'Class);
    function Input(
       Stream : not null access Ada.Streams.Root_Stream_Type'Class)
       return Text_Soup'Class;

   -- Other public operations.
PRIVATE
    For Text_Soup'Class'Input  use Input;
    For Text_Soup'Class'Output use Output;

Type Text_Soup(Length : Natural) is record
  case Length is
    when 0 => Acronym : Initialism;
    when others => Text : String(1..Length);
  end case;
end record;
--...


^ permalink raw reply	[relevance 6%]

* Re: Visibility issue
  @ 2020-09-17 21:47  5% ` Shark8
  0 siblings, 0 replies; 12+ results
From: Shark8 @ 2020-09-17 21:47 UTC (permalink / raw)


On Friday, September 11, 2020 at 4:37:29 AM UTC-6, Daniel wrote:
> Hello, 
> I want to use a tagged type as a link to communicate users of a library, in the way to make one part visible to them and also to hide some content that is only needed for the implementing of the library.

Here's how that's normally achieved; I've compiled the following but haven't written a testbed/driver:

-- Daniel.ads
Package Daniel with Pure is
   -- Base Interface which all API objects implement.
   Type Abstract_Base is interface;
   
   -- All common methods.
   Function As_String(Object : Abstract_Base) return String is abstract;
   
   -- All Classwide methods.
   Function Print( Object : Abstract_Base'Class ) return String;
   
   
   -- The Callback type.
   Type Callback is access
     procedure(Item : in out Abstract_Base'Class);
   
Private
   -- The classwide "Print" returns the given object's As_String result.
   Function Print( Object : Abstract_Base'Class ) return String is
      (Object.As_String);
End Daniel;

-----------------------------------------------
-- Daniel-Implementation.ads
With
Ada.Finalization,
Ada.Strings.Equal_Case_Insensitive,
Ada.Strings.Less_Case_Insensitive,
Ada.Containers.Indefinite_Ordered_Maps;

Private Package Daniel.Implementation with Preelaborate is
   -- Fwd decl.
   Type Implementation_Base(Name_Length : Positive) is tagged private;
   
   -- Implementation_Base and its descendents have a Name, that is within the
   -- private-portion of the implementation and therefore we need an accessor.
   -- Note: Name is unique and case-insensitive.
   Function Get_Name(Object: Implementation_Base'Class) Return String;

   -- Given a name, this retrieves the object; raises constraint-error if that
   -- name is not associated with an object.
   Function Make  (Name : String) return Implementation_Base'Class;
   Function Create(Name : String) return Implementation_Base;
   Function "="(Left, Right : Implementation_Base) return Boolean;
   
Private
   -- Full decl. Note, also, that this is hidden from the API package.
   Type Implementation_Base(Name_Length : Positive) is
     new Ada.Finalization.Controlled with record
      Name : String(1..Name_Length);
   End record;
   
   -- Finalization; this will remove the registered Name from the object-map.
   overriding
   procedure Finalize   (Object : in out Implementation_Base);

   -- Instantiate the package mapping Names to Objects.
   Package Name_Map is new Ada.Containers.Indefinite_Ordered_Maps(
         Key_Type     => String,
         Element_Type => Implementation_Base'Class,
         "<" => Ada.Strings.Less_Case_Insensitive,
         "=" => "="
        );
   
   -- This is the map that associates objects and their names.
   Core_Map : Name_Map.Map;
End Daniel.Implementation;

------------------------------------------------
-- Daniel-API.ads
Private With
Daniel.Implementation;

Private Package Daniel.API with Preelaborate is
   -- The base API-visable type.
   Type API_Base(<>) is new Abstract_Base with private;
   
   -- Creation functions.
   Function Create(Name : String) return API_Base;
   Function Create(Name : String; Op : Callback) return API_Base;
   
   -- Interface functions.
   Function As_String (Object :        API_Base) return String;
   Procedure Execute  (Object : in out API_Base);
Private
   -- We derive from implementation's base, and add a discriminant for the
   -- callback and another fata-field.
   Type API_Base( CBK : Callback; Length : Positive ) is
     new Daniel.Implementation.Implementation_Base( Name_Length => Length )
     and Abstract_Base with record
      A_1 : Character := 'C';
   end record;
   
   -- We raise an exception when there is no callback given.
   Function Create(Name : String) return API_Base is
     (raise Program_Error with "Callback MUST be specified.");
   
   -- Finally, we construct an object from a call to implementation's create
   -- and fill-in the missing information using an "extension aggrigate".
   Function Create(Name : String; Op : Callback) return API_Base is
     (Implementation.Create(Name) with
      CBK => Op, Length => Name'Length, others => <>);
   
End Daniel.API;

------------------------------------------------------------------------------
-- Daniel-Implementation.adb
with
Ada.Exceptions,
Ada.Finalization;

use
Ada.Finalization;

Package Body Daniel.Implementation is
   Function "=" (Left, Right : String) return Boolean
    renames Ada.Strings.Equal_Case_Insensitive;
   
   Function Get_Name(Object: Implementation_Base'Class) Return String is
     (Object.Name);

   Function Make(Name : String) return Implementation_Base'Class is
   Begin
      Return Core_Map(Name);
   Exception
      when PE : Program_Error =>
         raise Constraint_Error with Ada.Exceptions.Exception_Message(PE);
   End Make;

   Function "="(Left, Right : Implementation_Base) return boolean is
      (Left.Name = Right.Name);
   
   Function Create(Name : String) return Implementation_Base is
   begin
      Return Result : Constant Implementation_Base :=
        (Controlled with Name_Length => Name'Length, Name => Name) do
         Core_Map.Include(New_Item => Result, Key => Name);
      end return;
   end Create;
   
   Procedure Finalize(Object : in out Implementation_Base) is
   Begin
      Core_Map.Delete( Object.Name );
   End Finalize;
   
End Daniel.Implementation;

------------------------------------------------------
-- Daniel-API.adb
Package Body Daniel.API is
   Procedure Execute  (Object : in out API_Base) is
   Begin
      Object.CBK.All(Object);
   End Execute;

   Function As_String (Object : in API_Base) return String is
   Begin
      Return '(' & Object.Get_Name & ", " & Object.A_1 & ')';
   End As_String;
End Daniel.API;

^ permalink raw reply	[relevance 5%]

* Re: Suggestions needed to split a package
  @ 2019-05-24 21:21  7%     ` Shark8
  0 siblings, 0 replies; 12+ results
From: Shark8 @ 2019-05-24 21:21 UTC (permalink / raw)


On Friday, May 24, 2019 at 2:26:04 PM UTC-6, Randy Brukardt wrote:
> "Björn Lundin" wrote in message 
> news:qc9595$ime$1...
> > Den 2019-05-24 kl. 17:49, skrev A. Cervetti:
> >> A package in the program I am writing is getting too long.
> >> So I thought it would be a good idea to split it.
> >>
> >> The package is here: 
> >> https://github.com/andreacervetti/ada-virt-monitor/tree/master/avm/src/monitor 
> >> (files monitor-structures.ad*).
> >>
> >> My problems are:
> >> I'd like to avoid forcing clients of the package to "with" too many 
> >> modules.
> >> I want keep private types private.
> >
> > If it is only file size that is your concern, you
> > can look at moving some functions via 'separate' to other files.
> > It does not change your structure, and clients of
> > the package does not know -> not more withs than current solution
> 
> Yes, although if there are a lot of small subprograms, it's not very 
> effective as you would end up with a *lot* of files (making it hard to find 
> things and slowing compilation). And you can't make overloaded subprograms 
> separate (the names have to be unique).

The way I've gotten around this is by putting these small subprograms in a nested-package within the body, making *that* package separate, and using renames.

Package Public is
  Type T1 is private;
  Procedure P1;
  Procedure P2;
  --...
End Public;

Package Body Public is
  Package Internal is
    Procedure P1;
    Procedure P2;
  End Internal;
  Package Body Internal is Separate;
  
  Procedure P1 renames Internal.P1;
  Procedure P2 renames Internal.P2;
End Public;

-------
As to making overloaded subprograms separate, is there a way to correct this? That, plus [TTBOMK] not being able to overload subprograms in the library hierarchy seem to be fairly related and could arguably make maintenance easier.

e.g. We can't have both
function Ada.Strings.Equal_Case_Insensitive (Left, Right : String) return Boolean;
function Ada.Strings.Equal_Case_Insensitive (Left, Right : Wide_Wide_String) return Boolean;

^ permalink raw reply	[relevance 7%]

* Re: Unicode string comparision functions
  2015-11-13  0:10  0%       ` Randy Brukardt
@ 2015-11-13  8:22  0%         ` Simon Wright
  0 siblings, 0 replies; 12+ results
From: Simon Wright @ 2015-11-13  8:22 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
> news:n233vr$1h5$2@dont-email.me...
>> On 11/12/2015 01:01 PM, Shark8 wrote:
>>>
>>> ...Wide_Wide_Equal_Case_Insensitive --- Testing it out, the
>>> compiler's giving me an error saying
>>> ""Ada.Strings.Wide_Wide_Equal_Case_Insensitive" is not a predefined
>>> library unit", which is good in that it saves me from feeling
>>> **REALLY** stupid.
>>
>> ARM A.4.8 clearly indicates that there should be such a library
>> function, similar to Ada.Strings.Equal_Case_Insensitive from A.4.10
>> for String.
>>
>> They were added by Ada 12, so if you're using a compiler for an
>> earlier version they probably won't exist. If you are using an Ada-12
>> compiler, you should probably complain.
>
> Right, assuming you spelled it right (with the Wide Wide madness,
> spelling it wrong isn't that uncommon!).

GNAT GPL 2015 provides Equal_Case_Insensitive only in plain Strings,
Bounded, Fixed, Unbounded.

^ permalink raw reply	[relevance 0%]

* Re: Unicode string comparision functions
  2015-11-12 22:33  6%     ` Jeffrey R. Carter
@ 2015-11-13  0:10  0%       ` Randy Brukardt
  2015-11-13  8:22  0%         ` Simon Wright
  0 siblings, 1 reply; 12+ results
From: Randy Brukardt @ 2015-11-13  0:10 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:n233vr$1h5$2@dont-email.me...
> On 11/12/2015 01:01 PM, Shark8 wrote:
>>
>> ...Wide_Wide_Equal_Case_Insensitive --- Testing it out, the compiler's 
>> giving
>> me an error saying ""Ada.Strings.Wide_Wide_Equal_Case_Insensitive" is not 
>> a
>> predefined library unit", which is good in that it saves me from feeling
>> **REALLY** stupid.
>
> ARM A.4.8 clearly indicates that there should be such a library function,
> similar to Ada.Strings.Equal_Case_Insensitive from A.4.10 for String.
>
> They were added by Ada 12, so if you're using a compiler for an earlier 
> version
> they probably won't exist. If you are using an Ada-12 compiler, you should
> probably complain.

Right, assuming you spelled it right (with the Wide Wide madness, spelling 
it wrong isn't that uncommon!).

                                  Randy.



^ permalink raw reply	[relevance 0%]

* Re: Unicode string comparision functions
  @ 2015-11-12 22:33  6%     ` Jeffrey R. Carter
  2015-11-13  0:10  0%       ` Randy Brukardt
  0 siblings, 1 reply; 12+ results
From: Jeffrey R. Carter @ 2015-11-12 22:33 UTC (permalink / raw)


On 11/12/2015 01:01 PM, Shark8 wrote:
> 
> ...Wide_Wide_Equal_Case_Insensitive --- Testing it out, the compiler's giving
> me an error saying ""Ada.Strings.Wide_Wide_Equal_Case_Insensitive" is not a
> predefined library unit", which is good in that it saves me from feeling
> **REALLY** stupid.

ARM A.4.8 clearly indicates that there should be such a library function,
similar to Ada.Strings.Equal_Case_Insensitive from A.4.10 for String.

They were added by Ada 12, so if you're using a compiler for an earlier version
they probably won't exist. If you are using an Ada-12 compiler, you should
probably complain.

-- 
Jeff Carter
"Sons of a silly person."
Monty Python & the Holy Grail
02


^ permalink raw reply	[relevance 6%]

* Re: String_Holder ?
  @ 2011-12-19 11:12  6% ` Martin
  0 siblings, 0 replies; 12+ results
From: Martin @ 2011-12-19 11:12 UTC (permalink / raw)


On Dec 18, 12:34 pm, Natasha Kerensikova <lithium...@gmail.com> wrote:
> Hello,
>
> in my few Ada projects so far, I have quite often encountered the need
> of storing a string along with other information in records. So I went
> for discriminants containing the string size, and putting the string
> directly in the record.
>
> This works well when there is only one or two strings, but with several
> of them, or in variant records, I find it quite heavy. So I was thinking
> about something like that:
>
> type String_Holder is still to be defined;
>
> function Hold (S : String) return String_Holder;
>
> function To_String (Holder : String_Holder) return String;
>
> procedure Query (Holder : String_Holder;
>                  Process : not null access procedure (S : String));
>
> I'm still unsure on what kind of type String_Holder should be (private,
> tagged private or interface). It would basically be a constant-size
> reference to an immutable string that is stored "somewhere".
>
> The simplest implementation would be an Unbounded_String, though if
> needed it could be improved reference counting to make assignments
> cheaper, or with a hash table to deduplicate identical strings, etc.
>
> So my question is, does it make sense to have such objects? Or am I
> getting blinded by my C past, where strings are always manipulated
> through a char* object?
>
> Assuming it does make sense, am I right in thinking it's better to have
> such a type, even if it's a thin wrapper around Unbounded_String,
> instead of using directly Unbounded_String?
>
> Assuming it does make sense to have a String_Holder, would it be better
> to have it private, tagged private or interface?
> My guess is that tagged private has no advantage over interface,
> especially with a default implementation around Unbounded_String, which
> doesn't need to be controlled, but then controlled extension would be
> heavier. Then the choice between private and interface amounts to
> whether or not it could be useful to use simultaneously several
> implementations of String_Holder in the same project. I cannot think of
> any project where it would be the case, so I would lean towards private,
> but maybe I'm lacking imagination here.
>
> Still under the same assumption, is the above specification sane, or am
> I missing something? Query procedure is probably not absolutely
> necessary, but I guess it can be occasionally useful to save a string
> copy compared to To_String, and it seems to be a very small
> implementation burden anyway.
>
> Still under the same assumption, can it be useful to provide unary "+"
> functions to tersely convert String_Holder to String, and maybe
> vice-versa, or would it do more harm (obfuscation) than good?
>
> And lastly, is there any trick to allow a String_Holder object or
> similar to be pre-elaborable?
>
> Thanks in advance for your insights,
> Natasha

Have you considered a "Flyweight"?

Here's an example in Ada2012 (which is soooo much easier to acheive
than in previous Ada versions).

The coffee flavour string is repeated in each order but only unique
strings are stored and each order context contains a reference to the
string.

In a real application, you'd want probably want to add finalization.

-- Martin



-- main.adb
with Applications; use Applications;
procedure Main is
   App : Application := Create;
begin
   App.Execute;
end Main;

-- applications.ads
        private with Ada.Containers.Vectors;
        private with Coffee_Orders.Flavours;
        private with Coffee_Orders.Flavours.Factories;
limited private with Coffee_Order_Contexts;
package Applications is
   type Application (<>) is tagged limited private;
   function Create return Application;
   procedure Execute (A : in out Application);
private
   use Coffee_Orders.Flavours.Factories;
   type Order is record
      Context : access Coffee_Order_Contexts.Coffee_Order_Context;
      Flavour : access Coffee_Orders.Flavours.Flavour;
   end record;
   package Order_Vectors is
      new Ada.Containers.Vectors (Natural, Order);
   type Application is tagged limited record
      Orders          : Order_Vectors.Vector;
      Flavour_Factory : Coffee_Orders.Flavours.Factories.Factory;
   end record;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer);
end Applications;

-- applications.adb
with Ada.Text_IO;            use Ada.Text_IO;
with Coffee_Order_Contexts;  use Coffee_Order_Contexts;
with Coffee_Orders.Flavours; use Coffee_Orders.Flavours;
package body Applications is
   function Create return Application is
   begin
      return Result : Application do
         null;
      end return;
   end Create;
   procedure Take_Orders (A       : in out Application;
                          Flavour :        String;
                          Table   :        Integer) is
   begin
      A.Orders.Append ((Context => new Coffee_Order_Context'(Create
(Table)),
                        Flavour =>
Flavour_Ref'(A.Flavour_Factory.Get_Flavour (Flavour))));
   end Take_Orders;
   procedure Execute (A : in out Application) is
   begin
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Cappuccino", 2);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Frappe", 1);
      A.Take_Orders ("Xpresso", 1);
      A.Take_Orders ("Frappe", 897);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Cappuccino", 97);
      A.Take_Orders ("Frappe", 3);
      A.Take_Orders ("Xpresso", 3);
      A.Take_Orders ("Cappuccino", 3);
      A.Take_Orders ("Xpresso", 96);
      A.Take_Orders ("Frappe", 552);
      A.Take_Orders ("Cappuccino", 121);
      A.Take_Orders ("Xpresso", 121);
      for Order of A.Orders loop
         Order.Flavour.Serve_Coffee (Order.Context.all);
      end loop;
      Put_Line ("Total Coffee_Flavor objects made:" & Integer'Image
(A.Flavour_Factory.Total_Flavours_Made));
   end Execute;
end Applications;

-- coffee_order_contexts.ads
package Coffee_Order_Contexts is
   type Coffee_Order_Context (<>) is tagged private;
   function Create (Table : Integer) return Coffee_Order_Context;
   function Table_No (COC : Coffee_Order_Context) return Integer;
private
   type Coffee_Order_Context is tagged record
      Table : Integer := 0;
   end record;
end Coffee_Order_Contexts;

-- coffee_order_contexts.adb
package body Coffee_Order_Contexts is
   function Create (Table : Integer) return Coffee_Order_Context is
   begin
      return Result : Coffee_Order_Context do
         Result.Table := Table;
      end return;
   end Create;
   function Table_No (COC : Coffee_Order_Context) return Integer is
   begin
      return COC.Table;
   end Table_No;
end Coffee_Order_Contexts;

-- coffee_order_contexts-vectors.ads
with Ada.Containers.Indefinite_Vectors;
package Coffee_Order_Contexts.Vectors is
   new Ada.Containers.Indefinite_Vectors (Natural,
Coffee_Order_Context);

-- coffee_orders.ads
with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders is
   type Coffee_Order is interface;
   procedure Serve_Coffee (CO  : Coffee_Order;
                           COC : Coffee_Order_Context) is abstract;
end Coffee_Orders;

-- coffee_orders-flavours.ads
private with Ada.Strings.Unbounded;
        with Coffee_Order_Contexts; use Coffee_Order_Contexts;
package Coffee_Orders.Flavours is
   type Flavour (<>) is new Coffee_Order with private;
   type Flavour_Ref is access all Flavour'Class;
   function Create (Name : String) return Flavour;
   function "=" (L, R : Flavour) return Boolean;
   overriding
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context);
private
   use Ada.Strings.Unbounded;
   type Flavour is new Coffee_Order with record
      Name : Unbounded_String;
   end record;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours.adb
with Ada.Strings.Equal_Case_Insensitive;
with Ada.Text_IO; use Ada.Text_IO;
package body Coffee_Orders.Flavours is
   function Create (Name : String) return Flavour is
   begin
      return Result : Flavour do
         Result.Name := To_Unbounded_String (Name);
      end return;
   end Create;
   function "=" (L, R : Flavour) return Boolean is
   begin
      return Ada.Strings.Equal_Case_Insensitive (To_String (L.Name),
To_String (R.Name));
   end "=";
   procedure Serve_Coffee (F   : Flavour;
                           COC : Coffee_Order_Context) is
   begin
      Put_Line ("Serving Coffee flavor " & To_String (F.Name)
                & " to table number " & Integer'Image (COC.Table_No));
   end Serve_Coffee;
end Coffee_Orders.Flavours;

-- coffee_orders-flavours-vectors.ads
with Ada.Containers.Vectors;
package Coffee_Orders.Flavours.Vectors is
   new Ada.Containers.Vectors (Natural, Flavour_Ref);

-- coffee_orders-flavours-factories.ads
private with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Strings.Equal_Case_Insensitive;
private with Ada.Strings.Hash_Case_Insensitive;
private with Ada.Strings.Unbounded;
package Coffee_Orders.Flavours.Factories is
   type Factory is tagged private;
   function Get_Flavour (F    : in out Factory;
                         Name :        String)
                         return not null access Flavour;
   function Total_Flavours_Made (F : Factory) return Natural;
private
   use Ada.Strings.Unbounded;
   package Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type        =>
String,
                                                Element_Type    =>
Flavour,
                                                Hash            =>
Ada.Strings.Hash_Case_Insensitive,
                                                Equivalent_Keys =>
Ada.Strings.Equal_Case_Insensitive);
   type Factory is tagged record
      Flavours : Maps.Map;
   end record;
end Coffee_Orders.Flavours.Factories;

-- coffee_orders-flavours-factories.adb
package body Coffee_Orders.Flavours.Factories is
   function Get_Flavour (F    : in out Factory;
                         Name :        String) return not null access
Flavour is
      use type Maps.Cursor;
      C : constant Maps.Cursor := F.Flavours.Find (Name);
   begin
      if C /= Maps.No_Element then
         return F.Flavours.Constant_Reference (Name).Element;
      end if;
      F.Flavours.Insert (Name, Create (Name));
      return F.Flavours.Constant_Reference (Name).Element;
   end Get_Flavour;
   function Total_Flavours_Made (F : Factory) return Natural is
   begin
      return Natural (F.Flavours.Length);
   end Total_Flavours_Made;
end Coffee_Orders.Flavours.Factories;



^ permalink raw reply	[relevance 6%]

* Re: Why no Ada.Wide_Directories?
  2011-10-18  1:10  5%       ` Adam Beneschan
  2011-10-18  2:32  0%         ` ytomino
@ 2011-10-18  3:15  0%         ` Yannick Duchêne (Hibou57)
  1 sibling, 0 replies; 12+ results
From: Yannick Duchêne (Hibou57) @ 2011-10-18  3:15 UTC (permalink / raw)


Le Tue, 18 Oct 2011 03:10:35 +0200, Adam Beneschan <adam@irvine.com> a  
écrit:
> That's why it doesn't
> make sense to have string routines (like
> Ada.Strings.Equal_Case_Insensitive or Ada.Character_Handling.To_Upper)
> that work with UTF-8.
That would make sens, if String was an array container for _one_ Unicode  
character subset and nothing else. What a mess if someone pass an UTF-8  
string to such a casing mapping method (*)… don't expect to decode it  
after that.

(*) Except if the string is restricted to US-ASCII, in which case, you  
will not get anything wrong, but just still a pure US-ASCII string, which  
is always UTF-8 by definition. Not the same story for ISO-8859-1 strings.

-- 
“Syntactic sugar causes cancer of the semi-colons.”  [Epigrams on  
Programming — Alan J. — P. Yale University]
“Structured Programming supports the law of the excluded muddle.” [Idem]
Java: Write once, Never revisit



^ permalink raw reply	[relevance 0%]

* Re: Why no Ada.Wide_Directories?
  2011-10-18  1:10  5%       ` Adam Beneschan
@ 2011-10-18  2:32  0%         ` ytomino
  2011-10-18  3:15  0%         ` Yannick Duchêne (Hibou57)
  1 sibling, 0 replies; 12+ results
From: ytomino @ 2011-10-18  2:32 UTC (permalink / raw)


On Oct 18, 10:10 am, Adam Beneschan <a...@irvine.com> wrote:
> On Oct 17, 4:47 pm, ytomino <aghi...@gmail.com> wrote:
>
>
>
>
>
>
>
>
>
> > On Oct 18, 6:33 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
> > > Say what?
>
> > > Ada.Strings.Encoding (new in Ada 2012) uses a subtype of String to store
> > > UTF-8 encoded strings. As such, I'd find it pretty surprising if doing so
> > > was "a violation of the standard".
>
> > > The intent has always been that Open, Ada.Directories, etc. take UTF-8
> > > strings as an option. Presumably the implementation would use a Form to
> > > specify that the file names in UTF-8 form rather than Latin-1. (I wasn't
> > > able to find a reference for this in a quick search, but I know it has been
> > > talked about on several occasions.)
>
> > > One of the primary reasons that Ada.Strings.Encoding uses a subtype of
> > > String rather than a separate type is so that it can be passed to Open and
> > > the like.
>
> > > It's probably true that we should standardize on the Form needed to use
> > > UTF-8 strings in these contexts, or at least come up with Implementation
> > > Advice on that point.
>
> > >                                        Randy.
>
> > Good news. Thanks for letting know.
> > My worry is decreased a little.
>
> > However, even if that is right, Form parameters are missing for many
> > subprograms.
> > Probably, All subprograms in Ada.Directories,
> > Ada.Directories.Hierarchical_File_Names, Ada.Command_Line,
> > Ada.Environment_Variables and other subprograms having Name parameter
> > or returning a file name should have Form parameter.
> > (For example, I do Open (X, Form => "UTF-8"). Which does Name (X)
> > returns UTF-8 or Latin-1?)
>
> > Moreover, in the future, we will always use I/O subprograms as UTF-8
> > mode if what you say is realized.
> > But other libraries in the standard are explicitly defined as Latin-1.
> > It's certain that Ada.Character.Handling.To_Upper breaks UTF-8.
>
> I have a feeling you're fundamentally confused about what UTF-8 is, as
> compared to "Latin-1".  Latin-1 is a character mapping.  It defines,
> for all integers in the range 0..255, what character that integer
> represents (e.g. 77 represents 'M', etc.).  Unicode is a character
> mapping that defines characters for a much larger integer range.  For
> integers in the range 0..255, the character represented in Unicode is
> the same as that in Latin-1; higher integers represent characters in
> other alphabets, other symbols, etc.  Those mappings just tell you
> what symbols go with what numbers, and they don't say anything about
> how the numbers are supposed to be stored.
>
> UTF-8 is an encoding (representation).  It defines, for each non-
> negative integer up to a certain point, what bits are used to
> represent that integer.  The number of bits is not fixed.  So even if
> you're working with characters all in the 0..255 range, some of those
> characters will be represented in 8 bits (one byte) and some will take
> 16 bits (two bytes).
>
> Because of this, it is not feasible to work with strings or characters
> in UTF-8 encoding.  Suppose you declare a string
>
>    S : String (1 .. 100);
>
> but you want it to be a UTF-8 string.  How would that work?  If you
> want to look at S(50), the computer would have to start at the
> beginning of the string and figure out whether each character is
> represented as 1 or 2 bytes.  Nobody wants that.
>
> The only sane way to work with strings in memory is to use a format
> where every character is the same size (String if all your characters
> are in the 0..255 range, Wide_String for 0..65535, Wide_Wide_String
> for 0..2**32-1).  Then, if you have a string of bytes in UTF-8 format,
> you convert it to a regular (Wide_)(Wide_)String with routines in
> Ada.Strings.UTF_Encoding; and it also has routines for converting
> regular strings to UTF-8 format.  But you don't want to *keep* strings
> in memory and work with them in UTF-8 format.  That's why it doesn't
> make sense to have string routines (like
> Ada.Strings.Equal_Case_Insensitive or Ada.Character_Handling.To_Upper)
> that work with UTF-8.
>
> Hope this solves your problem.
>
>                              -- Adam

I'm not confused. Your misreading.

Of course, if applications always hold file names as Wide_Wide_String,
and encode to UTF-8 only/every calling I/O subprograms as what you
say, so it's very simple and it is perhaps intended method. I
understand it.

But, where do these file names come from?
These are usually told by command-line or configuration file (written
by user).
It is probably encoded UTF-8 if the locale setting of OS is UTF-8.
So Form parameters of subprograms in Ada.Command_Line are necessary
and it's natural keeping UTF-8.

(Some file systems like Linux accept broken code as correct file name.
Applications must not (can not?) decode/encode file names in this
case.
Broken file name may be right file name if user sets LANG variable.
Same thing is in NTFS/NFS+. These file systems can accept broken
UTF-16. Strictly speaking, always, an application should not encode/
decode file names. But, Ada decides file names are stored into String
(as long as Randy says). So we have to give up about UTF-16 file
systems.)

And, it's popular that text processing functions keep encoded strings
in many other libraries or languages. I do not necessarily want to
deny the way of Ada, but I feel your opinion is prejudiced. It is not
so difficult as you say in fact.



^ permalink raw reply	[relevance 0%]

* Re: Why no Ada.Wide_Directories?
  2011-10-17 23:47  5%     ` ytomino
@ 2011-10-18  1:10  5%       ` Adam Beneschan
  2011-10-18  2:32  0%         ` ytomino
  2011-10-18  3:15  0%         ` Yannick Duchêne (Hibou57)
  0 siblings, 2 replies; 12+ results
From: Adam Beneschan @ 2011-10-18  1:10 UTC (permalink / raw)


On Oct 17, 4:47 pm, ytomino <aghi...@gmail.com> wrote:
> On Oct 18, 6:33 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
>
>
>
>
>
>
> > Say what?
>
> > Ada.Strings.Encoding (new in Ada 2012) uses a subtype of String to store
> > UTF-8 encoded strings. As such, I'd find it pretty surprising if doing so
> > was "a violation of the standard".
>
> > The intent has always been that Open, Ada.Directories, etc. take UTF-8
> > strings as an option. Presumably the implementation would use a Form to
> > specify that the file names in UTF-8 form rather than Latin-1. (I wasn't
> > able to find a reference for this in a quick search, but I know it has been
> > talked about on several occasions.)
>
> > One of the primary reasons that Ada.Strings.Encoding uses a subtype of
> > String rather than a separate type is so that it can be passed to Open and
> > the like.
>
> > It's probably true that we should standardize on the Form needed to use
> > UTF-8 strings in these contexts, or at least come up with Implementation
> > Advice on that point.
>
> >                                        Randy.
>
> Good news. Thanks for letting know.
> My worry is decreased a little.
>
> However, even if that is right, Form parameters are missing for many
> subprograms.
> Probably, All subprograms in Ada.Directories,
> Ada.Directories.Hierarchical_File_Names, Ada.Command_Line,
> Ada.Environment_Variables and other subprograms having Name parameter
> or returning a file name should have Form parameter.
> (For example, I do Open (X, Form => "UTF-8"). Which does Name (X)
> returns UTF-8 or Latin-1?)
>
> Moreover, in the future, we will always use I/O subprograms as UTF-8
> mode if what you say is realized.
> But other libraries in the standard are explicitly defined as Latin-1.
> It's certain that Ada.Character.Handling.To_Upper breaks UTF-8.

I have a feeling you're fundamentally confused about what UTF-8 is, as
compared to "Latin-1".  Latin-1 is a character mapping.  It defines,
for all integers in the range 0..255, what character that integer
represents (e.g. 77 represents 'M', etc.).  Unicode is a character
mapping that defines characters for a much larger integer range.  For
integers in the range 0..255, the character represented in Unicode is
the same as that in Latin-1; higher integers represent characters in
other alphabets, other symbols, etc.  Those mappings just tell you
what symbols go with what numbers, and they don't say anything about
how the numbers are supposed to be stored.

UTF-8 is an encoding (representation).  It defines, for each non-
negative integer up to a certain point, what bits are used to
represent that integer.  The number of bits is not fixed.  So even if
you're working with characters all in the 0..255 range, some of those
characters will be represented in 8 bits (one byte) and some will take
16 bits (two bytes).

Because of this, it is not feasible to work with strings or characters
in UTF-8 encoding.  Suppose you declare a string

   S : String (1 .. 100);

but you want it to be a UTF-8 string.  How would that work?  If you
want to look at S(50), the computer would have to start at the
beginning of the string and figure out whether each character is
represented as 1 or 2 bytes.  Nobody wants that.

The only sane way to work with strings in memory is to use a format
where every character is the same size (String if all your characters
are in the 0..255 range, Wide_String for 0..65535, Wide_Wide_String
for 0..2**32-1).  Then, if you have a string of bytes in UTF-8 format,
you convert it to a regular (Wide_)(Wide_)String with routines in
Ada.Strings.UTF_Encoding; and it also has routines for converting
regular strings to UTF-8 format.  But you don't want to *keep* strings
in memory and work with them in UTF-8 format.  That's why it doesn't
make sense to have string routines (like
Ada.Strings.Equal_Case_Insensitive or Ada.Character_Handling.To_Upper)
that work with UTF-8.

Hope this solves your problem.

                             -- Adam



^ permalink raw reply	[relevance 5%]

* Re: Why no Ada.Wide_Directories?
  @ 2011-10-17 23:47  5%     ` ytomino
  2011-10-18  1:10  5%       ` Adam Beneschan
  0 siblings, 1 reply; 12+ results
From: ytomino @ 2011-10-17 23:47 UTC (permalink / raw)


On Oct 18, 6:33 am, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
>
> Say what?
>
> Ada.Strings.Encoding (new in Ada 2012) uses a subtype of String to store
> UTF-8 encoded strings. As such, I'd find it pretty surprising if doing so
> was "a violation of the standard".
>
> The intent has always been that Open, Ada.Directories, etc. take UTF-8
> strings as an option. Presumably the implementation would use a Form to
> specify that the file names in UTF-8 form rather than Latin-1. (I wasn't
> able to find a reference for this in a quick search, but I know it has been
> talked about on several occasions.)
>
> One of the primary reasons that Ada.Strings.Encoding uses a subtype of
> String rather than a separate type is so that it can be passed to Open and
> the like.
>
> It's probably true that we should standardize on the Form needed to use
> UTF-8 strings in these contexts, or at least come up with Implementation
> Advice on that point.
>
>                                        Randy.

Good news. Thanks for letting know.
My worry is decreased a little.

However, even if that is right, Form parameters are missing for many
subprograms.
Probably, All subprograms in Ada.Directories,
Ada.Directories.Hierarchical_File_Names, Ada.Command_Line,
Ada.Environment_Variables and other subprograms having Name parameter
or returning a file name should have Form parameter.
(For example, I do Open (X, Form => "UTF-8"). Which does Name (X)
returns UTF-8 or Latin-1?)

Moreover, in the future, we will always use I/O subprograms as UTF-8
mode if what you say is realized.
But other libraries in the standard are explicitly defined as Latin-1.
It's certain that Ada.Character.Handling.To_Upper breaks UTF-8.
So we can not use almost subprograms in Ada.Characters and Ada.Strings
for handling file names.
(For example, Ada.Directories.Name_Case_Equivalence returns
Case_Insensitive. We can not use Ada.Strings.Equal_Case_Insensitive to
compare two file names.)
It means standard libraries are separated UTF-8 from Latin-1.
It's not reasonable.

I wish it be solved.



^ permalink raw reply	[relevance 5%]

* Re: OO Style with Ada Containers
  @ 2007-11-19  2:24  5%       ` Matthew Heaney
  0 siblings, 0 replies; 12+ results
From: Matthew Heaney @ 2007-11-19  2:24 UTC (permalink / raw)


braver <deliverable@gmail.com> writes:

> As you can see, I've managed to do prefix notation everywhere except
> cursors.  How do they coexist with prefix notation -- or are they
> replaced by something cooler already, too?  :)

No, cursors aren't tagged because an operation can only be primitive for a
single tagged type, and the container type is already tagged.


> I'd appreciate any improvements to the above, which I deduced from ARM
> and Rosetta Stone examples in an hour and then prefix'ised thanks to
> Adam's hint!  (Well I've followed Ada since 1987 so the spirit is easy
> to follow...)

The problem with your code is here:

   Ngram_Cursor := Ngram_Counts.Find(s);

   if not Has_Element(Ngram_Cursor) then
       Ngram_Counts.Insert(s, 1);
       New_Word_Count := New_Word_Count + 1;
   else -- a valid position in Ngram_Pos
       Count := Element(Ngram_Cursor);
       Ngram_Counts.Replace_Element(Ngram_Cursor, Count+1);
  end if;


The issue is that Find duplicates the search that must already be performed by
Insert. You don't want to be doing this if the map has many elements.

The solution is to use the conditional form of Insert, which does an atomic
search-and-insert and reports back the result of the search.  If the key is
already in the map, the cursor returned designates the existing key/element
pair (which is not modified); if the key is not in the map, the key/element
pair is inserted and the cursor passed back designates the newly-inserted pair.

What you do here is insert a count of 0 for the word, and then increment the
count. If the word is already in the map, the existing count is increment.  If
the word is not already in the map, the count is 0, so it gets incremented to
the value 1 (which is the desired value).

I have included an example program below.  Also included is a simple scanner
that returns a lexeme for each whitespace-delimited word on a line of text.

Feel free to write if you have any comments or questions.

Regards,
Matt


--STX
with Ada.Command_Line;  use Ada.Command_Line;
with Ada.Text_IO;  use Ada.Text_IO;
with Ada.Integer_Text_IO;  use Ada.Integer_Text_IO;
with Scanners;     use Scanners;
with Ada.Containers.Indefinite_Hashed_Maps;  use Ada.Containers;
with Ada.Strings.Hash_Case_Insensitive;
with Ada.Strings.Equal_Case_Insensitive;  use Ada.Strings;

procedure Count_Words is
   Line      : String (1 .. 256);
   Line_Last : Natural;

   package Map_Types is new Indefinite_Hashed_Maps
     (String,
      Natural,
      Hash_Case_Insensitive,
      Equal_Case_Insensitive);
   
   M : Map_Types.Map;
   use Map_Types;

   F : File_Type;

begin
   Open (F, In_File, Argument (1));

   while not End_Of_File (F) loop
      Get_Line(F, Line, Line_Last);

      declare
         procedure Increment_Count 
           (Word  : String; 
            Count : in out Natural)
         is
         begin
            Count := Count + 1;
         end;

         S : Scanner := Scan (Line (Line'First .. Line_Last));
         
         C : Map_Types.Cursor;
         B : Boolean;

      begin
         while S.Has_Word loop
            M.Insert (S.Word, 0, C, B);
            M.Update_Element (C, Increment_Count'Access);
         end loop;
      end;
   end loop;

   declare
      procedure Process (C : Map_Types.Cursor) is
         Word  : constant String := Key (C);
         Count : constant Natural := Element (C);

      begin
         Put (Word);
         Put (':');
         Put (Count, Width => 0);
         New_Line;
      end Process;

   begin
      M.Iterate (Process'Access);
   end;

end Count_Words;

package Scanners is
   pragma Pure;

   type Scanner (<>) is tagged limited private;

   function Scan (Line : String) return Scanner;

   function Has_Word (S : Scanner) return Boolean;
   function Word (S : Scanner) return String;

private

   type Handle (S : not null access Scanner) is limited null record;

   type Scanner (Last : Natural) is tagged limited record
      H          : Handle (Scanner'Access);
      Line       : String (1 .. Last);
      Word_First : Positive;
      Word_Last  : Natural;
   end record;

end Scanners;

with Ada.Characters.Latin_1;  use Ada.Characters;

package body Scanners is

   function Is_Whitespace (C : Character) return Boolean is
   begin
      case C is
         when ' ' | Latin_1.HT => 
            return True;
         when others =>
            return False;
      end case;
   end Is_Whitespace;
      

   procedure Next (S : in out Scanner) is
      I : Integer renames S.Word_First;
      J : Integer renames S.Word_Last;
      
   begin
      I := J + 1;
      while I <= S.Last 
        and then Is_Whitespace (S.Line (I))
      loop
         I := I + 1;
      end loop;
      
      if I > S.Last then
         return;  -- no more words on this line
      end if;
      
      J := I;
      while J < S.Last 
        and then not Is_Whitespace (S.Line (J + 1))
      loop
         J := J + 1;
      end loop;
   end Next;
      

   function Scan (Line : String) return Scanner is
   begin
      return S : Scanner (Line'Length) do
        S.Line := Line;
        -- S.Word_First := 1;
        S.Word_Last := 0;
        Next (S);
      end return;
   end Scan;


   function Has_Word (S : Scanner) return Boolean is
   begin
      return S.Word_First <= S.Word_Last;
   end Has_Word;


   function Word (S : Scanner) return String is
      L : constant Positive := S.Word_Last - S.Word_First + 1;
      
   begin
      return Result : String (1 .. L) do
        Result := S.Line (S.Word_First .. S.Word_Last);
        Next (S.H.S.all);
      end return;
   end Word;

end Scanners;



^ permalink raw reply	[relevance 5%]

Results 1-12 of 12 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2007-11-14 23:28     OO Style with Ada Containers braver
2007-11-14 23:50     ` Adam Beneschan
2007-11-14 23:59       ` braver
2007-11-15  0:24         ` braver
2007-11-19  2:24  5%       ` Matthew Heaney
2011-10-14  6:58     Why no Ada.Wide_Directories? Michael Rohan
2011-10-15  1:06     ` ytomino
2011-10-17 21:33       ` Randy Brukardt
2011-10-17 23:47  5%     ` ytomino
2011-10-18  1:10  5%       ` Adam Beneschan
2011-10-18  2:32  0%         ` ytomino
2011-10-18  3:15  0%         ` Yannick Duchêne (Hibou57)
2011-12-18 12:34     String_Holder ? Natasha Kerensikova
2011-12-19 11:12  6% ` Martin
2015-11-12  4:06     Unicode string comparision functions Shark8
2015-11-12  5:04     ` Jeffrey R. Carter
2015-11-12 20:01       ` Shark8
2015-11-12 22:33  6%     ` Jeffrey R. Carter
2015-11-13  0:10  0%       ` Randy Brukardt
2015-11-13  8:22  0%         ` Simon Wright
2019-05-24 15:49     Suggestions needed to split a package A. Cervetti
2019-05-24 16:14     ` Björn Lundin
2019-05-24 20:26       ` Randy Brukardt
2019-05-24 21:21  7%     ` Shark8
2020-09-11 10:37     Visibility issue Daniel
2020-09-17 21:47  5% ` Shark8
2021-02-20 15:26     set_index and and end_of_file with just a stream reference Mehdi Saada
2021-02-20 16:04     ` Dmitry A. Kazakov
2021-02-20 16:22       ` Mehdi Saada
2021-02-20 16:30         ` Mehdi Saada
2021-02-20 17:59           ` Dmitry A. Kazakov
2021-02-20 19:08             ` Mehdi Saada
2021-02-23 17:21  6%           ` Shark8

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox