~ubuntu-branches/debian/squeeze/protobuf/squeeze

« back to all changes in this revision

Viewing changes to src/google/protobuf/message.h

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-06-02 16:19:00 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090602161900-vm176i3ryt35yk91
Tags: 2.0.3-2.2
* Non-maintainer upload.
* Fix FTBFS from -2.1: don't fail when we can't clean up the java build,
  such as when openjdk isn't installed.
* Disable parallel builds, because libtool is made of fail (if binary-arch
  and build-indep run concurrently, we relink a library while it's being
  used; that doesn't work so well).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// Protocol Buffers - Google's data interchange format
2
 
// Copyright 2008 Google Inc.
 
2
// Copyright 2008 Google Inc.  All rights reserved.
3
3
// http://code.google.com/p/protobuf/
4
4
//
5
 
// Licensed under the Apache License, Version 2.0 (the "License");
6
 
// you may not use this file except in compliance with the License.
7
 
// You may obtain a copy of the License at
8
 
//
9
 
//      http://www.apache.org/licenses/LICENSE-2.0
10
 
//
11
 
// Unless required by applicable law or agreed to in writing, software
12
 
// distributed under the License is distributed on an "AS IS" BASIS,
13
 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
// See the License for the specific language governing permissions and
15
 
// limitations under the License.
 
5
// Redistribution and use in source and binary forms, with or without
 
6
// modification, are permitted provided that the following conditions are
 
7
// met:
 
8
//
 
9
//     * Redistributions of source code must retain the above copyright
 
10
// notice, this list of conditions and the following disclaimer.
 
11
//     * Redistributions in binary form must reproduce the above
 
12
// copyright notice, this list of conditions and the following disclaimer
 
13
// in the documentation and/or other materials provided with the
 
14
// distribution.
 
15
//     * Neither the name of Google Inc. nor the names of its
 
16
// contributors may be used to endorse or promote products derived from
 
17
// this software without specific prior written permission.
 
18
//
 
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
30
 
17
31
// Author: kenton@google.com (Kenton Varda)
18
32
//  Based on original Protocol Buffers design by
81
95
//     foo->ParseFromString(data);
82
96
//
83
97
//     // Use the reflection interface to examine the contents.
84
 
//     Message::Reflection* reflection = foo->GetReflection();
85
 
//     assert(reflection->GetString(text_field) == "Hello World!");
86
 
//     assert(reflection->CountField(numbers_field) == 3);
87
 
//     assert(reflection->GetInt32(numbers_field, 0) == 1);
88
 
//     assert(reflection->GetInt32(numbers_field, 1) == 5);
89
 
//     assert(reflection->GetInt32(numbers_field, 2) == 42);
 
98
//     const Reflection* reflection = foo->GetReflection();
 
99
//     assert(reflection->GetString(foo, text_field) == "Hello World!");
 
100
//     assert(reflection->CountField(foo, numbers_field) == 3);
 
101
//     assert(reflection->GetInt32(foo, numbers_field, 0) == 1);
 
102
//     assert(reflection->GetInt32(foo, numbers_field, 1) == 5);
 
103
//     assert(reflection->GetInt32(foo, numbers_field, 2) == 42);
90
104
//
91
105
//     delete foo;
92
106
//   }
96
110
 
97
111
#include <vector>
98
112
#include <string>
 
113
 
 
114
#ifdef __DECCXX
 
115
// HP C++'s iosfwd doesn't work.
 
116
#include <iostream>
 
117
#else
99
118
#include <iosfwd>
 
119
#endif
 
120
 
100
121
#include <google/protobuf/stubs/common.h>
101
122
 
102
123
namespace google {
105
126
 
106
127
// Defined in this file.
107
128
class Message;
 
129
class Reflection;
108
130
 
109
131
// Defined in other files.
110
132
class Descriptor;            // descriptor.h
293
315
  bool SerializePartialToOstream(ostream* output) const;
294
316
 
295
317
 
 
318
  // Make a string encoding the message. Is equivalent to calling
 
319
  // SerializeToString() on a string and using that.  Returns the empty
 
320
  // string if SerializeToString() would have returned an error.
 
321
  // Note: If you intend to generate many such strings, you may
 
322
  // reduce heap fragmentation by instead re-using the same string
 
323
  // object with calls to SerializeToString().
 
324
  string SerializeAsString() const;
 
325
  // Like SerializeAsString(), but allows missing required fields.
 
326
  string SerializePartialAsString() const;
 
327
 
296
328
  // Like SerializeToString(), but appends to the data to the string's existing
297
329
  // contents.  All required fields must be set.
298
330
  bool AppendToString(string* output) const;
304
336
  // this, it MUST override SetCachedSize().
305
337
  virtual int ByteSize() const;
306
338
 
 
339
  // Computes (an estimate of) the total number of bytes currently used for
 
340
  // storing the message in memory.  The default implementation calls the
 
341
  // Reflection object's SpaceUsed() method.
 
342
  virtual int SpaceUsed() const;
 
343
 
307
344
  // Serializes the message without recomputing the size.  The message must
308
345
  // not have changed since the last call to ByteSize(); if it has, the results
309
346
  // are undefined.
336
373
 
337
374
  // Introspection ---------------------------------------------------
338
375
 
339
 
  class Reflection;  // Defined below.
 
376
  // Typedef for backwards-compatibility.
 
377
  typedef google::protobuf::Reflection Reflection;
340
378
 
341
379
  // Get a Descriptor for this message's type.  This describes what
342
380
  // fields the message contains, the types of those fields, etc.
348
386
  // property of the Message.
349
387
  virtual const Reflection* GetReflection() const = 0;
350
388
 
351
 
  // Get the Reflection interface for this Message, which can be used to
352
 
  // read and modify the fields of the Message dynamically (in other words,
353
 
  // without knowing the message type at compile time).  This object remains
354
 
  // property of the Message.
355
 
  virtual Reflection* GetReflection() = 0;
356
 
 
357
389
 private:
358
390
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
359
391
};
367
399
// This interface is separate from Message only for efficiency reasons;
368
400
// the vast majority of implementations of Message will share the same
369
401
// implementation of Reflection (GeneratedMessageReflection,
370
 
// defined in generated_message.h).
 
402
// defined in generated_message.h), and all Messages of a particular class
 
403
// should share the same Reflection object (though you should not rely on
 
404
// the latter fact).
371
405
//
372
406
// There are several ways that these methods can be used incorrectly.  For
373
407
// example, any of the following conditions will lead to undefined
382
416
//   field.
383
417
// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated
384
418
//   field.
 
419
// - The Message object passed to any method is not of the right type for
 
420
//   this Reflection object (i.e. message.GetReflection() != reflection).
385
421
//
386
422
// You might wonder why there is not any abstract representation for a field
387
423
// of arbitrary type.  E.g., why isn't there just a "GetField()" method that
395
431
//
396
432
// TODO(kenton):  Create a utility class which callers can use to read and
397
433
//   write fields from a Reflection without paying attention to the type.
398
 
class LIBPROTOBUF_EXPORT Message::Reflection {
 
434
class LIBPROTOBUF_EXPORT Reflection {
399
435
 public:
 
436
  // TODO(kenton):  Remove parameter.
400
437
  inline Reflection() {}
401
438
  virtual ~Reflection();
402
439
 
403
440
  // Get the UnknownFieldSet for the message.  This contains fields which
404
441
  // were seen when the Message was parsed but were not recognized according
405
442
  // to the Message's definition.
406
 
  virtual const UnknownFieldSet& GetUnknownFields() const = 0;
 
443
  virtual const UnknownFieldSet& GetUnknownFields(
 
444
      const Message& message) const = 0;
407
445
  // Get a mutable pointer to the UnknownFieldSet for the message.  This
408
446
  // contains fields which were seen when the Message was parsed but were not
409
447
  // recognized according to the Message's definition.
410
 
  virtual UnknownFieldSet* MutableUnknownFields() = 0;
 
448
  virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
 
449
 
 
450
  // Estimate the amount of memory used by the message object.
 
451
  virtual int SpaceUsed(const Message& message) const = 0;
411
452
 
412
453
  // Check if the given non-repeated field is set.
413
 
  virtual bool HasField(const FieldDescriptor* field) const = 0;
 
454
  virtual bool HasField(const Message& message,
 
455
                        const FieldDescriptor* field) const = 0;
414
456
 
415
457
  // Get the number of elements of a repeated field.
416
 
  virtual int FieldSize(const FieldDescriptor* field) const = 0;
 
458
  virtual int FieldSize(const Message& message,
 
459
                        const FieldDescriptor* field) const = 0;
417
460
 
418
461
  // Clear the value of a field, so that HasField() returns false or
419
462
  // FieldSize() returns zero.
420
 
  virtual void ClearField(const FieldDescriptor* field) = 0;
 
463
  virtual void ClearField(Message* message,
 
464
                          const FieldDescriptor* field) const = 0;
421
465
 
422
466
  // List all fields of the message which are currently set.  This includes
423
467
  // extensions.  Singular fields will only be listed if HasField(field) would
424
468
  // return true and repeated fields will only be listed if FieldSize(field)
425
469
  // would return non-zero.  Fields (both normal fields and extension fields)
426
470
  // will be listed ordered by field number.
427
 
  virtual void ListFields(vector<const FieldDescriptor*>* output) const = 0;
 
471
  virtual void ListFields(const Message& message,
 
472
                          vector<const FieldDescriptor*>* output) const = 0;
428
473
 
429
474
  // Singular field getters ------------------------------------------
430
475
  // These get the value of a non-repeated field.  They return the default
431
476
  // value for fields that aren't set.
432
477
 
433
 
  virtual int32  GetInt32 (const FieldDescriptor* field) const = 0;
434
 
  virtual int64  GetInt64 (const FieldDescriptor* field) const = 0;
435
 
  virtual uint32 GetUInt32(const FieldDescriptor* field) const = 0;
436
 
  virtual uint64 GetUInt64(const FieldDescriptor* field) const = 0;
437
 
  virtual float  GetFloat (const FieldDescriptor* field) const = 0;
438
 
  virtual double GetDouble(const FieldDescriptor* field) const = 0;
439
 
  virtual bool   GetBool  (const FieldDescriptor* field) const = 0;
440
 
  virtual string GetString(const FieldDescriptor* field) const = 0;
 
478
  virtual int32  GetInt32 (const Message& message,
 
479
                           const FieldDescriptor* field) const = 0;
 
480
  virtual int64  GetInt64 (const Message& message,
 
481
                           const FieldDescriptor* field) const = 0;
 
482
  virtual uint32 GetUInt32(const Message& message,
 
483
                           const FieldDescriptor* field) const = 0;
 
484
  virtual uint64 GetUInt64(const Message& message,
 
485
                           const FieldDescriptor* field) const = 0;
 
486
  virtual float  GetFloat (const Message& message,
 
487
                           const FieldDescriptor* field) const = 0;
 
488
  virtual double GetDouble(const Message& message,
 
489
                           const FieldDescriptor* field) const = 0;
 
490
  virtual bool   GetBool  (const Message& message,
 
491
                           const FieldDescriptor* field) const = 0;
 
492
  virtual string GetString(const Message& message,
 
493
                           const FieldDescriptor* field) const = 0;
441
494
  virtual const EnumValueDescriptor* GetEnum(
442
 
      const FieldDescriptor* field) const = 0;
443
 
  virtual const Message& GetMessage(const FieldDescriptor* field) const = 0;
 
495
      const Message& message, const FieldDescriptor* field) const = 0;
 
496
  virtual const Message& GetMessage(const Message& message,
 
497
                                    const FieldDescriptor* field) const = 0;
444
498
 
445
499
  // Get a string value without copying, if possible.
446
500
  //
457
511
  //   a newly-constructed string, though, it's just as fast and more readable
458
512
  //   to use code like:
459
513
  //     string str = reflection->GetString(field);
460
 
  virtual const string& GetStringReference(const FieldDescriptor* field,
 
514
  virtual const string& GetStringReference(const Message& message,
 
515
                                           const FieldDescriptor* field,
461
516
                                           string* scratch) const = 0;
462
517
 
463
518
 
464
519
  // Singular field mutators -----------------------------------------
465
520
  // These mutate the value of a non-repeated field.
466
521
 
467
 
  virtual void SetInt32 (const FieldDescriptor* field, int32  value) = 0;
468
 
  virtual void SetInt64 (const FieldDescriptor* field, int64  value) = 0;
469
 
  virtual void SetUInt32(const FieldDescriptor* field, uint32 value) = 0;
470
 
  virtual void SetUInt64(const FieldDescriptor* field, uint64 value) = 0;
471
 
  virtual void SetFloat (const FieldDescriptor* field, float  value) = 0;
472
 
  virtual void SetDouble(const FieldDescriptor* field, double value) = 0;
473
 
  virtual void SetBool  (const FieldDescriptor* field, bool   value) = 0;
474
 
  virtual void SetString(const FieldDescriptor* field, const string& value) = 0;
475
 
  virtual void SetEnum  (const FieldDescriptor* field,
476
 
                         const EnumValueDescriptor* value) = 0;
 
522
  virtual void SetInt32 (Message* message,
 
523
                         const FieldDescriptor* field, int32  value) const = 0;
 
524
  virtual void SetInt64 (Message* message,
 
525
                         const FieldDescriptor* field, int64  value) const = 0;
 
526
  virtual void SetUInt32(Message* message,
 
527
                         const FieldDescriptor* field, uint32 value) const = 0;
 
528
  virtual void SetUInt64(Message* message,
 
529
                         const FieldDescriptor* field, uint64 value) const = 0;
 
530
  virtual void SetFloat (Message* message,
 
531
                         const FieldDescriptor* field, float  value) const = 0;
 
532
  virtual void SetDouble(Message* message,
 
533
                         const FieldDescriptor* field, double value) const = 0;
 
534
  virtual void SetBool  (Message* message,
 
535
                         const FieldDescriptor* field, bool   value) const = 0;
 
536
  virtual void SetString(Message* message,
 
537
                         const FieldDescriptor* field,
 
538
                         const string& value) const = 0;
 
539
  virtual void SetEnum  (Message* message,
 
540
                         const FieldDescriptor* field,
 
541
                         const EnumValueDescriptor* value) const = 0;
477
542
  // Get a mutable pointer to a field with a message type.
478
 
  virtual Message* MutableMessage(const FieldDescriptor* field) = 0;
 
543
  virtual Message* MutableMessage(Message* message,
 
544
                                  const FieldDescriptor* field) const = 0;
479
545
 
480
546
 
481
547
  // Repeated field getters ------------------------------------------
482
548
  // These get the value of one element of a repeated field.
483
549
 
484
 
  virtual int32  GetRepeatedInt32 (const FieldDescriptor* field,
485
 
                                   int index) const = 0;
486
 
  virtual int64  GetRepeatedInt64 (const FieldDescriptor* field,
487
 
                                   int index) const = 0;
488
 
  virtual uint32 GetRepeatedUInt32(const FieldDescriptor* field,
489
 
                                   int index) const = 0;
490
 
  virtual uint64 GetRepeatedUInt64(const FieldDescriptor* field,
491
 
                                   int index) const = 0;
492
 
  virtual float  GetRepeatedFloat (const FieldDescriptor* field,
493
 
                                   int index) const = 0;
494
 
  virtual double GetRepeatedDouble(const FieldDescriptor* field,
495
 
                                   int index) const = 0;
496
 
  virtual bool   GetRepeatedBool  (const FieldDescriptor* field,
497
 
                                   int index) const = 0;
498
 
  virtual string GetRepeatedString(const FieldDescriptor* field,
 
550
  virtual int32  GetRepeatedInt32 (const Message& message,
 
551
                                   const FieldDescriptor* field,
 
552
                                   int index) const = 0;
 
553
  virtual int64  GetRepeatedInt64 (const Message& message,
 
554
                                   const FieldDescriptor* field,
 
555
                                   int index) const = 0;
 
556
  virtual uint32 GetRepeatedUInt32(const Message& message,
 
557
                                   const FieldDescriptor* field,
 
558
                                   int index) const = 0;
 
559
  virtual uint64 GetRepeatedUInt64(const Message& message,
 
560
                                   const FieldDescriptor* field,
 
561
                                   int index) const = 0;
 
562
  virtual float  GetRepeatedFloat (const Message& message,
 
563
                                   const FieldDescriptor* field,
 
564
                                   int index) const = 0;
 
565
  virtual double GetRepeatedDouble(const Message& message,
 
566
                                   const FieldDescriptor* field,
 
567
                                   int index) const = 0;
 
568
  virtual bool   GetRepeatedBool  (const Message& message,
 
569
                                   const FieldDescriptor* field,
 
570
                                   int index) const = 0;
 
571
  virtual string GetRepeatedString(const Message& message,
 
572
                                   const FieldDescriptor* field,
499
573
                                   int index) const = 0;
500
574
  virtual const EnumValueDescriptor* GetRepeatedEnum(
 
575
      const Message& message,
501
576
      const FieldDescriptor* field, int index) const = 0;
502
577
  virtual const Message& GetRepeatedMessage(
 
578
      const Message& message,
503
579
      const FieldDescriptor* field, int index) const = 0;
504
580
 
505
581
  // See GetStringReference(), above.
506
582
  virtual const string& GetRepeatedStringReference(
507
 
      const FieldDescriptor* field, int index,
508
 
      string* scratch) const = 0;
 
583
      const Message& message, const FieldDescriptor* field,
 
584
      int index, string* scratch) const = 0;
509
585
 
510
586
 
511
587
  // Repeated field mutators -----------------------------------------
512
588
  // These mutate the value of one element of a repeated field.
513
589
 
514
 
  virtual void SetRepeatedInt32 (const FieldDescriptor* field,
515
 
                                 int index, int32  value) = 0;
516
 
  virtual void SetRepeatedInt64 (const FieldDescriptor* field,
517
 
                                 int index, int64  value) = 0;
518
 
  virtual void SetRepeatedUInt32(const FieldDescriptor* field,
519
 
                                 int index, uint32 value) = 0;
520
 
  virtual void SetRepeatedUInt64(const FieldDescriptor* field,
521
 
                                 int index, uint64 value) = 0;
522
 
  virtual void SetRepeatedFloat (const FieldDescriptor* field,
523
 
                                 int index, float  value) = 0;
524
 
  virtual void SetRepeatedDouble(const FieldDescriptor* field,
525
 
                                 int index, double value) = 0;
526
 
  virtual void SetRepeatedBool  (const FieldDescriptor* field,
527
 
                                 int index, bool   value) = 0;
528
 
  virtual void SetRepeatedString(const FieldDescriptor* field,
529
 
                                 int index, const string& value) = 0;
530
 
  virtual void SetRepeatedEnum(const FieldDescriptor* field,
531
 
                               int index, const EnumValueDescriptor* value) = 0;
 
590
  virtual void SetRepeatedInt32 (Message* message,
 
591
                                 const FieldDescriptor* field,
 
592
                                 int index, int32  value) const = 0;
 
593
  virtual void SetRepeatedInt64 (Message* message,
 
594
                                 const FieldDescriptor* field,
 
595
                                 int index, int64  value) const = 0;
 
596
  virtual void SetRepeatedUInt32(Message* message,
 
597
                                 const FieldDescriptor* field,
 
598
                                 int index, uint32 value) const = 0;
 
599
  virtual void SetRepeatedUInt64(Message* message,
 
600
                                 const FieldDescriptor* field,
 
601
                                 int index, uint64 value) const = 0;
 
602
  virtual void SetRepeatedFloat (Message* message,
 
603
                                 const FieldDescriptor* field,
 
604
                                 int index, float  value) const = 0;
 
605
  virtual void SetRepeatedDouble(Message* message,
 
606
                                 const FieldDescriptor* field,
 
607
                                 int index, double value) const = 0;
 
608
  virtual void SetRepeatedBool  (Message* message,
 
609
                                 const FieldDescriptor* field,
 
610
                                 int index, bool   value) const = 0;
 
611
  virtual void SetRepeatedString(Message* message,
 
612
                                 const FieldDescriptor* field,
 
613
                                 int index, const string& value) const = 0;
 
614
  virtual void SetRepeatedEnum(Message* message,
 
615
                               const FieldDescriptor* field, int index,
 
616
                               const EnumValueDescriptor* value) const = 0;
532
617
  // Get a mutable pointer to an element of a repeated field with a message
533
618
  // type.
534
619
  virtual Message* MutableRepeatedMessage(
535
 
      const FieldDescriptor* field, int index) = 0;
 
620
      Message* message, const FieldDescriptor* field, int index) const = 0;
536
621
 
537
622
 
538
623
  // Repeated field adders -------------------------------------------
539
624
  // These add an element to a repeated field.
540
625
 
541
 
  virtual void AddInt32 (const FieldDescriptor* field, int32  value) = 0;
542
 
  virtual void AddInt64 (const FieldDescriptor* field, int64  value) = 0;
543
 
  virtual void AddUInt32(const FieldDescriptor* field, uint32 value) = 0;
544
 
  virtual void AddUInt64(const FieldDescriptor* field, uint64 value) = 0;
545
 
  virtual void AddFloat (const FieldDescriptor* field, float  value) = 0;
546
 
  virtual void AddDouble(const FieldDescriptor* field, double value) = 0;
547
 
  virtual void AddBool  (const FieldDescriptor* field, bool   value) = 0;
548
 
  virtual void AddString(const FieldDescriptor* field, const string& value) = 0;
549
 
  virtual void AddEnum  (const FieldDescriptor* field,
550
 
                         const EnumValueDescriptor* value) = 0;
551
 
  virtual Message* AddMessage(const FieldDescriptor* field) = 0;
 
626
  virtual void AddInt32 (Message* message,
 
627
                         const FieldDescriptor* field, int32  value) const = 0;
 
628
  virtual void AddInt64 (Message* message,
 
629
                         const FieldDescriptor* field, int64  value) const = 0;
 
630
  virtual void AddUInt32(Message* message,
 
631
                         const FieldDescriptor* field, uint32 value) const = 0;
 
632
  virtual void AddUInt64(Message* message,
 
633
                         const FieldDescriptor* field, uint64 value) const = 0;
 
634
  virtual void AddFloat (Message* message,
 
635
                         const FieldDescriptor* field, float  value) const = 0;
 
636
  virtual void AddDouble(Message* message,
 
637
                         const FieldDescriptor* field, double value) const = 0;
 
638
  virtual void AddBool  (Message* message,
 
639
                         const FieldDescriptor* field, bool   value) const = 0;
 
640
  virtual void AddString(Message* message,
 
641
                         const FieldDescriptor* field,
 
642
                         const string& value) const = 0;
 
643
  virtual void AddEnum  (Message* message,
 
644
                         const FieldDescriptor* field,
 
645
                         const EnumValueDescriptor* value) const = 0;
 
646
  virtual Message* AddMessage(Message* message,
 
647
                              const FieldDescriptor* field) const = 0;
552
648
 
553
649
 
554
650
  // Extensions ------------------------------------------------------