Don't shadow the system() function
[oweals/gnunet.git] / src / util / time.c
index 3a6f380413c8e894d87546bcd8bedf2ec8d5d2b0..01a3cddd5adac5e316b9c0ac7cfea6d068b6f101 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2006, 2009 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2001-2013 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -24,7 +24,7 @@
  * @brief functions for handling time and time arithmetic
  */
 #include "platform.h"
  * @brief functions for handling time and time arithmetic
  */
 #include "platform.h"
-#include "gnunet_time_lib.h"
+#include "gnunet_util_lib.h"
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
@@ -44,6 +44,19 @@ GNUNET_TIME_set_offset (long long offset)
   timestamp_offset = offset;
 }
 
   timestamp_offset = offset;
 }
 
+
+/**
+ * Get the timestamp offset for this instance.
+ *
+ * @return the offset we currently skew the locale time by
+ */
+long long
+GNUNET_TIME_get_offset ()
+{
+  return timestamp_offset;
+}
+
+
 /**
  * Get the current time (works just as "time", just that we use the
  * unit of time that the cron-jobs use (and is 64 bit)).
 /**
  * Get the current time (works just as "time", just that we use the
  * unit of time that the cron-jobs use (and is 64 bit)).
@@ -57,9 +70,9 @@ GNUNET_TIME_absolute_get ()
   struct timeval tv;
 
   GETTIMEOFDAY (&tv, NULL);
   struct timeval tv;
 
   GETTIMEOFDAY (&tv, NULL);
-  ret.abs_value =
-      (uint64_t) (((uint64_t) tv.tv_sec * 1000LL) +
-                  ((uint64_t) tv.tv_usec / 1000LL)) + timestamp_offset;
+  ret.abs_value_us =
+      (uint64_t) (((uint64_t) tv.tv_sec * 1000LL * 1000LL) +
+                  ((uint64_t) tv.tv_usec)) + timestamp_offset;
   return ret;
 }
 
   return ret;
 }
 
@@ -68,7 +81,7 @@ GNUNET_TIME_absolute_get ()
  * Return relative time of 0ms.
  */
 struct GNUNET_TIME_Relative
  * Return relative time of 0ms.
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_zero ()
+GNUNET_TIME_relative_get_zero_ ()
 {
   static struct GNUNET_TIME_Relative zero;
 
 {
   static struct GNUNET_TIME_Relative zero;
 
@@ -80,28 +93,74 @@ GNUNET_TIME_relative_get_zero ()
  * Return absolute time of 0ms.
  */
 struct GNUNET_TIME_Absolute
  * Return absolute time of 0ms.
  */
 struct GNUNET_TIME_Absolute
-GNUNET_TIME_absolute_get_zero ()
+GNUNET_TIME_absolute_get_zero_ ()
 {
   static struct GNUNET_TIME_Absolute zero;
 
   return zero;
 }
 
 {
   static struct GNUNET_TIME_Absolute zero;
 
   return zero;
 }
 
+
 /**
 /**
- * Return relative time of 1ms.
+ * Return relative time of 1us.
  */
 struct GNUNET_TIME_Relative
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_unit ()
+GNUNET_TIME_relative_get_unit_ ()
 {
   static struct GNUNET_TIME_Relative one = { 1 };
   return one;
 }
 
 {
   static struct GNUNET_TIME_Relative one = { 1 };
   return one;
 }
 
+
+/**
+ * Return relative time of 1ms.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_millisecond_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 1000 };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1s.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_second_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 1000 * 1000LL };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1 minute.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_minute_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 60 * 1000 * 1000LL };
+  return one;
+}
+
+
+/**
+ * Return relative time of 1 hour.
+ */
+struct GNUNET_TIME_Relative
+GNUNET_TIME_relative_get_hour_ ()
+{
+  static struct GNUNET_TIME_Relative one = { 60 * 60 * 1000 * 1000LL };
+  return one;
+}
+
+
 /**
  * Return "forever".
  */
 struct GNUNET_TIME_Relative
 /**
  * Return "forever".
  */
 struct GNUNET_TIME_Relative
-GNUNET_TIME_relative_get_forever ()
+GNUNET_TIME_relative_get_forever_ ()
 {
   static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
   return forever;
 {
   static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
   return forever;
@@ -111,7 +170,7 @@ GNUNET_TIME_relative_get_forever ()
  * Return "forever".
  */
 struct GNUNET_TIME_Absolute
  * Return "forever".
  */
 struct GNUNET_TIME_Absolute
-GNUNET_TIME_absolute_get_forever ()
+GNUNET_TIME_absolute_get_forever_ ()
 {
   static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
   return forever;
 {
   static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
   return forever;
@@ -128,16 +187,16 @@ GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
 {
   struct GNUNET_TIME_Absolute ret;
 
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if (rel.rel_value == UINT64_MAX)
-    return GNUNET_TIME_absolute_get_forever ();
+  if (rel.rel_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
-  if (rel.rel_value + now.abs_value < rel.rel_value)
+  if (rel.rel_value_us + now.abs_value_us < rel.rel_value_us)
   {
     GNUNET_break (0);           /* overflow... */
   {
     GNUNET_break (0);           /* overflow... */
-    return GNUNET_TIME_absolute_get_forever ();
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
   }
   }
-  ret.abs_value = rel.rel_value + now.abs_value;
+  ret.abs_value_us = rel.rel_value_us + now.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -153,7 +212,7 @@ struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
                           struct GNUNET_TIME_Relative t2)
 {
 GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
                           struct GNUNET_TIME_Relative t2)
 {
-  return (t1.rel_value < t2.rel_value) ? t1 : t2;
+  return (t1.rel_value_us < t2.rel_value_us) ? t1 : t2;
 }
 
 
 }
 
 
@@ -168,7 +227,7 @@ struct GNUNET_TIME_Relative
 GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
                           struct GNUNET_TIME_Relative t2)
 {
 GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
                           struct GNUNET_TIME_Relative t2)
 {
-  return (t1.rel_value > t2.rel_value) ? t1 : t2;
+  return (t1.rel_value_us > t2.rel_value_us) ? t1 : t2;
 }
 
 
 }
 
 
@@ -184,7 +243,7 @@ struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
                           struct GNUNET_TIME_Absolute t2)
 {
 GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
                           struct GNUNET_TIME_Absolute t2)
 {
-  return (t1.abs_value < t2.abs_value) ? t1 : t2;
+  return (t1.abs_value_us < t2.abs_value_us) ? t1 : t2;
 }
 
 
 }
 
 
@@ -199,7 +258,7 @@ struct GNUNET_TIME_Absolute
 GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
                           struct GNUNET_TIME_Absolute t2)
 {
 GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
                           struct GNUNET_TIME_Absolute t2)
 {
-  return (t1.abs_value > t2.abs_value) ? t1 : t2;
+  return (t1.abs_value_us > t2.abs_value_us) ? t1 : t2;
 }
 
 
 }
 
 
@@ -214,13 +273,13 @@ GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (future.abs_value == UINT64_MAX)
-    return GNUNET_TIME_relative_get_forever ();
+  if (future.abs_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
 
-  if (now.abs_value > future.abs_value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.rel_value = future.abs_value - now.abs_value;
+  if (now.abs_value_us > future.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = future.abs_value_us - now.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -237,11 +296,11 @@ GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (end.abs_value == UINT64_MAX)
-    return GNUNET_TIME_relative_get_forever ();
-  if (end.abs_value < start.abs_value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.rel_value = end.abs_value - start.abs_value;
+  if (end.abs_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  if (end.abs_value_us < start.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = end.abs_value_us - start.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -258,10 +317,10 @@ GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
   struct GNUNET_TIME_Relative ret;
 
   now = GNUNET_TIME_absolute_get ();
   struct GNUNET_TIME_Relative ret;
 
   now = GNUNET_TIME_absolute_get ();
-  GNUNET_assert (whence.abs_value != UINT64_MAX);
-  if (whence.abs_value > now.abs_value)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.rel_value = now.abs_value - whence.abs_value;
+  GNUNET_assert (whence.abs_value_us != UINT64_MAX);
+  if (whence.abs_value_us > now.abs_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  ret.rel_value_us = now.abs_value_us - whence.abs_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -278,14 +337,14 @@ GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Absolute ret;
 
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if ((start.abs_value == UINT64_MAX) || (duration.rel_value == UINT64_MAX))
-    return GNUNET_TIME_absolute_get_forever ();
-  if (start.abs_value + duration.rel_value < start.abs_value)
+  if ((start.abs_value_us == UINT64_MAX) || (duration.rel_value_us == UINT64_MAX))
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
+  if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
   {
     GNUNET_break (0);
   {
     GNUNET_break (0);
-    return GNUNET_TIME_absolute_get_forever ();
+    return GNUNET_TIME_UNIT_FOREVER_ABS;
   }
   }
-  ret.abs_value = start.abs_value + duration.rel_value;
+  ret.abs_value_us = start.abs_value_us + duration.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -304,11 +363,11 @@ GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
 {
   struct GNUNET_TIME_Absolute ret;
 
 {
   struct GNUNET_TIME_Absolute ret;
 
-  if (start.abs_value <= duration.rel_value)
+  if (start.abs_value_us <= duration.rel_value_us)
     return GNUNET_TIME_UNIT_ZERO_ABS;
     return GNUNET_TIME_UNIT_ZERO_ABS;
-  if (start.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
+  if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
     return GNUNET_TIME_UNIT_FOREVER_ABS;
     return GNUNET_TIME_UNIT_FOREVER_ABS;
-  ret.abs_value = start.abs_value - duration.rel_value;
+  ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -324,13 +383,15 @@ GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (factor == 0)
-    return GNUNET_TIME_relative_get_zero ();
-  ret.rel_value = rel.rel_value * (unsigned long long) factor;
-  if (ret.rel_value / factor != rel.rel_value)
+  if (0 == factor)
+    return GNUNET_TIME_UNIT_ZERO;
+  if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  ret.rel_value_us = rel.rel_value_us * (unsigned long long) factor;
+  if (ret.rel_value_us / factor != rel.rel_value_us)
   {
     GNUNET_break (0);
   {
     GNUNET_break (0);
-    return GNUNET_TIME_relative_get_forever ();
+    return GNUNET_TIME_UNIT_FOREVER_REL;
   }
   return ret;
 }
   }
   return ret;
 }
@@ -349,10 +410,10 @@ GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if ((factor == 0) ||
-      (rel.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value))
+  if ((0 == factor) ||
+      (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
     return GNUNET_TIME_UNIT_FOREVER_REL;
     return GNUNET_TIME_UNIT_FOREVER_REL;
-  ret.rel_value = rel.rel_value / (unsigned long long) factor;
+  ret.rel_value_us = rel.rel_value_us / (unsigned long long) factor;
   return ret;
 }
 
   return ret;
 }
 
@@ -378,11 +439,11 @@ GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished,
   GNUNET_break (finished <= total);
   if (finished >= total)
     return GNUNET_TIME_UNIT_ZERO;
   GNUNET_break (finished <= total);
   if (finished >= total)
     return GNUNET_TIME_UNIT_ZERO;
-  if (finished == 0)
+  if (0 == finished)
     return GNUNET_TIME_UNIT_FOREVER_REL;
   dur = GNUNET_TIME_absolute_get_duration (start);
     return GNUNET_TIME_UNIT_FOREVER_REL;
   dur = GNUNET_TIME_absolute_get_duration (start);
-  exp = ((double) dur.rel_value) * ((double) total) / ((double) finished);
-  ret.rel_value = ((uint64_t) exp) - dur.rel_value;
+  exp = ((double) dur.rel_value_us) * ((double) total) / ((double) finished);
+  ret.rel_value_us = ((uint64_t) exp) - dur.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -400,14 +461,14 @@ GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if ((a1.rel_value == UINT64_MAX) || (a2.rel_value == UINT64_MAX))
-    return GNUNET_TIME_relative_get_forever ();
-  if (a1.rel_value + a2.rel_value < a1.rel_value)
+  if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX))
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us)
   {
     GNUNET_break (0);
   {
     GNUNET_break (0);
-    return GNUNET_TIME_relative_get_forever ();
+    return GNUNET_TIME_UNIT_FOREVER_REL;
   }
   }
-  ret.rel_value = a1.rel_value + a2.rel_value;
+  ret.rel_value_us = a1.rel_value_us + a2.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -425,11 +486,11 @@ GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  if (a2.rel_value >= a1.rel_value)
-    return GNUNET_TIME_relative_get_zero ();
-  if (a1.rel_value == UINT64_MAX)
-    return GNUNET_TIME_relative_get_forever ();
-  ret.rel_value = a1.rel_value - a2.rel_value;
+  if (a2.rel_value_us >= a1.rel_value_us)
+    return GNUNET_TIME_UNIT_ZERO;
+  if (a1.rel_value_us == UINT64_MAX)
+    return GNUNET_TIME_UNIT_FOREVER_REL;
+  ret.rel_value_us = a1.rel_value_us - a2.rel_value_us;
   return ret;
 }
 
   return ret;
 }
 
@@ -445,10 +506,11 @@ GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
 {
   struct GNUNET_TIME_RelativeNBO ret;
 
 {
   struct GNUNET_TIME_RelativeNBO ret;
 
-  ret.rel_value__ = GNUNET_htonll (a.rel_value);
+  ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us);
   return ret;
 }
 
   return ret;
 }
 
+
 /**
  * Convert relative time from network byte order.
  *
 /**
  * Convert relative time from network byte order.
  *
@@ -460,11 +522,12 @@ GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
 {
   struct GNUNET_TIME_Relative ret;
 
 {
   struct GNUNET_TIME_Relative ret;
 
-  ret.rel_value = GNUNET_ntohll (a.rel_value__);
+  ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__);
   return ret;
 
 }
 
   return ret;
 
 }
 
+
 /**
  * Convert absolute time to network byte order.
  *
 /**
  * Convert absolute time to network byte order.
  *
@@ -476,10 +539,11 @@ GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
 {
   struct GNUNET_TIME_AbsoluteNBO ret;
 
 {
   struct GNUNET_TIME_AbsoluteNBO ret;
 
-  ret.abs_value__ = GNUNET_htonll (a.abs_value);
+  ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us);
   return ret;
 }
 
   return ret;
 }
 
+
 /**
  * Convert absolute time from network byte order.
  *
 /**
  * Convert absolute time from network byte order.
  *
@@ -491,29 +555,78 @@ GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
 {
   struct GNUNET_TIME_Absolute ret;
 
 {
   struct GNUNET_TIME_Absolute ret;
 
-  ret.abs_value = GNUNET_ntohll (a.abs_value__);
+  ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__);
   return ret;
 
 }
 
   return ret;
 
 }
 
+
+/**
+ * Return the current year (i.e. '2011').
+ */
+unsigned int
+GNUNET_TIME_get_current_year ()
+{
+  time_t tp;
+  struct tm *t;
+
+  tp = time (NULL);
+  t = gmtime (&tp);
+  if (t == NULL)
+    return 0;
+  return t->tm_year + 1900;
+}
+
+
 /**
 /**
- * Convert a relative time to a string.
- * This is one of the very few calls in the entire API that is
- * NOT reentrant!
+ * Convert an expiration time to the respective year (rounds)
  *
  *
- * @param time the time to print
- *
- * @return string form of the time (as milliseconds)
+ * @param at absolute time
+ * @return year a year (after 1970), 0 on error
  */
  */
-const char *
-GNUNET_TIME_relative_to_string (struct GNUNET_TIME_Relative time)
+unsigned int
+GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
 {
 {
-  static char time_string[21];
+  struct tm *t;
+  time_t tp;
+
+  tp = at.abs_value_us / 1000LL / 1000LL;    /* microseconds to seconds */
+  t = gmtime (&tp);
+  if (t == NULL)
+    return 0;
+  return t->tm_year + 1900;
 
 
-  memset (time_string, 0, sizeof (time_string));
+}
 
 
-  sprintf (time_string, "%llu", (unsigned long long) time.rel_value);
-  return (const char *) time_string;
+
+/**
+ * Convert a year to an expiration time of January 1st of that year.
+ *
+ * @param year a year (after 1970, please ;-)).
+ * @return absolute time for January 1st of that year.
+ */
+struct GNUNET_TIME_Absolute
+GNUNET_TIME_year_to_time (unsigned int year)
+{
+  struct GNUNET_TIME_Absolute ret;
+  time_t tp;
+  struct tm t;
+
+  memset (&t, 0, sizeof (t));
+  if (year < 1900)
+  {
+    GNUNET_break (0);
+    return GNUNET_TIME_absolute_get (); /* now */
+  }
+  t.tm_year = year - 1900;
+  t.tm_mday = 1;
+  t.tm_mon = 1;
+  t.tm_wday = 1;
+  t.tm_yday = 1;
+  tp = mktime (&t);
+  GNUNET_break (tp != (time_t) - 1);
+  ret.abs_value_us = tp * 1000LL * 1000LL;  /* seconds to microseconds */
+  return ret;
 }
 
 
 }